Files
mirror-processhacker/2.x/trunk/ProcessHacker/mainwnd.c
T
wj32 c5965bdcad improved dbghelp finding code
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@5563 21ef857c-d57f-4fe0-8362-d861dc6d29cd
2013-11-14 00:58:06 +00:00

5035 lines
148 KiB
C

/*
* Process Hacker -
* main window
*
* Copyright (C) 2009-2013 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#define PH_MAINWND_PRIVATE
#include <phapp.h>
#include <kphuser.h>
#include <settings.h>
#include <emenu.h>
#include <phplug.h>
#include <cpysave.h>
#include <mainwndp.h>
#include <notifico.h>
#include <memsrch.h>
#include <symprv.h>
#include <windowsx.h>
#include <shlobj.h>
#include <winsta.h>
#include <iphlpapi.h>
#define RUNAS_MODE_ADMIN 1
#define RUNAS_MODE_LIMITED 2
typedef HRESULT (WINAPI *_LoadIconMetric)(
_In_ HINSTANCE hinst,
_In_ PCWSTR pszName,
_In_ int lims,
_Out_ HICON *phico
);
PHAPPAPI HWND PhMainWndHandle;
BOOLEAN PhMainWndExiting = FALSE;
HMENU PhMainWndMenuHandle;
static BOOLEAN NeedsMaximize = FALSE;
static ULONG NeedsSelectPid = 0;
static BOOLEAN AlwaysOnTop = FALSE;
static BOOLEAN DelayedLoadCompleted = FALSE;
static ULONG NotifyIconNotifyMask;
static PH_CALLBACK_DECLARE(LayoutPaddingCallback);
static RECT LayoutPadding = { 0, 0, 0, 0 };
static BOOLEAN LayoutPaddingValid = TRUE;
static HWND TabControlHandle;
static INT ProcessesTabIndex;
static INT ServicesTabIndex;
static INT NetworkTabIndex;
static INT MaxTabIndex;
static INT OldTabIndex;
static PPH_LIST AdditionalTabPageList = NULL;
static HWND ProcessTreeListHandle;
static HWND ServiceTreeListHandle;
static HWND NetworkTreeListHandle;
static HFONT CurrentCustomFont;
static BOOLEAN NetworkFirstTime = TRUE;
static BOOLEAN ServiceTreeListLoaded = FALSE;
static BOOLEAN NetworkTreeListLoaded = FALSE;
static HMENU SubMenuHandles[5];
static PPH_EMENU SubMenuObjects[5];
static PPH_LIST LegacyAddMenuItemList;
static BOOLEAN UsersMenuInitialized = FALSE;
static BOOLEAN UpdateAutomatically = TRUE;
static PH_CALLBACK_REGISTRATION SymInitRegistration;
static PH_PROVIDER_REGISTRATION ProcessProviderRegistration;
static PH_CALLBACK_REGISTRATION ProcessAddedRegistration;
static PH_CALLBACK_REGISTRATION ProcessModifiedRegistration;
static PH_CALLBACK_REGISTRATION ProcessRemovedRegistration;
static PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
static BOOLEAN ProcessesNeedsRedraw = FALSE;
static PPH_PROCESS_NODE ProcessToScrollTo = NULL;
static PH_PROVIDER_REGISTRATION ServiceProviderRegistration;
static PH_CALLBACK_REGISTRATION ServiceAddedRegistration;
static PH_CALLBACK_REGISTRATION ServiceModifiedRegistration;
static PH_CALLBACK_REGISTRATION ServiceRemovedRegistration;
static PH_CALLBACK_REGISTRATION ServicesUpdatedRegistration;
static PPH_POINTER_LIST ServicesPendingList;
static BOOLEAN ServicesNeedsRedraw = FALSE;
static PH_PROVIDER_REGISTRATION NetworkProviderRegistration;
static PH_CALLBACK_REGISTRATION NetworkItemAddedRegistration;
static PH_CALLBACK_REGISTRATION NetworkItemModifiedRegistration;
static PH_CALLBACK_REGISTRATION NetworkItemRemovedRegistration;
static PH_CALLBACK_REGISTRATION NetworkItemsUpdatedRegistration;
static BOOLEAN NetworkNeedsRedraw = FALSE;
static ULONG SelectedRunAsMode;
static HWND SelectedProcessWindowHandle;
static BOOLEAN SelectedProcessVirtualizationEnabled;
static ULONG SelectedUserSessionId;
static PPH_TN_FILTER_ENTRY CurrentUserFilterEntry = NULL;
static PPH_TN_FILTER_ENTRY SignedFilterEntry = NULL;
//static PPH_TN_FILTER_ENTRY CurrentUserNetworkFilterEntry = NULL;
//static PPH_TN_FILTER_ENTRY SignedNetworkFilterEntry = NULL;
static PPH_TN_FILTER_ENTRY DriverFilterEntry = NULL;
BOOLEAN PhMainWndInitialization(
_In_ INT ShowCommand
)
{
PH_RECTANGLE windowRectangle;
if (PhGetIntegerSetting(L"FirstRun"))
{
PPH_STRING autoDbghelpPath;
// Try to set up the dbghelp path automatically if this is the first run.
autoDbghelpPath = PhMwpFindDbghelpPath();
if (autoDbghelpPath)
{
PhSetStringSetting2(L"DbgHelpPath", &autoDbghelpPath->sr);
PhDereferenceObject(autoDbghelpPath);
}
PhSetIntegerSetting(L"FirstRun", FALSE);
}
// This was added to be able to delay-load dbghelp.dll and symsrv.dll.
PhRegisterCallback(&PhSymInitCallback, PhMwpSymInitHandler, NULL, &SymInitRegistration);
PhMwpInitializeProviders();
if (!PhMwpInitializeWindowClass())
return FALSE;
windowRectangle.Position = PhGetIntegerPairSetting(L"MainWindowPosition");
windowRectangle.Size = PhGetIntegerPairSetting(L"MainWindowSize");
PhMainWndHandle = CreateWindow(
PH_MAINWND_CLASSNAME,
PhApplicationName,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
windowRectangle.Left,
windowRectangle.Top,
windowRectangle.Width,
windowRectangle.Height,
NULL,
NULL,
PhInstanceHandle,
NULL
);
PhMainWndMenuHandle = GetMenu(PhMainWndHandle);
if (!PhMainWndHandle)
return FALSE;
PhMwpInitializeMainMenu(PhMainWndMenuHandle);
// Choose a more appropriate rectangle for the window.
PhAdjustRectangleToWorkingArea(
PhMainWndHandle,
&windowRectangle
);
MoveWindow(PhMainWndHandle, windowRectangle.Left, windowRectangle.Top,
windowRectangle.Width, windowRectangle.Height, FALSE);
// Allow WM_PH_ACTIVATE to pass through UIPI.
if (WINDOWS_HAS_UAC)
ChangeWindowMessageFilter_I(WM_PH_ACTIVATE, MSGFLT_ADD);
// Create the window title.
{
PH_STRING_BUILDER stringBuilder;
PhInitializeStringBuilder(&stringBuilder, 100);
PhAppendStringBuilder2(&stringBuilder, L"Process Hacker");
if (PhCurrentUserName)
{
PhAppendStringBuilder2(&stringBuilder, L" [");
PhAppendStringBuilder(&stringBuilder, PhCurrentUserName);
PhAppendCharStringBuilder(&stringBuilder, ']');
if (KphIsConnected()) PhAppendCharStringBuilder(&stringBuilder, '+');
}
if (WINDOWS_HAS_UAC && PhElevationType == TokenElevationTypeFull)
PhAppendStringBuilder2(&stringBuilder, L" (Administrator)");
SetWindowText(PhMainWndHandle, stringBuilder.String->Buffer);
PhDeleteStringBuilder(&stringBuilder);
}
PhMwpOnSettingChange();
// Initialize child controls.
PhMwpInitializeControls();
PhMwpLoadSettings();
PhLogInitialization();
PhQueueItemGlobalWorkQueue(PhMwpDelayedLoadFunction, NULL);
PhMwpSelectionChangedTabControl(-1);
// Perform a layout.
PhMwpOnSize();
PhStartProviderThread(&PhPrimaryProviderThread);
PhStartProviderThread(&PhSecondaryProviderThread);
UpdateWindow(PhMainWndHandle);
if ((PhStartupParameters.ShowHidden || PhGetIntegerSetting(L"StartHidden")) && PhNfTestIconMask(PH_ICON_ALL))
ShowCommand = SW_HIDE;
if (PhStartupParameters.ShowVisible)
ShowCommand = SW_SHOW;
if (PhGetIntegerSetting(L"MainWindowState") == SW_MAXIMIZE)
{
if (ShowCommand != SW_HIDE)
{
ShowCommand = SW_MAXIMIZE;
}
else
{
// We can't maximize it while having it hidden. Set it as pending.
NeedsMaximize = TRUE;
}
}
NeedsSelectPid = PhStartupParameters.SelectPid;
if (PhPluginsEnabled)
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMainWindowShowing), (PVOID)ShowCommand);
if (ShowCommand != SW_HIDE)
ShowWindow(PhMainWndHandle, ShowCommand);
return TRUE;
}
LRESULT CALLBACK PhMwpWndProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_DESTROY:
{
PhMwpOnDestroy();
}
break;
case WM_ENDSESSION:
{
PhMwpOnEndSession();
}
break;
case WM_SETTINGCHANGE:
{
PhMwpOnSettingChange();
}
break;
case WM_COMMAND:
{
PhMwpOnCommand(LOWORD(wParam));
}
break;
case WM_SHOWWINDOW:
{
PhMwpOnShowWindow(!!wParam, (ULONG)lParam);
}
break;
case WM_SYSCOMMAND:
{
if (PhMwpOnSysCommand((ULONG)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)))
return 0;
}
break;
case WM_MENUCOMMAND:
{
PhMwpOnMenuCommand((ULONG)wParam, (HMENU)lParam);
}
break;
case WM_INITMENUPOPUP:
{
PhMwpOnInitMenuPopup((HMENU)wParam, LOWORD(lParam), !!HIWORD(lParam));
}
break;
case WM_SIZE:
{
PhMwpOnSize();
}
break;
case WM_SIZING:
{
PhMwpOnSizing((ULONG)wParam, (PRECT)lParam);
}
break;
case WM_SETFOCUS:
{
PhMwpOnSetFocus();
}
break;
case WM_NOTIFY:
{
LRESULT result;
if (PhMwpOnNotify((NMHDR *)lParam, &result))
return result;
}
break;
case WM_WTSSESSION_CHANGE:
{
PhMwpOnWtsSessionChange((ULONG)wParam, (ULONG)lParam);
}
break;
}
if (uMsg >= WM_PH_FIRST && uMsg <= WM_PH_LAST)
{
return PhMwpOnUserMessage(uMsg, wParam, lParam);
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
BOOLEAN PhMwpInitializeWindowClass(
VOID
)
{
WNDCLASSEX wcex;
memset(&wcex, 0, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = PhMwpWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = PhInstanceHandle;
wcex.hIcon = LoadIcon(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
//wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MAINWND);
wcex.lpszClassName = PH_MAINWND_CLASSNAME;
wcex.hIconSm = (HICON)LoadImage(PhInstanceHandle, MAKEINTRESOURCE(IDI_PROCESSHACKER), IMAGE_ICON, 16, 16, 0);
if (!RegisterClassEx(&wcex))
return FALSE;
return TRUE;
}
VOID PhMwpInitializeProviders(
VOID
)
{
ULONG interval;
interval = PhGetIntegerSetting(L"UpdateInterval");
if (interval == 0)
{
interval = 1000;
PH_SET_INTEGER_CACHED_SETTING(UpdateInterval, interval);
}
PhInitializeProviderThread(&PhPrimaryProviderThread, interval);
PhInitializeProviderThread(&PhSecondaryProviderThread, interval);
PhRegisterProvider(&PhPrimaryProviderThread, PhProcessProviderUpdate, NULL, &ProcessProviderRegistration);
PhSetEnabledProvider(&ProcessProviderRegistration, TRUE);
PhRegisterProvider(&PhPrimaryProviderThread, PhServiceProviderUpdate, NULL, &ServiceProviderRegistration);
PhSetEnabledProvider(&ServiceProviderRegistration, TRUE);
PhRegisterProvider(&PhPrimaryProviderThread, PhNetworkProviderUpdate, NULL, &NetworkProviderRegistration);
}
VOID PhMwpInitializeControls(
VOID
)
{
TabControlHandle = CreateWindow(
WC_TABCONTROL,
NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TCS_MULTILINE,
0,
0,
3,
3,
PhMainWndHandle,
NULL,
PhInstanceHandle,
NULL
);
SendMessage(TabControlHandle, WM_SETFONT, (WPARAM)PhApplicationFont, FALSE);
BringWindowToTop(TabControlHandle);
ProcessesTabIndex = PhAddTabControlTab(TabControlHandle, 0, L"Processes");
ServicesTabIndex = PhAddTabControlTab(TabControlHandle, 1, L"Services");
NetworkTabIndex = PhAddTabControlTab(TabControlHandle, 2, L"Network");
MaxTabIndex = NetworkTabIndex;
ProcessTreeListHandle = CreateWindow(
PH_TREENEW_CLASSNAME,
NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_BORDER | TN_STYLE_ICONS | TN_STYLE_DOUBLE_BUFFERED | TN_STYLE_ANIMATE_DIVIDER,
0,
0,
3,
3,
PhMainWndHandle,
(HMENU)ID_MAINWND_PROCESSTL,
PhLibImageBase,
NULL
);
BringWindowToTop(ProcessTreeListHandle);
ServiceTreeListHandle = CreateWindow(
PH_TREENEW_CLASSNAME,
NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_BORDER | TN_STYLE_ICONS | TN_STYLE_DOUBLE_BUFFERED,
0,
0,
3,
3,
PhMainWndHandle,
(HMENU)ID_MAINWND_SERVICETL,
PhLibImageBase,
NULL
);
BringWindowToTop(ServiceTreeListHandle);
NetworkTreeListHandle = CreateWindow(
PH_TREENEW_CLASSNAME,
NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_BORDER | TN_STYLE_ICONS | TN_STYLE_DOUBLE_BUFFERED,
0,
0,
3,
3,
PhMainWndHandle,
(HMENU)ID_MAINWND_NETWORKTL,
PhLibImageBase,
NULL
);
BringWindowToTop(NetworkTreeListHandle);
PhProcessTreeListInitialization();
PhInitializeProcessTreeList(ProcessTreeListHandle);
PhServiceTreeListInitialization();
PhInitializeServiceTreeList(ServiceTreeListHandle);
PhNetworkTreeListInitialization();
PhInitializeNetworkTreeList(NetworkTreeListHandle);
PhRegisterCallback(
&PhProcessAddedEvent,
PhMwpProcessAddedHandler,
NULL,
&ProcessAddedRegistration
);
PhRegisterCallback(
&PhProcessModifiedEvent,
PhMwpProcessModifiedHandler,
NULL,
&ProcessModifiedRegistration
);
PhRegisterCallback(
&PhProcessRemovedEvent,
PhMwpProcessRemovedHandler,
NULL,
&ProcessRemovedRegistration
);
PhRegisterCallback(
&PhProcessesUpdatedEvent,
PhMwpProcessesUpdatedHandler,
NULL,
&ProcessesUpdatedRegistration
);
PhRegisterCallback(
&PhServiceAddedEvent,
PhMwpServiceAddedHandler,
NULL,
&ServiceAddedRegistration
);
PhRegisterCallback(
&PhServiceModifiedEvent,
PhMwpServiceModifiedHandler,
NULL,
&ServiceModifiedRegistration
);
PhRegisterCallback(
&PhServiceRemovedEvent,
PhMwpServiceRemovedHandler,
NULL,
&ServiceRemovedRegistration
);
PhRegisterCallback(
&PhServicesUpdatedEvent,
PhMwpServicesUpdatedHandler,
NULL,
&ServicesUpdatedRegistration
);
PhRegisterCallback(
&PhNetworkItemAddedEvent,
PhMwpNetworkItemAddedHandler,
NULL,
&NetworkItemAddedRegistration
);
PhRegisterCallback(
&PhNetworkItemModifiedEvent,
PhMwpNetworkItemModifiedHandler,
NULL,
&NetworkItemModifiedRegistration
);
PhRegisterCallback(
&PhNetworkItemRemovedEvent,
PhMwpNetworkItemRemovedHandler,
NULL,
&NetworkItemRemovedRegistration
);
PhRegisterCallback(
&PhNetworkItemsUpdatedEvent,
PhMwpNetworkItemsUpdatedHandler,
NULL,
&NetworkItemsUpdatedRegistration
);
}
NTSTATUS PhMwpDelayedLoadFunction(
_In_ PVOID Parameter
)
{
// Register for window station notifications.
WinStationRegisterConsoleNotification(NULL, PhMainWndHandle, WNOTIFY_ALL_SESSIONS);
PhNfLoadStage2();
// Make sure we get closed late in the shutdown process.
SetProcessShutdownParameters(0x100, 0);
DelayedLoadCompleted = TRUE;
//PostMessage(PhMainWndHandle, WM_PH_DELAYED_LOAD_COMPLETED, 0, 0);
return STATUS_SUCCESS;
}
PPH_STRING PhMwpFindDbghelpPath(
VOID
)
{
static struct
{
ULONG Folder;
PWSTR AppendPath;
} locations[] =
{
#ifdef _M_IX86
{ CSIDL_PROGRAM_FILES, L"\\Windows Kits\\8.1\\Debuggers\\x86\\dbghelp.dll" },
{ CSIDL_PROGRAM_FILES, L"\\Windows Kits\\8.0\\Debuggers\\x86\\dbghelp.dll" },
{ CSIDL_PROGRAM_FILES, L"\\Debugging Tools for Windows (x86)\\dbghelp.dll" }
#else
{ CSIDL_PROGRAM_FILESX86, L"\\Windows Kits\\8.1\\Debuggers\\x64\\dbghelp.dll" },
{ CSIDL_PROGRAM_FILESX86, L"\\Windows Kits\\8.0\\Debuggers\\x64\\dbghelp.dll" },
{ CSIDL_PROGRAM_FILES, L"\\Debugging Tools for Windows (x64)\\dbghelp.dll" }
#endif
};
PPH_STRING path;
ULONG i;
for (i = 0; i < sizeof(locations) / sizeof(locations[0]); i++)
{
path = PhGetKnownLocation(locations[i].Folder, locations[i].AppendPath);
if (path)
{
if (RtlDoesFileExists_U(path->Buffer))
return path;
PhDereferenceObject(path);
}
}
return NULL;
}
VOID PhMwpOnDestroy(
VOID
)
{
// Notify plugins that we are shutting down.
if (PhPluginsEnabled)
PhUnloadPlugins();
if (!PhMainWndExiting)
ProcessHacker_SaveAllSettings(PhMainWndHandle);
PhNfUninitialization();
PostQuitMessage(0);
}
VOID PhMwpOnEndSession(
VOID
)
{
PhMwpOnDestroy();
}
VOID PhMwpOnSettingChange(
VOID
)
{
PhSysWindowColor = GetSysColor(COLOR_WINDOW);
if (PhApplicationFont)
DeleteObject(PhApplicationFont);
PhInitializeFont(PhMainWndHandle);
SendMessage(TabControlHandle, WM_SETFONT, (WPARAM)PhApplicationFont, FALSE);
}
VOID PhMwpOnCommand(
_In_ ULONG Id
)
{
switch (Id)
{
case ID_ESC_EXIT:
{
if (PhGetIntegerSetting(L"HideOnClose"))
{
if (PhNfTestIconMask(PH_ICON_ALL))
ShowWindow(PhMainWndHandle, SW_HIDE);
}
else if (PhGetIntegerSetting(L"CloseOnEscape"))
{
ProcessHacker_Destroy(PhMainWndHandle);
}
}
break;
case ID_HACKER_RUN:
{
if (RunFileDlg)
{
SelectedRunAsMode = 0;
RunFileDlg(PhMainWndHandle, NULL, NULL, NULL, NULL, 0);
}
}
break;
case ID_HACKER_RUNASADMINISTRATOR:
{
if (RunFileDlg)
{
SelectedRunAsMode = RUNAS_MODE_ADMIN;
RunFileDlg(
PhMainWndHandle,
NULL,
NULL,
NULL,
L"Type the name of a program that will be opened under alternate credentials.",
0
);
}
}
break;
case ID_HACKER_RUNASLIMITEDUSER:
{
if (RunFileDlg)
{
SelectedRunAsMode = RUNAS_MODE_LIMITED;
RunFileDlg(
PhMainWndHandle,
NULL,
NULL,
NULL,
L"Type the name of a program that will be opened under standard user privileges.",
0
);
}
}
break;
case ID_HACKER_RUNAS:
{
PhShowRunAsDialog(PhMainWndHandle, NULL);
}
break;
case ID_HACKER_SHOWDETAILSFORALLPROCESSES:
{
ProcessHacker_PrepareForEarlyShutdown(PhMainWndHandle);
if (PhShellProcessHacker(
PhMainWndHandle,
L"-v",
SW_SHOW,
PH_SHELL_EXECUTE_ADMIN,
PH_SHELL_APP_PROPAGATE_PARAMETERS | PH_SHELL_APP_PROPAGATE_PARAMETERS_IGNORE_VISIBILITY,
0,
NULL
))
{
ProcessHacker_Destroy(PhMainWndHandle);
}
else
{
ProcessHacker_CancelEarlyShutdown(PhMainWndHandle);
}
}
break;
case ID_HACKER_SAVE:
{
static PH_FILETYPE_FILTER filters[] =
{
{ L"Text files (*.txt;*.log)", L"*.txt;*.log" },
{ L"Comma-separated values (*.csv)", L"*.csv" },
{ L"All files (*.*)", L"*.*" }
};
PVOID fileDialog = PhCreateSaveFileDialog();
PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));
PhSetFileDialogFileName(fileDialog, L"Process Hacker.txt");
if (PhShowFileDialog(PhMainWndHandle, fileDialog))
{
NTSTATUS status;
PPH_STRING fileName;
ULONG filterIndex;
PPH_FILE_STREAM fileStream;
fileName = PhGetFileDialogFileName(fileDialog);
PhaDereferenceObject(fileName);
filterIndex = PhGetFileDialogFilterIndex(fileDialog);
if (NT_SUCCESS(status = PhCreateFileStream(
&fileStream,
fileName->Buffer,
FILE_GENERIC_WRITE,
FILE_SHARE_READ,
FILE_OVERWRITE_IF,
0
)))
{
ULONG mode;
ULONG selectedTab;
if (filterIndex == 2)
mode = PH_EXPORT_MODE_CSV;
else
mode = PH_EXPORT_MODE_TABS;
PhWritePhTextHeader(fileStream);
selectedTab = TabCtrl_GetCurSel(TabControlHandle);
if (selectedTab == ProcessesTabIndex)
{
PhWriteProcessTree(fileStream, mode);
}
else if (selectedTab == ServicesTabIndex)
{
PhWriteServiceList(fileStream, mode);
}
else if (selectedTab == NetworkTabIndex)
{
PhWriteNetworkList(fileStream, mode);
}
else if (AdditionalTabPageList)
{
ULONG i;
for (i = 0; i < AdditionalTabPageList->Count; i++)
{
PPH_ADDITIONAL_TAB_PAGE tabPage = AdditionalTabPageList->Items[i];
if (tabPage->Index == selectedTab)
{
if (tabPage->SaveContentCallback)
{
tabPage->SaveContentCallback(fileStream, UlongToPtr(mode), NULL, tabPage->Context);
}
break;
}
}
}
PhDereferenceObject(fileStream);
}
if (!NT_SUCCESS(status))
PhShowStatus(PhMainWndHandle, L"Unable to create the file", status, 0);
}
PhFreeFileDialog(fileDialog);
}
break;
case ID_HACKER_FINDHANDLESORDLLS:
{
PhShowFindObjectsDialog();
}
break;
case ID_HACKER_OPTIONS:
{
PhShowOptionsDialog(PhMainWndHandle);
}
break;
case ID_HACKER_PLUGINS:
{
PhShowPluginsDialog(PhMainWndHandle);
}
break;
case ID_COMPUTER_LOCK:
case ID_COMPUTER_LOGOFF:
case ID_COMPUTER_SLEEP:
case ID_COMPUTER_HIBERNATE:
case ID_COMPUTER_RESTART:
case ID_COMPUTER_RESTARTBOOTOPTIONS:
case ID_COMPUTER_SHUTDOWN:
case ID_COMPUTER_SHUTDOWNHYBRID:
PhMwpExecuteComputerCommand(Id);
break;
case ID_HACKER_EXIT:
ProcessHacker_Destroy(PhMainWndHandle);
break;
case ID_VIEW_SYSTEMINFORMATION:
PhShowSystemInformationDialog(NULL);
break;
case ID_TRAYICONS_CPUHISTORY:
case ID_TRAYICONS_CPUUSAGE:
case ID_TRAYICONS_IOHISTORY:
case ID_TRAYICONS_COMMITHISTORY:
case ID_TRAYICONS_PHYSICALMEMORYHISTORY:
{
ULONG i;
switch (Id)
{
case ID_TRAYICONS_CPUHISTORY:
i = PH_ICON_CPU_HISTORY;
break;
case ID_TRAYICONS_CPUUSAGE:
i = PH_ICON_CPU_USAGE;
break;
case ID_TRAYICONS_IOHISTORY:
i = PH_ICON_IO_HISTORY;
break;
case ID_TRAYICONS_COMMITHISTORY:
i = PH_ICON_COMMIT_HISTORY;
break;
case ID_TRAYICONS_PHYSICALMEMORYHISTORY:
i = PH_ICON_PHYSICAL_HISTORY;
break;
}
PhNfSetVisibleIcon(i, !PhNfTestIconMask(i));
}
break;
case ID_VIEW_HIDEPROCESSESFROMOTHERUSERS:
{
if (!CurrentUserFilterEntry)
{
CurrentUserFilterEntry = PhAddTreeNewFilter(PhGetFilterSupportProcessTreeList(), PhMwpCurrentUserProcessTreeFilter, NULL);
}
else
{
PhRemoveTreeNewFilter(PhGetFilterSupportProcessTreeList(), CurrentUserFilterEntry);
CurrentUserFilterEntry = NULL;
}
PhApplyTreeNewFilters(PhGetFilterSupportProcessTreeList());
PhSetIntegerSetting(L"HideOtherUserProcesses", !!CurrentUserFilterEntry);
}
break;
case ID_VIEW_HIDESIGNEDPROCESSES:
{
if (!SignedFilterEntry)
{
if (!PhEnableProcessQueryStage2)
{
PhShowInformation(
PhMainWndHandle,
L"This filter cannot function because digital signature checking is not enabled. "
L"Enable it in Options > Advanced and restart Process Hacker."
);
}
SignedFilterEntry = PhAddTreeNewFilter(PhGetFilterSupportProcessTreeList(), PhMwpSignedProcessTreeFilter, NULL);
}
else
{
PhRemoveTreeNewFilter(PhGetFilterSupportProcessTreeList(), SignedFilterEntry);
SignedFilterEntry = NULL;
}
PhApplyTreeNewFilters(PhGetFilterSupportProcessTreeList());
PhSetIntegerSetting(L"HideSignedProcesses", !!SignedFilterEntry);
}
break;
case ID_VIEW_SCROLLTONEWPROCESSES:
{
PH_SET_INTEGER_CACHED_SETTING(ScrollToNewProcesses, !PhCsScrollToNewProcesses);
}
break;
case ID_VIEW_SHOWCPUBELOW001:
{
PH_SET_INTEGER_CACHED_SETTING(ShowCpuBelow001, !PhCsShowCpuBelow001);
PhInvalidateAllProcessNodes();
}
break;
case ID_VIEW_HIDEDRIVERSERVICES:
{
if (!DriverFilterEntry)
{
DriverFilterEntry = PhAddTreeNewFilter(PhGetFilterSupportServiceTreeList(), PhMwpDriverServiceTreeFilter, NULL);
}
else
{
PhRemoveTreeNewFilter(PhGetFilterSupportServiceTreeList(), DriverFilterEntry);
DriverFilterEntry = NULL;
}
PhApplyTreeNewFilters(PhGetFilterSupportServiceTreeList());
PhSetIntegerSetting(L"HideDriverServices", !!DriverFilterEntry);
}
break;
case ID_VIEW_ALWAYSONTOP:
{
AlwaysOnTop = !AlwaysOnTop;
SetWindowPos(PhMainWndHandle, AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
PhSetIntegerSetting(L"MainWindowAlwaysOnTop", AlwaysOnTop);
}
break;
case ID_OPACITY_10:
case ID_OPACITY_20:
case ID_OPACITY_30:
case ID_OPACITY_40:
case ID_OPACITY_50:
case ID_OPACITY_60:
case ID_OPACITY_70:
case ID_OPACITY_80:
case ID_OPACITY_90:
case ID_OPACITY_OPAQUE:
{
ULONG opacity;
opacity = 100 - ((Id - ID_OPACITY_10) + 1) * 10;
PhSetIntegerSetting(L"MainWindowOpacity", opacity);
PhMwpSetWindowOpacity(opacity);
}
break;
case ID_VIEW_REFRESH:
{
PhBoostProvider(&ProcessProviderRegistration, NULL);
PhBoostProvider(&ServiceProviderRegistration, NULL);
}
break;
case ID_UPDATEINTERVAL_FAST:
case ID_UPDATEINTERVAL_NORMAL:
case ID_UPDATEINTERVAL_BELOWNORMAL:
case ID_UPDATEINTERVAL_SLOW:
case ID_UPDATEINTERVAL_VERYSLOW:
{
ULONG interval;
switch (Id)
{
case ID_UPDATEINTERVAL_FAST:
interval = 500;
break;
case ID_UPDATEINTERVAL_NORMAL:
interval = 1000;
break;
case ID_UPDATEINTERVAL_BELOWNORMAL:
interval = 2000;
break;
case ID_UPDATEINTERVAL_SLOW:
interval = 5000;
break;
case ID_UPDATEINTERVAL_VERYSLOW:
interval = 10000;
break;
}
PH_SET_INTEGER_CACHED_SETTING(UpdateInterval, interval);
PhApplyUpdateInterval(interval);
}
break;
case ID_VIEW_UPDATEAUTOMATICALLY:
{
UpdateAutomatically = !UpdateAutomatically;
PhSetEnabledProvider(&ProcessProviderRegistration, UpdateAutomatically);
PhSetEnabledProvider(&ServiceProviderRegistration, UpdateAutomatically);
if (TabCtrl_GetCurSel(TabControlHandle) == NetworkTabIndex)
PhSetEnabledProvider(&NetworkProviderRegistration, UpdateAutomatically);
}
break;
case ID_TOOLS_CREATESERVICE:
{
PhShowCreateServiceDialog(PhMainWndHandle);
}
break;
case ID_TOOLS_HIDDENPROCESSES:
{
PhShowHiddenProcessesDialog();
}
break;
case ID_TOOLS_PAGEFILES:
{
PhShowPagefilesDialog(PhMainWndHandle);
}
break;
case ID_TOOLS_STARTTASKMANAGER:
{
PPH_STRING systemDirectory;
PPH_STRING taskmgrFileName;
systemDirectory = PhGetSystemDirectory();
taskmgrFileName = PhConcatStrings2(systemDirectory->Buffer, L"\\taskmgr.exe");
PhDereferenceObject(systemDirectory);
PhCreateProcessIgnoreIfeoDebugger(taskmgrFileName->Buffer);
PhDereferenceObject(taskmgrFileName);
}
break;
case ID_TOOLS_VERIFYFILESIGNATURE:
{
static PH_FILETYPE_FILTER filters[] =
{
{ L"Executable files (*.exe;*.dll;*.ocx;*.sys;*.scr;*.cpl)", L"*.exe;*.dll;*.ocx;*.sys;*.scr;*.cpl" },
{ L"All files (*.*)", L"*.*" }
};
PVOID fileDialog = PhCreateOpenFileDialog();
PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));
if (PhShowFileDialog(PhMainWndHandle, fileDialog))
{
PPH_STRING fileName;
VERIFY_RESULT result;
PPH_STRING signerName;
fileName = PhGetFileDialogFileName(fileDialog);
result = PhVerifyFile(fileName->Buffer, &signerName);
if (result == VrTrusted)
{
PhShowInformation(PhMainWndHandle, L"\"%s\" is trusted and signed by \"%s\".",
fileName->Buffer, signerName->Buffer);
}
else if (result == VrNoSignature)
{
PhShowInformation(PhMainWndHandle, L"\"%s\" does not have a digital signature.",
fileName->Buffer);
}
else
{
PhShowInformation(PhMainWndHandle, L"\"%s\" is not trusted.",
fileName->Buffer);
}
if (signerName)
PhDereferenceObject(signerName);
PhDereferenceObject(fileName);
}
PhFreeFileDialog(fileDialog);
}
break;
case ID_USER_CONNECT:
{
PhUiConnectSession(PhMainWndHandle, SelectedUserSessionId);
}
break;
case ID_USER_DISCONNECT:
{
PhUiDisconnectSession(PhMainWndHandle, SelectedUserSessionId);
}
break;
case ID_USER_LOGOFF:
{
PhUiLogoffSession(PhMainWndHandle, SelectedUserSessionId);
}
break;
case ID_USER_REMOTECONTROL:
{
PhShowSessionShadowDialog(PhMainWndHandle, SelectedUserSessionId);
}
break;
case ID_USER_SENDMESSAGE:
{
PhShowSessionSendMessageDialog(PhMainWndHandle, SelectedUserSessionId);
}
break;
case ID_USER_PROPERTIES:
{
PhShowSessionProperties(PhMainWndHandle, SelectedUserSessionId);
}
break;
case ID_HELP_LOG:
{
PhShowLogDialog();
}
break;
case ID_HELP_DONATE:
{
PhShellExecute(PhMainWndHandle, L"https://sourceforge.net/project/project_donations.php?group_id=242527", NULL);
}
break;
case ID_HELP_DEBUGCONSOLE:
{
PhShowDebugConsole();
}
break;
case ID_HELP_ABOUT:
{
PhShowAboutDialog(PhMainWndHandle);
}
break;
case ID_PROCESS_TERMINATE:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhGetSelectedProcessItems(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
if (PhUiTerminateProcesses(PhMainWndHandle, processes, numberOfProcesses))
PhDeselectAllProcessNodes();
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_PROCESS_TERMINATETREE:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
if (PhUiTerminateTreeProcess(PhMainWndHandle, processItem))
PhDeselectAllProcessNodes();
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_SUSPEND:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhGetSelectedProcessItems(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
PhUiSuspendProcesses(PhMainWndHandle, processes, numberOfProcesses);
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_PROCESS_RESUME:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhGetSelectedProcessItems(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
PhUiResumeProcesses(PhMainWndHandle, processes, numberOfProcesses);
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_PROCESS_RESTART:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
if (PhUiRestartProcess(PhMainWndHandle, processItem))
PhDeselectAllProcessNodes();
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_CREATEDUMPFILE:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhUiCreateDumpFileProcess(PhMainWndHandle, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_DEBUG:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhUiDebugProcess(PhMainWndHandle, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_VIRTUALIZATION:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhUiSetVirtualizationProcess(
PhMainWndHandle,
processItem,
!SelectedProcessVirtualizationEnabled
);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_AFFINITY:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhShowProcessAffinityDialog(PhMainWndHandle, processItem, NULL);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_DETACHFROMDEBUGGER:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhUiDetachFromDebuggerProcess(PhMainWndHandle, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_GDIHANDLES:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhShowGdiHandlesDialog(PhMainWndHandle, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_HEAPS:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhShowProcessHeapsDialog(PhMainWndHandle, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_INJECTDLL:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhUiInjectDllProcess(PhMainWndHandle, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_I_0:
case ID_I_1:
case ID_I_2:
case ID_I_3:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
ULONG ioPriority;
switch (Id)
{
case ID_I_0:
ioPriority = 0;
break;
case ID_I_1:
ioPriority = 1;
break;
case ID_I_2:
ioPriority = 2;
break;
case ID_I_3:
ioPriority = 3;
break;
}
PhReferenceObject(processItem);
PhUiSetIoPriorityProcess(PhMainWndHandle, processItem, ioPriority);
PhDereferenceObject(processItem);
}
}
break;
case ID_PAGEPRIORITY_1:
case ID_PAGEPRIORITY_2:
case ID_PAGEPRIORITY_3:
case ID_PAGEPRIORITY_4:
case ID_PAGEPRIORITY_5:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
ULONG pagePriority;
switch (Id)
{
case ID_PAGEPRIORITY_1:
pagePriority = 1;
break;
case ID_PAGEPRIORITY_2:
pagePriority = 2;
break;
case ID_PAGEPRIORITY_3:
pagePriority = 3;
break;
case ID_PAGEPRIORITY_4:
pagePriority = 4;
break;
case ID_PAGEPRIORITY_5:
pagePriority = 5;
break;
}
PhReferenceObject(processItem);
PhUiSetPagePriorityProcess(PhMainWndHandle, processItem, pagePriority);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_REDUCEWORKINGSET:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhGetSelectedProcessItems(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
PhUiReduceWorkingSetProcesses(PhMainWndHandle, processes, numberOfProcesses);
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_MISCELLANEOUS_RUNAS:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem && processItem->FileName)
{
PhSetStringSetting2(L"RunAsProgram", &processItem->FileName->sr);
PhShowRunAsDialog(PhMainWndHandle, NULL);
}
}
break;
case ID_MISCELLANEOUS_RUNASTHISUSER:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhShowRunAsDialog(PhMainWndHandle, processItem->ProcessId);
}
}
break;
case ID_MISCELLANEOUS_TERMINATOR:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
// The object relies on the list view reference, which could
// disappear if we don't reference the object here.
PhReferenceObject(processItem);
PhShowProcessTerminatorDialog(PhMainWndHandle, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_PRIORITY_REALTIME:
case ID_PRIORITY_HIGH:
case ID_PRIORITY_ABOVENORMAL:
case ID_PRIORITY_NORMAL:
case ID_PRIORITY_BELOWNORMAL:
case ID_PRIORITY_IDLE:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhReferenceObject(processItem);
PhMwpExecuteProcessPriorityCommand(Id, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_WINDOW_BRINGTOFRONT:
{
if (IsWindow(SelectedProcessWindowHandle))
{
WINDOWPLACEMENT placement = { sizeof(placement) };
GetWindowPlacement(SelectedProcessWindowHandle, &placement);
if (placement.showCmd == SW_MINIMIZE)
ShowWindowAsync(SelectedProcessWindowHandle, SW_RESTORE);
else
SetForegroundWindow(SelectedProcessWindowHandle);
}
}
break;
case ID_WINDOW_RESTORE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
ShowWindowAsync(SelectedProcessWindowHandle, SW_RESTORE);
}
}
break;
case ID_WINDOW_MINIMIZE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
ShowWindowAsync(SelectedProcessWindowHandle, SW_MINIMIZE);
}
}
break;
case ID_WINDOW_MAXIMIZE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
ShowWindowAsync(SelectedProcessWindowHandle, SW_MAXIMIZE);
}
}
break;
case ID_WINDOW_CLOSE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
PostMessage(SelectedProcessWindowHandle, WM_CLOSE, 0, 0);
}
}
break;
case ID_PROCESS_PROPERTIES:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
// No reference needed; no messages pumped.
PhMwpShowProcessProperties(processItem);
}
}
break;
case ID_PROCESS_OPENFILELOCATION:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem && processItem->FileName)
{
PhReferenceObject(processItem);
PhShellExploreFile(PhMainWndHandle, processItem->FileName->Buffer);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_SEARCHONLINE:
{
PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem();
if (processItem)
{
PhSearchOnlineString(PhMainWndHandle, processItem->ProcessName->Buffer);
}
}
break;
case ID_PROCESS_COPY:
{
PhCopyProcessTree();
}
break;
case ID_SERVICE_GOTOPROCESS:
{
PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
PPH_PROCESS_NODE processNode;
if (serviceItem)
{
if (processNode = PhFindProcessNode(serviceItem->ProcessId))
{
PhMwpSelectTabPage(ProcessesTabIndex);
SetFocus(ProcessTreeListHandle);
PhSelectAndEnsureVisibleProcessNode(processNode);
}
}
}
break;
case ID_SERVICE_START:
{
PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiStartService(PhMainWndHandle, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_CONTINUE:
{
PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiContinueService(PhMainWndHandle, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_PAUSE:
{
PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiPauseService(PhMainWndHandle, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_STOP:
{
PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiStopService(PhMainWndHandle, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_DELETE:
{
PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
PhReferenceObject(serviceItem);
if (PhUiDeleteService(PhMainWndHandle, serviceItem))
PhDeselectAllServiceNodes();
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_PROPERTIES:
{
PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
// The object relies on the list view reference, which could
// disappear if we don't reference the object here.
PhReferenceObject(serviceItem);
PhShowServiceProperties(PhMainWndHandle, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_COPY:
{
PhCopyServiceList();
}
break;
case ID_NETWORK_GOTOPROCESS:
{
PPH_NETWORK_ITEM networkItem = PhGetSelectedNetworkItem();
PPH_PROCESS_NODE processNode;
if (networkItem)
{
if (processNode = PhFindProcessNode(networkItem->ProcessId))
{
PhMwpSelectTabPage(ProcessesTabIndex);
SetFocus(ProcessTreeListHandle);
PhSelectAndEnsureVisibleProcessNode(processNode);
}
}
}
break;
case ID_NETWORK_VIEWSTACK:
{
PPH_NETWORK_ITEM networkItem = PhGetSelectedNetworkItem();
if (networkItem)
{
PhReferenceObject(networkItem);
PhShowNetworkStackDialog(PhMainWndHandle, networkItem);
PhDereferenceObject(networkItem);
}
}
break;
case ID_NETWORK_CLOSE:
{
PPH_NETWORK_ITEM *networkItems;
ULONG numberOfNetworkItems;
PhGetSelectedNetworkItems(&networkItems, &numberOfNetworkItems);
PhReferenceObjects(networkItems, numberOfNetworkItems);
if (PhUiCloseConnections(PhMainWndHandle, networkItems, numberOfNetworkItems))
PhDeselectAllNetworkNodes();
PhDereferenceObjects(networkItems, numberOfNetworkItems);
PhFree(networkItems);
}
break;
case ID_NETWORK_COPY:
{
PhCopyNetworkList();
}
break;
case ID_TAB_NEXT:
{
ULONG selectedIndex = TabCtrl_GetCurSel(TabControlHandle);
if (selectedIndex != MaxTabIndex)
selectedIndex++;
else
selectedIndex = 0;
PhMwpSelectTabPage(selectedIndex);
}
break;
case ID_TAB_PREV:
{
ULONG selectedIndex = TabCtrl_GetCurSel(TabControlHandle);
if (selectedIndex != 0)
selectedIndex--;
else
selectedIndex = MaxTabIndex;
PhMwpSelectTabPage(selectedIndex);
}
break;
}
}
VOID PhMwpOnShowWindow(
_In_ BOOLEAN Showing,
_In_ ULONG State
)
{
if (NeedsMaximize)
{
ShowWindow(PhMainWndHandle, SW_MAXIMIZE);
NeedsMaximize = FALSE;
}
}
BOOLEAN PhMwpOnSysCommand(
_In_ ULONG Type,
_In_ LONG CursorScreenX,
_In_ LONG CursorScreenY
)
{
switch (Type)
{
case SC_CLOSE:
{
if (PhGetIntegerSetting(L"HideOnClose") && PhNfTestIconMask(PH_ICON_ALL))
{
ShowWindow(PhMainWndHandle, SW_HIDE);
return TRUE;
}
}
break;
case SC_MINIMIZE:
{
// Save the current window state because we
// may not have a chance to later.
PhMwpSaveWindowSettings();
if (PhGetIntegerSetting(L"HideOnMinimize") && PhNfTestIconMask(PH_ICON_ALL))
{
ShowWindow(PhMainWndHandle, SW_HIDE);
return TRUE;
}
}
break;
}
return FALSE;
}
VOID PhMwpOnMenuCommand(
_In_ ULONG Index,
_In_ HMENU Menu
)
{
MENUITEMINFO menuItemInfo;
menuItemInfo.cbSize = sizeof(MENUITEMINFO);
menuItemInfo.fMask = MIIM_ID | MIIM_DATA;
if (GetMenuItemInfo(Menu, Index, TRUE, &menuItemInfo))
{
PhMwpDispatchMenuCommand(Menu, Index, menuItemInfo.wID, menuItemInfo.dwItemData);
}
}
VOID PhMwpOnInitMenuPopup(
_In_ HMENU Menu,
_In_ ULONG Index,
_In_ BOOLEAN IsWindowMenu
)
{
ULONG i;
BOOLEAN found;
PPH_EMENU menu;
found = FALSE;
for (i = 0; i < sizeof(SubMenuHandles) / sizeof(HWND); i++)
{
if (Menu == SubMenuHandles[i])
{
found = TRUE;
break;
}
}
if (!found)
return;
if (Index == 3)
{
// Special case for Users menu.
if (!UsersMenuInitialized)
{
PhMwpUpdateUsersMenu();
UsersMenuInitialized = TRUE;
}
return;
}
// Delete all items in this submenu.
while (DeleteMenu(Menu, 0, MF_BYPOSITION)) ;
// Delete the previous EMENU for this submenu.
if (SubMenuObjects[Index])
PhDestroyEMenu(SubMenuObjects[Index]);
menu = PhCreateEMenu();
PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_MAINWND), Index);
PhMwpInitializeSubMenu(menu, Index);
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.OwnerWindow = PhMainWndHandle;
menuInfo.u.MainMenu.SubMenuIndex = Index;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMainMenuInitializing), &menuInfo);
}
PhEMenuToHMenu2(Menu, menu, 0, NULL);
SubMenuObjects[Index] = menu;
}
VOID PhMwpOnSize(
VOID
)
{
if (!IsIconic(PhMainWndHandle))
{
HDWP deferHandle;
deferHandle = BeginDeferWindowPos(2);
PhMwpLayout(&deferHandle);
EndDeferWindowPos(deferHandle);
}
}
VOID PhMwpOnSizing(
_In_ ULONG Edge,
_In_ PRECT DragRectangle
)
{
PhResizingMinimumSize(DragRectangle, Edge, 400, 340);
}
VOID PhMwpOnSetFocus(
VOID
)
{
INT selectedIndex = TabCtrl_GetCurSel(TabControlHandle);
if (selectedIndex == ProcessesTabIndex)
SetFocus(ProcessTreeListHandle);
else if (selectedIndex == ServicesTabIndex)
SetFocus(ServiceTreeListHandle);
else if (selectedIndex == NetworkTabIndex)
SetFocus(NetworkTreeListHandle);
}
BOOLEAN PhMwpOnNotify(
_In_ NMHDR *Header,
_Out_ LRESULT *Result
)
{
if (Header->hwndFrom == TabControlHandle)
{
PhMwpNotifyTabControl(Header);
}
else if (Header->code == RFN_VALIDATE)
{
LPNMRUNFILEDLG runFileDlg = (LPNMRUNFILEDLG)Header;
if (SelectedRunAsMode == RUNAS_MODE_ADMIN)
{
PH_STRINGREF string;
PH_STRINGREF fileName;
PH_STRINGREF arguments;
PPH_STRING fullFileName;
PPH_STRING argumentsString;
PhInitializeStringRef(&string, (PWSTR)runFileDlg->lpszFile);
PhParseCommandLineFuzzy(&string, &fileName, &arguments, &fullFileName);
if (!fullFileName)
fullFileName = PhCreateStringEx(fileName.Buffer, fileName.Length);
argumentsString = PhCreateStringEx(arguments.Buffer, arguments.Length);
if (PhShellExecuteEx(PhMainWndHandle, fullFileName->Buffer, argumentsString->Buffer,
runFileDlg->nShow, PH_SHELL_EXECUTE_ADMIN, 0, NULL))
{
*Result = RF_CANCEL;
}
else
{
*Result = RF_RETRY;
}
PhDereferenceObject(fullFileName);
PhDereferenceObject(argumentsString);
return TRUE;
}
else if (SelectedRunAsMode == RUNAS_MODE_LIMITED)
{
NTSTATUS status;
HANDLE tokenHandle;
HANDLE newTokenHandle;
if (NT_SUCCESS(status = NtOpenProcessToken(
NtCurrentProcess(),
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT | READ_CONTROL | WRITE_DAC,
&tokenHandle
)))
{
if (NT_SUCCESS(status = PhFilterTokenForLimitedUser(
tokenHandle,
&newTokenHandle
)))
{
status = PhCreateProcessWin32(
NULL,
(PWSTR)runFileDlg->lpszFile,
NULL,
NULL,
0,
newTokenHandle,
NULL,
NULL
);
NtClose(newTokenHandle);
}
NtClose(tokenHandle);
}
if (NT_SUCCESS(status))
{
*Result = RF_CANCEL;
}
else
{
PhShowStatus(PhMainWndHandle, L"Unable to execute the program", status, 0);
*Result = RF_RETRY;
}
return TRUE;
}
}
return FALSE;
}
VOID PhMwpOnWtsSessionChange(
_In_ ULONG Reason,
_In_ ULONG SessionId
)
{
if (Reason == WTS_SESSION_LOGON || Reason == WTS_SESSION_LOGOFF)
{
if (UsersMenuInitialized)
{
PhMwpUpdateUsersMenu();
}
}
}
ULONG_PTR PhMwpOnUserMessage(
_In_ ULONG Message,
_In_ ULONG_PTR WParam,
_In_ ULONG_PTR LParam
)
{
switch (Message)
{
case WM_PH_ACTIVATE:
{
if (!PhMainWndExiting)
{
if (WParam != 0)
{
PPH_PROCESS_NODE processNode;
if (processNode = PhFindProcessNode((HANDLE)WParam))
PhSelectAndEnsureVisibleProcessNode(processNode);
}
if (!IsWindowVisible(PhMainWndHandle))
{
ShowWindow(PhMainWndHandle, SW_SHOW);
}
if (IsIconic(PhMainWndHandle))
{
ShowWindow(PhMainWndHandle, SW_RESTORE);
}
return PH_ACTIVATE_REPLY;
}
else
{
return 0;
}
}
break;
case WM_PH_SHOW_PROCESS_PROPERTIES:
{
PhMwpShowProcessProperties((PPH_PROCESS_ITEM)LParam);
}
break;
case WM_PH_DESTROY:
{
DestroyWindow(PhMainWndHandle);
}
break;
case WM_PH_SAVE_ALL_SETTINGS:
{
PhMwpSaveSettings();
}
break;
case WM_PH_PREPARE_FOR_EARLY_SHUTDOWN:
{
PhMwpSaveSettings();
PhMainWndExiting = TRUE;
}
break;
case WM_PH_CANCEL_EARLY_SHUTDOWN:
{
PhMainWndExiting = FALSE;
}
break;
case WM_PH_DELAYED_LOAD_COMPLETED:
{
// Nothing
}
break;
case WM_PH_NOTIFY_ICON_MESSAGE:
{
PhNfForwardMessage(WParam, LParam);
}
break;
case WM_PH_TOGGLE_VISIBLE:
{
PhMwpActivateWindow(!WParam);
}
break;
case WM_PH_SHOW_MEMORY_EDITOR:
{
PPH_SHOWMEMORYEDITOR showMemoryEditor = (PPH_SHOWMEMORYEDITOR)LParam;
PhShowMemoryEditorDialog(
showMemoryEditor->ProcessId,
showMemoryEditor->BaseAddress,
showMemoryEditor->RegionSize,
showMemoryEditor->SelectOffset,
showMemoryEditor->SelectLength
);
PhFree(showMemoryEditor);
}
break;
case WM_PH_SHOW_MEMORY_RESULTS:
{
PPH_SHOWMEMORYRESULTS showMemoryResults = (PPH_SHOWMEMORYRESULTS)LParam;
PhShowMemoryResultsDialog(
showMemoryResults->ProcessId,
showMemoryResults->Results
);
PhDereferenceMemoryResults(
(PPH_MEMORY_RESULT *)showMemoryResults->Results->Items,
showMemoryResults->Results->Count
);
PhDereferenceObject(showMemoryResults->Results);
PhFree(showMemoryResults);
}
break;
case WM_PH_SELECT_TAB_PAGE:
{
ULONG index = (ULONG)WParam;
PhMwpSelectTabPage(index);
if (index == ProcessesTabIndex)
SetFocus(ProcessTreeListHandle);
else if (index == ServicesTabIndex)
SetFocus(ServiceTreeListHandle);
else if (index == NetworkTabIndex)
SetFocus(NetworkTreeListHandle);
}
break;
case WM_PH_GET_CALLBACK_LAYOUT_PADDING:
{
return (ULONG_PTR)&LayoutPaddingCallback;
}
break;
case WM_PH_INVALIDATE_LAYOUT_PADDING:
{
LayoutPaddingValid = FALSE;
}
break;
case WM_PH_SELECT_PROCESS_NODE:
{
PhSelectAndEnsureVisibleProcessNode((PPH_PROCESS_NODE)LParam);
}
break;
case WM_PH_SELECT_SERVICE_ITEM:
{
PPH_SERVICE_NODE serviceNode;
PhMwpNeedServiceTreeList();
// For compatibility, LParam is a service item, not node.
if (serviceNode = PhFindServiceNode((PPH_SERVICE_ITEM)LParam))
{
PhSelectAndEnsureVisibleServiceNode(serviceNode);
}
}
break;
case WM_PH_SELECT_NETWORK_ITEM:
{
PPH_NETWORK_NODE networkNode;
PhMwpNeedNetworkTreeList();
// For compatibility, LParam is a network item, not node.
if (networkNode = PhFindNetworkNode((PPH_NETWORK_ITEM)LParam))
{
PhSelectAndEnsureVisibleNetworkNode(networkNode);
}
}
break;
case WM_PH_UPDATE_FONT:
{
PPH_STRING fontHexString;
LOGFONT font;
fontHexString = PhGetStringSetting(L"Font");
if (
fontHexString->Length / 2 / 2 == sizeof(LOGFONT) &&
PhHexStringToBuffer(&fontHexString->sr, (PUCHAR)&font)
)
{
HFONT newFont;
newFont = CreateFontIndirect(&font);
if (newFont)
{
if (CurrentCustomFont)
DeleteObject(CurrentCustomFont);
CurrentCustomFont = newFont;
SendMessage(ProcessTreeListHandle, WM_SETFONT, (WPARAM)newFont, TRUE);
SendMessage(ServiceTreeListHandle, WM_SETFONT, (WPARAM)newFont, TRUE);
SendMessage(NetworkTreeListHandle, WM_SETFONT, (WPARAM)newFont, TRUE);
if (AdditionalTabPageList)
{
ULONG i;
for (i = 0; i < AdditionalTabPageList->Count; i++)
{
PPH_ADDITIONAL_TAB_PAGE tabPage = AdditionalTabPageList->Items[i];
if (tabPage->FontChangedCallback)
{
tabPage->FontChangedCallback((PVOID)newFont, NULL, NULL, tabPage->Context);
}
}
}
}
}
PhDereferenceObject(fontHexString);
}
break;
case WM_PH_GET_FONT:
return SendMessage(ProcessTreeListHandle, WM_GETFONT, 0, 0);
case WM_PH_INVOKE:
{
VOID (NTAPI *function)(PVOID);
function = (PVOID)LParam;
function((PVOID)WParam);
}
break;
case WM_PH_ADD_MENU_ITEM:
{
PPH_ADDMENUITEM addMenuItem = (PPH_ADDMENUITEM)LParam;
return PhMwpLegacyAddPluginMenuItem(addMenuItem);
}
break;
case WM_PH_ADD_TAB_PAGE:
{
return (ULONG_PTR)PhMwpAddTabPage((PPH_ADDITIONAL_TAB_PAGE)LParam);
}
break;
case WM_PH_REFRESH:
{
SendMessage(PhMainWndHandle, WM_COMMAND, ID_VIEW_REFRESH, 0);
}
break;
case WM_PH_GET_UPDATE_AUTOMATICALLY:
{
return UpdateAutomatically;
}
break;
case WM_PH_SET_UPDATE_AUTOMATICALLY:
{
if (!!WParam != UpdateAutomatically)
{
SendMessage(PhMainWndHandle, WM_COMMAND, ID_VIEW_UPDATEAUTOMATICALLY, 0);
}
}
break;
case WM_PH_ICON_CLICK:
{
PhMwpActivateWindow(!!PhGetIntegerSetting(L"IconTogglesVisibility"));
}
break;
case WM_PH_PROCESS_ADDED:
{
ULONG runId = (ULONG)WParam;
PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)LParam;
PhMwpOnProcessAdded(processItem, runId);
}
break;
case WM_PH_PROCESS_MODIFIED:
{
PhMwpOnProcessModified((PPH_PROCESS_ITEM)LParam);
}
break;
case WM_PH_PROCESS_REMOVED:
{
PhMwpOnProcessRemoved((PPH_PROCESS_ITEM)LParam);
}
break;
case WM_PH_PROCESSES_UPDATED:
{
PhMwpOnProcessesUpdated();
}
break;
case WM_PH_SERVICE_ADDED:
{
ULONG runId = (ULONG)WParam;
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)LParam;
PhMwpOnServiceAdded(serviceItem, runId);
}
break;
case WM_PH_SERVICE_MODIFIED:
{
PPH_SERVICE_MODIFIED_DATA serviceModifiedData = (PPH_SERVICE_MODIFIED_DATA)LParam;
PhMwpOnServiceModified(serviceModifiedData);
PhFree(serviceModifiedData);
}
break;
case WM_PH_SERVICE_REMOVED:
{
PhMwpOnServiceRemoved((PPH_SERVICE_ITEM)LParam);
}
break;
case WM_PH_SERVICES_UPDATED:
{
PhMwpOnServicesUpdated();
}
break;
case WM_PH_NETWORK_ITEM_ADDED:
{
ULONG runId = (ULONG)WParam;
PPH_NETWORK_ITEM networkItem = (PPH_NETWORK_ITEM)LParam;
PhMwpOnNetworkItemAdded(runId, networkItem);
}
break;
case WM_PH_NETWORK_ITEM_MODIFIED:
{
PhMwpOnNetworkItemModified((PPH_NETWORK_ITEM)LParam);
}
break;
case WM_PH_NETWORK_ITEM_REMOVED:
{
PhMwpOnNetworkItemRemoved((PPH_NETWORK_ITEM)LParam);
}
break;
case WM_PH_NETWORK_ITEMS_UPDATED:
{
PhMwpOnNetworkItemsUpdated();
}
break;
}
return 0;
}
VOID NTAPI PhMwpProcessAddedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)Parameter;
// Reference the process item so it doesn't get deleted before
// we handle the event in the main thread.
PhReferenceObject(processItem);
PostMessage(
PhMainWndHandle,
WM_PH_PROCESS_ADDED,
(WPARAM)PhGetRunIdProvider(&ProcessProviderRegistration),
(LPARAM)processItem
);
}
VOID NTAPI PhMwpProcessModifiedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)Parameter;
PostMessage(PhMainWndHandle, WM_PH_PROCESS_MODIFIED, 0, (LPARAM)processItem);
}
VOID NTAPI PhMwpProcessRemovedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)Parameter;
// We already have a reference to the process item, so we don't need to
// reference it here.
PostMessage(PhMainWndHandle, WM_PH_PROCESS_REMOVED, 0, (LPARAM)processItem);
}
VOID NTAPI PhMwpProcessesUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PostMessage(PhMainWndHandle, WM_PH_PROCESSES_UPDATED, 0, 0);
}
VOID NTAPI PhMwpServiceAddedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)Parameter;
PhReferenceObject(serviceItem);
PostMessage(
PhMainWndHandle,
WM_PH_SERVICE_ADDED,
PhGetRunIdProvider(&ServiceProviderRegistration),
(LPARAM)serviceItem
);
}
VOID NTAPI PhMwpServiceModifiedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_SERVICE_MODIFIED_DATA serviceModifiedData = (PPH_SERVICE_MODIFIED_DATA)Parameter;
PPH_SERVICE_MODIFIED_DATA copy;
copy = PhAllocateCopy(serviceModifiedData, sizeof(PH_SERVICE_MODIFIED_DATA));
PostMessage(PhMainWndHandle, WM_PH_SERVICE_MODIFIED, 0, (LPARAM)copy);
}
VOID NTAPI PhMwpServiceRemovedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)Parameter;
PostMessage(PhMainWndHandle, WM_PH_SERVICE_REMOVED, 0, (LPARAM)serviceItem);
}
VOID NTAPI PhMwpServicesUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PostMessage(PhMainWndHandle, WM_PH_SERVICES_UPDATED, 0, 0);
}
VOID NTAPI PhMwpNetworkItemAddedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_NETWORK_ITEM networkItem = (PPH_NETWORK_ITEM)Parameter;
PhReferenceObject(networkItem);
PostMessage(
PhMainWndHandle,
WM_PH_NETWORK_ITEM_ADDED,
PhGetRunIdProvider(&NetworkProviderRegistration),
(LPARAM)networkItem
);
}
VOID NTAPI PhMwpNetworkItemModifiedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_NETWORK_ITEM networkItem = (PPH_NETWORK_ITEM)Parameter;
PostMessage(PhMainWndHandle, WM_PH_NETWORK_ITEM_MODIFIED, 0, (LPARAM)networkItem);
}
VOID NTAPI PhMwpNetworkItemRemovedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_NETWORK_ITEM networkItem = (PPH_NETWORK_ITEM)Parameter;
PostMessage(PhMainWndHandle, WM_PH_NETWORK_ITEM_REMOVED, 0, (LPARAM)networkItem);
}
VOID NTAPI PhMwpNetworkItemsUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PostMessage(PhMainWndHandle, WM_PH_NETWORK_ITEMS_UPDATED, 0, 0);
}
VOID PhMwpLoadSettings(
VOID
)
{
ULONG opacity;
PPH_STRING customFont;
if (PhGetIntegerSetting(L"MainWindowAlwaysOnTop"))
{
AlwaysOnTop = TRUE;
SetWindowPos(PhMainWndHandle, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
}
opacity = PhGetIntegerSetting(L"MainWindowOpacity");
if (opacity != 0)
PhMwpSetWindowOpacity(opacity);
PhStatisticsSampleCount = PhGetIntegerSetting(L"SampleCount");
PhEnableProcessQueryStage2 = !!PhGetIntegerSetting(L"EnableStage2");
PhEnablePurgeProcessRecords = !PhGetIntegerSetting(L"NoPurgeProcessRecords");
PhEnableCycleCpuUsage = !!PhGetIntegerSetting(L"EnableCycleCpuUsage");
PhEnableServiceNonPoll = !!PhGetIntegerSetting(L"EnableServiceNonPoll");
PhEnableNetworkProviderResolve = !!PhGetIntegerSetting(L"EnableNetworkResolve");
PhNfLoadStage1();
NotifyIconNotifyMask = PhGetIntegerSetting(L"IconNotifyMask");
if (PhGetIntegerSetting(L"HideOtherUserProcesses"))
{
CurrentUserFilterEntry = PhAddTreeNewFilter(PhGetFilterSupportProcessTreeList(), PhMwpCurrentUserProcessTreeFilter, NULL);
}
if (PhGetIntegerSetting(L"HideSignedProcesses"))
{
SignedFilterEntry = PhAddTreeNewFilter(PhGetFilterSupportProcessTreeList(), PhMwpSignedProcessTreeFilter, NULL);
}
customFont = PhGetStringSetting(L"Font");
if (customFont->Length / 2 / 2 == sizeof(LOGFONT))
SendMessage(PhMainWndHandle, WM_PH_UPDATE_FONT, 0, 0);
PhDereferenceObject(customFont);
PhLoadSettingsProcessTreeList();
// Service and network list settings are loaded on demand.
}
VOID PhMwpSaveSettings(
VOID
)
{
PhSaveSettingsProcessTreeList();
if (ServiceTreeListLoaded)
PhSaveSettingsServiceTreeList();
if (NetworkTreeListLoaded)
PhSaveSettingsNetworkTreeList();
PhNfSaveSettings();
PhSetIntegerSetting(L"IconNotifyMask", NotifyIconNotifyMask);
PhSaveWindowPlacementToSetting(L"MainWindowPosition", L"MainWindowSize", PhMainWndHandle);
PhMwpSaveWindowSettings();
if (PhSettingsFileName)
PhSaveSettings(PhSettingsFileName->Buffer);
}
VOID PhMwpSaveWindowSettings(
VOID
)
{
WINDOWPLACEMENT placement = { sizeof(placement) };
GetWindowPlacement(PhMainWndHandle, &placement);
if (placement.showCmd == SW_NORMAL)
PhSetIntegerSetting(L"MainWindowState", SW_NORMAL);
else if (placement.showCmd == SW_MAXIMIZE)
PhSetIntegerSetting(L"MainWindowState", SW_MAXIMIZE);
}
VOID PhMwpSymInitHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_STRING dbghelpPath;
HMODULE dbghelpModule;
dbghelpPath = PhGetStringSetting(L"DbgHelpPath");
if (dbghelpModule = LoadLibrary(dbghelpPath->Buffer))
{
PPH_STRING fullDbghelpPath;
ULONG indexOfFileName;
PH_STRINGREF dbghelpFolder;
PPH_STRING symsrvPath;
PhSymPreferredDbgHelpBase = dbghelpModule;
fullDbghelpPath = PhGetDllFileName(dbghelpModule, &indexOfFileName);
if (fullDbghelpPath)
{
if (indexOfFileName != 0)
{
static PH_STRINGREF symsrvString = PH_STRINGREF_INIT(L"\\symsrv.dll");
dbghelpFolder.Buffer = fullDbghelpPath->Buffer;
dbghelpFolder.Length = indexOfFileName * sizeof(WCHAR);
symsrvPath = PhConcatStringRef2(&dbghelpFolder, &symsrvString);
LoadLibrary(symsrvPath->Buffer);
PhDereferenceObject(symsrvPath);
}
PhDereferenceObject(fullDbghelpPath);
}
}
else
{
LoadLibrary(L"dbghelp.dll");
}
PhDereferenceObject(dbghelpPath);
PhSymbolProviderDynamicImport();
}
VOID PhMwpUpdateLayoutPadding(
VOID
)
{
PH_LAYOUT_PADDING_DATA data;
memset(&data, 0, sizeof(PH_LAYOUT_PADDING_DATA));
PhInvokeCallback(&LayoutPaddingCallback, &data);
LayoutPadding = data.Padding;
}
VOID PhMwpApplyLayoutPadding(
_Inout_ PRECT Rect,
_In_ PRECT Padding
)
{
Rect->left += Padding->left;
Rect->top += Padding->top;
Rect->right -= Padding->right;
Rect->bottom -= Padding->bottom;
}
VOID PhMwpLayout(
_Inout_ HDWP *DeferHandle
)
{
RECT rect;
// Resize the tab control.
// Don't defer the resize. The tab control doesn't repaint properly.
if (!LayoutPaddingValid)
{
PhMwpUpdateLayoutPadding();
LayoutPaddingValid = TRUE;
}
GetClientRect(PhMainWndHandle, &rect);
PhMwpApplyLayoutPadding(&rect, &LayoutPadding);
SetWindowPos(TabControlHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
UpdateWindow(TabControlHandle);
PhMwpLayoutTabControl(DeferHandle);
}
VOID PhMwpSetWindowOpacity(
_In_ ULONG Opacity
)
{
if (Opacity == 0)
{
// Make things a bit faster by removing the WS_EX_LAYERED bit.
PhSetWindowExStyle(PhMainWndHandle, WS_EX_LAYERED, 0);
RedrawWindow(PhMainWndHandle, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
return;
}
PhSetWindowExStyle(PhMainWndHandle, WS_EX_LAYERED, WS_EX_LAYERED);
// Disallow opacity values of less than 10%.
if (Opacity > 90)
return;
SetLayeredWindowAttributes(
PhMainWndHandle,
0,
(BYTE)(255 * (100 - Opacity) / 100),
LWA_ALPHA
);
}
VOID PhMwpSetupComputerMenu(
_In_ PPH_EMENU_ITEM Root
)
{
PPH_EMENU_ITEM menuItem;
if (WindowsVersion < WINDOWS_8)
{
if (menuItem = PhFindEMenuItem(Root, PH_EMENU_FIND_DESCEND, NULL, ID_COMPUTER_RESTARTBOOTOPTIONS))
PhDestroyEMenuItem(menuItem);
if (menuItem = PhFindEMenuItem(Root, PH_EMENU_FIND_DESCEND, NULL, ID_COMPUTER_SHUTDOWNHYBRID))
PhDestroyEMenuItem(menuItem);
}
}
BOOLEAN PhMwpExecuteComputerCommand(
_In_ ULONG Id
)
{
switch (Id)
{
case ID_COMPUTER_LOCK:
PhUiLockComputer(PhMainWndHandle);
return TRUE;
case ID_COMPUTER_LOGOFF:
PhUiLogoffComputer(PhMainWndHandle);
return TRUE;
case ID_COMPUTER_SLEEP:
PhUiSleepComputer(PhMainWndHandle);
return TRUE;
case ID_COMPUTER_HIBERNATE:
PhUiHibernateComputer(PhMainWndHandle);
return TRUE;
case ID_COMPUTER_RESTART:
PhUiRestartComputer(PhMainWndHandle, 0);
return TRUE;
case ID_COMPUTER_RESTARTBOOTOPTIONS:
PhUiRestartComputer(PhMainWndHandle, EWX_BOOTOPTIONS);
return TRUE;
case ID_COMPUTER_SHUTDOWN:
PhUiShutdownComputer(PhMainWndHandle, 0);
return TRUE;
case ID_COMPUTER_SHUTDOWNHYBRID:
PhUiShutdownComputer(PhMainWndHandle, EWX_HYBRID_SHUTDOWN);
return TRUE;
}
return FALSE;
}
VOID PhMwpActivateWindow(
_In_ BOOLEAN Toggle
)
{
if (IsIconic(PhMainWndHandle))
{
ShowWindow(PhMainWndHandle, SW_RESTORE);
SetForegroundWindow(PhMainWndHandle);
}
else if (IsWindowVisible(PhMainWndHandle))
{
if (Toggle)
ShowWindow(PhMainWndHandle, SW_HIDE);
else
SetForegroundWindow(PhMainWndHandle);
}
else
{
ShowWindow(PhMainWndHandle, SW_SHOW);
SetForegroundWindow(PhMainWndHandle);
}
}
VOID PhMwpInitializeMainMenu(
_In_ HMENU Menu
)
{
MENUINFO menuInfo;
ULONG i;
menuInfo.cbSize = sizeof(MENUINFO);
menuInfo.fMask = MIM_STYLE;
menuInfo.dwStyle = MNS_NOTIFYBYPOS;
SetMenuInfo(Menu, &menuInfo);
for (i = 0; i < sizeof(SubMenuHandles) / sizeof(HMENU); i++)
{
SubMenuHandles[i] = GetSubMenu(PhMainWndMenuHandle, i);
}
}
VOID PhMwpDispatchMenuCommand(
_In_ HMENU MenuHandle,
_In_ ULONG ItemIndex,
_In_ ULONG ItemId,
_In_ ULONG_PTR ItemData
)
{
switch (ItemId)
{
case ID_PLUGIN_MENU_ITEM:
{
PPH_EMENU_ITEM menuItem;
menuItem = (PPH_EMENU_ITEM)ItemData;
if (menuItem)
PhPluginTriggerEMenuItem(PhMainWndHandle, menuItem);
return;
}
break;
case ID_TRAYICONS_REGISTERED:
{
PPH_EMENU_ITEM menuItem;
menuItem = (PPH_EMENU_ITEM)ItemData;
if (menuItem)
{
PPH_NF_ICON icon;
icon = menuItem->Context;
PhNfSetVisibleIcon(icon->IconId, !PhNfTestIconMask(icon->IconId));
}
return;
}
break;
case ID_USER_CONNECT:
case ID_USER_DISCONNECT:
case ID_USER_LOGOFF:
case ID_USER_REMOTECONTROL:
case ID_USER_SENDMESSAGE:
case ID_USER_PROPERTIES:
{
SelectedUserSessionId = (ULONG)ItemData;
}
break;
}
SendMessage(PhMainWndHandle, WM_COMMAND, ItemId, 0);
}
ULONG_PTR PhMwpLegacyAddPluginMenuItem(
_In_ PPH_ADDMENUITEM AddMenuItem
)
{
PPH_ADDMENUITEM addMenuItem;
PPH_PLUGIN_MENU_ITEM pluginMenuItem;
if (!LegacyAddMenuItemList)
LegacyAddMenuItemList = PhCreateList(8);
addMenuItem = PhAllocateCopy(AddMenuItem, sizeof(PH_ADDMENUITEM));
PhAddItemList(LegacyAddMenuItemList, addMenuItem);
pluginMenuItem = PhAllocate(sizeof(PH_PLUGIN_MENU_ITEM));
memset(pluginMenuItem, 0, sizeof(PH_PLUGIN_MENU_ITEM));
pluginMenuItem->Plugin = AddMenuItem->Plugin;
pluginMenuItem->Id = AddMenuItem->Id;
pluginMenuItem->Context = AddMenuItem->Context;
addMenuItem->Context = pluginMenuItem;
return TRUE;
}
VOID PhMwpInitializeSubMenu(
_In_ PPH_EMENU Menu,
_In_ ULONG Index
)
{
PPH_EMENU_ITEM menuItem;
if (Index == 0) // Hacker
{
// Fix some menu items.
if (PhElevated)
{
if (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_HACKER_RUNASADMINISTRATOR))
PhDestroyEMenuItem(menuItem);
if (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_HACKER_SHOWDETAILSFORALLPROCESSES))
PhDestroyEMenuItem(menuItem);
}
else
{
static HBITMAP shieldBitmap = NULL;
if (!shieldBitmap)
{
_LoadIconMetric loadIconMetric;
HICON shieldIcon = NULL;
// It is necessary to use LoadIconMetric because otherwise the icons are at the wrong
// resolution and look very bad when scaled down to the small icon size.
loadIconMetric = (_LoadIconMetric)PhGetProcAddress(L"comctl32.dll", "LoadIconMetric");
if (loadIconMetric)
{
if (SUCCEEDED(loadIconMetric(NULL, IDI_SHIELD, LIM_SMALL, &shieldIcon)))
{
shieldBitmap = PhIconToBitmap(shieldIcon, PhSmallIconSize.X, PhSmallIconSize.Y);
DestroyIcon(shieldIcon);
}
}
}
if (shieldBitmap)
{
if (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_HACKER_SHOWDETAILSFORALLPROCESSES))
menuItem->Bitmap = shieldBitmap;
}
}
// Fix up the Computer menu.
PhMwpSetupComputerMenu(Menu);
}
else if (Index == 1) // View
{
PPH_EMENU_ITEM trayIconsMenuItem;
ULONG i;
PPH_EMENU_ITEM menuItem;
ULONG id;
ULONG placeholderIndex;
trayIconsMenuItem = PhMwpFindTrayIconsMenuItem(Menu);
if (trayIconsMenuItem)
{
ULONG maximum;
PPH_NF_ICON icon;
// Add menu items for the registered tray icons.
id = PH_ICON_DEFAULT_MAXIMUM;
maximum = PhNfGetMaximumIconId();
for (; id != maximum; id <<= 1)
{
if (icon = PhNfGetIconById(id))
{
PhInsertEMenuItem(trayIconsMenuItem, PhCreateEMenuItem(0, ID_TRAYICONS_REGISTERED, icon->Text, NULL, icon), -1);
}
}
// Update the text and check marks on the menu items.
for (i = 0; i < trayIconsMenuItem->Items->Count; i++)
{
menuItem = trayIconsMenuItem->Items->Items[i];
id = -1;
icon = NULL;
switch (menuItem->Id)
{
case ID_TRAYICONS_CPUHISTORY:
id = PH_ICON_CPU_HISTORY;
break;
case ID_TRAYICONS_IOHISTORY:
id = PH_ICON_IO_HISTORY;
break;
case ID_TRAYICONS_COMMITHISTORY:
id = PH_ICON_COMMIT_HISTORY;
break;
case ID_TRAYICONS_PHYSICALMEMORYHISTORY:
id = PH_ICON_PHYSICAL_HISTORY;
break;
case ID_TRAYICONS_CPUUSAGE:
id = PH_ICON_CPU_USAGE;
break;
case ID_TRAYICONS_REGISTERED:
icon = menuItem->Context;
id = icon->IconId;
break;
}
if (id != -1)
{
if (PhNfTestIconMask(id))
menuItem->Flags |= PH_EMENU_CHECKED;
if (icon && (icon->Flags & PH_NF_ICON_UNAVAILABLE))
{
PPH_STRING newText;
if (menuItem->Text && (menuItem->Flags & PH_EMENU_TEXT_OWNED))
PhFree(menuItem->Text);
newText = PhaConcatStrings2(icon->Text, L" (Unavailable)");
menuItem->Text = PhAllocateCopy(newText->Buffer, newText->Length + sizeof(WCHAR));
menuItem->Flags |= PH_EMENU_TEXT_OWNED;
}
}
}
}
if (menuItem = PhFindEMenuItemEx(Menu, 0, NULL, ID_VIEW_SECTIONPLACEHOLDER, NULL, &placeholderIndex))
{
PhDestroyEMenuItem(menuItem);
PhMwpInitializeSectionMenuItems(Menu, placeholderIndex);
}
if (AlwaysOnTop && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_ALWAYSONTOP)))
menuItem->Flags |= PH_EMENU_CHECKED;
// The opacity setting is stored backwards - 0 means opaque, 100 means transparent.
id = ID_OPACITY_10 + (10 - PhGetIntegerSetting(L"MainWindowOpacity") / 10) - 1;
if (menuItem = PhFindEMenuItem(Menu, PH_EMENU_FIND_DESCEND, NULL, id))
menuItem->Flags |= PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK;
switch (PhGetIntegerSetting(L"UpdateInterval"))
{
case 500:
id = ID_UPDATEINTERVAL_FAST;
break;
case 1000:
id = ID_UPDATEINTERVAL_NORMAL;
break;
case 2000:
id = ID_UPDATEINTERVAL_BELOWNORMAL;
break;
case 5000:
id = ID_UPDATEINTERVAL_SLOW;
break;
case 10000:
id = ID_UPDATEINTERVAL_VERYSLOW;
break;
default:
id = -1;
break;
}
if (id != -1 && (menuItem = PhFindEMenuItem(Menu, PH_EMENU_FIND_DESCEND, NULL, id)))
menuItem->Flags |= PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK;
if (UpdateAutomatically && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_UPDATEAUTOMATICALLY)))
menuItem->Flags |= PH_EMENU_CHECKED;
}
else if (Index == 2) // Tools
{
#ifdef _M_X64
if (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_TOOLS_HIDDENPROCESSES))
PhDestroyEMenuItem(menuItem);
#endif
// Windows 8 Task Manager requires elevation.
if (WindowsVersion >= WINDOWS_8 && !PhElevated)
{
if (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_TOOLS_STARTTASKMANAGER))
PhDestroyEMenuItem(menuItem);
}
}
if (LegacyAddMenuItemList)
{
ULONG i;
PPH_ADDMENUITEM addMenuItem;
for (i = 0; i < LegacyAddMenuItemList->Count; i++)
{
addMenuItem = LegacyAddMenuItemList->Items[i];
if (addMenuItem->Location == Index)
{
ULONG insertIndex;
if (addMenuItem->InsertAfter)
{
for (insertIndex = 0; insertIndex < Menu->Items->Count; insertIndex++)
{
menuItem = Menu->Items->Items[insertIndex];
if (!(menuItem->Flags & PH_EMENU_SEPARATOR) && (PhCompareUnicodeStringZIgnoreMenuPrefix(
addMenuItem->InsertAfter,
menuItem->Text,
TRUE,
TRUE
) == 0))
{
insertIndex++;
break;
}
}
}
else
{
insertIndex = 0;
}
if (addMenuItem->Text[0] == '-' && addMenuItem->Text[1] == 0)
PhInsertEMenuItem(Menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, L"", NULL, NULL), insertIndex);
else
PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_PLUGIN_MENU_ITEM, addMenuItem->Text, NULL, addMenuItem->Context), insertIndex);
}
}
}
}
PPH_EMENU_ITEM PhMwpFindTrayIconsMenuItem(
_In_ PPH_EMENU Menu
)
{
ULONG i;
PPH_EMENU_ITEM menuItem;
for (i = 0; i < Menu->Items->Count; i++)
{
menuItem = Menu->Items->Items[i];
if (PhFindEMenuItem(menuItem, 0, NULL, ID_TRAYICONS_CPUHISTORY))
return menuItem;
}
return NULL;
}
VOID PhMwpInitializeSectionMenuItems(
_In_ PPH_EMENU Menu,
_In_ ULONG StartIndex
)
{
INT selectedIndex;
PPH_EMENU_ITEM menuItem;
selectedIndex = TabCtrl_GetCurSel(TabControlHandle);
if (selectedIndex == ProcessesTabIndex)
{
PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_VIEW_HIDEPROCESSESFROMOTHERUSERS, L"Hide Processes From Other Users", NULL, NULL), StartIndex);
PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_VIEW_HIDESIGNEDPROCESSES, L"Hide Signed Processes", NULL, NULL), StartIndex + 1);
PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_VIEW_SCROLLTONEWPROCESSES, L"Scroll to New Processes", NULL, NULL), StartIndex + 2);
PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_VIEW_SHOWCPUBELOW001, L"Show CPU Below 0.01", NULL, NULL), StartIndex + 3);
if (CurrentUserFilterEntry && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_HIDEPROCESSESFROMOTHERUSERS)))
menuItem->Flags |= PH_EMENU_CHECKED;
if (SignedFilterEntry && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_HIDESIGNEDPROCESSES)))
menuItem->Flags |= PH_EMENU_CHECKED;
if (PhCsScrollToNewProcesses && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_SCROLLTONEWPROCESSES)))
menuItem->Flags |= PH_EMENU_CHECKED;
if (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_SHOWCPUBELOW001))
{
if (WindowsVersion >= WINDOWS_7 && PhEnableCycleCpuUsage)
{
if (PhCsShowCpuBelow001)
menuItem->Flags |= PH_EMENU_CHECKED;
}
else
{
menuItem->Flags |= PH_EMENU_DISABLED;
}
}
}
else if (selectedIndex == ServicesTabIndex)
{
PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_VIEW_HIDEDRIVERSERVICES, L"Hide Driver Services", NULL, NULL), StartIndex);
if (DriverFilterEntry && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_HIDEDRIVERSERVICES)))
menuItem->Flags |= PH_EMENU_CHECKED;
}
else if (selectedIndex == NetworkTabIndex)
{
// Remove the extra separator.
PhRemoveEMenuItem(Menu, NULL, StartIndex);
// Disabled for now - may cause user confusion.
//PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_VIEW_HIDEPROCESSESFROMOTHERUSERS, L"Hide Processes From Other Users", NULL, NULL), StartIndex);
//PhInsertEMenuItem(Menu, PhCreateEMenuItem(0, ID_VIEW_HIDESIGNEDPROCESSES, L"Hide Signed Processes", NULL, NULL), StartIndex + 1);
//if (CurrentUserFilterEntry && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_HIDEPROCESSESFROMOTHERUSERS)))
// menuItem->Flags |= PH_EMENU_CHECKED;
//if (SignedFilterEntry && (menuItem = PhFindEMenuItem(Menu, 0, NULL, ID_VIEW_HIDESIGNEDPROCESSES)))
// menuItem->Flags |= PH_EMENU_CHECKED;
}
else if (AdditionalTabPageList)
{
ULONG i;
for (i = 0; i < AdditionalTabPageList->Count; i++)
{
PPH_ADDITIONAL_TAB_PAGE tabPage = AdditionalTabPageList->Items[i];
if (selectedIndex == tabPage->Index)
{
if (tabPage->InitializeSectionMenuItemsCallback)
{
tabPage->InitializeSectionMenuItemsCallback(Menu, (PVOID)StartIndex, NULL, tabPage->Context);
}
else
{
// Remove the extra separator.
PhRemoveEMenuItem(Menu, NULL, StartIndex);
}
break;
}
}
}
}
VOID PhMwpLayoutTabControl(
_Inout_ HDWP *DeferHandle
)
{
RECT rect;
INT selectedIndex;
if (!LayoutPaddingValid)
{
PhMwpUpdateLayoutPadding();
LayoutPaddingValid = TRUE;
}
GetClientRect(PhMainWndHandle, &rect);
PhMwpApplyLayoutPadding(&rect, &LayoutPadding);
TabCtrl_AdjustRect(TabControlHandle, FALSE, &rect);
selectedIndex = TabCtrl_GetCurSel(TabControlHandle);
if (selectedIndex == ProcessesTabIndex)
{
*DeferHandle = DeferWindowPos(*DeferHandle, ProcessTreeListHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
else if (selectedIndex == ServicesTabIndex)
{
*DeferHandle = DeferWindowPos(*DeferHandle, ServiceTreeListHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
else if (selectedIndex == NetworkTabIndex)
{
*DeferHandle = DeferWindowPos(*DeferHandle, NetworkTreeListHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
else if (AdditionalTabPageList)
{
ULONG i;
for (i = 0; i < AdditionalTabPageList->Count; i++)
{
PPH_ADDITIONAL_TAB_PAGE tabPage = AdditionalTabPageList->Items[i];
if (selectedIndex == tabPage->Index)
{
// Create the tab page window if it doesn't exist.
if (!tabPage->WindowHandle)
{
tabPage->WindowHandle = tabPage->CreateFunction(tabPage->Context);
BringWindowToTop(tabPage->WindowHandle);
if (CurrentCustomFont && tabPage->FontChangedCallback)
tabPage->FontChangedCallback((PVOID)CurrentCustomFont, NULL, NULL, tabPage->Context);
}
if (tabPage->WindowHandle)
{
*DeferHandle = DeferWindowPos(*DeferHandle, tabPage->WindowHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
break;
}
}
}
}
VOID PhMwpNotifyTabControl(
_In_ NMHDR *Header
)
{
if (Header->code == TCN_SELCHANGING)
{
OldTabIndex = TabCtrl_GetCurSel(TabControlHandle);
}
else if (Header->code == TCN_SELCHANGE)
{
PhMwpSelectionChangedTabControl(OldTabIndex);
}
}
VOID PhMwpSelectionChangedTabControl(
_In_ ULONG OldIndex
)
{
INT selectedIndex;
HDWP deferHandle;
selectedIndex = TabCtrl_GetCurSel(TabControlHandle);
deferHandle = BeginDeferWindowPos(1);
PhMwpLayoutTabControl(&deferHandle);
EndDeferWindowPos(deferHandle);
// Built-in tabs
if (selectedIndex == ServicesTabIndex)
PhMwpNeedServiceTreeList();
if (selectedIndex == NetworkTabIndex)
{
PhMwpNeedNetworkTreeList();
PhSetEnabledProvider(&NetworkProviderRegistration, UpdateAutomatically);
if (UpdateAutomatically || NetworkFirstTime)
{
PhBoostProvider(&NetworkProviderRegistration, NULL);
NetworkFirstTime = FALSE;
}
}
else
{
PhSetEnabledProvider(&NetworkProviderRegistration, FALSE);
}
ShowWindow(ProcessTreeListHandle, selectedIndex == ProcessesTabIndex ? SW_SHOW : SW_HIDE);
ShowWindow(ServiceTreeListHandle, selectedIndex == ServicesTabIndex ? SW_SHOW : SW_HIDE);
ShowWindow(NetworkTreeListHandle, selectedIndex == NetworkTabIndex ? SW_SHOW : SW_HIDE);
// Additional tabs
if (AdditionalTabPageList)
{
ULONG i;
for (i = 0; i < AdditionalTabPageList->Count; i++)
{
PPH_ADDITIONAL_TAB_PAGE tabPage = AdditionalTabPageList->Items[i];
if (tabPage->SelectionChangedCallback)
{
if (tabPage->Index == OldIndex)
{
tabPage->SelectionChangedCallback((PVOID)FALSE, 0, 0, tabPage->Context);
}
else if (tabPage->Index == selectedIndex)
{
tabPage->SelectionChangedCallback((PVOID)TRUE, 0, 0, tabPage->Context);
}
}
ShowWindow(tabPage->WindowHandle, selectedIndex == tabPage->Index ? SW_SHOW : SW_HIDE);
}
}
if (PhPluginsEnabled)
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMainWindowTabChanged), (PVOID)selectedIndex);
}
PPH_ADDITIONAL_TAB_PAGE PhMwpAddTabPage(
_In_ PPH_ADDITIONAL_TAB_PAGE TabPage
)
{
PPH_ADDITIONAL_TAB_PAGE newTabPage;
HDWP deferHandle;
if (!AdditionalTabPageList)
AdditionalTabPageList = PhCreateList(2);
newTabPage = PhAllocateCopy(TabPage, sizeof(PH_ADDITIONAL_TAB_PAGE));
PhAddItemList(AdditionalTabPageList, newTabPage);
newTabPage->Index = PhAddTabControlTab(TabControlHandle, MAXINT, newTabPage->Text);
MaxTabIndex = newTabPage->Index;
if (newTabPage->WindowHandle)
BringWindowToTop(newTabPage->WindowHandle);
// The tab control might need multiple lines, so we need to refresh the layout.
deferHandle = BeginDeferWindowPos(1);
PhMwpLayoutTabControl(&deferHandle);
EndDeferWindowPos(deferHandle);
return newTabPage;
}
VOID PhMwpSelectTabPage(
_In_ ULONG Index
)
{
INT oldIndex;
oldIndex = TabCtrl_GetCurSel(TabControlHandle);
TabCtrl_SetCurSel(TabControlHandle, Index);
PhMwpSelectionChangedTabControl(oldIndex);
}
static int __cdecl IconProcessesCpuUsageCompare(
_In_ const void *elem1,
_In_ const void *elem2
)
{
PPH_PROCESS_ITEM processItem1 = *(PPH_PROCESS_ITEM *)elem1;
PPH_PROCESS_ITEM processItem2 = *(PPH_PROCESS_ITEM *)elem2;
return -singlecmp(processItem1->CpuUsage, processItem2->CpuUsage);
}
static int __cdecl IconProcessesNameCompare(
_In_ const void *elem1,
_In_ const void *elem2
)
{
PPH_PROCESS_ITEM processItem1 = *(PPH_PROCESS_ITEM *)elem1;
PPH_PROCESS_ITEM processItem2 = *(PPH_PROCESS_ITEM *)elem2;
return PhCompareString(processItem1->ProcessName, processItem2->ProcessName, TRUE);
}
VOID PhMwpAddIconProcesses(
_In_ PPH_EMENU_ITEM Menu,
_In_ ULONG NumberOfProcesses
)
{
ULONG i;
PPH_PROCESS_ITEM *processItems;
ULONG numberOfProcessItems;
PPH_LIST processList;
PPH_PROCESS_ITEM processItem;
PhEnumProcessItems(&processItems, &numberOfProcessItems);
processList = PhCreateList(numberOfProcessItems);
PhAddItemsList(processList, processItems, numberOfProcessItems);
// Remove non-real processes.
for (i = 0; i < processList->Count; i++)
{
processItem = processList->Items[i];
if (!PH_IS_REAL_PROCESS_ID(processItem->ProcessId))
{
PhRemoveItemList(processList, i);
i--;
}
}
// Remove processes with zero CPU usage and those running as other users.
for (i = 0; i < processList->Count && processList->Count > NumberOfProcesses; i++)
{
processItem = processList->Items[i];
if (
processItem->CpuUsage == 0 ||
!processItem->UserName ||
(PhCurrentUserName && !PhEqualString(processItem->UserName, PhCurrentUserName, TRUE))
)
{
PhRemoveItemList(processList, i);
i--;
}
}
// Sort the processes by CPU usage and remove the extra processes at the end of the list.
qsort(processList->Items, processList->Count, sizeof(PVOID), IconProcessesCpuUsageCompare);
if (processList->Count > NumberOfProcesses)
{
PhRemoveItemsList(processList, NumberOfProcesses, processList->Count - NumberOfProcesses);
}
// Lastly, sort by name.
qsort(processList->Items, processList->Count, sizeof(PVOID), IconProcessesNameCompare);
// Delete all menu items.
PhRemoveAllEMenuItems(Menu);
// Add the processes.
for (i = 0; i < processList->Count; i++)
{
PPH_EMENU_ITEM subMenu;
PPH_EMENU_ITEM priorityMenu;
HBITMAP iconBitmap;
CLIENT_ID clientId;
PPH_STRING clientIdName;
PPH_STRING escapedName;
processItem = processList->Items[i];
// Priority
priorityMenu = PhCreateEMenuItem(0, 0, L"Priority", NULL, NULL);
PhInsertEMenuItem(priorityMenu, PhCreateEMenuItem(0, ID_PRIORITY_REALTIME, L"Real Time", NULL, NULL), -1);
PhInsertEMenuItem(priorityMenu, PhCreateEMenuItem(0, ID_PRIORITY_HIGH, L"High", NULL, NULL), -1);
PhInsertEMenuItem(priorityMenu, PhCreateEMenuItem(0, ID_PRIORITY_ABOVENORMAL, L"Above Normal", NULL, NULL), -1);
PhInsertEMenuItem(priorityMenu, PhCreateEMenuItem(0, ID_PRIORITY_NORMAL, L"Normal", NULL, NULL), -1);
PhInsertEMenuItem(priorityMenu, PhCreateEMenuItem(0, ID_PRIORITY_BELOWNORMAL, L"Below Normal", NULL, NULL), -1);
PhInsertEMenuItem(priorityMenu, PhCreateEMenuItem(0, ID_PRIORITY_IDLE, L"Idle", NULL, NULL), -1);
PhMwpSetProcessMenuPriorityChecks(priorityMenu, processItem, TRUE, FALSE, FALSE);
// Process
clientId.UniqueProcess = processItem->ProcessId;
clientId.UniqueThread = NULL;
clientIdName = PhGetClientIdName(&clientId);
escapedName = PhEscapeStringForMenuPrefix(&clientIdName->sr);
PhDereferenceObject(clientIdName);
PhaDereferenceObject(escapedName);
subMenu = PhCreateEMenuItem(
0,
0,
escapedName->Buffer,
NULL,
processItem->ProcessId
);
// Menu icons only work properly on Vista and above.
if (WindowsVersion >= WINDOWS_VISTA)
{
if (processItem->SmallIcon)
{
iconBitmap = PhIconToBitmap(processItem->SmallIcon, PhSmallIconSize.X, PhSmallIconSize.Y);
}
else
{
HICON icon;
PhGetStockApplicationIcon(&icon, NULL);
iconBitmap = PhIconToBitmap(icon, PhSmallIconSize.X, PhSmallIconSize.Y);
}
}
else
{
iconBitmap = NULL;
}
subMenu->Bitmap = iconBitmap;
subMenu->Flags |= PH_EMENU_BITMAP_OWNED; // automatically destroy the bitmap when necessary
PhInsertEMenuItem(subMenu, PhCreateEMenuItem(0, ID_PROCESS_TERMINATE, L"Terminate", NULL, NULL), -1);
PhInsertEMenuItem(subMenu, PhCreateEMenuItem(0, ID_PROCESS_SUSPEND, L"Suspend", NULL, NULL), -1);
PhInsertEMenuItem(subMenu, PhCreateEMenuItem(0, ID_PROCESS_RESUME, L"Resume", NULL, NULL), -1);
PhInsertEMenuItem(subMenu, priorityMenu, -1);
PhInsertEMenuItem(subMenu, PhCreateEMenuItem(0, ID_PROCESS_PROPERTIES, L"Properties", NULL, NULL), -1);
PhInsertEMenuItem(Menu, subMenu, -1);
}
PhDereferenceObject(processList);
PhDereferenceObjects(processItems, numberOfProcessItems);
PhFree(processItems);
}
VOID PhShowIconContextMenu(
_In_ POINT Location
)
{
PPH_EMENU menu;
PPH_EMENU_ITEM item;
ULONG numberOfProcesses;
ULONG id;
ULONG i;
// This function seems to be called recursively under some circumstances.
// To reproduce:
// 1. Hold right mouse button on tray icon, then left click.
// 2. Make the menu disappear by clicking on the menu then clicking somewhere else.
// So, don't store any global state or bad things will happen.
menu = PhCreateEMenu();
PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_ICON), 0);
// Check the Notifications menu items.
for (i = PH_NOTIFY_MINIMUM; i != PH_NOTIFY_MAXIMUM; i <<= 1)
{
if (NotifyIconNotifyMask & i)
{
switch (i)
{
case PH_NOTIFY_PROCESS_CREATE:
id = ID_NOTIFICATIONS_NEWPROCESSES;
break;
case PH_NOTIFY_PROCESS_DELETE:
id = ID_NOTIFICATIONS_TERMINATEDPROCESSES;
break;
case PH_NOTIFY_SERVICE_CREATE:
id = ID_NOTIFICATIONS_NEWSERVICES;
break;
case PH_NOTIFY_SERVICE_DELETE:
id = ID_NOTIFICATIONS_DELETEDSERVICES;
break;
case PH_NOTIFY_SERVICE_START:
id = ID_NOTIFICATIONS_STARTEDSERVICES;
break;
case PH_NOTIFY_SERVICE_STOP:
id = ID_NOTIFICATIONS_STOPPEDSERVICES;
break;
}
PhSetFlagsEMenuItem(menu, id, PH_EMENU_CHECKED, PH_EMENU_CHECKED);
}
}
// Add processes to the menu.
numberOfProcesses = PhGetIntegerSetting(L"IconProcesses");
item = PhFindEMenuItem(menu, 0, L"Processes", 0);
if (item)
PhMwpAddIconProcesses(item, numberOfProcesses);
// Fix up the Computer menu.
PhMwpSetupComputerMenu(menu);
// Give plugins a chance to modify the menu.
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.OwnerWindow = PhMainWndHandle;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackIconMenuInitializing), &menuInfo);
}
SetForegroundWindow(PhMainWndHandle); // window must be foregrounded so menu will disappear properly
item = PhShowEMenu(
menu,
PhMainWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
Location.x,
Location.y
);
if (item)
{
PPH_EMENU_ITEM parentItem;
HANDLE processId;
BOOLEAN handled = FALSE;
parentItem = item->Parent;
while (parentItem)
{
if (parentItem->Context)
processId = parentItem->Context;
parentItem = parentItem->Parent;
}
if (PhPluginsEnabled && !handled)
handled = PhPluginTriggerEMenuItem(PhMainWndHandle, item);
if (!handled)
handled = PhMwpExecuteComputerCommand(item->Id);
if (!handled)
{
switch (item->Id)
{
case ID_ICON_SHOWHIDEPROCESSHACKER:
SendMessage(PhMainWndHandle, WM_PH_TOGGLE_VISIBLE, 0, 0);
break;
case ID_ICON_SYSTEMINFORMATION:
SendMessage(PhMainWndHandle, WM_COMMAND, ID_VIEW_SYSTEMINFORMATION, 0);
break;
case ID_NOTIFICATIONS_ENABLEALL:
NotifyIconNotifyMask |= PH_NOTIFY_VALID_MASK;
break;
case ID_NOTIFICATIONS_DISABLEALL:
NotifyIconNotifyMask &= ~PH_NOTIFY_VALID_MASK;
break;
case ID_NOTIFICATIONS_NEWPROCESSES:
case ID_NOTIFICATIONS_TERMINATEDPROCESSES:
case ID_NOTIFICATIONS_NEWSERVICES:
case ID_NOTIFICATIONS_STARTEDSERVICES:
case ID_NOTIFICATIONS_STOPPEDSERVICES:
case ID_NOTIFICATIONS_DELETEDSERVICES:
{
ULONG bit;
switch (item->Id)
{
case ID_NOTIFICATIONS_NEWPROCESSES:
bit = PH_NOTIFY_PROCESS_CREATE;
break;
case ID_NOTIFICATIONS_TERMINATEDPROCESSES:
bit = PH_NOTIFY_PROCESS_DELETE;
break;
case ID_NOTIFICATIONS_NEWSERVICES:
bit = PH_NOTIFY_SERVICE_CREATE;
break;
case ID_NOTIFICATIONS_STARTEDSERVICES:
bit = PH_NOTIFY_SERVICE_START;
break;
case ID_NOTIFICATIONS_STOPPEDSERVICES:
bit = PH_NOTIFY_SERVICE_STOP;
break;
case ID_NOTIFICATIONS_DELETEDSERVICES:
bit = PH_NOTIFY_SERVICE_DELETE;
break;
}
NotifyIconNotifyMask ^= bit;
}
break;
case ID_PROCESS_TERMINATE:
case ID_PROCESS_SUSPEND:
case ID_PROCESS_RESUME:
case ID_PROCESS_PROPERTIES:
{
PPH_PROCESS_ITEM processItem;
if (processItem = PhReferenceProcessItem(processId))
{
switch (item->Id)
{
case ID_PROCESS_TERMINATE:
PhUiTerminateProcesses(PhMainWndHandle, &processItem, 1);
break;
case ID_PROCESS_SUSPEND:
PhUiSuspendProcesses(PhMainWndHandle, &processItem, 1);
break;
case ID_PROCESS_RESUME:
PhUiResumeProcesses(PhMainWndHandle, &processItem, 1);
break;
case ID_PROCESS_PROPERTIES:
ProcessHacker_ShowProcessProperties(PhMainWndHandle, processItem);
break;
}
PhDereferenceObject(processItem);
}
else
{
PhShowError(PhMainWndHandle, L"The process does not exist.");
}
}
break;
case ID_PRIORITY_REALTIME:
case ID_PRIORITY_HIGH:
case ID_PRIORITY_ABOVENORMAL:
case ID_PRIORITY_NORMAL:
case ID_PRIORITY_BELOWNORMAL:
case ID_PRIORITY_IDLE:
{
PPH_PROCESS_ITEM processItem;
if (processItem = PhReferenceProcessItem(processId))
{
PhMwpExecuteProcessPriorityCommand(item->Id, processItem);
PhDereferenceObject(processItem);
}
else
{
PhShowError(PhMainWndHandle, L"The process does not exist.");
}
}
break;
case ID_ICON_EXIT:
SendMessage(PhMainWndHandle, WM_COMMAND, ID_HACKER_EXIT, 0);
break;
}
}
}
PhDestroyEMenu(menu);
}
VOID PhShowIconNotification(
_In_ PWSTR Title,
_In_ PWSTR Text,
_In_ ULONG Flags
)
{
PhNfShowBalloonTip(0, Title, Text, 10, Flags);
}
BOOLEAN PhMwpPluginNotifyEvent(
_In_ ULONG Type,
_In_ PVOID Parameter
)
{
PH_PLUGIN_NOTIFY_EVENT notifyEvent;
notifyEvent.Type = Type;
notifyEvent.Handled = FALSE;
notifyEvent.Parameter = Parameter;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackNotifyEvent), &notifyEvent);
return notifyEvent.Handled;
}
VOID PhMwpShowProcessProperties(
_In_ PPH_PROCESS_ITEM ProcessItem
)
{
PPH_PROCESS_PROPCONTEXT propContext;
propContext = PhCreateProcessPropContext(
PhMainWndHandle,
ProcessItem
);
if (propContext)
{
PhShowProcessProperties(propContext);
PhDereferenceObject(propContext);
}
}
BOOLEAN PhMwpCurrentUserProcessTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
)
{
PPH_PROCESS_NODE processNode = (PPH_PROCESS_NODE)Node;
if (!processNode->ProcessItem->UserName)
return FALSE;
if (!PhCurrentUserName)
return FALSE;
if (!PhEqualString(processNode->ProcessItem->UserName, PhCurrentUserName, TRUE))
return FALSE;
return TRUE;
}
BOOLEAN PhMwpSignedProcessTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
)
{
PPH_PROCESS_NODE processNode = (PPH_PROCESS_NODE)Node;
if (processNode->ProcessItem->VerifyResult == VrTrusted)
return FALSE;
return TRUE;
}
BOOLEAN PhMwpExecuteProcessPriorityCommand(
_In_ ULONG Id,
_In_ PPH_PROCESS_ITEM ProcessItem
)
{
ULONG priorityClass;
switch (Id)
{
case ID_PRIORITY_REALTIME:
priorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
break;
case ID_PRIORITY_HIGH:
priorityClass = PROCESS_PRIORITY_CLASS_HIGH;
break;
case ID_PRIORITY_ABOVENORMAL:
priorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
break;
case ID_PRIORITY_NORMAL:
priorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
break;
case ID_PRIORITY_BELOWNORMAL:
priorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
break;
case ID_PRIORITY_IDLE:
priorityClass = PROCESS_PRIORITY_CLASS_IDLE;
break;
default:
return FALSE;
}
PhUiSetPriorityProcess(PhMainWndHandle, ProcessItem, priorityClass);
return TRUE;
}
VOID PhMwpSetProcessMenuPriorityChecks(
_In_ PPH_EMENU Menu,
_In_ PPH_PROCESS_ITEM Process,
_In_ BOOLEAN SetPriority,
_In_ BOOLEAN SetIoPriority,
_In_ BOOLEAN SetPagePriority
)
{
HANDLE processHandle;
PROCESS_PRIORITY_CLASS priorityClass = { 0 };
ULONG ioPriority = -1;
ULONG pagePriority = -1;
ULONG id = 0;
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
ProcessQueryAccess,
Process->ProcessId
)))
{
if (SetPriority)
{
NtQueryInformationProcess(processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS), NULL);
}
if (SetIoPriority && WindowsVersion >= WINDOWS_VISTA)
{
if (!NT_SUCCESS(PhGetProcessIoPriority(
processHandle,
&ioPriority
)))
{
ioPriority = -1;
}
}
if (SetPagePriority && WindowsVersion >= WINDOWS_VISTA)
{
if (!NT_SUCCESS(PhGetProcessPagePriority(
processHandle,
&pagePriority
)))
{
pagePriority = -1;
}
}
NtClose(processHandle);
}
if (SetPriority)
{
switch (priorityClass.PriorityClass)
{
case PROCESS_PRIORITY_CLASS_REALTIME:
id = ID_PRIORITY_REALTIME;
break;
case PROCESS_PRIORITY_CLASS_HIGH:
id = ID_PRIORITY_HIGH;
break;
case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
id = ID_PRIORITY_ABOVENORMAL;
break;
case PROCESS_PRIORITY_CLASS_NORMAL:
id = ID_PRIORITY_NORMAL;
break;
case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
id = ID_PRIORITY_BELOWNORMAL;
break;
case PROCESS_PRIORITY_CLASS_IDLE:
id = ID_PRIORITY_IDLE;
break;
}
if (id != 0)
{
PhSetFlagsEMenuItem(Menu, id,
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK,
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK);
}
}
if (SetIoPriority && ioPriority != -1)
{
id = 0;
switch (ioPriority)
{
case 0:
id = ID_I_0;
break;
case 1:
id = ID_I_1;
break;
case 2:
id = ID_I_2;
break;
case 3:
id = ID_I_3;
break;
}
if (id != 0)
{
PhSetFlagsEMenuItem(Menu, id,
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK,
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK);
}
}
if (SetPagePriority && pagePriority != -1)
{
id = 0;
switch (pagePriority)
{
case 1:
id = ID_PAGEPRIORITY_1;
break;
case 2:
id = ID_PAGEPRIORITY_2;
break;
case 3:
id = ID_PAGEPRIORITY_3;
break;
case 4:
id = ID_PAGEPRIORITY_4;
break;
case 5:
id = ID_PAGEPRIORITY_5;
break;
}
if (id != 0)
{
PhSetFlagsEMenuItem(Menu, id,
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK,
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK);
}
}
}
static BOOL CALLBACK EnumProcessWindowsProc(
_In_ HWND hwnd,
_In_ LPARAM lParam
)
{
ULONG processId;
HWND parentWindow;
if (!IsWindowVisible(hwnd))
return TRUE;
GetWindowThreadProcessId(hwnd, &processId);
if (
processId == (ULONG)lParam &&
!((parentWindow = GetParent(hwnd)) && IsWindowVisible(parentWindow)) && // skip windows with a visible parent
GetWindowTextLength(hwnd) != 0
)
{
SelectedProcessWindowHandle = hwnd;
return FALSE;
}
return TRUE;
}
VOID PhMwpInitializeProcessMenu(
_In_ PPH_EMENU Menu,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
)
{
PPH_EMENU_ITEM item;
if (NumberOfProcesses == 0)
{
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
else if (NumberOfProcesses == 1)
{
// All menu items are enabled by default.
// If the user selected a fake process, disable all but
// a few menu items.
if (PH_IS_FAKE_PROCESS_ID(Processes[0]->ProcessId))
{
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(Menu, ID_PROCESS_PROPERTIES, TRUE);
PhEnableEMenuItem(Menu, ID_PROCESS_SEARCHONLINE, TRUE);
}
}
else
{
ULONG menuItemsMultiEnabled[] =
{
ID_PROCESS_TERMINATE,
ID_PROCESS_SUSPEND,
ID_PROCESS_RESUME,
ID_MISCELLANEOUS_REDUCEWORKINGSET,
ID_PROCESS_COPY
};
ULONG i;
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
// Enable the Miscellaneous menu item but disable its children.
if (item = PhFindEMenuItem(Menu, 0, L"Miscellaneous", 0))
{
item->Flags &= ~PH_EMENU_DISABLED;
PhSetFlagsAllEMenuItems(item, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
// These menu items are capable of manipulating
// multiple processes.
for (i = 0; i < sizeof(menuItemsMultiEnabled) / sizeof(ULONG); i++)
{
PhSetFlagsEMenuItem(Menu, menuItemsMultiEnabled[i], PH_EMENU_DISABLED, 0);
}
}
// Remove irrelevant menu items.
if (WindowsVersion < WINDOWS_VISTA)
{
// Remove I/O priority.
if (item = PhFindEMenuItem(Menu, PH_EMENU_FIND_DESCEND, L"I/O Priority", 0))
PhDestroyEMenuItem(item);
// Remove page priority.
if (item = PhFindEMenuItem(Menu, PH_EMENU_FIND_DESCEND, L"Page Priority", 0))
PhDestroyEMenuItem(item);
}
// Virtualization
if (NumberOfProcesses == 1)
{
HANDLE processHandle;
HANDLE tokenHandle;
BOOLEAN allowed = FALSE;
BOOLEAN enabled = FALSE;
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
ProcessQueryAccess,
Processes[0]->ProcessId
)))
{
if (NT_SUCCESS(PhOpenProcessToken(
&tokenHandle,
TOKEN_QUERY,
processHandle
)))
{
PhGetTokenIsVirtualizationAllowed(tokenHandle, &allowed);
PhGetTokenIsVirtualizationEnabled(tokenHandle, &enabled);
SelectedProcessVirtualizationEnabled = enabled;
NtClose(tokenHandle);
}
NtClose(processHandle);
}
if (!allowed)
PhSetFlagsEMenuItem(Menu, ID_PROCESS_VIRTUALIZATION, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
else if (enabled)
PhSetFlagsEMenuItem(Menu, ID_PROCESS_VIRTUALIZATION, PH_EMENU_CHECKED, PH_EMENU_CHECKED);
}
// Priority
if (NumberOfProcesses == 1)
{
PhMwpSetProcessMenuPriorityChecks(Menu, Processes[0], TRUE, TRUE, TRUE);
}
item = PhFindEMenuItem(Menu, 0, L"Window", 0);
if (item)
{
// Window menu
if (NumberOfProcesses == 1)
{
WINDOWPLACEMENT placement = { sizeof(placement) };
// Get a handle to the process' top-level window (if any).
SelectedProcessWindowHandle = NULL;
PhEnumChildWindows(NULL, 0x800, EnumProcessWindowsProc, (ULONG)Processes[0]->ProcessId);
if (!SelectedProcessWindowHandle)
item->Flags |= PH_EMENU_DISABLED;
GetWindowPlacement(SelectedProcessWindowHandle, &placement);
if (placement.showCmd == SW_MINIMIZE)
PhEnableEMenuItem(item, ID_WINDOW_MINIMIZE, FALSE);
else if (placement.showCmd == SW_MAXIMIZE)
PhEnableEMenuItem(item, ID_WINDOW_MAXIMIZE, FALSE);
else if (placement.showCmd == SW_NORMAL)
PhEnableEMenuItem(item, ID_WINDOW_RESTORE, FALSE);
}
else
{
item->Flags |= PH_EMENU_DISABLED;
}
}
// Remove irrelevant menu items (continued)
if (!WINDOWS_HAS_UAC)
{
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_PROCESS_VIRTUALIZATION))
PhDestroyEMenuItem(item);
}
}
VOID PhShowProcessContextMenu(
_In_ PPH_TREENEW_CONTEXT_MENU ContextMenu
)
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhGetSelectedProcessItems(&processes, &numberOfProcesses);
if (numberOfProcesses != 0)
{
PPH_EMENU menu;
PPH_EMENU_ITEM item;
menu = PhCreateEMenu();
PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_PROCESS), 0);
PhSetFlagsEMenuItem(menu, ID_PROCESS_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
PhMwpInitializeProcessMenu(menu, processes, numberOfProcesses);
PhInsertCopyCellEMenuItem(menu, ID_PROCESS_COPY, ProcessTreeListHandle, ContextMenu->Column);
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.OwnerWindow = PhMainWndHandle;
menuInfo.u.Process.Processes = processes;
menuInfo.u.Process.NumberOfProcesses = numberOfProcesses;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackProcessMenuInitializing), &menuInfo);
}
item = PhShowEMenu(
menu,
PhMainWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
ContextMenu->Location.x,
ContextMenu->Location.y
);
if (item)
{
BOOLEAN handled = FALSE;
handled = PhHandleCopyCellEMenuItem(item);
if (!handled && PhPluginsEnabled)
handled = PhPluginTriggerEMenuItem(PhMainWndHandle, item);
if (!handled)
SendMessage(PhMainWndHandle, WM_COMMAND, item->Id, 0);
}
PhDestroyEMenu(menu);
}
PhFree(processes);
}
VOID PhMwpOnProcessAdded(
_In_ _Assume_refs_(1) PPH_PROCESS_ITEM ProcessItem,
_In_ ULONG RunId
)
{
PPH_PROCESS_NODE processNode;
if (!ProcessesNeedsRedraw)
{
TreeNew_SetRedraw(ProcessTreeListHandle, FALSE);
ProcessesNeedsRedraw = TRUE;
}
processNode = PhAddProcessNode(ProcessItem, RunId);
if (RunId != 1)
{
PPH_PROCESS_ITEM parentProcess;
HANDLE parentProcessId = NULL;
PPH_STRING parentName = NULL;
if (parentProcess = PhReferenceProcessItemForParent(
ProcessItem->ParentProcessId,
ProcessItem->ProcessId,
&ProcessItem->CreateTime
))
{
parentProcessId = parentProcess->ProcessId;
parentName = parentProcess->ProcessName;
}
PhLogProcessEntry(
PH_LOG_ENTRY_PROCESS_CREATE,
ProcessItem->ProcessId,
ProcessItem->ProcessName,
parentProcessId,
parentName
);
if (NotifyIconNotifyMask & PH_NOTIFY_PROCESS_CREATE)
{
if (!PhPluginsEnabled || !PhMwpPluginNotifyEvent(PH_NOTIFY_PROCESS_CREATE, ProcessItem))
{
PhShowIconNotification(L"Process Created", PhaFormatString(
L"The process %s (%u) was created by %s (%u)",
ProcessItem->ProcessName->Buffer,
(ULONG)ProcessItem->ProcessId,
PhGetStringOrDefault(parentName, L"Unknown Process"),
(ULONG)ProcessItem->ParentProcessId
)->Buffer, NIIF_INFO);
}
}
if (parentProcess)
PhDereferenceObject(parentProcess);
if (PhCsScrollToNewProcesses)
ProcessToScrollTo = processNode;
}
else
{
if (NeedsSelectPid != 0)
{
if (processNode->ProcessId == UlongToHandle(NeedsSelectPid))
ProcessToScrollTo = processNode;
}
}
// PhCreateProcessNode has its own reference.
PhDereferenceObject(ProcessItem);
}
VOID PhMwpOnProcessModified(
_In_ PPH_PROCESS_ITEM ProcessItem
)
{
PhUpdateProcessNode(PhFindProcessNode(ProcessItem->ProcessId));
if (SignedFilterEntry)
PhApplyTreeNewFilters(PhGetFilterSupportProcessTreeList());
}
VOID PhMwpOnProcessRemoved(
_In_ PPH_PROCESS_ITEM ProcessItem
)
{
PPH_PROCESS_NODE processNode;
if (!ProcessesNeedsRedraw)
{
TreeNew_SetRedraw(ProcessTreeListHandle, FALSE);
ProcessesNeedsRedraw = TRUE;
}
PhLogProcessEntry(PH_LOG_ENTRY_PROCESS_DELETE, ProcessItem->ProcessId, ProcessItem->ProcessName, NULL, NULL);
if (NotifyIconNotifyMask & PH_NOTIFY_PROCESS_DELETE)
{
if (!PhPluginsEnabled || !PhMwpPluginNotifyEvent(PH_NOTIFY_PROCESS_DELETE, ProcessItem))
{
PhShowIconNotification(L"Process Terminated", PhaFormatString(
L"The process %s (%u) was terminated.",
ProcessItem->ProcessName->Buffer,
(ULONG)ProcessItem->ProcessId
)->Buffer, NIIF_INFO);
}
}
processNode = PhFindProcessNode(ProcessItem->ProcessId);
PhRemoveProcessNode(processNode);
if (ProcessToScrollTo == processNode) // shouldn't happen, but just in case
ProcessToScrollTo = NULL;
}
VOID PhMwpOnProcessesUpdated(
VOID
)
{
// The modified notification is only sent for special cases.
// We have to invalidate the text on each update.
PhTickProcessNodes();
if (PhPluginsEnabled)
{
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackProcessesUpdated), NULL);
}
if (ProcessesNeedsRedraw)
{
TreeNew_SetRedraw(ProcessTreeListHandle, TRUE);
ProcessesNeedsRedraw = FALSE;
}
if (NeedsSelectPid != 0)
{
if (ProcessToScrollTo)
{
PhSelectAndEnsureVisibleProcessNode(ProcessToScrollTo);
ProcessToScrollTo = NULL;
}
NeedsSelectPid = 0;
}
if (ProcessToScrollTo)
{
TreeNew_EnsureVisible(ProcessTreeListHandle, &ProcessToScrollTo->Node);
ProcessToScrollTo = NULL;
}
}
VOID PhMwpNeedServiceTreeList(
VOID
)
{
if (!ServiceTreeListLoaded)
{
ServiceTreeListLoaded = TRUE;
PhLoadSettingsServiceTreeList();
if (PhGetIntegerSetting(L"HideDriverServices"))
{
DriverFilterEntry = PhAddTreeNewFilter(PhGetFilterSupportServiceTreeList(), PhMwpDriverServiceTreeFilter, NULL);
}
if (ServicesPendingList)
{
PPH_SERVICE_ITEM serviceItem;
ULONG enumerationKey = 0;
while (PhEnumPointerList(ServicesPendingList, &enumerationKey, (PPVOID)&serviceItem))
{
PhMwpOnServiceAdded(serviceItem, 1);
}
// Force a re-draw.
PhMwpOnServicesUpdated();
PhSwapReference(&ServicesPendingList, NULL);
}
}
}
BOOLEAN PhMwpDriverServiceTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
)
{
PPH_SERVICE_NODE serviceNode = (PPH_SERVICE_NODE)Node;
if (serviceNode->ServiceItem->Type & SERVICE_DRIVER)
return FALSE;
return TRUE;
}
VOID PhMwpInitializeServiceMenu(
_In_ PPH_EMENU Menu,
_In_ PPH_SERVICE_ITEM *Services,
_In_ ULONG NumberOfServices
)
{
if (NumberOfServices == 0)
{
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
else if (NumberOfServices == 1)
{
if (!Services[0]->ProcessId)
PhEnableEMenuItem(Menu, ID_SERVICE_GOTOPROCESS, FALSE);
}
else
{
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(Menu, ID_SERVICE_COPY, TRUE);
}
if (NumberOfServices == 1)
{
switch (Services[0]->State)
{
case SERVICE_RUNNING:
{
PhEnableEMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
PhEnableEMenuItem(Menu, ID_SERVICE_STOP,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_STOP);
}
break;
case SERVICE_PAUSED:
{
PhEnableEMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_STOP,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_STOP);
}
break;
case SERVICE_STOPPED:
{
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_STOP, FALSE);
}
break;
case SERVICE_START_PENDING:
case SERVICE_CONTINUE_PENDING:
case SERVICE_PAUSE_PENDING:
case SERVICE_STOP_PENDING:
{
PhEnableEMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_STOP, FALSE);
}
break;
}
if (!(Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE))
{
PPH_EMENU_ITEM item;
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_SERVICE_CONTINUE))
PhDestroyEMenuItem(item);
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_SERVICE_PAUSE))
PhDestroyEMenuItem(item);
}
}
}
VOID PhShowServiceContextMenu(
_In_ PPH_TREENEW_CONTEXT_MENU ContextMenu
)
{
PPH_SERVICE_ITEM *services;
ULONG numberOfServices;
PhGetSelectedServiceItems(&services, &numberOfServices);
if (numberOfServices != 0)
{
PPH_EMENU menu;
PPH_EMENU_ITEM item;
menu = PhCreateEMenu();
PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_SERVICE), 0);
PhSetFlagsEMenuItem(menu, ID_SERVICE_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
PhMwpInitializeServiceMenu(menu, services, numberOfServices);
PhInsertCopyCellEMenuItem(menu, ID_SERVICE_COPY, ServiceTreeListHandle, ContextMenu->Column);
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.OwnerWindow = PhMainWndHandle;
menuInfo.u.Service.Services = services;
menuInfo.u.Service.NumberOfServices = numberOfServices;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackServiceMenuInitializing), &menuInfo);
}
item = PhShowEMenu(
menu,
PhMainWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
ContextMenu->Location.x,
ContextMenu->Location.y
);
if (item)
{
BOOLEAN handled = FALSE;
handled = PhHandleCopyCellEMenuItem(item);
if (!handled && PhPluginsEnabled)
handled = PhPluginTriggerEMenuItem(PhMainWndHandle, item);
if (!handled)
SendMessage(PhMainWndHandle, WM_COMMAND, item->Id, 0);
}
PhDestroyEMenu(menu);
}
PhFree(services);
}
VOID PhMwpOnServiceAdded(
_In_ _Assume_refs_(1) PPH_SERVICE_ITEM ServiceItem,
_In_ ULONG RunId
)
{
PPH_SERVICE_NODE serviceNode;
if (ServiceTreeListLoaded)
{
if (!ServicesNeedsRedraw)
{
TreeNew_SetRedraw(ServiceTreeListHandle, FALSE);
ServicesNeedsRedraw = TRUE;
}
serviceNode = PhAddServiceNode(ServiceItem, RunId);
// ServiceItem dereferenced below
}
else
{
if (!ServicesPendingList)
ServicesPendingList = PhCreatePointerList(100);
PhAddItemPointerList(ServicesPendingList, ServiceItem);
}
if (RunId != 1)
{
PhLogServiceEntry(PH_LOG_ENTRY_SERVICE_CREATE, ServiceItem->Name, ServiceItem->DisplayName);
if (NotifyIconNotifyMask & PH_NOTIFY_SERVICE_CREATE)
{
if (!PhPluginsEnabled || !PhMwpPluginNotifyEvent(PH_NOTIFY_SERVICE_CREATE, ServiceItem))
{
PhShowIconNotification(L"Service Created", PhaFormatString(
L"The service %s (%s) has been created.",
ServiceItem->Name->Buffer,
ServiceItem->DisplayName->Buffer
)->Buffer, NIIF_INFO);
}
}
}
if (ServiceTreeListLoaded)
PhDereferenceObject(ServiceItem);
}
VOID PhMwpOnServiceModified(
_In_ PPH_SERVICE_MODIFIED_DATA ServiceModifiedData
)
{
PH_SERVICE_CHANGE serviceChange;
UCHAR logEntryType;
if (ServiceTreeListLoaded)
{
//if (!ServicesNeedsRedraw)
//{
// TreeNew_SetRedraw(ServiceTreeListHandle, FALSE);
// ServicesNeedsRedraw = TRUE;
//}
PhUpdateServiceNode(PhFindServiceNode(ServiceModifiedData->Service));
if (DriverFilterEntry)
PhApplyTreeNewFilters(PhGetFilterSupportServiceTreeList());
}
serviceChange = PhGetServiceChange(ServiceModifiedData);
switch (serviceChange)
{
case ServiceStarted:
logEntryType = PH_LOG_ENTRY_SERVICE_START;
break;
case ServiceStopped:
logEntryType = PH_LOG_ENTRY_SERVICE_STOP;
break;
case ServiceContinued:
logEntryType = PH_LOG_ENTRY_SERVICE_CONTINUE;
break;
case ServicePaused:
logEntryType = PH_LOG_ENTRY_SERVICE_PAUSE;
break;
default:
logEntryType = 0;
break;
}
if (logEntryType != 0)
PhLogServiceEntry(logEntryType, ServiceModifiedData->Service->Name, ServiceModifiedData->Service->DisplayName);
if (NotifyIconNotifyMask & (PH_NOTIFY_SERVICE_START | PH_NOTIFY_SERVICE_STOP))
{
PPH_SERVICE_ITEM serviceItem;
serviceItem = ServiceModifiedData->Service;
if (serviceChange == ServiceStarted && (NotifyIconNotifyMask & PH_NOTIFY_SERVICE_START))
{
if (!PhPluginsEnabled || !PhMwpPluginNotifyEvent(PH_NOTIFY_SERVICE_START, serviceItem))
{
PhShowIconNotification(L"Service Started", PhaFormatString(
L"The service %s (%s) has been started.",
serviceItem->Name->Buffer,
serviceItem->DisplayName->Buffer
)->Buffer, NIIF_INFO);
}
}
else if (serviceChange == ServiceStopped && (NotifyIconNotifyMask & PH_NOTIFY_SERVICE_STOP))
{
if (!PhPluginsEnabled || !PhMwpPluginNotifyEvent(PH_NOTIFY_SERVICE_STOP, serviceItem))
{
PhShowIconNotification(L"Service Stopped", PhaFormatString(
L"The service %s (%s) has been stopped.",
serviceItem->Name->Buffer,
serviceItem->DisplayName->Buffer
)->Buffer, NIIF_INFO);
}
}
}
}
VOID PhMwpOnServiceRemoved(
_In_ PPH_SERVICE_ITEM ServiceItem
)
{
if (ServiceTreeListLoaded)
{
if (!ServicesNeedsRedraw)
{
TreeNew_SetRedraw(ServiceTreeListHandle, FALSE);
ServicesNeedsRedraw = TRUE;
}
}
PhLogServiceEntry(PH_LOG_ENTRY_SERVICE_DELETE, ServiceItem->Name, ServiceItem->DisplayName);
if (NotifyIconNotifyMask & PH_NOTIFY_SERVICE_CREATE)
{
if (!PhPluginsEnabled || !PhMwpPluginNotifyEvent(PH_NOTIFY_SERVICE_DELETE, ServiceItem))
{
PhShowIconNotification(L"Service Deleted", PhaFormatString(
L"The service %s (%s) has been deleted.",
ServiceItem->Name->Buffer,
ServiceItem->DisplayName->Buffer
)->Buffer, NIIF_INFO);
}
}
if (ServiceTreeListLoaded)
{
PhRemoveServiceNode(PhFindServiceNode(ServiceItem));
}
else
{
if (ServicesPendingList)
{
HANDLE pointerHandle;
// Remove the service from the pending list so we don't try to add it
// later.
if (pointerHandle = PhFindItemPointerList(ServicesPendingList, ServiceItem))
PhRemoveItemPointerList(ServicesPendingList, pointerHandle);
PhDereferenceObject(ServiceItem);
}
}
}
VOID PhMwpOnServicesUpdated(
VOID
)
{
if (ServiceTreeListLoaded)
{
PhTickServiceNodes();
if (ServicesNeedsRedraw)
{
TreeNew_SetRedraw(ServiceTreeListHandle, TRUE);
ServicesNeedsRedraw = FALSE;
}
}
}
VOID PhMwpNeedNetworkTreeList(
VOID
)
{
if (!NetworkTreeListLoaded)
{
NetworkTreeListLoaded = TRUE;
PhLoadSettingsNetworkTreeList();
}
}
BOOLEAN PhMwpCurrentUserNetworkTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
)
{
PPH_NETWORK_NODE networkNode = (PPH_NETWORK_NODE)Node;
PPH_PROCESS_NODE processNode;
processNode = PhFindProcessNode(networkNode->NetworkItem->ProcessId);
if (processNode)
return PhMwpCurrentUserProcessTreeFilter(&processNode->Node, NULL);
return TRUE;
}
BOOLEAN PhMwpSignedNetworkTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
)
{
PPH_NETWORK_NODE networkNode = (PPH_NETWORK_NODE)Node;
PPH_PROCESS_NODE processNode;
processNode = PhFindProcessNode(networkNode->NetworkItem->ProcessId);
if (processNode)
return PhMwpSignedProcessTreeFilter(&processNode->Node, NULL);
return TRUE;
}
VOID PhMwpInitializeNetworkMenu(
_In_ PPH_EMENU Menu,
_In_ PPH_NETWORK_ITEM *NetworkItems,
_In_ ULONG NumberOfNetworkItems
)
{
ULONG i;
PPH_EMENU_ITEM item;
if (NumberOfNetworkItems == 0)
{
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
else if (NumberOfNetworkItems == 1)
{
if (!NetworkItems[0]->ProcessId)
PhEnableEMenuItem(Menu, ID_NETWORK_GOTOPROCESS, FALSE);
}
else
{
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(Menu, ID_NETWORK_CLOSE, TRUE);
PhEnableEMenuItem(Menu, ID_NETWORK_COPY, TRUE);
}
if (WindowsVersion >= WINDOWS_VISTA)
{
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_NETWORK_VIEWSTACK))
PhDestroyEMenuItem(item);
}
// Close
if (NumberOfNetworkItems != 0)
{
BOOLEAN closeOk = TRUE;
for (i = 0; i < NumberOfNetworkItems; i++)
{
if (
NetworkItems[i]->ProtocolType != PH_TCP4_NETWORK_PROTOCOL ||
NetworkItems[i]->State != MIB_TCP_STATE_ESTAB
)
{
closeOk = FALSE;
break;
}
}
if (!closeOk)
PhEnableEMenuItem(Menu, ID_NETWORK_CLOSE, FALSE);
}
}
VOID PhShowNetworkContextMenu(
_In_ PPH_TREENEW_CONTEXT_MENU ContextMenu
)
{
PPH_NETWORK_ITEM *networkItems;
ULONG numberOfNetworkItems;
PhGetSelectedNetworkItems(&networkItems, &numberOfNetworkItems);
if (numberOfNetworkItems != 0)
{
PPH_EMENU menu;
PPH_EMENU_ITEM item;
menu = PhCreateEMenu();
PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_NETWORK), 0);
PhSetFlagsEMenuItem(menu, ID_NETWORK_GOTOPROCESS, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
PhMwpInitializeNetworkMenu(menu, networkItems, numberOfNetworkItems);
PhInsertCopyCellEMenuItem(menu, ID_NETWORK_COPY, NetworkTreeListHandle, ContextMenu->Column);
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.OwnerWindow = PhMainWndHandle;
menuInfo.u.Network.NetworkItems = networkItems;
menuInfo.u.Network.NumberOfNetworkItems = numberOfNetworkItems;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackNetworkMenuInitializing), &menuInfo);
}
item = PhShowEMenu(
menu,
PhMainWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
ContextMenu->Location.x,
ContextMenu->Location.y
);
if (item)
{
BOOLEAN handled = FALSE;
handled = PhHandleCopyCellEMenuItem(item);
if (!handled && PhPluginsEnabled)
handled = PhPluginTriggerEMenuItem(PhMainWndHandle, item);
if (!handled)
SendMessage(PhMainWndHandle, WM_COMMAND, item->Id, 0);
}
PhDestroyEMenu(menu);
}
PhFree(networkItems);
}
VOID PhMwpOnNetworkItemAdded(
_In_ ULONG RunId,
_In_ _Assume_refs_(1) PPH_NETWORK_ITEM NetworkItem
)
{
PPH_NETWORK_NODE networkNode;
if (!NetworkNeedsRedraw)
{
TreeNew_SetRedraw(NetworkTreeListHandle, FALSE);
NetworkNeedsRedraw = TRUE;
}
networkNode = PhAddNetworkNode(NetworkItem, RunId);
PhDereferenceObject(NetworkItem);
}
VOID PhMwpOnNetworkItemModified(
_In_ PPH_NETWORK_ITEM NetworkItem
)
{
PhUpdateNetworkNode(PhFindNetworkNode(NetworkItem));
}
VOID PhMwpOnNetworkItemRemoved(
_In_ PPH_NETWORK_ITEM NetworkItem
)
{
if (!NetworkNeedsRedraw)
{
TreeNew_SetRedraw(NetworkTreeListHandle, FALSE);
NetworkNeedsRedraw = TRUE;
}
PhRemoveNetworkNode(PhFindNetworkNode(NetworkItem));
}
VOID PhMwpOnNetworkItemsUpdated(
VOID
)
{
PhTickNetworkNodes();
if (NetworkNeedsRedraw)
{
TreeNew_SetRedraw(NetworkTreeListHandle, TRUE);
NetworkNeedsRedraw = FALSE;
}
}
VOID PhMwpUpdateUsersMenu(
VOID
)
{
HMENU menu;
PSESSIONIDW sessions;
ULONG numberOfSessions;
ULONG i;
ULONG j;
MENUITEMINFO menuItemInfo = { sizeof(MENUITEMINFO) };
menu = SubMenuHandles[3];
// Delete all items in the Users menu.
while (DeleteMenu(menu, 0, MF_BYPOSITION)) ;
if (WinStationEnumerateW(NULL, &sessions, &numberOfSessions))
{
for (i = 0; i < numberOfSessions; i++)
{
HMENU userMenu;
PPH_STRING menuText;
PPH_STRING escapedMenuText;
WINSTATIONINFORMATION winStationInfo;
ULONG returnLength;
ULONG numberOfItems;
if (!WinStationQueryInformationW(
NULL,
sessions[i].SessionId,
WinStationInformation,
&winStationInfo,
sizeof(WINSTATIONINFORMATION),
&returnLength
))
{
winStationInfo.Domain[0] = 0;
winStationInfo.UserName[0] = 0;
}
if (winStationInfo.Domain[0] == 0 || winStationInfo.UserName[0] == 0)
{
// Probably the Services or RDP-Tcp session.
continue;
}
menuText = PhFormatString(
L"%u: %s\\%s",
sessions[i].SessionId,
winStationInfo.Domain,
winStationInfo.UserName
);
escapedMenuText = PhEscapeStringForMenuPrefix(&menuText->sr);
PhDereferenceObject(menuText);
userMenu = GetSubMenu(LoadMenu(PhInstanceHandle, MAKEINTRESOURCE(IDR_USER)), 0);
AppendMenu(
menu,
MF_STRING | MF_POPUP,
(UINT_PTR)userMenu,
escapedMenuText->Buffer
);
PhDereferenceObject(escapedMenuText);
menuItemInfo.fMask = MIIM_DATA;
menuItemInfo.dwItemData = sessions[i].SessionId;
numberOfItems = GetMenuItemCount(userMenu);
if (numberOfItems != -1)
{
for (j = 0; j < numberOfItems; j++)
SetMenuItemInfo(userMenu, j, TRUE, &menuItemInfo);
}
}
WinStationFreeMemory(sessions);
}
DrawMenuBar(PhMainWndHandle);
}