/* * Process Hacker Extended Tools - * handle properties extensions * * Copyright (C) 2010-2011 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 . */ #include "exttools.h" #include typedef struct _COMMON_PAGE_CONTEXT { PPH_HANDLE_ITEM HandleItem; HANDLE ProcessId; } COMMON_PAGE_CONTEXT, *PCOMMON_PAGE_CONTEXT; HPROPSHEETPAGE EtpCommonCreatePage( _In_ PPH_PLUGIN_HANDLE_PROPERTIES_CONTEXT Context, _In_ PWSTR Template, _In_ DLGPROC DlgProc ); INT CALLBACK EtpCommonPropPageProc( _In_ HWND hwnd, _In_ UINT uMsg, _In_ LPPROPSHEETPAGE ppsp ); INT_PTR CALLBACK EtpAlpcPortPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ); INT_PTR CALLBACK EtpTpWorkerFactoryPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ); VOID EtHandlePropertiesInitializing( _In_ PVOID Parameter ) { PPH_PLUGIN_OBJECT_PROPERTIES objectProperties = Parameter; PPH_PLUGIN_HANDLE_PROPERTIES_CONTEXT context = objectProperties->Parameter; if (objectProperties->NumberOfPages < objectProperties->MaximumNumberOfPages) { HPROPSHEETPAGE page = NULL; if (PhEqualString2(context->HandleItem->TypeName, L"ALPC Port", TRUE)) { page = EtpCommonCreatePage( context, MAKEINTRESOURCE(IDD_OBJALPCPORT), EtpAlpcPortPageDlgProc ); } else if (PhEqualString2(context->HandleItem->TypeName, L"TpWorkerFactory", TRUE)) { page = EtpCommonCreatePage( context, MAKEINTRESOURCE(IDD_OBJTPWORKERFACTORY), EtpTpWorkerFactoryPageDlgProc ); } // Insert our page into the second slot. if (page) { if (objectProperties->NumberOfPages > 1) { memmove(&objectProperties->Pages[2], &objectProperties->Pages[1], (objectProperties->NumberOfPages - 1) * sizeof(HPROPSHEETPAGE)); } objectProperties->Pages[1] = page; objectProperties->NumberOfPages++; } } } static HPROPSHEETPAGE EtpCommonCreatePage( _In_ PPH_PLUGIN_HANDLE_PROPERTIES_CONTEXT Context, _In_ PWSTR Template, _In_ DLGPROC DlgProc ) { HPROPSHEETPAGE propSheetPageHandle; PROPSHEETPAGE propSheetPage; PCOMMON_PAGE_CONTEXT pageContext; pageContext = PhCreateAlloc(sizeof(COMMON_PAGE_CONTEXT)); memset(pageContext, 0, sizeof(COMMON_PAGE_CONTEXT)); pageContext->HandleItem = Context->HandleItem; pageContext->ProcessId = Context->ProcessId; memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE)); propSheetPage.dwSize = sizeof(PROPSHEETPAGE); propSheetPage.dwFlags = PSP_USECALLBACK; propSheetPage.hInstance = PluginInstance->DllBase; propSheetPage.pszTemplate = Template; propSheetPage.pfnDlgProc = DlgProc; propSheetPage.lParam = (LPARAM)pageContext; propSheetPage.pfnCallback = EtpCommonPropPageProc; propSheetPageHandle = CreatePropertySheetPage(&propSheetPage); PhDereferenceObject(pageContext); // already got a ref from above call return propSheetPageHandle; } INT CALLBACK EtpCommonPropPageProc( _In_ HWND hwnd, _In_ UINT uMsg, _In_ LPPROPSHEETPAGE ppsp ) { PCOMMON_PAGE_CONTEXT pageContext; pageContext = (PCOMMON_PAGE_CONTEXT)ppsp->lParam; if (uMsg == PSPCB_ADDREF) PhReferenceObject(pageContext); else if (uMsg == PSPCB_RELEASE) PhDereferenceObject(pageContext); return 1; } static NTSTATUS EtpDuplicateHandleFromProcess( _Out_ PHANDLE Handle, _In_ ACCESS_MASK DesiredAccess, _In_ PCOMMON_PAGE_CONTEXT Context ) { NTSTATUS status; HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, Context->ProcessId ))) return status; status = NtDuplicateObject( processHandle, Context->HandleItem->Handle, NtCurrentProcess(), Handle, DesiredAccess, 0, 0 ); NtClose(processHandle); return status; } INT_PTR CALLBACK EtpAlpcPortPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PCOMMON_PAGE_CONTEXT context = (PCOMMON_PAGE_CONTEXT)propSheetPage->lParam; HANDLE portHandle; if (NT_SUCCESS(EtpDuplicateHandleFromProcess(&portHandle, READ_CONTROL, context))) { ALPC_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(NtAlpcQueryInformation( portHandle, AlpcBasicInformation, &basicInfo, sizeof(ALPC_BASIC_INFORMATION), NULL ))) { PH_FORMAT format[2]; PPH_STRING string; PhInitFormatS(&format[0], L"Sequence Number: "); PhInitFormatD(&format[1], basicInfo.SequenceNo); format[1].Type |= FormatGroupDigits; string = PhFormat(format, 2, 128); SetDlgItemText(hwndDlg, IDC_SEQUENCENUMBER, string->Buffer); PhDereferenceObject(string); SetDlgItemText(hwndDlg, IDC_PORTCONTEXT, PhaFormatString(L"Port Context: 0x%Ix", basicInfo.PortContext)->Buffer); } NtClose(portHandle); } } break; } return FALSE; } static BOOLEAN NTAPI EnumGenericModulesCallback( _In_ PPH_MODULE_INFO Module, _In_opt_ PVOID Context ) { if (Module->Type == PH_MODULE_TYPE_MODULE || Module->Type == PH_MODULE_TYPE_WOW64_MODULE) { PhLoadModuleSymbolProvider(Context, Module->FileName->Buffer, (ULONG64)Module->BaseAddress, Module->Size); } return TRUE; } INT_PTR CALLBACK EtpTpWorkerFactoryPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PCOMMON_PAGE_CONTEXT context = (PCOMMON_PAGE_CONTEXT)propSheetPage->lParam; HANDLE workerFactoryHandle; if (NT_SUCCESS(EtpDuplicateHandleFromProcess(&workerFactoryHandle, WORKER_FACTORY_QUERY_INFORMATION, context))) { WORKER_FACTORY_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(NtQueryInformationWorkerFactory( workerFactoryHandle, WorkerFactoryBasicInformation, &basicInfo, sizeof(WORKER_FACTORY_BASIC_INFORMATION), NULL ))) { PPH_SYMBOL_PROVIDER symbolProvider; PPH_STRING symbol = NULL; symbolProvider = PhCreateSymbolProvider(basicInfo.ProcessId); PhLoadSymbolProviderOptions(symbolProvider); if (symbolProvider->IsRealHandle) { PhEnumGenericModules(basicInfo.ProcessId, symbolProvider->ProcessHandle, 0, EnumGenericModulesCallback, symbolProvider); symbol = PhGetSymbolFromAddress(symbolProvider, (ULONG64)basicInfo.StartRoutine, NULL, NULL, NULL, NULL); } PhDereferenceObject(symbolProvider); if (symbol) { SetDlgItemText(hwndDlg, IDC_WORKERTHREADSTART, PhaFormatString(L"Worker Thread Start: %s", symbol->Buffer)->Buffer); PhDereferenceObject(symbol); } else { SetDlgItemText(hwndDlg, IDC_WORKERTHREADSTART, PhaFormatString(L"Worker Thread Start: 0x%Ix", basicInfo.StartRoutine)->Buffer); } SetDlgItemText(hwndDlg, IDC_WORKERTHREADCONTEXT, PhaFormatString(L"Worker Thread Context: 0x%Ix", basicInfo.StartParameter)->Buffer); } NtClose(workerFactoryHandle); } } break; } return FALSE; }