mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
57e77756e7
* added UserNotes plugin git-svn-id: svn://svn.code.sf.net/p/processhacker/code@4774 21ef857c-d57f-4fe0-8362-d861dc6d29cd
816 lines
24 KiB
C
816 lines
24 KiB
C
#include <phdk.h>
|
|
#include "db.h"
|
|
#include "resource.h"
|
|
|
|
#define COMMENT_COLUMN_ID 1
|
|
|
|
typedef struct _PROCESS_EXTENSION
|
|
{
|
|
LIST_ENTRY ListEntry;
|
|
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
|
|
);
|
|
|
|
PPH_PLUGIN PluginInstance;
|
|
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
|
|
PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration;
|
|
PH_CALLBACK_REGISTRATION TreeNewMessageCallbackRegistration;
|
|
PH_CALLBACK_REGISTRATION ProcessPropertiesInitializingCallbackRegistration;
|
|
PH_CALLBACK_REGISTRATION ServicePropertiesInitializingCallbackRegistration;
|
|
PH_CALLBACK_REGISTRATION ProcessTreeNewInitializingCallbackRegistration;
|
|
PH_CALLBACK_REGISTRATION ServiceTreeNewInitializingCallbackRegistration;
|
|
|
|
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;
|
|
|
|
VOID NTAPI LoadCallback(
|
|
__in_opt PVOID Parameter,
|
|
__in_opt PVOID Context
|
|
)
|
|
{
|
|
PPH_STRING path;
|
|
PPH_STRING realPath;
|
|
|
|
InitializeDb();
|
|
|
|
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 ShowOptionsCallback(
|
|
__in_opt PVOID Parameter,
|
|
__in_opt PVOID Context
|
|
)
|
|
{
|
|
DialogBox(
|
|
PluginInstance->DllBase,
|
|
MAKEINTRESOURCE(IDD_OPTIONS),
|
|
(HWND)Parameter,
|
|
OptionsDlgProc
|
|
);
|
|
}
|
|
|
|
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 = FindDbObject(FILE_TAG, &Node->ProcessItem->ProcessName->sr))
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
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 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 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);
|
|
}
|
|
|
|
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 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);
|
|
}
|
|
}
|
|
|
|
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 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));
|
|
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 comments for processes and services.";
|
|
info->Author = L"wj32";
|
|
info->HasOptions = TRUE;
|
|
|
|
PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
|
|
LoadCallback, NULL, &PluginLoadCallbackRegistration);
|
|
PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackShowOptions),
|
|
ShowOptionsCallback, NULL, &PluginShowOptionsCallbackRegistration);
|
|
PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackTreeNewMessage),
|
|
TreeNewMessageCallback, NULL, &TreeNewMessageCallbackRegistration);
|
|
PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackProcessPropertiesInitializing),
|
|
ProcessPropertiesInitializingCallback, NULL, &ProcessPropertiesInitializingCallbackRegistration);
|
|
PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackServicePropertiesInitializing),
|
|
ServicePropertiesInitializingCallback, NULL, &ServicePropertiesInitializingCallbackRegistration);
|
|
PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackProcessTreeNewInitializing),
|
|
ProcessTreeNewInitializingCallback, NULL, &ProcessTreeNewInitializingCallbackRegistration);
|
|
PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackServiceTreeNewInitializing),
|
|
ServiceTreeNewInitializingCallback, NULL, &ServiceTreeNewInitializingCallbackRegistration);
|
|
|
|
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 = FindDbObject(FILE_TAG, &processItem->ProcessName->sr))
|
|
{
|
|
comment = object->Comment;
|
|
PhReferenceObject(comment);
|
|
}
|
|
else
|
|
{
|
|
comment = PhReferenceEmptyString();
|
|
}
|
|
|
|
UnlockDb();
|
|
|
|
SetDlgItemText(hwndDlg, IDC_COMMENT, comment->Buffer);
|
|
context->OriginalComment = comment;
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
PDB_OBJECT object;
|
|
PPH_STRING comment;
|
|
|
|
comment = PhGetWindowText(GetDlgItem(hwndDlg, IDC_COMMENT));
|
|
|
|
LockDb();
|
|
|
|
if (comment->Length != 0)
|
|
{
|
|
CreateDbObject(FILE_TAG, &processItem->ProcessName->sr, comment);
|
|
}
|
|
else
|
|
{
|
|
if (object = FindDbObject(FILE_TAG, &processItem->ProcessName->sr))
|
|
DeleteDbObject(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);
|
|
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;
|
|
}
|