#include #include #include #include "db.h" #include "resource.h" #define INTENT_PROCESS_COMMENT 1 #define INTENT_PROCESS_PRIORITY_CLASS 2 #define PROCESS_SAVE_ID 1 #define PROCESS_SAVE_FOR_THIS_COMMAND_LINE_ID 2 #define COMMENT_COLUMN_ID 1 typedef struct _PROCESS_EXTENSION { LIST_ENTRY ListEntry; PPH_PROCESS_ITEM ProcessItem; BOOLEAN Valid; PPH_STRING Comment; } PROCESS_EXTENSION, *PPROCESS_EXTENSION; typedef struct _PROCESS_COMMENT_PAGE_CONTEXT { PPH_STRING OriginalComment; } PROCESS_COMMENT_PAGE_CONTEXT, *PPROCESS_COMMENT_PAGE_CONTEXT; typedef struct _SERVICE_EXTENSION { LIST_ENTRY ListEntry; BOOLEAN Valid; PPH_STRING Comment; } SERVICE_EXTENSION, *PSERVICE_EXTENSION; typedef struct _SERVICE_COMMENT_PAGE_CONTEXT { PPH_SERVICE_ITEM ServiceItem; PH_LAYOUT_MANAGER LayoutManager; } SERVICE_COMMENT_PAGE_CONTEXT, *PSERVICE_COMMENT_PAGE_CONTEXT; INT_PTR CALLBACK OptionsDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ); INT_PTR CALLBACK ProcessCommentPageDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ); INT_PTR CALLBACK ServiceCommentPageDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ); LRESULT CALLBACK MainWndSubclassProc( __in HWND hWnd, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam, __in UINT_PTR uIdSubclass, __in DWORD_PTR dwRefData ); PPH_PLUGIN PluginInstance; PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration; PH_CALLBACK_REGISTRATION PluginUnloadCallbackRegistration; PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration; PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration; PH_CALLBACK_REGISTRATION TreeNewMessageCallbackRegistration; PH_CALLBACK_REGISTRATION MainWindowShowingCallbackRegistration; PH_CALLBACK_REGISTRATION ProcessPropertiesInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION ServicePropertiesInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION ProcessMenuInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION ProcessTreeNewInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION ServiceTreeNewInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION ProcessModifiedCallbackRegistration; PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration; HWND ProcessTreeNewHandle; LIST_ENTRY ProcessListHead = { &ProcessListHead, &ProcessListHead }; PH_QUEUED_LOCK ProcessListLock = PH_QUEUED_LOCK_INIT; HWND ServiceTreeNewHandle; LIST_ENTRY ServiceListHead = { &ServiceListHead, &ServiceListHead }; PH_QUEUED_LOCK ServiceListLock = PH_QUEUED_LOCK_INIT; BOOLEAN MatchDbObjectIntent( __in PDB_OBJECT Object, __in ULONG Intent ) { return (!(Intent & INTENT_PROCESS_COMMENT) || Object->Comment->Length != 0) && (!(Intent & INTENT_PROCESS_PRIORITY_CLASS) || Object->PriorityClass != 0); } PDB_OBJECT FindDbObjectForProcess( __in PPH_PROCESS_ITEM ProcessItem, __in ULONG Intent ) { PDB_OBJECT object; if ( ProcessItem->CommandLine && (object = FindDbObject(COMMAND_LINE_TAG, &ProcessItem->CommandLine->sr)) && MatchDbObjectIntent(object, Intent) ) return object; if ((object = FindDbObject(FILE_TAG, &ProcessItem->ProcessName->sr)) && MatchDbObjectIntent(object, Intent)) return object; return NULL; } VOID DeleteDbObjectForProcessIfUnused( __in PDB_OBJECT Object ) { if (Object->Comment->Length == 0 && Object->PriorityClass == 0) { DeleteDbObject(Object); } } VOID NTAPI LoadCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_STRING path; PPH_STRING realPath; path = PhGetStringSetting(L"ProcessHacker.UserNotes.DatabasePath"); realPath = PhExpandEnvironmentStrings(&path->sr); PhDereferenceObject(path); path = realPath; if (RtlDetermineDosPathNameType_U(path->Buffer) == RtlPathTypeRelative) { PPH_STRING directory; directory = PhGetApplicationDirectory(); realPath = PhConcatStringRef2(&directory->sr, &path->sr); PhDereferenceObject(directory); PhDereferenceObject(path); path = realPath; } SetDbPath(path); PhDereferenceObject(path); LoadDb(); } VOID NTAPI UnloadCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { SaveDb(); } VOID NTAPI ShowOptionsCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { DialogBox( PluginInstance->DllBase, MAKEINTRESOURCE(IDD_OPTIONS), (HWND)Parameter, OptionsDlgProc ); } VOID NTAPI MenuItemCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_MENU_ITEM menuItem = Parameter; PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem(); PDB_OBJECT object; if (!processItem) return; switch (menuItem->Id) { case PROCESS_SAVE_ID: { LockDb(); if ((object = FindDbObject(FILE_TAG, &processItem->ProcessName->sr)) && object->PriorityClass != 0) { object->PriorityClass = 0; DeleteDbObjectForProcessIfUnused(object); } else { object = CreateDbObject(FILE_TAG, &processItem->ProcessName->sr, NULL); object->PriorityClass = processItem->PriorityClass; } UnlockDb(); SaveDb(); } break; case PROCESS_SAVE_FOR_THIS_COMMAND_LINE_ID: { if (processItem->CommandLine) { LockDb(); if ((object = FindDbObject(COMMAND_LINE_TAG, &processItem->CommandLine->sr)) && object->PriorityClass != 0) { object->PriorityClass = 0; DeleteDbObjectForProcessIfUnused(object); } else { object = CreateDbObject(COMMAND_LINE_TAG, &processItem->CommandLine->sr, NULL); object->PriorityClass = processItem->PriorityClass; } UnlockDb(); SaveDb(); } } break; } } VOID InvalidateProcessComments( VOID ) { PLIST_ENTRY listEntry; PhAcquireQueuedLockExclusive(&ProcessListLock); listEntry = ProcessListHead.Flink; while (listEntry != &ProcessListHead) { PPROCESS_EXTENSION extension; extension = CONTAINING_RECORD(listEntry, PROCESS_EXTENSION, ListEntry); extension->Valid = FALSE; listEntry = listEntry->Flink; } PhReleaseQueuedLockExclusive(&ProcessListLock); } VOID UpdateProcessComment( __in PPH_PROCESS_NODE Node, __in PPROCESS_EXTENSION Extension ) { if (!Extension->Valid) { PDB_OBJECT object; LockDb(); if (object = FindDbObjectForProcess(Node->ProcessItem, INTENT_PROCESS_COMMENT)) { PhSwapReference(&Extension->Comment, object->Comment); } else { PhSwapReference(&Extension->Comment, NULL); } UnlockDb(); Extension->Valid = TRUE; } } VOID InvalidateServiceComments( VOID ) { PLIST_ENTRY listEntry; PhAcquireQueuedLockExclusive(&ServiceListLock); listEntry = ServiceListHead.Flink; while (listEntry != &ServiceListHead) { PSERVICE_EXTENSION extension; extension = CONTAINING_RECORD(listEntry, SERVICE_EXTENSION, ListEntry); extension->Valid = FALSE; listEntry = listEntry->Flink; } PhReleaseQueuedLockExclusive(&ServiceListLock); } VOID UpdateServiceComment( __in PPH_SERVICE_NODE Node, __in PSERVICE_EXTENSION Extension ) { if (!Extension->Valid) { PDB_OBJECT object; LockDb(); if (object = FindDbObject(SERVICE_TAG, &Node->ServiceItem->Name->sr)) { PhSwapReference(&Extension->Comment, object->Comment); } else { PhSwapReference(&Extension->Comment, NULL); } UnlockDb(); Extension->Valid = TRUE; } } VOID TreeNewMessageCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_TREENEW_MESSAGE message = Parameter; switch (message->Message) { case TreeNewGetCellText: { PPH_TREENEW_GET_CELL_TEXT getCellText = message->Parameter1; if (message->TreeNewHandle == ProcessTreeNewHandle) { PPH_PROCESS_NODE node; node = (PPH_PROCESS_NODE)getCellText->Node; switch (message->SubId) { case COMMENT_COLUMN_ID: { PPROCESS_EXTENSION extension; extension = PhPluginGetObjectExtension(PluginInstance, node->ProcessItem, EmProcessItemType); UpdateProcessComment(node, extension); getCellText->Text = PhGetStringRef(extension->Comment); } break; } } else if (message->TreeNewHandle == ServiceTreeNewHandle) { PPH_SERVICE_NODE node; node = (PPH_SERVICE_NODE)getCellText->Node; switch (message->SubId) { case COMMENT_COLUMN_ID: { PSERVICE_EXTENSION extension; extension = PhPluginGetObjectExtension(PluginInstance, node->ServiceItem, EmServiceItemType); UpdateServiceComment(node, extension); getCellText->Text = PhGetStringRef(extension->Comment); } break; } } } break; } } VOID MainWindowShowingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { SetWindowSubclass(PhMainWndHandle, MainWndSubclassProc, 0, 0); } VOID ProcessPropertiesInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_PROCESS_PROPCONTEXT propContext = Parameter; PhAddProcessPropPage( propContext->PropContext, PhCreateProcessPropPageContextEx(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_PROCCOMMENT), ProcessCommentPageDlgProc, NULL) ); } VOID ProcessMenuInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; PPH_PROCESS_ITEM processItem; PPH_EMENU_ITEM priorityMenuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Priority", 0); PPH_EMENU_ITEM saveMenuItem; PPH_EMENU_ITEM saveForCommandLineMenuItem; PDB_OBJECT object; if (!priorityMenuItem) return; if (menuInfo->u.Process.NumberOfProcesses != 1) return; processItem = menuInfo->u.Process.Processes[0]; PhInsertEMenuItem(priorityMenuItem, PhPluginCreateEMenuItem(PluginInstance, PH_EMENU_SEPARATOR, 0, L"", NULL), -1); PhInsertEMenuItem(priorityMenuItem, saveMenuItem = PhPluginCreateEMenuItem(PluginInstance, 0, PROCESS_SAVE_ID, PhaFormatString(L"Save for %s", processItem->ProcessName->Buffer)->Buffer, NULL), -1); PhInsertEMenuItem(priorityMenuItem, saveForCommandLineMenuItem = PhPluginCreateEMenuItem(PluginInstance, 0, PROCESS_SAVE_FOR_THIS_COMMAND_LINE_ID, L"Save for this command line", NULL), -1); if (!processItem->CommandLine) saveForCommandLineMenuItem->Flags |= PH_EMENU_DISABLED; LockDb(); if ((object = FindDbObject(FILE_TAG, &processItem->ProcessName->sr)) && object->PriorityClass != 0) saveMenuItem->Flags |= PH_EMENU_CHECKED; if (processItem->CommandLine && (object = FindDbObject(COMMAND_LINE_TAG, &processItem->CommandLine->sr)) && object->PriorityClass != 0) saveForCommandLineMenuItem->Flags |= PH_EMENU_CHECKED; UnlockDb(); } LONG NTAPI ProcessCommentSortFunction( __in PVOID Node1, __in PVOID Node2, __in ULONG SubId, __in PVOID Context ) { PPH_PROCESS_NODE node1 = Node1; PPH_PROCESS_NODE node2 = Node2; PPROCESS_EXTENSION extension1 = PhPluginGetObjectExtension(PluginInstance, node1->ProcessItem, EmProcessItemType); PPROCESS_EXTENSION extension2 = PhPluginGetObjectExtension(PluginInstance, node2->ProcessItem, EmProcessItemType); UpdateProcessComment(node1, extension1); UpdateProcessComment(node2, extension2); return PhCompareStringWithNull(extension1->Comment, extension2->Comment, TRUE); } VOID ProcessTreeNewInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_TREENEW_INFORMATION info = Parameter; PH_TREENEW_COLUMN column; ProcessTreeNewHandle = info->TreeNewHandle; memset(&column, 0, sizeof(PH_TREENEW_COLUMN)); column.Text = L"Comment"; column.Width = 120; column.Alignment = PH_ALIGN_LEFT; PhPluginAddTreeNewColumn(PluginInstance, info->CmData, &column, COMMENT_COLUMN_ID, NULL, ProcessCommentSortFunction); } VOID ServicePropertiesInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_OBJECT_PROPERTIES objectProperties = Parameter; PROPSHEETPAGE propSheetPage; if (objectProperties->NumberOfPages < objectProperties->MaximumNumberOfPages) { memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE)); propSheetPage.dwSize = sizeof(PROPSHEETPAGE); propSheetPage.dwFlags = PSP_USETITLE; propSheetPage.hInstance = PluginInstance->DllBase; propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_SRVCOMMENT); propSheetPage.pszTitle = L"Comment"; propSheetPage.pfnDlgProc = ServiceCommentPageDlgProc; propSheetPage.lParam = (LPARAM)objectProperties->Parameter; objectProperties->Pages[objectProperties->NumberOfPages++] = CreatePropertySheetPage(&propSheetPage); } } LONG NTAPI ServiceCommentSortFunction( __in PVOID Node1, __in PVOID Node2, __in ULONG SubId, __in PVOID Context ) { PPH_SERVICE_NODE node1 = Node1; PPH_SERVICE_NODE node2 = Node2; PSERVICE_EXTENSION extension1 = PhPluginGetObjectExtension(PluginInstance, node1->ServiceItem, EmServiceItemType); PSERVICE_EXTENSION extension2 = PhPluginGetObjectExtension(PluginInstance, node2->ServiceItem, EmServiceItemType); UpdateServiceComment(node1, extension1); UpdateServiceComment(node2, extension2); return PhCompareStringWithNull(extension1->Comment, extension2->Comment, TRUE); } VOID ServiceTreeNewInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_TREENEW_INFORMATION info = Parameter; PH_TREENEW_COLUMN column; ServiceTreeNewHandle = info->TreeNewHandle; memset(&column, 0, sizeof(PH_TREENEW_COLUMN)); column.Text = L"Comment"; column.Width = 120; column.Alignment = PH_ALIGN_LEFT; PhPluginAddTreeNewColumn(PluginInstance, info->CmData, &column, COMMENT_COLUMN_ID, NULL, ServiceCommentSortFunction); } VOID ProcessModifiedCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PROCESS_ITEM processItem = Parameter; PPROCESS_EXTENSION extension = PhPluginGetObjectExtension(PluginInstance, processItem, EmProcessItemType); extension->Valid = FALSE; } VOID ProcessesUpdatedCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PLIST_ENTRY listEntry; PhAcquireQueuedLockExclusive(&ProcessListLock); LockDb(); listEntry = ProcessListHead.Flink; while (listEntry != &ProcessListHead) { PPROCESS_EXTENSION extension; PPH_PROCESS_ITEM processItem; PDB_OBJECT object; extension = CONTAINING_RECORD(listEntry, PROCESS_EXTENSION, ListEntry); processItem = extension->ProcessItem; if (object = FindDbObjectForProcess(processItem, INTENT_PROCESS_PRIORITY_CLASS)) { if (processItem->PriorityClass != object->PriorityClass) { HANDLE processHandle; PROCESS_PRIORITY_CLASS priorityClass; if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_SET_INFORMATION, processItem->ProcessId ))) { priorityClass.Foreground = FALSE; priorityClass.PriorityClass = (UCHAR)object->PriorityClass; NtSetInformationProcess(processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS)); NtClose(processHandle); } } } listEntry = listEntry->Flink; } UnlockDb(); PhReleaseQueuedLockExclusive(&ProcessListLock); } VOID ProcessItemCreateCallback( __in PVOID Object, __in PH_EM_OBJECT_TYPE ObjectType, __in PVOID Extension ) { PPH_PROCESS_ITEM processItem = Object; PPROCESS_EXTENSION extension = Extension; memset(extension, 0, sizeof(PROCESS_EXTENSION)); extension->ProcessItem = processItem; PhAcquireQueuedLockExclusive(&ProcessListLock); InsertTailList(&ProcessListHead, &extension->ListEntry); PhReleaseQueuedLockExclusive(&ProcessListLock); } VOID ProcessItemDeleteCallback( __in PVOID Object, __in PH_EM_OBJECT_TYPE ObjectType, __in PVOID Extension ) { PPH_PROCESS_ITEM processItem = Object; PPROCESS_EXTENSION extension = Extension; PhSwapReference(&extension->Comment, NULL); PhAcquireQueuedLockExclusive(&ProcessListLock); RemoveEntryList(&extension->ListEntry); PhReleaseQueuedLockExclusive(&ProcessListLock); } VOID ServiceItemCreateCallback( __in PVOID Object, __in PH_EM_OBJECT_TYPE ObjectType, __in PVOID Extension ) { PPH_SERVICE_ITEM processItem = Object; PSERVICE_EXTENSION extension = Extension; memset(extension, 0, sizeof(SERVICE_EXTENSION)); PhAcquireQueuedLockExclusive(&ServiceListLock); InsertTailList(&ServiceListHead, &extension->ListEntry); PhReleaseQueuedLockExclusive(&ServiceListLock); } VOID ServiceItemDeleteCallback( __in PVOID Object, __in PH_EM_OBJECT_TYPE ObjectType, __in PVOID Extension ) { PPH_SERVICE_ITEM processItem = Object; PSERVICE_EXTENSION extension = Extension; PhSwapReference(&extension->Comment, NULL); PhAcquireQueuedLockExclusive(&ServiceListLock); RemoveEntryList(&extension->ListEntry); PhReleaseQueuedLockExclusive(&ServiceListLock); } LOGICAL DllMain( __in HINSTANCE Instance, __in ULONG Reason, __reserved PVOID Reserved ) { if (Reason == DLL_PROCESS_ATTACH) { PPH_PLUGIN_INFORMATION info; PluginInstance = PhRegisterPlugin(L"ProcessHacker.UserNotes", Instance, &info); if (!PluginInstance) return FALSE; info->DisplayName = L"User Notes"; info->Description = L"Allows the user to add comments for processes and services. Also allows the user to save process priority."; info->Author = L"wj32"; info->HasOptions = TRUE; InitializeDb(); PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackLoad), LoadCallback, NULL, &PluginLoadCallbackRegistration); PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackUnload), UnloadCallback, NULL, &PluginUnloadCallbackRegistration); PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackShowOptions), ShowOptionsCallback, NULL, &PluginShowOptionsCallbackRegistration); PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem), MenuItemCallback, NULL, &PluginMenuItemCallbackRegistration); PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackTreeNewMessage), TreeNewMessageCallback, NULL, &TreeNewMessageCallbackRegistration); PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackMainWindowShowing), MainWindowShowingCallback, NULL, &MainWindowShowingCallbackRegistration); PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackProcessPropertiesInitializing), ProcessPropertiesInitializingCallback, NULL, &ProcessPropertiesInitializingCallbackRegistration); PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackServicePropertiesInitializing), ServicePropertiesInitializingCallback, NULL, &ServicePropertiesInitializingCallbackRegistration); PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackProcessMenuInitializing), ProcessMenuInitializingCallback, NULL, &ProcessMenuInitializingCallbackRegistration); PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackProcessTreeNewInitializing), ProcessTreeNewInitializingCallback, NULL, &ProcessTreeNewInitializingCallbackRegistration); PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackServiceTreeNewInitializing), ServiceTreeNewInitializingCallback, NULL, &ServiceTreeNewInitializingCallbackRegistration); PhRegisterCallback(&PhProcessModifiedEvent, ProcessModifiedCallback, NULL, &ProcessModifiedCallbackRegistration); PhRegisterCallback(&PhProcessesUpdatedEvent, ProcessesUpdatedCallback, NULL, &ProcessesUpdatedCallbackRegistration); PhPluginSetObjectExtension(PluginInstance, EmProcessItemType, sizeof(PROCESS_EXTENSION), ProcessItemCreateCallback, ProcessItemDeleteCallback); PhPluginSetObjectExtension(PluginInstance, EmServiceItemType, sizeof(SERVICE_EXTENSION), ServiceItemCreateCallback, ServiceItemDeleteCallback); { static PH_SETTING_CREATE settings[] = { { StringSettingType, L"ProcessHacker.UserNotes.DatabasePath", L"%APPDATA%\\Process Hacker 2\\usernotesdb.xml" } }; PhAddSettings(settings, sizeof(settings) / sizeof(PH_SETTING_CREATE)); } } return TRUE; } INT_PTR CALLBACK OptionsDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PPH_STRING path; path = PhGetStringSetting(L"ProcessHacker.UserNotes.DatabasePath"); SetDlgItemText(hwndDlg, IDC_DATABASE, path->Buffer); PhDereferenceObject(path); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { PhSetStringSetting2(L"ProcessHacker.UserNotes.DatabasePath", &PHA_GET_DLGITEM_TEXT(hwndDlg, IDC_DATABASE)->sr); EndDialog(hwndDlg, IDOK); } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"XML files (*.xml)", L"*.xml" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhGetFileName(PHA_GET_DLGITEM_TEXT(hwndDlg, IDC_DATABASE)); PhSetFileDialogFileName(fileDialog, fileName->Buffer); PhDereferenceObject(fileName); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_DATABASE, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; } } break; } return FALSE; } INT_PTR CALLBACK ProcessCommentPageDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PPROCESS_COMMENT_PAGE_CONTEXT context; if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { context = propPageContext->Context; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { PDB_OBJECT object; PPH_STRING comment; context = PhAllocate(sizeof(PROCESS_COMMENT_PAGE_CONTEXT)); propPageContext->Context = context; // Load the comment. SendMessage(GetDlgItem(hwndDlg, IDC_COMMENT), EM_SETLIMITTEXT, UNICODE_STRING_MAX_CHARS, 0); LockDb(); if (object = FindDbObjectForProcess(processItem, INTENT_PROCESS_COMMENT)) { comment = object->Comment; PhReferenceObject(comment); if (processItem->CommandLine && (object = FindDbObject(COMMAND_LINE_TAG, &processItem->CommandLine->sr)) && object->Comment->Length != 0) { Button_SetCheck(GetDlgItem(hwndDlg, IDC_MATCHCOMMANDLINE), BST_CHECKED); } } else { comment = PhReferenceEmptyString(); } UnlockDb(); SetDlgItemText(hwndDlg, IDC_COMMENT, comment->Buffer); context->OriginalComment = comment; if (!processItem->CommandLine) EnableWindow(GetDlgItem(hwndDlg, IDC_MATCHCOMMANDLINE), FALSE); } break; case WM_DESTROY: { PDB_OBJECT object; PPH_STRING comment; BOOLEAN matchCommandLine; BOOLEAN done = FALSE; comment = PhGetWindowText(GetDlgItem(hwndDlg, IDC_COMMENT)); matchCommandLine = Button_GetCheck(GetDlgItem(hwndDlg, IDC_MATCHCOMMANDLINE)) == BST_CHECKED; if (!processItem->CommandLine) matchCommandLine = FALSE; LockDb(); if (processItem->CommandLine && !matchCommandLine) { PDB_OBJECT objectForProcessName; object = FindDbObject(COMMAND_LINE_TAG, &processItem->CommandLine->sr); objectForProcessName = FindDbObject(FILE_TAG, &processItem->ProcessName->sr); if (object && objectForProcessName && object->Comment->Length != 0 && objectForProcessName->Comment->Length != 0 && !PhEqualString(comment, objectForProcessName->Comment, FALSE)) { PPH_STRING message; message = PhFormatString( L"Do you want to replace the comment for %s which is currently\n \"%s\"\n" L"with\n \"%s\"?", processItem->ProcessName->Buffer, objectForProcessName->Comment->Buffer, comment->Buffer ); if (MessageBox(hwndDlg, message->Buffer, L"Comment", MB_ICONQUESTION | MB_YESNO) == IDNO) { done = TRUE; } PhDereferenceObject(message); } if (object) { PhSwapReference2(&object->Comment, PhReferenceEmptyString()); DeleteDbObjectForProcessIfUnused(object); } } if (!done) { if (comment->Length != 0) { if (matchCommandLine) CreateDbObject(COMMAND_LINE_TAG, &processItem->CommandLine->sr, comment); else CreateDbObject(FILE_TAG, &processItem->ProcessName->sr, comment); } else { if ( (!matchCommandLine && (object = FindDbObject(FILE_TAG, &processItem->ProcessName->sr))) || (matchCommandLine && (object = FindDbObject(COMMAND_LINE_TAG, &processItem->CommandLine->sr))) ) { PhSwapReference2(&object->Comment, PhReferenceEmptyString()); DeleteDbObjectForProcessIfUnused(object); } } } UnlockDb(); PhDereferenceObject(comment); PhDereferenceObject(context->OriginalComment); PhFree(context); PhPropPageDlgProcDestroy(hwndDlg); SaveDb(); InvalidateProcessComments(); } break; case WM_SHOWWINDOW: { PPH_LAYOUT_ITEM dialogItem; if (dialogItem = PhBeginPropPageLayout(hwndDlg, propPageContext)) { PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_COMMENT), dialogItem, PH_ANCHOR_ALL); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_REVERT), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_BOTTOM); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_MATCHCOMMANDLINE), dialogItem, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhEndPropPageLayout(hwndDlg, propPageContext); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_COMMENT: { if (HIWORD(wParam) == EN_CHANGE) EnableWindow(GetDlgItem(hwndDlg, IDC_REVERT), TRUE); } break; case IDC_REVERT: { SetDlgItemText(hwndDlg, IDC_COMMENT, context->OriginalComment->Buffer); SendMessage(GetDlgItem(hwndDlg, IDC_COMMENT), EM_SETSEL, 0, -1); SetFocus(GetDlgItem(hwndDlg, IDC_COMMENT)); EnableWindow(GetDlgItem(hwndDlg, IDC_REVERT), FALSE); } break; } } break; } return FALSE; } INT_PTR CALLBACK ServiceCommentPageDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PSERVICE_COMMENT_PAGE_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(SERVICE_COMMENT_PAGE_CONTEXT)); memset(context, 0, sizeof(SERVICE_COMMENT_PAGE_CONTEXT)); SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PSERVICE_COMMENT_PAGE_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam; PDB_OBJECT object; PPH_STRING comment; context->ServiceItem = serviceItem; PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_COMMENT), NULL, PH_ANCHOR_ALL); // Load the comment. SendMessage(GetDlgItem(hwndDlg, IDC_COMMENT), EM_SETLIMITTEXT, UNICODE_STRING_MAX_CHARS, 0); LockDb(); if (object = FindDbObject(SERVICE_TAG, &serviceItem->Name->sr)) { comment = object->Comment; PhReferenceObject(comment); } else { comment = PhReferenceEmptyString(); } UnlockDb(); SetDlgItemText(hwndDlg, IDC_COMMENT, comment->Buffer); PhDereferenceObject(comment); } break; case WM_DESTROY: { PhDeleteLayoutManager(&context->LayoutManager); PhFree(context); } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_COMMENT: { if (HIWORD(wParam) == EN_CHANGE) EnableWindow(GetDlgItem(hwndDlg, IDC_REVERT), TRUE); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_KILLACTIVE: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); } return TRUE; case PSN_APPLY: { PDB_OBJECT object; PPH_STRING comment; comment = PhGetWindowText(GetDlgItem(hwndDlg, IDC_COMMENT)); LockDb(); if (comment->Length != 0) { CreateDbObject(SERVICE_TAG, &context->ServiceItem->Name->sr, comment); } else { if (object = FindDbObject(SERVICE_TAG, &context->ServiceItem->Name->sr)) DeleteDbObject(object); } UnlockDb(); PhDereferenceObject(comment); SaveDb(); InvalidateServiceComments(); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); } return TRUE; } } break; } return FALSE; } ULONG GetPriorityClassFromId( __in ULONG Id ) { switch (Id) { case PHAPP_ID_PRIORITY_REALTIME: return PROCESS_PRIORITY_CLASS_REALTIME; case PHAPP_ID_PRIORITY_HIGH: return PROCESS_PRIORITY_CLASS_HIGH; case PHAPP_ID_PRIORITY_ABOVENORMAL: return PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; case PHAPP_ID_PRIORITY_NORMAL: return PROCESS_PRIORITY_CLASS_NORMAL; case PHAPP_ID_PRIORITY_BELOWNORMAL: return PROCESS_PRIORITY_CLASS_BELOW_NORMAL; case PHAPP_ID_PRIORITY_IDLE: return PROCESS_PRIORITY_CLASS_IDLE; } return 0; } LRESULT CALLBACK MainWndSubclassProc( __in HWND hWnd, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam, __in UINT_PTR uIdSubclass, __in DWORD_PTR dwRefData ) { switch (uMsg) { case WM_COMMAND: { switch (LOWORD(wParam)) { case PHAPP_ID_PRIORITY_REALTIME: case PHAPP_ID_PRIORITY_HIGH: case PHAPP_ID_PRIORITY_ABOVENORMAL: case PHAPP_ID_PRIORITY_NORMAL: case PHAPP_ID_PRIORITY_BELOWNORMAL: case PHAPP_ID_PRIORITY_IDLE: { PPH_PROCESS_ITEM processItem = PhGetSelectedProcessItem(); if (processItem) { PDB_OBJECT object; BOOLEAN changed = FALSE; LockDb(); if (object = FindDbObjectForProcess(processItem, INTENT_PROCESS_PRIORITY_CLASS)) { ULONG newPriorityClass = GetPriorityClassFromId(LOWORD(wParam)); if (object->PriorityClass != newPriorityClass) { object->PriorityClass = newPriorityClass; changed = TRUE; } } UnlockDb(); if (changed) SaveDb(); } } break; } } break; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); //DefaultWndProc: // return DefWindowProc(hWnd, uMsg, wParam, lParam); }