Files
mirror-processhacker/2.x/trunk/ProcessHacker/mainwnd.c
T
wj32 4fce2ef5a6 * implemented tree list keyboard item search
* implemented tree list input handlers

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3038 21ef857c-d57f-4fe0-8362-d861dc6d29cd
2010-04-08 01:09:10 +00:00

2021 lines
62 KiB
C

/*
* Process Hacker -
* main window
*
* Copyright (C) 2009-2010 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 MAINWND_PRIVATE
#include <phapp.h>
#include <treelist.h>
#include <settings.h>
#include <wtsapi32.h>
typedef BOOL (WINAPI *_FileIconInit)(
__in BOOL RestoreCache
);
typedef BOOL (WINAPI *_WTSRegisterSessionNotification)(
__in HWND hWnd,
__in DWORD dwFlags
);
VOID PhMainWndOnCreate();
VOID PhMainWndOnLayout(HDWP *deferHandle);
VOID PhMainWndTabControlOnLayout(HDWP *deferHandle);
VOID PhMainWndTabControlOnNotify(
__in LPNMHDR Header
);
VOID PhMainWndTabControlOnSelectionChanged();
VOID PhMainWndProcessListViewOnNotify(
__in LPNMHDR Header
);
VOID PhMainWndServiceListViewOnNotify(
__in LPNMHDR Header
);
VOID PhReloadSysParameters();
VOID PhpSaveWindowState();
VOID PhpSaveAllSettings();
VOID PhpPrepareForEarlyShutdown();
VOID PhpCancelEarlyShutdown();
VOID PhpRefreshUsersMenu();
PPH_PROCESS_ITEM PhpGetSelectedProcess();
VOID PhpGetSelectedProcesses(
__out PPH_PROCESS_ITEM **Processes,
__out PULONG NumberOfProcesses
);
PPH_SERVICE_ITEM PhpGetSelectedService();
VOID PhpGetSelectedServices(
__out PPH_SERVICE_ITEM **Services,
__out PULONG NumberOfServices
);
VOID PhpShowProcessProperties(
__in PPH_PROCESS_ITEM ProcessItem
);
VOID PhMainWndOnProcessAdded(
__in __assumeRefs(1) PPH_PROCESS_ITEM ProcessItem
);
VOID PhMainWndOnProcessModified(
__in PPH_PROCESS_ITEM ProcessItem
);
VOID PhMainWndOnProcessRemoved(
__in PPH_PROCESS_ITEM ProcessItem
);
VOID PhMainWndOnServiceAdded(
__in ULONG RunId,
__in PPH_SERVICE_ITEM ServiceItem
);
VOID PhMainWndOnServiceModified(
__in PPH_SERVICE_MODIFIED_DATA ServiceModifiedData
);
VOID PhMainWndOnServiceRemoved(
__in PPH_SERVICE_ITEM ServiceItem
);
VOID PhMainWndOnServicesUpdated();
HWND PhMainWndHandle;
BOOLEAN PhMainWndExiting = FALSE;
static HWND TabControlHandle;
static INT ProcessesTabIndex;
static INT ServicesTabIndex;
static INT NetworkTabIndex;
static HWND ProcessTreeListHandle;
static HWND ServiceListViewHandle;
static HWND NetworkListViewHandle;
static PH_PROVIDER_REGISTRATION ProcessProviderRegistration;
static PH_CALLBACK_REGISTRATION ProcessAddedRegistration;
static PH_CALLBACK_REGISTRATION ProcessModifiedRegistration;
static PH_CALLBACK_REGISTRATION ProcessRemovedRegistration;
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 BOOLEAN SelectedRunAsAdmin;
static HWND SelectedProcessWindowHandle;
static BOOLEAN SelectedProcessVirtualizationEnabled;
static ULONG SelectedUserSessionId;
BOOLEAN PhMainWndInitialization(
__in INT ShowCommand
)
{
PH_RECTANGLE windowRectangle;
// Enable some privileges.
{
HANDLE tokenHandle;
if (NT_SUCCESS(PhOpenProcessToken(
&tokenHandle,
TOKEN_ADJUST_PRIVILEGES,
NtCurrentProcess()
)))
{
PhSetTokenPrivilege(tokenHandle, L"SeDebugPrivilege", NULL, SE_PRIVILEGE_ENABLED);
PhSetTokenPrivilege(tokenHandle, L"SeIncreaseBasePriorityPrivilege", NULL, SE_PRIVILEGE_ENABLED);
PhSetTokenPrivilege(tokenHandle, L"SeLoadDriverPrivilege", NULL, SE_PRIVILEGE_ENABLED);
PhSetTokenPrivilege(tokenHandle, L"SeRestorePrivilege", NULL, SE_PRIVILEGE_ENABLED);
PhSetTokenPrivilege(tokenHandle, L"SeShutdownPrivilege", NULL, SE_PRIVILEGE_ENABLED);
PhSetTokenPrivilege(tokenHandle, L"SeTakeOwnershipPrivilege", NULL, SE_PRIVILEGE_ENABLED);
NtClose(tokenHandle);
}
}
// Initialize the system image lists.
{
HMODULE shell32;
_FileIconInit fileIconInit;
shell32 = LoadLibrary(L"shell32.dll");
if (shell32)
{
fileIconInit = (_FileIconInit)GetProcAddress(shell32, (PSTR)660);
if (fileIconInit)
fileIconInit(FALSE);
}
}
// Initialize dbghelp.
{
PPH_STRING dbghelpPath;
HMODULE dbghelpModule;
// Try to set up the path automatically if this is the first run.
{
if (PhGetIntegerSetting(L"FirstRun"))
{
PPH_STRING autoDbghelpPath;
autoDbghelpPath = PHA_DEREFERENCE(PhGetKnownLocation(
CSIDL_PROGRAM_FILES,
#ifdef _M_IX86
L"\\Debugging Tools for Windows (x86)\\dbghelp.dll"
#else
L"\\Debugging Tools for Windows (x64)\\dbghelp.dll"
#endif
));
if (autoDbghelpPath)
{
if (PhFileExists(autoDbghelpPath->Buffer))
{
PhSetStringSetting2(L"DbgHelpPath", &autoDbghelpPath->sr);
}
}
}
}
dbghelpPath = PhGetStringSetting(L"DbgHelpPath");
if (dbghelpModule = LoadLibrary(dbghelpPath->Buffer))
{
PPH_STRING fullDbghelpPath;
ULONG indexOfFileName;
PPH_STRING dbghelpFolder;
PPH_STRING symsrvPath;
fullDbghelpPath = PhGetApplicationModuleFileName(dbghelpModule, &indexOfFileName);
if (fullDbghelpPath)
{
if (indexOfFileName != -1)
{
dbghelpFolder = PhSubstring(fullDbghelpPath, 0, indexOfFileName);
symsrvPath = PhConcatStrings2(dbghelpFolder->Buffer, L"\\symsrv.dll");
LoadLibrary(symsrvPath->Buffer);
PhDereferenceObject(symsrvPath);
PhDereferenceObject(dbghelpFolder);
}
PhDereferenceObject(fullDbghelpPath);
}
}
else
{
LoadLibrary(L"dbghelp.dll");
}
PhDereferenceObject(dbghelpPath);
PhSymbolProviderDynamicImport();
}
PhSetIntegerSetting(L"FirstRun", FALSE);
// Initialize the providers.
PhInitializeProviderThread(&PhPrimaryProviderThread, 1000);
PhInitializeProviderThread(&PhSecondaryProviderThread, 1000);
PhRegisterProvider(&PhPrimaryProviderThread, PhProcessProviderUpdate, NULL, &ProcessProviderRegistration);
PhSetProviderEnabled(&ProcessProviderRegistration, TRUE);
PhRegisterProvider(&PhPrimaryProviderThread, PhServiceProviderUpdate, NULL, &ServiceProviderRegistration);
PhSetProviderEnabled(&ServiceProviderRegistration, TRUE);
windowRectangle.Position = PhGetIntegerPairSetting(L"MainWindowPosition");
windowRectangle.Size = PhGetIntegerPairSetting(L"MainWindowSize");
PhMainWndHandle = CreateWindow(
PhWindowClassName,
PhApplicationName,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
windowRectangle.Left,
windowRectangle.Top,
windowRectangle.Width,
windowRectangle.Height,
NULL,
NULL,
PhInstanceHandle,
NULL
);
if (!PhMainWndHandle)
return FALSE;
// Choose a more appropriate rectangle for the window.
PhAdjustRectangleToWorkingArea(
PhMainWndHandle,
&windowRectangle
);
MoveWindow(PhMainWndHandle, windowRectangle.Left, windowRectangle.Top,
windowRectangle.Width, windowRectangle.Height, FALSE);
PhInitializeFont(PhMainWndHandle);
// Allow WM_PH_ACTIVATE to pass through UIPI.
if (WINDOWS_HAS_UAC)
ChangeWindowMessageFilter_I(WM_PH_ACTIVATE, MSGFLT_ADD);
PhReloadSysParameters();
// Initialize child controls.
PhMainWndOnCreate();
PhMainWndTabControlOnSelectionChanged();
// Perform a layout.
SendMessage(PhMainWndHandle, WM_SIZE, 0, 0);
PhStartProviderThread(&PhPrimaryProviderThread);
PhStartProviderThread(&PhSecondaryProviderThread);
UpdateWindow(PhMainWndHandle);
if (PhGetIntegerSetting(L"MainWindowState") == SW_MAXIMIZE)
{
ShowWindow(PhMainWndHandle, SW_SHOWMAXIMIZED);
}
else
{
ShowWindow(PhMainWndHandle, ShowCommand);
}
// Register for WTS notifications.
{
_WTSRegisterSessionNotification WTSRegisterSessionNotification_I;
WTSRegisterSessionNotification_I = (_WTSRegisterSessionNotification)GetProcAddress(
GetModuleHandle(L"wtsapi32.dll"),
"WTSRegisterSessionNotification"
);
if (WTSRegisterSessionNotification_I)
WTSRegisterSessionNotification_I(PhMainWndHandle, NOTIFY_FOR_ALL_SESSIONS);
}
PhpRefreshUsersMenu();
return TRUE;
}
LRESULT CALLBACK PhMainWndProc(
__in HWND hWnd,
__in UINT uMsg,
__in WPARAM wParam,
__in LPARAM lParam
)
{
switch (uMsg)
{
case WM_DESTROY:
{
if (!PhMainWndExiting)
PhpSaveAllSettings();
PostQuitMessage(0);
}
break;
case WM_SETTINGCHANGE:
{
PhReloadSysParameters();
}
break;
case WM_COMMAND:
{
INT id = LOWORD(wParam);
switch (id)
{
case ID_HACKER_RUN:
{
if (RunFileDlg)
{
SelectedRunAsAdmin = FALSE;
RunFileDlg(hWnd, NULL, NULL, NULL, NULL, 0);
}
}
break;
case ID_HACKER_RUNASADMINISTRATOR:
{
if (RunFileDlg)
{
SelectedRunAsAdmin = TRUE;
RunFileDlg(
hWnd,
NULL,
NULL,
NULL,
L"Type the name of a program that will be opened under alternate credentials.",
0
);
}
}
break;
case ID_HACKER_RUNAS:
{
PhShowRunAsDialog(hWnd, NULL);
}
break;
case ID_HACKER_SHOWDETAILSFORALLPROCESSES:
{
ProcessHacker_PrepareForEarlyShutdown(hWnd);
if (PhShellExecuteEx(hWnd, PhApplicationFileName->Buffer,
L"", SW_SHOW, PH_SHELL_EXECUTE_ADMIN, 0, NULL))
{
ProcessHacker_Destroy(hWnd);
}
else
{
ProcessHacker_CancelEarlyShutdown(hWnd);
}
}
break;
case ID_HACKER_SAVE:
{
static PH_FILETYPE_FILTER filters[] =
{
{ L"Text files (*.txt;*.log)", L"*.txt;*.log" },
{ L"All files (*.*)", L"*.*" }
};
PVOID saveFileDialog = PhCreateSaveFileDialog();
PhSetFileDialogFilter(saveFileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));
if (PhShowFileDialog(hWnd, saveFileDialog))
{
PPH_STRING fileName;
fileName = PhGetFileDialogFileName(saveFileDialog);
PhShowMessage(
hWnd,
MB_ICONINFORMATION,
L"You selected:\n\n%s",
fileName->Buffer
);
PhDereferenceObject(fileName);
}
PhFreeFileDialog(saveFileDialog);
}
break;
case ID_HACKER_FINDHANDLESORDLLS:
{
PhShowFindObjectsDialog();
}
break;
case ID_HACKER_EXIT:
ProcessHacker_Destroy(hWnd);
break;
case ID_VIEW_REFRESH:
{
PhBoostProvider(&ProcessProviderRegistration, NULL);
PhBoostProvider(&ServiceProviderRegistration, NULL);
}
break;
case ID_TOOLS_HIDDENPROCESSES:
{
PhShowHiddenProcessesDialog();
}
break;
case ID_TOOLS_PAGEFILES:
{
PhShowPagefilesDialog(hWnd);
}
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(hWnd, fileDialog))
{
PPH_STRING fileName;
VERIFY_RESULT result;
PPH_STRING signerName;
fileName = PhGetFileDialogFileName(fileDialog);
result = PhVerifyFile(fileName->Buffer, &signerName);
if (result == VrTrusted)
{
PhShowInformation(hWnd, L"\"%s\" is trusted and signed by \"%s\".",
fileName->Buffer, signerName->Buffer);
}
else if (result == VrNoSignature)
{
PhShowInformation(hWnd, L"\"%s\" does not have a digital signature.",
fileName->Buffer);
}
else
{
PhShowInformation(hWnd, L"\"%s\" is not trusted.",
fileName->Buffer);
}
if (signerName)
PhDereferenceObject(signerName);
PhDereferenceObject(fileName);
}
PhFreeFileDialog(fileDialog);
}
break;
case ID_USER_DISCONNECT:
{
if (!WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE, SelectedUserSessionId, FALSE))
PhShowStatus(hWnd, L"Unable to disconnect the session", 0, GetLastError());
}
break;
case ID_USER_LOGOFF:
{
if (PhShowConfirmMessage(
hWnd,
L"logoff",
L"the user",
NULL,
FALSE
))
{
if (!WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, SelectedUserSessionId, FALSE))
PhShowStatus(hWnd, L"Unable to logoff the session", 0, GetLastError());
}
}
break;
case ID_USER_SENDMESSAGE:
{
PhShowSessionSendMessageDialog(hWnd, SelectedUserSessionId);
}
break;
case ID_USER_PROPERTIES:
{
PhShowSessionProperties(hWnd, SelectedUserSessionId);
}
break;
case ID_HELP_DEBUGCONSOLE:
{
PhShowDebugConsole();
}
break;
case ID_HELP_ABOUT:
{
PhShowAboutDialog(hWnd);
}
break;
case ID_PROCESS_TERMINATE:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhpGetSelectedProcesses(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
PhUiTerminateProcesses(hWnd, processes, numberOfProcesses);
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_PROCESS_SUSPEND:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhpGetSelectedProcesses(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
PhUiSuspendProcesses(hWnd, processes, numberOfProcesses);
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_PROCESS_RESUME:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhpGetSelectedProcesses(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
PhUiResumeProcesses(hWnd, processes, numberOfProcesses);
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_PROCESS_RESTART:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhReferenceObject(processItem);
PhUiRestartProcess(hWnd, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_REDUCEWORKINGSET:
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhpGetSelectedProcesses(&processes, &numberOfProcesses);
PhReferenceObjects(processes, numberOfProcesses);
PhUiReduceWorkingSetProcesses(hWnd, processes, numberOfProcesses);
PhDereferenceObjects(processes, numberOfProcesses);
PhFree(processes);
}
break;
case ID_PROCESS_VIRTUALIZATION:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhReferenceObject(processItem);
PhUiSetVirtualizationProcess(
hWnd,
processItem,
!SelectedProcessVirtualizationEnabled
);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_AFFINITY:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhReferenceObject(processItem);
PhShowProcessAffinityDialog(hWnd, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_CREATEDUMPFILE:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhReferenceObject(processItem);
PhUiCreateDumpFileProcess(hWnd, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_TERMINATOR:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
// The object relies on the list view reference, which could
// disappear if we don't reference the object here.
PhReferenceObject(processItem);
PhShowProcessTerminatorDialog(hWnd, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_DETACHFROMDEBUGGER:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhReferenceObject(processItem);
PhUiDetachFromDebuggerProcess(hWnd, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_HEAPS:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhReferenceObject(processItem);
PhShowProcessHeapsDialog(hWnd, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_MISCELLANEOUS_INJECTDLL:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhReferenceObject(processItem);
PhUiInjectDllProcess(hWnd, processItem);
PhDereferenceObject(processItem);
}
}
break;
case ID_I_0:
case ID_I_1:
case ID_I_2:
case ID_I_3:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
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(hWnd, processItem, ioPriority);
PhDereferenceObject(processItem);
}
}
break;
case ID_PROCESS_PROPERTIES:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
// No reference needed; no messages pumped.
PhpShowProcessProperties(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 = PhpGetSelectedProcess();
if (processItem)
{
ULONG priorityClassWin32;
switch (id)
{
case ID_PRIORITY_REALTIME:
priorityClassWin32 = REALTIME_PRIORITY_CLASS;
break;
case ID_PRIORITY_HIGH:
priorityClassWin32 = HIGH_PRIORITY_CLASS;
break;
case ID_PRIORITY_ABOVENORMAL:
priorityClassWin32 = ABOVE_NORMAL_PRIORITY_CLASS;
break;
case ID_PRIORITY_NORMAL:
priorityClassWin32 = NORMAL_PRIORITY_CLASS;
break;
case ID_PRIORITY_BELOWNORMAL:
priorityClassWin32 = BELOW_NORMAL_PRIORITY_CLASS;
break;
case ID_PRIORITY_IDLE:
priorityClassWin32 = IDLE_PRIORITY_CLASS;
break;
}
PhReferenceObject(processItem);
PhUiSetPriorityProcess(hWnd, processItem, priorityClassWin32);
PhDereferenceObject(processItem);
}
}
break;
case ID_WINDOW_BRINGTOFRONT:
{
if (IsWindow(SelectedProcessWindowHandle))
{
WINDOWPLACEMENT placement = { sizeof(placement) };
GetWindowPlacement(SelectedProcessWindowHandle, &placement);
if (placement.showCmd == SW_MINIMIZE)
ShowWindow(SelectedProcessWindowHandle, SW_RESTORE);
else
SetForegroundWindow(SelectedProcessWindowHandle);
}
}
break;
case ID_WINDOW_RESTORE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
ShowWindow(SelectedProcessWindowHandle, SW_RESTORE);
}
}
break;
case ID_WINDOW_MINIMIZE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
ShowWindow(SelectedProcessWindowHandle, SW_MINIMIZE);
}
}
break;
case ID_WINDOW_MAXIMIZE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
ShowWindow(SelectedProcessWindowHandle, SW_MAXIMIZE);
}
}
break;
case ID_WINDOW_CLOSE:
{
if (IsWindow(SelectedProcessWindowHandle))
{
PostMessage(SelectedProcessWindowHandle, WM_CLOSE, 0, 0);
}
}
break;
case ID_PROCESS_SEARCHONLINE:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
if (processItem)
{
PhSearchOnlineString(hWnd, processItem->ProcessName->Buffer);
}
}
break;
case ID_SERVICE_START:
{
PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiStartService(hWnd, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_CONTINUE:
{
PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiContinueService(hWnd, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_PAUSE:
{
PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiPauseService(hWnd, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_STOP:
{
PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiStopService(hWnd, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_DELETE:
{
PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
if (serviceItem)
{
PhReferenceObject(serviceItem);
PhUiDeleteService(hWnd, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
case ID_SERVICE_PROPERTIES:
{
PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
if (serviceItem)
{
// The object relies on the list view reference, which could
// disappear if we don't reference the object here.
PhReferenceObject(serviceItem);
PhShowServiceProperties(hWnd, serviceItem);
PhDereferenceObject(serviceItem);
}
}
break;
}
}
break;
case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_MINIMIZE:
{
// Save the current window state because we
// may not have a chance to later.
PhpSaveWindowState();
}
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
case WM_MENUSELECT:
{
switch (LOWORD(wParam))
{
case ID_USER_DISCONNECT:
case ID_USER_LOGOFF:
case ID_USER_SENDMESSAGE:
case ID_USER_PROPERTIES:
{
MENUITEMINFO menuItemInfo = { sizeof(menuItemInfo) };
menuItemInfo.fMask = MIIM_DATA;
if (GetMenuItemInfo((HMENU)lParam, LOWORD(wParam), FALSE, &menuItemInfo))
{
SelectedUserSessionId = (ULONG)menuItemInfo.dwItemData;
}
}
break;
}
}
break;
case WM_SIZE:
{
if (!IsIconic(hWnd))
{
HDWP deferHandle = BeginDeferWindowPos(2);
PhMainWndOnLayout(&deferHandle);
EndDeferWindowPos(deferHandle);
}
}
break;
case WM_SIZING:
{
PhResizingMinimumSize((PRECT)lParam, wParam, 400, 340);
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
if (header->hwndFrom == TabControlHandle)
{
PhMainWndTabControlOnNotify(header);
}
else if (header->hwndFrom == ServiceListViewHandle)
{
PhMainWndServiceListViewOnNotify(header);
}
else if (header->code == RFN_VALIDATE && SelectedRunAsAdmin)
{
LPNMRUNFILEDLG runFileDlg = (LPNMRUNFILEDLG)header;
if (PhShellExecuteEx(hWnd, (PWSTR)runFileDlg->lpszFile,
NULL, runFileDlg->nShow, PH_SHELL_EXECUTE_ADMIN, 0, NULL))
{
return RF_CANCEL;
}
else
{
return RF_RETRY;
}
}
}
break;
case WM_WTSSESSION_CHANGE:
{
if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_LOGOFF)
{
PhpRefreshUsersMenu();
}
}
break;
case WM_PH_ACTIVATE:
{
if (!PhMainWndExiting)
{
if (IsIconic(hWnd))
{
ShowWindow(hWnd, SW_RESTORE);
}
return PH_ACTIVATE_REPLY;
}
else
{
return 0;
}
}
break;
case WM_PH_SHOW_PROCESS_PROPERTIES:
{
PhpShowProcessProperties((PPH_PROCESS_ITEM)lParam);
}
break;
case WM_PH_DESTROY:
{
DestroyWindow(hWnd);
}
break;
case WM_PH_SAVE_ALL_SETTINGS:
{
PhpSaveAllSettings();
}
break;
case WM_PH_PREPARE_FOR_EARLY_SHUTDOWN:
{
PhpPrepareForEarlyShutdown();
}
break;
case WM_PH_CANCEL_EARLY_SHUTDOWN:
{
PhpCancelEarlyShutdown();
}
break;
case WM_PH_PROCESS_ADDED:
{
PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)lParam;
PhMainWndOnProcessAdded(processItem);
}
break;
case WM_PH_PROCESS_MODIFIED:
{
PhMainWndOnProcessModified((PPH_PROCESS_ITEM)lParam);
}
break;
case WM_PH_PROCESS_REMOVED:
{
PhMainWndOnProcessRemoved((PPH_PROCESS_ITEM)lParam);
}
break;
case WM_PH_SERVICE_ADDED:
{
ULONG runId = (ULONG)wParam;
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)lParam;
PhMainWndOnServiceAdded(runId, serviceItem);
PhDereferenceObject(serviceItem);
}
break;
case WM_PH_SERVICE_MODIFIED:
{
PPH_SERVICE_MODIFIED_DATA serviceModifiedData = (PPH_SERVICE_MODIFIED_DATA)lParam;
PhMainWndOnServiceModified(serviceModifiedData);
PhFree(serviceModifiedData);
}
break;
case WM_PH_SERVICE_REMOVED:
{
PhMainWndOnServiceRemoved((PPH_SERVICE_ITEM)lParam);
}
break;
case WM_PH_SERVICES_UPDATED:
{
PhMainWndOnServicesUpdated();
}
break;
}
REFLECT_MESSAGE(ServiceListViewHandle, uMsg, wParam, lParam);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
VOID PhpReloadListViewFont()
{
HFONT fontHandle;
LOGFONT font;
if (ServiceListViewHandle && (fontHandle = (HFONT)SendMessage(ServiceListViewHandle, WM_GETFONT, 0, 0)))
{
if (GetObject(fontHandle, sizeof(LOGFONT), &font))
{
font.lfWeight = FW_BOLD;
fontHandle = CreateFontIndirect(&font);
if (fontHandle)
{
if (PhBoldListViewFont)
DeleteObject(PhBoldListViewFont);
PhBoldListViewFont = fontHandle;
}
}
}
}
VOID PhReloadSysParameters()
{
PhSysWindowColor = GetSysColor(COLOR_WINDOW);
DeleteObject(PhApplicationFont);
DeleteObject(PhBoldMessageFont);
PhInitializeFont(PhMainWndHandle);
SendMessage(TabControlHandle, WM_SETFONT, (WPARAM)PhApplicationFont, FALSE);
PhpReloadListViewFont();
}
VOID PhpSaveWindowState()
{
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 PhpSaveAllSettings()
{
WINDOWPLACEMENT placement = { sizeof(placement) };
PH_RECTANGLE windowRectangle;
GetWindowPlacement(PhMainWndHandle, &placement);
windowRectangle = PhRectToRectangle(placement.rcNormalPosition);
PhSetIntegerPairSetting(L"MainWindowPosition", windowRectangle.Position);
PhSetIntegerPairSetting(L"MainWindowSize", windowRectangle.Size);
PhpSaveWindowState();
if (PhSettingsFileName)
PhSaveSettings(PhSettingsFileName->Buffer);
}
VOID PhpPrepareForEarlyShutdown()
{
PhpSaveAllSettings();
PhMainWndExiting = TRUE;
}
VOID PhpCancelEarlyShutdown()
{
PhMainWndExiting = FALSE;
}
VOID PhpRefreshUsersMenu()
{
HMENU menu;
PWTS_SESSION_INFO sessions;
ULONG numberOfSessions;
ULONG i;
ULONG j;
MENUITEMINFO menuItemInfo = { sizeof(MENUITEMINFO) };
menu = GetMenu(PhMainWndHandle);
menu = GetSubMenu(menu, 3);
// Delete all items in the Users menu.
while (DeleteMenu(menu, 0, MF_BYPOSITION)) ;
if (WTSEnumerateSessions(
WTS_CURRENT_SERVER_HANDLE,
0,
1,
&sessions,
&numberOfSessions
))
{
for (i = 0; i < numberOfSessions; i++)
{
HMENU userMenu;
PPH_STRING domainName;
PPH_STRING userName;
PPH_STRING menuText;
ULONG numberOfItems;
domainName = PHA_DEREFERENCE(PhGetSessionInformationString(
WTS_CURRENT_SERVER_HANDLE,
sessions[i].SessionId,
WTSDomainName
));
userName = PHA_DEREFERENCE(PhGetSessionInformationString(
WTS_CURRENT_SERVER_HANDLE,
sessions[i].SessionId,
WTSUserName
));
if (PhIsStringNullOrEmpty(domainName) || PhIsStringNullOrEmpty(userName))
{
// Probably the Services or RDP-Tcp session.
continue;
}
menuText = PhaFormatString(
L"%u: %s\\%s",
sessions[i].SessionId,
domainName->Buffer,
userName->Buffer
);
userMenu = GetSubMenu(LoadMenu(PhInstanceHandle, MAKEINTRESOURCE(IDR_USER)), 0);
AppendMenu(
menu,
MF_STRING | MF_POPUP,
(UINT_PTR)userMenu,
menuText->Buffer
);
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);
}
}
WTSFreeMemory(sessions);
}
DrawMenuBar(PhMainWndHandle);
}
PPH_PROCESS_ITEM PhpGetSelectedProcess()
{
return PhGetSelectedProcessItem();
}
VOID PhpGetSelectedProcesses(
__out PPH_PROCESS_ITEM **Processes,
__out PULONG NumberOfProcesses
)
{
PhGetSelectedProcessItems(Processes, NumberOfProcesses);
}
VOID PhpShowProcessProperties(
__in PPH_PROCESS_ITEM ProcessItem
)
{
PPH_PROCESS_PROPCONTEXT propContext;
propContext = PhCreateProcessPropContext(
PhMainWndHandle,
ProcessItem
);
if (propContext)
{
PhShowProcessProperties(propContext);
PhDereferenceObject(propContext);
}
}
PPH_SERVICE_ITEM PhpGetSelectedService()
{
return PhGetSelectedListViewItemParam(
ServiceListViewHandle
);
}
VOID PhpGetSelectedServices(
__out PPH_SERVICE_ITEM **Services,
__out PULONG NumberOfServices
)
{
PhGetSelectedListViewItemParams(
ServiceListViewHandle,
Services,
NumberOfServices
);
}
static VOID NTAPI ProcessAddedHandler(
__in PVOID Parameter,
__in 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, 0, (LPARAM)processItem);
}
static VOID NTAPI ProcessModifiedHandler(
__in PVOID Parameter,
__in PVOID Context
)
{
PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)Parameter;
PostMessage(PhMainWndHandle, WM_PH_PROCESS_MODIFIED, 0, (LPARAM)processItem);
}
static VOID NTAPI ProcessRemovedHandler(
__in PVOID Parameter,
__in 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);
}
static VOID NTAPI ServiceAddedHandler(
__in PVOID Parameter,
__in PVOID Context
)
{
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)Parameter;
PhReferenceObject(serviceItem);
PostMessage(
PhMainWndHandle,
WM_PH_SERVICE_ADDED,
PhGetProviderRunId(&ServiceProviderRegistration),
(LPARAM)serviceItem
);
}
static VOID NTAPI ServiceModifiedHandler(
__in PVOID Parameter,
__in 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);
}
static VOID NTAPI ServiceRemovedHandler(
__in PVOID Parameter,
__in PVOID Context
)
{
PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)Parameter;
PostMessage(PhMainWndHandle, WM_PH_SERVICE_REMOVED, 0, (LPARAM)serviceItem);
}
static VOID NTAPI ServicesUpdatedHandler(
__in PVOID Parameter,
__in PVOID Context
)
{
PostMessage(PhMainWndHandle, WM_PH_SERVICES_UPDATED, 0, 0);
}
VOID PhMainWndOnCreate()
{
TabControlHandle = PhCreateTabControl(PhMainWndHandle);
BringWindowToTop(TabControlHandle);
ProcessesTabIndex = PhAddTabControlTab(TabControlHandle, 0, L"Processes");
ServicesTabIndex = PhAddTabControlTab(TabControlHandle, 1, L"Services");
NetworkTabIndex = PhAddTabControlTab(TabControlHandle, 2, L"Network");
ProcessTreeListHandle = PhCreateTreeListControl(PhMainWndHandle, ID_MAINWND_PROCESSTL);
BringWindowToTop(ProcessTreeListHandle);
ServiceListViewHandle = PhCreateListViewControl(PhMainWndHandle, ID_MAINWND_SERVICELV);
PhSetListViewStyle(ServiceListViewHandle, TRUE, TRUE);
BringWindowToTop(ServiceListViewHandle);
PhpReloadListViewFont();
NetworkListViewHandle = PhCreateListViewControl(PhMainWndHandle, ID_MAINWND_NETWORKLV);
PhSetListViewStyle(NetworkListViewHandle, TRUE, TRUE);
BringWindowToTop(NetworkListViewHandle);
PhSetControlTheme(ServiceListViewHandle, L"explorer");
PhSetControlTheme(NetworkListViewHandle, L"explorer");
PhAddListViewColumn(ServiceListViewHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Name");
PhAddListViewColumn(ServiceListViewHandle, 1, 1, 1, LVCFMT_LEFT, 140, L"Display Name");
PhAddListViewColumn(ServiceListViewHandle, 2, 2, 2, LVCFMT_LEFT, 50, L"PID");
PhAddListViewColumn(NetworkListViewHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Process Name");
PhProcessTreeListInitialization();
PhInitializeProcessTreeList(ProcessTreeListHandle);
PhSetExtendedListView(ServiceListViewHandle);
ExtendedListView_SetStateHighlighting(ServiceListViewHandle, TRUE);
PhRegisterCallback(
&PhProcessAddedEvent,
ProcessAddedHandler,
NULL,
&ProcessAddedRegistration
);
PhRegisterCallback(
&PhProcessModifiedEvent,
ProcessModifiedHandler,
NULL,
&ProcessModifiedRegistration
);
PhRegisterCallback(
&PhProcessRemovedEvent,
ProcessRemovedHandler,
NULL,
&ProcessRemovedRegistration
);
PhRegisterCallback(
&PhServiceAddedEvent,
ServiceAddedHandler,
NULL,
&ServiceAddedRegistration
);
PhRegisterCallback(
&PhServiceModifiedEvent,
ServiceModifiedHandler,
NULL,
&ServiceModifiedRegistration
);
PhRegisterCallback(
&PhServiceRemovedEvent,
ServiceRemovedHandler,
NULL,
&ServiceRemovedRegistration
);
PhRegisterCallback(
&PhServicesUpdatedEvent,
ServicesUpdatedHandler,
NULL,
&ServicesUpdatedRegistration
);
}
VOID PhMainWndOnLayout(HDWP *deferHandle)
{
RECT rect;
// Resize the tab control.
GetClientRect(PhMainWndHandle, &rect);
// Don't defer the resize. The tab control doesn't repaint properly.
SetWindowPos(TabControlHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
UpdateWindow(TabControlHandle);
PhMainWndTabControlOnLayout(deferHandle);
}
VOID PhMainWndTabControlOnLayout(HDWP *deferHandle)
{
RECT rect;
INT selectedIndex;
GetClientRect(PhMainWndHandle, &rect);
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, ServiceListViewHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
else if (selectedIndex == NetworkTabIndex)
{
*deferHandle = DeferWindowPos(*deferHandle, NetworkListViewHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
}
VOID PhMainWndTabControlOnNotify(
__in LPNMHDR Header
)
{
if (Header->code == TCN_SELCHANGE)
{
PhMainWndTabControlOnSelectionChanged();
}
}
VOID PhMainWndTabControlOnSelectionChanged()
{
INT selectedIndex;
selectedIndex = TabCtrl_GetCurSel(TabControlHandle);
{
HDWP deferHandle = BeginDeferWindowPos(1);
PhMainWndTabControlOnLayout(&deferHandle);
EndDeferWindowPos(deferHandle);
}
ShowWindow(ProcessTreeListHandle, selectedIndex == ProcessesTabIndex ? SW_SHOW : SW_HIDE);
ShowWindow(ServiceListViewHandle, selectedIndex == ServicesTabIndex ? SW_SHOW : SW_HIDE);
ShowWindow(NetworkListViewHandle, selectedIndex == NetworkTabIndex ? SW_SHOW : SW_HIDE);
}
BOOL CALLBACK PhpEnumProcessWindowsProc(
__in HWND hwnd,
__in LPARAM lParam
)
{
ULONG processId;
if (!IsWindowVisible(hwnd))
return TRUE;
GetWindowThreadProcessId(hwnd, &processId);
if (processId == (ULONG)lParam)
{
SelectedProcessWindowHandle = hwnd;
return FALSE;
}
return TRUE;
}
VOID PhpInitializeProcessMenu(
__in HMENU Menu,
__in PPH_PROCESS_ITEM *Processes,
__in ULONG NumberOfProcesses
)
{
#define MISCELLANEOUS_MENU_INDEX 11
#define WINDOW_MENU_INDEX 13
if (NumberOfProcesses == 0)
{
PhEnableAllMenuItems(Menu, FALSE);
}
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 (
Processes[0]->ProcessId == DPCS_PROCESS_ID ||
Processes[0]->ProcessId == INTERRUPTS_PROCESS_ID
)
{
PhEnableAllMenuItems(Menu, FALSE);
EnableMenuItem(Menu, ID_PROCESS_PROPERTIES, MF_ENABLED);
EnableMenuItem(Menu, ID_PROCESS_SEARCHONLINE, MF_ENABLED);
}
}
else
{
ULONG menuItemsMultiEnabled[] =
{
ID_PROCESS_TERMINATE,
ID_PROCESS_TERMINATETREE,
ID_PROCESS_SUSPEND,
ID_PROCESS_RESUME,
ID_PROCESS_REDUCEWORKINGSET
};
ULONG i;
PhEnableAllMenuItems(Menu, FALSE);
// These menu items are capable of manipulating
// multiple processes.
for (i = 0; i < sizeof(menuItemsMultiEnabled) / sizeof(ULONG); i++)
{
EnableMenuItem(Menu, menuItemsMultiEnabled[i], MF_ENABLED);
}
}
// Remove irrelevant menu items.
if (WindowsVersion < WINDOWS_VISTA)
{
HMENU miscMenu;
// Remove I/O priority.
miscMenu = GetSubMenu(Menu, MISCELLANEOUS_MENU_INDEX);
DeleteMenu(miscMenu, 3, MF_BYPOSITION);
}
// 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)
{
EnableMenuItem(Menu, ID_PROCESS_VIRTUALIZATION, MF_DISABLED | MF_GRAYED);
}
else
{
CheckMenuItem(Menu, ID_PROCESS_VIRTUALIZATION, enabled ? MF_CHECKED : MF_UNCHECKED);
}
}
// Priority
if (NumberOfProcesses == 1)
{
HANDLE processHandle;
ULONG priorityClass = 0;
ULONG ioPriority = -1;
ULONG id = 0;
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
ProcessQueryAccess,
Processes[0]->ProcessId
)))
{
priorityClass = GetPriorityClass(processHandle);
if (WindowsVersion >= WINDOWS_VISTA)
{
if (!NT_SUCCESS(PhGetProcessIoPriority(
processHandle,
&ioPriority
)))
{
ioPriority = -1;
}
}
NtClose(processHandle);
}
switch (priorityClass)
{
case REALTIME_PRIORITY_CLASS:
id = ID_PRIORITY_REALTIME;
break;
case HIGH_PRIORITY_CLASS:
id = ID_PRIORITY_HIGH;
break;
case ABOVE_NORMAL_PRIORITY_CLASS:
id = ID_PRIORITY_ABOVENORMAL;
break;
case NORMAL_PRIORITY_CLASS:
id = ID_PRIORITY_NORMAL;
break;
case BELOW_NORMAL_PRIORITY_CLASS:
id = ID_PRIORITY_BELOWNORMAL;
break;
case IDLE_PRIORITY_CLASS:
id = ID_PRIORITY_IDLE;
break;
}
if (id != 0)
{
CheckMenuItem(Menu, id, MF_CHECKED);
PhSetRadioCheckMenuItem(Menu, id, TRUE);
}
if (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)
{
CheckMenuItem(Menu, id, MF_CHECKED);
PhSetRadioCheckMenuItem(Menu, id, TRUE);
}
}
}
// Window menu
if (NumberOfProcesses == 1)
{
WINDOWPLACEMENT placement = { sizeof(placement) };
// Get a handle to the process' top-level window (if any).
SelectedProcessWindowHandle = NULL;
EnumWindows(PhpEnumProcessWindowsProc, (ULONG)Processes[0]->ProcessId);
if (SelectedProcessWindowHandle)
{
EnableMenuItem(Menu, WINDOW_MENU_INDEX, MF_ENABLED | MF_BYPOSITION);
}
else
{
EnableMenuItem(Menu, WINDOW_MENU_INDEX, MF_DISABLED | MF_GRAYED | MF_BYPOSITION);
}
GetWindowPlacement(SelectedProcessWindowHandle, &placement);
PhEnableAllMenuItems(GetSubMenu(Menu, WINDOW_MENU_INDEX), TRUE);
if (placement.showCmd == SW_MINIMIZE)
EnableMenuItem(Menu, ID_WINDOW_MINIMIZE, MF_DISABLED | MF_GRAYED);
else if (placement.showCmd == SW_MAXIMIZE)
EnableMenuItem(Menu, ID_WINDOW_MAXIMIZE, MF_DISABLED | MF_GRAYED);
else if (placement.showCmd == SW_NORMAL)
EnableMenuItem(Menu, ID_WINDOW_RESTORE, MF_DISABLED | MF_GRAYED);
}
else
{
EnableMenuItem(Menu, WINDOW_MENU_INDEX, MF_DISABLED | MF_GRAYED | MF_BYPOSITION);
}
// Remove irrelevant menu items (continued)
if (!WINDOWS_HAS_UAC)
{
DeleteMenu(Menu, ID_PROCESS_VIRTUALIZATION, 0);
}
}
VOID PhShowProcessContextMenu(
__in POINT Location
)
{
PPH_PROCESS_ITEM *processes;
ULONG numberOfProcesses;
PhpGetSelectedProcesses(&processes, &numberOfProcesses);
if (numberOfProcesses != 0)
{
HMENU menu;
HMENU subMenu;
menu = LoadMenu(PhInstanceHandle, MAKEINTRESOURCE(IDR_PROCESS));
subMenu = GetSubMenu(menu, 0);
SetMenuDefaultItem(subMenu, ID_PROCESS_PROPERTIES, FALSE);
PhpInitializeProcessMenu(subMenu, processes, numberOfProcesses);
PhShowContextMenu(
PhMainWndHandle,
ProcessTreeListHandle,
subMenu,
Location
);
DestroyMenu(menu);
}
PhFree(processes);
}
VOID PhpInitializeServiceMenu(
__in HMENU Menu,
__in PPH_SERVICE_ITEM *Services,
__in ULONG NumberOfServices
)
{
if (NumberOfServices == 0)
{
PhEnableAllMenuItems(Menu, FALSE);
}
else if (NumberOfServices == 1)
{
// Nothing
}
else
{
// None of the menu items work with multiple items.
PhEnableAllMenuItems(Menu, FALSE);
}
if (NumberOfServices == 1)
{
switch (Services[0]->State)
{
case SERVICE_RUNNING:
{
PhEnableMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_STOP);
}
break;
case SERVICE_PAUSED:
{
PhEnableMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_STOP);
}
break;
case SERVICE_STOPPED:
{
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP, FALSE);
}
break;
case SERVICE_START_PENDING:
case SERVICE_CONTINUE_PENDING:
case SERVICE_PAUSE_PENDING:
case SERVICE_STOP_PENDING:
{
PhEnableMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP, FALSE);
}
break;
}
if (!(Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE))
{
DeleteMenu(Menu, ID_SERVICE_CONTINUE, 0);
DeleteMenu(Menu, ID_SERVICE_PAUSE, 0);
}
}
}
VOID PhMainWndServiceListViewOnNotify(
__in LPNMHDR Header
)
{
switch (Header->code)
{
case NM_DBLCLK:
{
SendMessage(PhMainWndHandle, WM_COMMAND, ID_SERVICE_PROPERTIES, 0);
}
break;
case NM_RCLICK:
{
LPNMITEMACTIVATE itemActivate = (LPNMITEMACTIVATE)Header;
PPH_SERVICE_ITEM *services;
ULONG numberOfServices;
PhpGetSelectedServices(&services, &numberOfServices);
if (numberOfServices != 0)
{
HMENU menu;
HMENU subMenu;
menu = LoadMenu(PhInstanceHandle, MAKEINTRESOURCE(IDR_SERVICE));
subMenu = GetSubMenu(menu, 0);
SetMenuDefaultItem(subMenu, ID_SERVICE_PROPERTIES, FALSE);
PhpInitializeServiceMenu(subMenu, services, numberOfServices);
PhShowContextMenu(
PhMainWndHandle,
ServiceListViewHandle,
subMenu,
itemActivate->ptAction
);
DestroyMenu(menu);
}
PhFree(services);
}
break;
case LVN_KEYDOWN:
{
LPNMLVKEYDOWN keyDown = (LPNMLVKEYDOWN)Header;
switch (keyDown->wVKey)
{
case VK_DELETE:
SendMessage(PhMainWndHandle, WM_COMMAND, ID_SERVICE_DELETE, 0);
break;
case VK_RETURN:
SendMessage(PhMainWndHandle, WM_COMMAND, ID_SERVICE_PROPERTIES, 0);
break;
}
}
break;
}
}
VOID PhMainWndOnProcessAdded(
__in __assumeRefs(1) PPH_PROCESS_ITEM ProcessItem
)
{
PhCreateProcessNode(ProcessItem);
}
VOID PhMainWndOnProcessModified(
__in PPH_PROCESS_ITEM ProcessItem
)
{
PhUpdateProcessNode(PhFindProcessNode(ProcessItem->ProcessId));
}
VOID PhMainWndOnProcessRemoved(
__in PPH_PROCESS_ITEM ProcessItem
)
{
PhRemoveProcessNode(PhFindProcessNode(ProcessItem->ProcessId));
// Remove the reference for the process item being displayed.
PhDereferenceObject(ProcessItem);
}
VOID PhMainWndOnServiceAdded(
__in ULONG RunId,
__in PPH_SERVICE_ITEM ServiceItem
)
{
INT lvItemIndex;
// Add a reference for the pointer being stored in the list view item.
PhReferenceObject(ServiceItem);
if (RunId == 1) ExtendedListView_SetStateHighlighting(ServiceListViewHandle, FALSE);
lvItemIndex = PhAddListViewItem(
ServiceListViewHandle,
MAXINT,
ServiceItem->Name->Buffer,
ServiceItem
);
if (RunId == 1) ExtendedListView_SetStateHighlighting(ServiceListViewHandle, TRUE);
PhSetListViewSubItem(ServiceListViewHandle, lvItemIndex, 1, PhGetString(ServiceItem->DisplayName));
PhSetListViewSubItem(ServiceListViewHandle, lvItemIndex, 2, ServiceItem->ProcessIdString);
}
VOID PhMainWndOnServiceModified(
__in PPH_SERVICE_MODIFIED_DATA ServiceModifiedData
)
{
INT lvItemIndex;
lvItemIndex = PhFindListViewItemByParam(ServiceListViewHandle, -1, ServiceModifiedData->Service);
PhSetListViewSubItem(ServiceListViewHandle, lvItemIndex, 2, ServiceModifiedData->Service->ProcessIdString);
}
VOID PhMainWndOnServiceRemoved(
__in PPH_SERVICE_ITEM ServiceItem
)
{
PhRemoveListViewItem(
ServiceListViewHandle,
PhFindListViewItemByParam(ServiceListViewHandle, -1, ServiceItem)
);
// Remove the reference we added in PhMainWndOnServiceAdded.
PhDereferenceObject(ServiceItem);
}
VOID PhMainWndOnServicesUpdated()
{
ExtendedListView_Tick(ServiceListViewHandle);
}