BOOLEAN PhpCreateProcessMiniDumpWithProgress( _In_ HWND hWnd, _In_ HANDLE ProcessId, _In_ PWSTR FileName, _In_ MINIDUMP_TYPE DumpType ) { NTSTATUS status; PROCESS_MINIDUMP_CONTEXT context; memset(&context, 0, sizeof(PROCESS_MINIDUMP_CONTEXT)); context.ProcessId = ProcessId; context.FileName = FileName; context.DumpType = DumpType; if (!NT_SUCCESS(status = PhOpenProcess( &context.ProcessHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, ProcessId ))) { PhShowStatus(hWnd, L"Unable to open the process", status, 0); return FALSE; } #ifdef _WIN64 PhGetProcessIsWow64(context.ProcessHandle, &context.IsWow64); #endif status = PhCreateFileWin32( &context.FileHandle, FileName, FILE_GENERIC_WRITE | DELETE, 0, 0, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { PhShowStatus(hWnd, L"Unable to access the dump file", status, 0); NtClose(context.ProcessHandle); return FALSE; } DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_PROGRESS), hWnd, PhpProcessMiniDumpDlgProc, (LPARAM)&context ); NtClose(context.FileHandle); NtClose(context.ProcessHandle); return context.Succeeded; }
NTSTATUS RunAsTrustedInstallerThread( _In_ PVOID Parameter ) { NTSTATUS status; HANDLE threadHandle; THREAD_BASIC_INFORMATION basicInfo; if (threadHandle = PhCreateThread(0, RunAsCreateProcessThread, NULL)) { NtWaitForSingleObject(threadHandle, FALSE, NULL); status = PhGetThreadBasicInformation(threadHandle, &basicInfo); if (NT_SUCCESS(status)) { status = basicInfo.ExitStatus; } if (!NT_SUCCESS(status)) { PhShowStatus( PhMainWndHandle, L"Error creating process with TrustedInstaller privileges", basicInfo.ExitStatus, 0 ); } NtClose(threadHandle); } return STATUS_SUCCESS; }
INT_PTR CALLBACK PhpTimerPageProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PCOMMON_PAGE_CONTEXT pageContext; pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam); if (!pageContext) return FALSE; switch (uMsg) { case WM_INITDIALOG: { PhpRefreshTimerPageInfo(hwndDlg, pageContext); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_CANCEL: { NTSTATUS status; HANDLE timerHandle; if (NT_SUCCESS(status = pageContext->OpenObject( &timerHandle, TIMER_MODIFY_STATE, pageContext->Context ))) { switch (LOWORD(wParam)) { case IDC_CANCEL: NtCancelTimer(timerHandle, NULL); break; } NtClose(timerHandle); } PhpRefreshTimerPageInfo(hwndDlg, pageContext); if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to open the timer", status, 0); } break; } } break; } return FALSE; }
VOID PhShowProcessTerminatorDialog( _In_ HWND ParentWindowHandle, _In_ PPH_PROCESS_ITEM ProcessItem ) { NTSTATUS status; HANDLE processHandle; HANDLE debugObjectHandle; if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_SUSPEND_RESUME, ProcessItem->ProcessId ))) { if (NT_SUCCESS(PhGetProcessDebugObject( processHandle, &debugObjectHandle ))) { if (PhShowMessage( ParentWindowHandle, MB_ICONWARNING | MB_YESNO, L"The selected process is currently being debugged, which can prevent it from being terminated. " L"Do you want to detach the process from its debugger?" ) == IDYES) { ULONG flags; // Disable kill-on-close. flags = 0; NtSetInformationDebugObject( debugObjectHandle, DebugObjectFlags, &flags, sizeof(ULONG), NULL ); if (!NT_SUCCESS(status = NtRemoveProcessDebug(processHandle, debugObjectHandle))) PhShowStatus(ParentWindowHandle, L"Unable to detach the process", status, 0); } NtClose(debugObjectHandle); } NtClose(processHandle); } DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_TERMINATOR), ParentWindowHandle, PhpProcessTerminatorDlgProc, (LPARAM)ProcessItem ); }
VOID PhShowProcessHeapsDialog( __in HWND ParentWindowHandle, __in PPH_PROCESS_ITEM ProcessItem ) { NTSTATUS status; PROCESS_HEAPS_CONTEXT context; PRTL_DEBUG_INFORMATION debugBuffer; HANDLE processHandle; context.ProcessItem = ProcessItem; context.ProcessHeap = NULL; debugBuffer = RtlCreateQueryDebugBuffer(0, FALSE); if (!debugBuffer) return; status = RtlQueryProcessDebugInformation( ProcessItem->ProcessId, RTL_QUERY_PROCESS_HEAP_SUMMARY | RTL_QUERY_PROCESS_HEAP_ENTRIES, debugBuffer ); if (NT_SUCCESS(status)) { context.ProcessHeaps = debugBuffer->Heaps; if (NT_SUCCESS(PhOpenProcess( &processHandle, ProcessQueryAccess | PROCESS_VM_READ, ProcessItem->ProcessId ))) { PhGetProcessDefaultHeap(processHandle, &context.ProcessHeap); NtClose(processHandle); } DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_HEAPS), ParentWindowHandle, PhpProcessHeapsDlgProc, (LPARAM)&context ); } else { PhShowStatus(ParentWindowHandle, L"Unable to query heap information", status, 0); } RtlDestroyQueryDebugBuffer(debugBuffer); }
VOID ShowDialog(VOID) { if (!GfxWindowHandle) { if (!(GfxThreadHandle = PhCreateThread(0, WindowThreadStart, NULL))) { PhShowStatus(PhMainWndHandle, L"Unable to create the Graphics information window.", 0, GetLastError()); return; } PhWaitForEvent(&InitializedEvent, NULL); } SendMessage(GfxWindowHandle, WM_GFX_ACTIVATE, 0, 0); }
VOID ShowUpdateDialog( _In_opt_ PPH_UPDATER_CONTEXT Context ) { if (!UpdateDialogThreadHandle) { if (!(UpdateDialogThreadHandle = PhCreateThread(0, ShowUpdateDialogThread, Context))) { PhShowStatus(PhMainWndHandle, L"Unable to create the updater window.", 0, GetLastError()); return; } PhWaitForEvent(&InitializedEvent, NULL); } PostMessage(UpdateDialogHandle, PH_SHOWDIALOG, 0, 0); }
VOID ShowUpdateDialog( VOID ) { if (!UpdaterDialogThreadHandle) { if (!(UpdaterDialogThreadHandle = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)ShowUpdateDialogThreadStart, NULL))) { PhShowStatus(PhMainWndHandle, L"Unable to create the updater window.", 0, GetLastError()); return; } PhWaitForEvent(&InitializedEvent, NULL); } SendMessage(UpdateDialogHandle, WM_SHOWDIALOG, 0, 0); }
BOOLEAN EtUiCancelIoThread( __in HWND hWnd, __in PPH_THREAD_ITEM Thread ) { NTSTATUS status; BOOLEAN cont = FALSE; HANDLE threadHandle; IO_STATUS_BLOCK isb; if (!PhGetIntegerSetting(L"EnableWarnings") || PhShowConfirmMessage( hWnd, L"end", L"I/O for the selected thread", NULL, FALSE )) cont = TRUE; if (!cont) return FALSE; if (NT_SUCCESS(status = PhOpenThread(&threadHandle, THREAD_TERMINATE, Thread->ThreadId))) { status = NtCancelSynchronousIoFile(threadHandle, NULL, &isb); } if (status == STATUS_NOT_FOUND) { PhShowInformation(hWnd, L"There is no synchronous I/O to cancel."); return FALSE; } else if (!NT_SUCCESS(status)) { PhShowStatus(hWnd, L"Unable to cancel synchronous I/O", status, 0); return FALSE; } return TRUE; }
VOID PvLibProperties( VOID ) { NTSTATUS status; PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) }; PROPSHEETPAGE propSheetPage; HPROPSHEETPAGE pages[1]; status = PhLoadMappedArchive(PvFileName->Buffer, NULL, TRUE, &PvMappedArchive); if (!NT_SUCCESS(status)) { PhShowStatus(NULL, L"Unable to load the archive file", status, 0); return; } propSheetHeader.dwFlags = PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP | PSH_PROPTITLE; propSheetHeader.hwndParent = NULL; propSheetHeader.pszCaption = PvFileName->Buffer; propSheetHeader.nPages = 0; propSheetHeader.nStartPage = 0; propSheetHeader.phpage = pages; // Exports page memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE)); propSheetPage.dwSize = sizeof(PROPSHEETPAGE); propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_LIBEXPORTS); propSheetPage.pfnDlgProc = PvpLibExportsDlgProc; pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage); PropertySheet(&propSheetHeader); PhUnloadMappedArchive(&PvMappedArchive); }
static VOID PhpRefreshProcessList( _In_ HWND hwndDlg, _In_ PCHOOSE_PROCESS_DIALOG_CONTEXT Context ) { NTSTATUS status; HWND lvHandle; PVOID processes; PSYSTEM_PROCESS_INFORMATION process; lvHandle = Context->ListViewHandle; ListView_DeleteAllItems(lvHandle); ImageList_RemoveAll(Context->ImageList); if (!NT_SUCCESS(status = PhEnumProcesses(&processes))) { PhShowStatus(hwndDlg, L"Unable to enumerate processes", status, 0); return; } ExtendedListView_SetRedraw(lvHandle, FALSE); process = PH_FIRST_PROCESS(processes); do { INT lvItemIndex; PPH_STRING name; HANDLE processHandle; PPH_STRING fileName = NULL; HICON icon = NULL; WCHAR processIdString[PH_INT32_STR_LEN_1]; PPH_STRING userName = NULL; INT imageIndex; if (process->UniqueProcessId != SYSTEM_IDLE_PROCESS_ID) name = PhCreateStringFromUnicodeString(&process->ImageName); else name = PhCreateString(SYSTEM_IDLE_PROCESS_NAME); lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, name->Buffer, process->UniqueProcessId); PhDereferenceObject(name); if (NT_SUCCESS(PhOpenProcess(&processHandle, ProcessQueryAccess, process->UniqueProcessId))) { HANDLE tokenHandle; PTOKEN_USER user; if (!WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID) PhGetProcessImageFileName(processHandle, &fileName); if (NT_SUCCESS(PhOpenProcessToken(&tokenHandle, TOKEN_QUERY, processHandle))) { if (NT_SUCCESS(PhGetTokenUser(tokenHandle, &user))) { userName = PhGetSidFullName(user->User.Sid, TRUE, NULL); PhFree(user); } NtClose(tokenHandle); } NtClose(processHandle); } if (process->UniqueProcessId == SYSTEM_IDLE_PROCESS_ID && !userName && PhLocalSystemName) PhSetReference(&userName, PhLocalSystemName); if (WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID) PhGetProcessImageFileNameByProcessId(process->UniqueProcessId, &fileName); if (process->UniqueProcessId == SYSTEM_PROCESS_ID) fileName = PhGetKernelFileName(); if (fileName) PhMoveReference(&fileName, PhGetFileName(fileName)); icon = PhGetFileShellIcon(PhGetString(fileName), L".exe", FALSE); // Icon if (icon) { imageIndex = ImageList_AddIcon(Context->ImageList, icon); PhSetListViewItemImageIndex(Context->ListViewHandle, lvItemIndex, imageIndex); DestroyIcon(icon); } // PID PhPrintUInt32(processIdString, HandleToUlong(process->UniqueProcessId)); PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 1, processIdString); // User Name PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 2, PhGetString(userName)); if (userName) PhDereferenceObject(userName); if (fileName) PhDereferenceObject(fileName); } while (process = PH_NEXT_PROCESS(process)); PhFree(processes); ExtendedListView_SortItems(lvHandle); ExtendedListView_SetRedraw(lvHandle, TRUE); }
VOID PhShowProcessMitigationPolicyDialog( _In_ HWND ParentWindowHandle, _In_ HANDLE ProcessId ) { NTSTATUS status; HANDLE processHandle; PH_PROCESS_MITIGATION_POLICY_ALL_INFORMATION information; MITIGATION_POLICY_CONTEXT context; PROCESS_MITIGATION_POLICY policy; PPH_STRING shortDescription; PPH_STRING longDescription; memset(&context, 0, sizeof(MITIGATION_POLICY_CONTEXT)); memset(&context.Entries, 0, sizeof(context.Entries)); if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, ProcessId ))) { PPS_SYSTEM_DLL_INIT_BLOCK dllInitBlock; if (NT_SUCCESS(PhpGetProcessSystemDllInitBlock(processHandle, &dllInitBlock))) { context.SystemDllInitBlock = dllInitBlock; } NtClose(processHandle); } if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION, ProcessId ))) { if (NT_SUCCESS(PhGetProcessMitigationPolicy(processHandle, &information))) { for (policy = 0; policy < MaxProcessMitigationPolicy; policy++) { if (information.Pointers[policy] && PhDescribeProcessMitigationPolicy( policy, information.Pointers[policy], &shortDescription, &longDescription )) { context.Entries[policy].ShortDescription = shortDescription; context.Entries[policy].LongDescription = longDescription; } } DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_MITIGATION), ParentWindowHandle, PhpProcessMitigationPolicyDlgProc, (LPARAM)&context ); for (policy = 0; policy < MaxProcessMitigationPolicy; policy++) { PhClearReference(&context.Entries[policy].ShortDescription); PhClearReference(&context.Entries[policy].LongDescription); } } if (context.SystemDllInitBlock) PhFree(context.SystemDllInitBlock); NtClose(processHandle); } else { PhShowStatus(ParentWindowHandle, L"Unable to open the process", status, 0); } }
VOID PhpAdvancedPageSave( _In_ HWND hwndDlg ) { ULONG sampleCount; SetSettingForDlgItemCheck(hwndDlg, IDC_ENABLEWARNINGS, L"EnableWarnings"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLEKERNELMODEDRIVER, L"EnableKph"); SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEUNNAMEDHANDLES, L"HideUnnamedHandles"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLESTAGE2, L"EnableStage2"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLENETWORKRESOLVE, L"EnableNetworkResolve"); SetSettingForDlgItemCheck(hwndDlg, IDC_PROPAGATECPUUSAGE, L"PropagateCpuUsage"); SetSettingForDlgItemCheck(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS, L"EnableInstantTooltips"); if (WindowsVersion >= WINDOWS_7) SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLECYCLECPUUSAGE, L"EnableCycleCpuUsage"); sampleCount = GetDlgItemInt(hwndDlg, IDC_SAMPLECOUNT, NULL, FALSE); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC, L"SampleCountAutomatic"); if (sampleCount == 0) sampleCount = 1; if (sampleCount != PhGetIntegerSetting(L"SampleCount")) RestartRequired = TRUE; PhSetIntegerSetting(L"SampleCount", sampleCount); // Replace Task Manager if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER))) { NTSTATUS status; HANDLE taskmgrKeyHandle; BOOLEAN replaceTaskMgr; UNICODE_STRING valueName; replaceTaskMgr = Button_GetCheck(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER)) == BST_CHECKED; if (OldReplaceTaskMgr != replaceTaskMgr) { // We should have created the key back in PhpAdvancedPageLoad, which is why // we're opening the key here. if (NT_SUCCESS(PhOpenKey( &taskmgrKeyHandle, KEY_WRITE, PH_KEY_LOCAL_MACHINE, &TaskMgrImageOptionsKeyName, 0 ))) { RtlInitUnicodeString(&valueName, L"Debugger"); if (replaceTaskMgr) { PPH_STRING quotedFileName; quotedFileName = PH_AUTO(PhConcatStrings(3, L"\"", PhApplicationFileName->Buffer, L"\"")); status = NtSetValueKey(taskmgrKeyHandle, &valueName, 0, REG_SZ, quotedFileName->Buffer, (ULONG)quotedFileName->Length + 2); } else { status = NtDeleteValueKey(taskmgrKeyHandle, &valueName); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to replace Task Manager", status, 0); NtClose(taskmgrKeyHandle); } } } }
HRESULT CALLBACK FinalTaskDialogCallbackProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ LONG_PTR dwRefData ) { PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData; switch (uMsg) { case TDN_NAVIGATED: { if (!UpdaterCheckApplicationDirectory()) { SendMessage(hwndDlg, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, IDYES, TRUE); } } break; case TDN_BUTTON_CLICKED: { INT buttonId = (INT)wParam; if (buttonId == IDRETRY) { ShowCheckForUpdatesDialog(context); return S_FALSE; } else if (buttonId == IDYES) { SHELLEXECUTEINFO info = { sizeof(SHELLEXECUTEINFO) }; PPH_STRING parameters; if (PhIsNullOrEmptyString(context->SetupFilePath)) break; parameters = PH_AUTO(PhGetApplicationDirectory()); parameters = PH_AUTO(PhBufferToHexString((PUCHAR)parameters->Buffer, (ULONG)parameters->Length)); parameters = PH_AUTO(PhConcatStrings(3, L"-update \"", PhGetStringOrEmpty(parameters), L"\"")); info.lpFile = PhGetStringOrEmpty(context->SetupFilePath); info.lpParameters = PhGetString(parameters); info.lpVerb = UpdaterCheckApplicationDirectory() ? NULL : L"runas"; info.nShow = SW_SHOW; info.hwnd = hwndDlg; info.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOZONECHECKS; ProcessHacker_PrepareForEarlyShutdown(PhMainWndHandle); if (ShellExecuteEx(&info)) { ProcessHacker_Destroy(PhMainWndHandle); } else { ULONG errorCode = GetLastError(); // Install failed, cancel the shutdown. ProcessHacker_CancelEarlyShutdown(PhMainWndHandle); // Show error dialog. if (errorCode != ERROR_CANCELLED) // Ignore UAC decline. { PhShowStatus(hwndDlg, L"Unable to execute the setup.", 0, errorCode); if (context->StartupCheck) ShowAvailableDialog(context); else ShowCheckForUpdatesDialog(context); } return S_FALSE; } } } break; case TDN_HYPERLINK_CLICKED: { TaskDialogLinkClicked(context); return S_FALSE; } break; } return S_OK; }
INT_PTR CALLBACK PhpMemoryResultsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_RESULTS_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_RESULTS_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhRegisterDialog(hwndDlg); { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"Results - %s (%u)", processItem->ProcessName->Buffer, HandleToUlong(processItem->ProcessId))->Buffer); PhDereferenceObject(processItem); } } lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 120, L"Address"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"Length"); PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 200, L"Result"); PhLoadListViewColumnsFromSetting(L"MemResultsListViewColumns", lvHandle); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LIST), NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_FILTER), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 250; rect.bottom = 180; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } ListView_SetItemCount(lvHandle, context->Results->Count); SetDlgItemText(hwndDlg, IDC_INTRO, PhaFormatString(L"%s results.", PhaFormatUInt64(context->Results->Count, TRUE)->Buffer)->Buffer); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemResultsPosition"); windowRectangle.Size = PhGetIntegerPairSetting(L"MemResultsSize"); PhAdjustRectangleToWorkingArea(hwndDlg, &windowRectangle); MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top, windowRectangle.Width, windowRectangle.Height, FALSE); // Implement cascading by saving an offsetted rectangle. windowRectangle.Left += 20; windowRectangle.Top += 20; PhSetIntegerPairSetting(L"MemResultsPosition", windowRectangle.Position); PhSetIntegerPairSetting(L"MemResultsSize", windowRectangle.Size); } } break; case WM_DESTROY: { PhSaveWindowPlacementToSetting(L"MemResultsPosition", L"MemResultsSize", hwndDlg); PhSaveListViewColumnsToSetting(L"MemResultsListViewColumns", GetDlgItem(hwndDlg, IDC_LIST)); PhDeleteLayoutManager(&context->LayoutManager); PhUnregisterDialog(hwndDlg); RemoveProp(hwndDlg, PhMakeContextAtom()); PhDereferenceMemoryResults((PPH_MEMORY_RESULT *)context->Results->Items, context->Results->Count); PhDereferenceObject(context->Results); PhFree(context); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_COPY: { HWND lvHandle; PPH_STRING string; ULONG selectedCount; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); selectedCount = ListView_GetSelectedCount(lvHandle); if (selectedCount == 0) { // User didn't select anything, so copy all items. string = PhpGetStringForSelectedResults(lvHandle, context->Results, TRUE); PhSetStateAllListViewItems(lvHandle, LVIS_SELECTED, LVIS_SELECTED); } else { string = PhpGetStringForSelectedResults(lvHandle, context->Results, FALSE); } PhSetClipboardString(hwndDlg, &string->sr); PhDereferenceObject(string); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)lvHandle, TRUE); } break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Text files (*.txt)", L"*.txt" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, L"Search Results.txt"); if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; PPH_STRING string; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { PhWriteStringAsUtf8FileStream(fileStream, &PhUnicodeByteOrderMark); PhWritePhTextHeader(fileStream); string = PhpGetStringForSelectedResults(GetDlgItem(hwndDlg, IDC_LIST), context->Results, TRUE); PhWriteStringAsUtf8FileStreamEx(fileStream, string->Buffer, string->Length); PhDereferenceObject(string); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_FILTER: { PPH_EMENU menu; RECT buttonRect; POINT point; PPH_EMENU_ITEM selectedItem; ULONG filterType = 0; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_MEMFILTER), 0); GetClientRect(GetDlgItem(hwndDlg, IDC_FILTER), &buttonRect); point.x = 0; point.y = buttonRect.bottom; ClientToScreen(GetDlgItem(hwndDlg, IDC_FILTER), &point); selectedItem = PhShowEMenu(menu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y); if (selectedItem) { switch (selectedItem->Id) { case ID_FILTER_CONTAINS: filterType = FILTER_CONTAINS; break; case ID_FILTER_CONTAINS_CASEINSENSITIVE: filterType = FILTER_CONTAINS_IGNORECASE; break; case ID_FILTER_REGEX: filterType = FILTER_REGEX; break; case ID_FILTER_REGEX_CASEINSENSITIVE: filterType = FILTER_REGEX_IGNORECASE; break; } } if (filterType != 0) FilterResults(hwndDlg, context, filterType); PhDestroyEMenu(menu); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; HWND lvHandle; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhHandleListViewNotifyForCopy(lParam, lvHandle); switch (header->code) { case LVN_GETDISPINFO: { NMLVDISPINFO *dispInfo = (NMLVDISPINFO *)header; if (dispInfo->item.mask & LVIF_TEXT) { PPH_MEMORY_RESULT result = context->Results->Items[dispInfo->item.iItem]; switch (dispInfo->item.iSubItem) { case 0: { WCHAR addressString[PH_PTR_STR_LEN_1]; PhPrintPointer(addressString, result->Address); wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, addressString, _TRUNCATE ); } break; case 1: { WCHAR lengthString[PH_INT32_STR_LEN_1]; PhPrintUInt32(lengthString, (ULONG)result->Length); wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, lengthString, _TRUNCATE ); } break; case 2: wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, result->Display.Buffer, _TRUNCATE ); break; } } } break; case NM_DBLCLK: { if (header->hwndFrom == lvHandle) { INT index; if ((index = ListView_GetNextItem( lvHandle, -1, LVNI_SELECTED )) != -1) { NTSTATUS status; PPH_MEMORY_RESULT result = context->Results->Items[index]; HANDLE processHandle; MEMORY_BASIC_INFORMATION basicInfo; PPH_SHOWMEMORYEDITOR showMemoryEditor; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, context->ProcessId ))) { if (NT_SUCCESS(status = NtQueryVirtualMemory( processHandle, result->Address, MemoryBasicInformation, &basicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL ))) { showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR)); memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR)); showMemoryEditor->ProcessId = context->ProcessId; showMemoryEditor->BaseAddress = basicInfo.BaseAddress; showMemoryEditor->RegionSize = basicInfo.RegionSize; showMemoryEditor->SelectOffset = (ULONG)((ULONG_PTR)result->Address - (ULONG_PTR)basicInfo.BaseAddress); showMemoryEditor->SelectLength = (ULONG)result->Length; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); } NtClose(processHandle); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to edit memory", status, 0); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; } return FALSE; }
INT_PTR CALLBACK PhpProcessThreadsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PPH_THREADS_CONTEXT threadsContext; HWND tnHandle; if (PhpPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { threadsContext = (PPH_THREADS_CONTEXT)propPageContext->Context; if (threadsContext) tnHandle = threadsContext->ListContext.TreeNewHandle; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { threadsContext = propPageContext->Context = PhAllocate(PhEmGetObjectSize(EmThreadsContextType, sizeof(PH_THREADS_CONTEXT))); // The thread provider has a special registration mechanism. threadsContext->Provider = PhCreateThreadProvider( processItem->ProcessId ); PhRegisterCallback( &threadsContext->Provider->ThreadAddedEvent, ThreadAddedHandler, threadsContext, &threadsContext->AddedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->ThreadModifiedEvent, ThreadModifiedHandler, threadsContext, &threadsContext->ModifiedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->ThreadRemovedEvent, ThreadRemovedHandler, threadsContext, &threadsContext->RemovedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->UpdatedEvent, ThreadsUpdatedHandler, threadsContext, &threadsContext->UpdatedEventRegistration ); PhRegisterCallback( &threadsContext->Provider->LoadingStateChangedEvent, ThreadsLoadingStateChangedHandler, threadsContext, &threadsContext->LoadingStateChangedEventRegistration ); threadsContext->WindowHandle = hwndDlg; // Initialize the list. tnHandle = GetDlgItem(hwndDlg, IDC_LIST); BringWindowToTop(tnHandle); PhInitializeThreadList(hwndDlg, tnHandle, &threadsContext->ListContext); TreeNew_SetEmptyText(tnHandle, &EmptyThreadsText, 0); PhInitializeProviderEventQueue(&threadsContext->EventQueue, 100); // Use Cycles instead of Context Switches on Vista and above, but only when we can // open the process, since cycle time information requires sufficient access to the // threads. if (WINDOWS_HAS_CYCLE_TIME) { HANDLE processHandle; PROCESS_EXTENDED_BASIC_INFORMATION extendedBasicInfo; // We make a distinction between PROCESS_QUERY_INFORMATION and PROCESS_QUERY_LIMITED_INFORMATION since // the latter can be used when opening audiodg.exe even though we can't access its threads using // THREAD_QUERY_LIMITED_INFORMATION. if (processItem->ProcessId == SYSTEM_IDLE_PROCESS_ID) { threadsContext->ListContext.UseCycleTime = TRUE; } else if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_QUERY_INFORMATION, processItem->ProcessId))) { threadsContext->ListContext.UseCycleTime = TRUE; NtClose(processHandle); } else if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_QUERY_LIMITED_INFORMATION, processItem->ProcessId))) { threadsContext->ListContext.UseCycleTime = TRUE; // We can't use cycle time for protected processes (without KProcessHacker). if (NT_SUCCESS(PhGetProcessExtendedBasicInformation(processHandle, &extendedBasicInfo)) && extendedBasicInfo.IsProtectedProcess) { threadsContext->ListContext.UseCycleTime = FALSE; } NtClose(processHandle); } } if (processItem->ServiceList && processItem->ServiceList->Count != 0 && WINDOWS_HAS_SERVICE_TAGS) threadsContext->ListContext.HasServices = TRUE; PhEmCallObjectOperation(EmThreadsContextType, threadsContext, EmObjectCreate); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &threadsContext->ListContext.Cm; treeNewInfo.SystemContext = threadsContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadTreeNewInitializing), &treeNewInfo); } PhLoadSettingsThreadList(&threadsContext->ListContext); PhThreadProviderInitialUpdate(threadsContext->Provider); PhRegisterThreadProvider(threadsContext->Provider, &threadsContext->ProviderRegistration); SET_BUTTON_ICON(IDC_OPENSTARTMODULE, PH_LOAD_SHARED_ICON_SMALL(MAKEINTRESOURCE(IDI_FOLDER))); } break; case WM_DESTROY: { PhEmCallObjectOperation(EmThreadsContextType, threadsContext, EmObjectDelete); PhUnregisterCallback( &threadsContext->Provider->ThreadAddedEvent, &threadsContext->AddedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->ThreadModifiedEvent, &threadsContext->ModifiedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->ThreadRemovedEvent, &threadsContext->RemovedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->UpdatedEvent, &threadsContext->UpdatedEventRegistration ); PhUnregisterCallback( &threadsContext->Provider->LoadingStateChangedEvent, &threadsContext->LoadingStateChangedEventRegistration ); PhUnregisterThreadProvider(threadsContext->Provider, &threadsContext->ProviderRegistration); PhSetTerminatingThreadProvider(threadsContext->Provider); PhDereferenceObject(threadsContext->Provider); PhDeleteProviderEventQueue(&threadsContext->EventQueue); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &threadsContext->ListContext.Cm; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadTreeNewUninitializing), &treeNewInfo); } PhSaveSettingsThreadList(&threadsContext->ListContext); PhDeleteThreadList(&threadsContext->ListContext); PhFree(threadsContext); PhpPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { if (!propPageContext->LayoutInitialized) { PPH_LAYOUT_ITEM dialogItem; dialogItem = PhAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_LIST), dialogItem, PH_ANCHOR_ALL); #define ADD_BL_ITEM(Id) \ PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, Id), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_BOTTOM) // Thread details area { ULONG id; for (id = IDC_STATICBL1; id <= IDC_STATICBL11; id++) ADD_BL_ITEM(id); // Not in sequence ADD_BL_ITEM(IDC_STATICBL12); } PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_STARTMODULE), dialogItem, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_OPENSTARTMODULE), dialogItem, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); ADD_BL_ITEM(IDC_STARTED); ADD_BL_ITEM(IDC_KERNELTIME); ADD_BL_ITEM(IDC_USERTIME); ADD_BL_ITEM(IDC_CONTEXTSWITCHES); ADD_BL_ITEM(IDC_CYCLES); ADD_BL_ITEM(IDC_STATE); ADD_BL_ITEM(IDC_PRIORITY); ADD_BL_ITEM(IDC_BASEPRIORITY); ADD_BL_ITEM(IDC_IOPRIORITY); ADD_BL_ITEM(IDC_PAGEPRIORITY); ADD_BL_ITEM(IDC_IDEALPROCESSOR); PhDoPropPageLayout(hwndDlg); propPageContext->LayoutInitialized = TRUE; } } break; case WM_COMMAND: { INT id = LOWORD(wParam); switch (id) { case ID_SHOWCONTEXTMENU: { PhShowThreadContextMenu(hwndDlg, processItem, threadsContext, (PPH_TREENEW_CONTEXT_MENU)lParam); } break; case ID_THREAD_INSPECT: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadsContext->Provider); PhShowThreadStackDialog( hwndDlg, threadsContext->Provider->ProcessId, threadItem->ThreadId, threadsContext->Provider ); PhDereferenceObject(threadsContext->Provider); } } break; case ID_THREAD_TERMINATE: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); if (PhUiTerminateThreads(hwndDlg, threads, numberOfThreads)) PhDeselectAllThreadNodes(&threadsContext->ListContext); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_SUSPEND: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); PhUiSuspendThreads(hwndDlg, threads, numberOfThreads); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_RESUME: { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PhGetSelectedThreadItems(&threadsContext->ListContext, &threads, &numberOfThreads); PhReferenceObjects(threads, numberOfThreads); PhUiResumeThreads(hwndDlg, threads, numberOfThreads); PhDereferenceObjects(threads, numberOfThreads); PhFree(threads); } break; case ID_THREAD_AFFINITY: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadItem); PhShowProcessAffinityDialog(hwndDlg, NULL, threadItem); PhDereferenceObject(threadItem); } } break; case ID_THREAD_PERMISSIONS: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); PH_STD_OBJECT_SECURITY stdObjectSecurity; PPH_ACCESS_ENTRY accessEntries; ULONG numberOfAccessEntries; if (threadItem) { stdObjectSecurity.OpenObject = PhpThreadPermissionsOpenThread; stdObjectSecurity.ObjectType = L"Thread"; stdObjectSecurity.Context = threadItem->ThreadId; if (PhGetAccessEntries(L"Thread", &accessEntries, &numberOfAccessEntries)) { PhEditSecurity( hwndDlg, PhaFormatString(L"Thread %u", HandleToUlong(threadItem->ThreadId))->Buffer, PhStdGetObjectSecurity, PhStdSetObjectSecurity, &stdObjectSecurity, accessEntries, numberOfAccessEntries ); PhFree(accessEntries); } } } break; case ID_THREAD_TOKEN: { NTSTATUS status; PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); HANDLE threadHandle; if (threadItem) { if (NT_SUCCESS(status = PhOpenThread( &threadHandle, ThreadQueryAccess, threadItem->ThreadId ))) { PhShowTokenProperties( hwndDlg, PhpOpenThreadTokenObject, (PVOID)threadHandle, NULL ); NtClose(threadHandle); } else { PhShowStatus(hwndDlg, L"Unable to open the thread", status, 0); } } } break; case ID_ANALYZE_WAIT: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { PhReferenceObject(threadsContext->Provider->SymbolProvider); PhUiAnalyzeWaitThread( hwndDlg, processItem->ProcessId, threadItem->ThreadId, threadsContext->Provider->SymbolProvider ); PhDereferenceObject(threadsContext->Provider->SymbolProvider); } } break; case ID_PRIORITY_TIMECRITICAL: case ID_PRIORITY_HIGHEST: case ID_PRIORITY_ABOVENORMAL: case ID_PRIORITY_NORMAL: case ID_PRIORITY_BELOWNORMAL: case ID_PRIORITY_LOWEST: case ID_PRIORITY_IDLE: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { ULONG threadPriorityWin32; switch (id) { case ID_PRIORITY_TIMECRITICAL: threadPriorityWin32 = THREAD_PRIORITY_TIME_CRITICAL; break; case ID_PRIORITY_HIGHEST: threadPriorityWin32 = THREAD_PRIORITY_HIGHEST; break; case ID_PRIORITY_ABOVENORMAL: threadPriorityWin32 = THREAD_PRIORITY_ABOVE_NORMAL; break; case ID_PRIORITY_NORMAL: threadPriorityWin32 = THREAD_PRIORITY_NORMAL; break; case ID_PRIORITY_BELOWNORMAL: threadPriorityWin32 = THREAD_PRIORITY_BELOW_NORMAL; break; case ID_PRIORITY_LOWEST: threadPriorityWin32 = THREAD_PRIORITY_LOWEST; break; case ID_PRIORITY_IDLE: threadPriorityWin32 = THREAD_PRIORITY_IDLE; break; } PhReferenceObject(threadItem); PhUiSetPriorityThread(hwndDlg, threadItem, threadPriorityWin32); PhDereferenceObject(threadItem); } } break; case ID_IOPRIORITY_VERYLOW: case ID_IOPRIORITY_LOW: case ID_IOPRIORITY_NORMAL: case ID_IOPRIORITY_HIGH: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { IO_PRIORITY_HINT ioPriority; switch (id) { case ID_IOPRIORITY_VERYLOW: ioPriority = IoPriorityVeryLow; break; case ID_IOPRIORITY_LOW: ioPriority = IoPriorityLow; break; case ID_IOPRIORITY_NORMAL: ioPriority = IoPriorityNormal; break; case ID_IOPRIORITY_HIGH: ioPriority = IoPriorityHigh; break; } PhReferenceObject(threadItem); PhUiSetIoPriorityThread(hwndDlg, threadItem, ioPriority); PhDereferenceObject(threadItem); } } break; case ID_PAGEPRIORITY_VERYLOW: case ID_PAGEPRIORITY_LOW: case ID_PAGEPRIORITY_MEDIUM: case ID_PAGEPRIORITY_BELOWNORMAL: case ID_PAGEPRIORITY_NORMAL: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem) { ULONG pagePriority; switch (id) { case ID_PAGEPRIORITY_VERYLOW: pagePriority = MEMORY_PRIORITY_VERY_LOW; break; case ID_PAGEPRIORITY_LOW: pagePriority = MEMORY_PRIORITY_LOW; break; case ID_PAGEPRIORITY_MEDIUM: pagePriority = MEMORY_PRIORITY_MEDIUM; break; case ID_PAGEPRIORITY_BELOWNORMAL: pagePriority = MEMORY_PRIORITY_BELOW_NORMAL; break; case ID_PAGEPRIORITY_NORMAL: pagePriority = MEMORY_PRIORITY_NORMAL; break; } PhReferenceObject(threadItem); PhUiSetPagePriorityThread(hwndDlg, threadItem, pagePriority); PhDereferenceObject(threadItem); } } break; case ID_THREAD_COPY: { PPH_STRING text; text = PhGetTreeNewText(tnHandle, 0); PhSetClipboardString(tnHandle, &text->sr); PhDereferenceObject(text); } break; case IDC_OPENSTARTMODULE: { PPH_THREAD_ITEM threadItem = PhGetSelectedThreadItem(&threadsContext->ListContext); if (threadItem && threadItem->StartAddressFileName) { PhShellExploreFile(hwndDlg, threadItem->StartAddressFileName->Buffer); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_SETACTIVE: break; case PSN_KILLACTIVE: // Can't disable, it screws up the deltas. break; } } break; case WM_PH_THREADS_UPDATED: { ULONG upToRunId = (ULONG)wParam; BOOLEAN firstRun = !!lParam; PPH_PROVIDER_EVENT events; ULONG count; ULONG i; events = PhFlushProviderEventQueue(&threadsContext->EventQueue, upToRunId, &count); if (events) { TreeNew_SetRedraw(tnHandle, FALSE); for (i = 0; i < count; i++) { PH_PROVIDER_EVENT_TYPE type = PH_PROVIDER_EVENT_TYPE(events[i]); PPH_THREAD_ITEM threadItem = PH_PROVIDER_EVENT_OBJECT(events[i]); switch (type) { case ProviderAddedEvent: PhAddThreadNode(&threadsContext->ListContext, threadItem, firstRun); PhDereferenceObject(threadItem); break; case ProviderModifiedEvent: PhUpdateThreadNode(&threadsContext->ListContext, PhFindThreadNode(&threadsContext->ListContext, threadItem->ThreadId)); break; case ProviderRemovedEvent: PhRemoveThreadNode(&threadsContext->ListContext, PhFindThreadNode(&threadsContext->ListContext, threadItem->ThreadId)); break; } } PhFree(events); } PhTickThreadNodes(&threadsContext->ListContext); if (count != 0) TreeNew_SetRedraw(tnHandle, TRUE); if (propPageContext->PropContext->SelectThreadId) { PPH_THREAD_NODE threadNode; if (threadNode = PhFindThreadNode(&threadsContext->ListContext, propPageContext->PropContext->SelectThreadId)) { if (threadNode->Node.Visible) { TreeNew_SetFocusNode(tnHandle, &threadNode->Node); TreeNew_SetMarkNode(tnHandle, &threadNode->Node); TreeNew_SelectRange(tnHandle, threadNode->Node.Index, threadNode->Node.Index); TreeNew_EnsureVisible(tnHandle, &threadNode->Node); } } propPageContext->PropContext->SelectThreadId = NULL; } PhpUpdateThreadDetails(hwndDlg, threadsContext, FALSE); } break; case WM_PH_THREAD_SELECTION_CHANGED: { PhpUpdateThreadDetails(hwndDlg, threadsContext, TRUE); } break; } return FALSE; }
VOID PhpProcessStartupParameters( VOID ) { static PH_COMMAND_LINE_OPTION options[] = { { PH_ARG_SETTINGS, L"settings", MandatoryArgumentType }, { PH_ARG_NOSETTINGS, L"nosettings", NoArgumentType }, { PH_ARG_SHOWVISIBLE, L"v", NoArgumentType }, { PH_ARG_SHOWHIDDEN, L"hide", NoArgumentType }, { PH_ARG_COMMANDMODE, L"c", NoArgumentType }, { PH_ARG_COMMANDTYPE, L"ctype", MandatoryArgumentType }, { PH_ARG_COMMANDOBJECT, L"cobject", MandatoryArgumentType }, { PH_ARG_COMMANDACTION, L"caction", MandatoryArgumentType }, { PH_ARG_COMMANDVALUE, L"cvalue", MandatoryArgumentType }, { PH_ARG_RUNASSERVICEMODE, L"ras", MandatoryArgumentType }, { PH_ARG_NOKPH, L"nokph", NoArgumentType }, { PH_ARG_INSTALLKPH, L"installkph", NoArgumentType }, { PH_ARG_UNINSTALLKPH, L"uninstallkph", NoArgumentType }, { PH_ARG_DEBUG, L"debug", NoArgumentType }, { PH_ARG_HWND, L"hwnd", MandatoryArgumentType }, { PH_ARG_POINT, L"point", MandatoryArgumentType }, { PH_ARG_SHOWOPTIONS, L"showoptions", NoArgumentType }, { PH_ARG_PHSVC, L"phsvc", NoArgumentType }, { PH_ARG_NOPLUGINS, L"noplugins", NoArgumentType }, { PH_ARG_NEWINSTANCE, L"newinstance", NoArgumentType }, { PH_ARG_ELEVATE, L"elevate", NoArgumentType }, { PH_ARG_SILENT, L"s", NoArgumentType }, { PH_ARG_HELP, L"help", NoArgumentType }, { PH_ARG_SELECTPID, L"selectpid", MandatoryArgumentType }, { PH_ARG_PRIORITY, L"priority", MandatoryArgumentType }, { PH_ARG_PLUGIN, L"plugin", MandatoryArgumentType }, { PH_ARG_SELECTTAB, L"selecttab", MandatoryArgumentType } }; PH_STRINGREF commandLine; PhUnicodeStringToStringRef(&NtCurrentPeb()->ProcessParameters->CommandLine, &commandLine); memset(&PhStartupParameters, 0, sizeof(PH_STARTUP_PARAMETERS)); if (!PhParseCommandLine( &commandLine, options, sizeof(options) / sizeof(PH_COMMAND_LINE_OPTION), PH_COMMAND_LINE_IGNORE_UNKNOWN_OPTIONS | PH_COMMAND_LINE_IGNORE_FIRST_PART, PhpCommandLineOptionCallback, NULL ) || PhStartupParameters.Help) { PhShowInformation( NULL, L"Command line options:\n\n" L"-c\n" L"-ctype command-type\n" L"-cobject command-object\n" L"-caction command-action\n" L"-cvalue command-value\n" L"-debug\n" L"-elevate\n" L"-help\n" L"-hide\n" L"-installkph\n" L"-newinstance\n" L"-nokph\n" L"-noplugins\n" L"-nosettings\n" L"-plugin pluginname:value\n" L"-priority r|h|n|l\n" L"-s\n" L"-selectpid pid-to-select\n" L"-selecttab name-of-tab-to-select\n" L"-settings filename\n" L"-uninstallkph\n" L"-v\n" ); if (PhStartupParameters.Help) RtlExitUserProcess(STATUS_SUCCESS); } if (PhStartupParameters.InstallKph) { NTSTATUS status; PPH_STRING kprocesshackerFileName; KPH_PARAMETERS parameters; kprocesshackerFileName = PhConcatStrings2(PhApplicationDirectory->Buffer, L"\\kprocesshacker.sys"); parameters.SecurityLevel = KphSecurityNone; parameters.CreateDynamicConfiguration = TRUE; status = KphInstallEx(L"KProcessHacker2", kprocesshackerFileName->Buffer, ¶meters); if (!NT_SUCCESS(status) && !PhStartupParameters.Silent) PhShowStatus(NULL, L"Unable to install KProcessHacker", status, 0); RtlExitUserProcess(status); } if (PhStartupParameters.UninstallKph) { NTSTATUS status; status = KphUninstall(L"KProcessHacker2"); if (!NT_SUCCESS(status) && !PhStartupParameters.Silent) PhShowStatus(NULL, L"Unable to uninstall KProcessHacker", status, 0); RtlExitUserProcess(status); } if (PhStartupParameters.Elevate && !PhElevated) { PhShellProcessHacker( NULL, NULL, SW_SHOW, PH_SHELL_EXECUTE_ADMIN, PH_SHELL_APP_PROPAGATE_PARAMETERS | PH_SHELL_APP_PROPAGATE_PARAMETERS_FORCE_SETTINGS, 0, NULL ); RtlExitUserProcess(STATUS_SUCCESS); } if (PhStartupParameters.Debug) { // The symbol provider won't work if this is chosen. PhShowDebugConsole(); } }
INT_PTR CALLBACK PhpMemoryEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_EDITOR_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_EDITOR_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; if (context->Title) { SetWindowText(hwndDlg, context->Title->Buffer); } else { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"%s (%u) (0x%Ix - 0x%Ix)", processItem->ProcessName->Buffer, HandleToUlong(context->ProcessId), context->BaseAddress, (ULONG_PTR)context->BaseAddress + context->RegionSize)->Buffer); PhDereferenceObject(processItem); } } PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); if (context->RegionSize > 1024 * 1024 * 1024) // 1 GB { PhShowError(NULL, L"Unable to edit the memory region because it is too large."); return TRUE; } if (!NT_SUCCESS(status = PhOpenProcess( &context->ProcessHandle, PROCESS_VM_READ, context->ProcessId ))) { PhShowStatus(NULL, L"Unable to open the process", status, 0); return TRUE; } context->Buffer = PhAllocatePage(context->RegionSize, NULL); if (!context->Buffer) { PhShowError(NULL, L"Unable to allocate memory for the buffer."); return TRUE; } if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(PhMainWndHandle, L"Unable to read memory", status, 0); return TRUE; } PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BYTESPERROW), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GOTO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_WRITE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REREAD), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 290; rect.bottom = 140; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } context->HexEditHandle = GetDlgItem(hwndDlg, IDC_MEMORY); PhAddLayoutItem(&context->LayoutManager, context->HexEditHandle, NULL, PH_ANCHOR_ALL); HexEdit_SetBuffer(context->HexEditHandle, context->Buffer, (ULONG)context->RegionSize); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemEditPosition"); windowRectangle.Size = PhGetScalableIntegerPairSetting(L"MemEditSize", TRUE).Pair; PhAdjustRectangleToWorkingArea(NULL, &windowRectangle); MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top, windowRectangle.Width, windowRectangle.Height, FALSE); // Implement cascading by saving an offsetted rectangle. windowRectangle.Left += 20; windowRectangle.Top += 20; PhSetIntegerPairSetting(L"MemEditPosition", windowRectangle.Position); PhSetScalableIntegerPairSetting2(L"MemEditSize", windowRectangle.Size); } { PWSTR bytesPerRowStrings[7]; ULONG i; ULONG bytesPerRow; for (i = 0; i < sizeof(bytesPerRowStrings) / sizeof(PWSTR); i++) bytesPerRowStrings[i] = PhaFormatString(L"%u bytes per row", 1 << (2 + i))->Buffer; PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_BYTESPERROW), bytesPerRowStrings, sizeof(bytesPerRowStrings) / sizeof(PWSTR)); bytesPerRow = PhGetIntegerSetting(L"MemEditBytesPerRow"); if (bytesPerRow >= 4) { HexEdit_SetBytesPerRow(context->HexEditHandle, bytesPerRow); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_BYTESPERROW), PhaFormatString(L"%u bytes per row", bytesPerRow)->Buffer, FALSE); } } context->LoadCompleted = TRUE; } break; case WM_DESTROY: { if (context->LoadCompleted) { PhSaveWindowPlacementToSetting(L"MemEditPosition", L"MemEditSize", hwndDlg); PhRemoveElementAvlTree(&PhMemoryEditorSet, &context->Links); PhUnregisterDialog(hwndDlg); } RemoveProp(hwndDlg, PhMakeContextAtom()); PhDeleteLayoutManager(&context->LayoutManager); if (context->Buffer) PhFreePage(context->Buffer); if (context->ProcessHandle) NtClose(context->ProcessHandle); PhClearReference(&context->Title); if ((context->Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && context->ProcessId == NtCurrentProcessId()) NtUnmapViewOfSection(NtCurrentProcess(), context->BaseAddress); PhFree(context); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Binary files (*.bin)", L"*.bin" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_PROCESS_ITEM processItem; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); if (!context->Title && (processItem = PhReferenceProcessItem(context->ProcessId))) { PhSetFileDialogFileName(fileDialog, PhaFormatString(L"%s_0x%Ix-0x%Ix.bin", processItem->ProcessName->Buffer, context->BaseAddress, context->RegionSize)->Buffer); PhDereferenceObject(processItem); } else { PhSetFileDialogFileName(fileDialog, L"Memory.bin"); } if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { status = PhWriteFileStream(fileStream, context->Buffer, (ULONG)context->RegionSize); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_GOTO: { PPH_STRING selectedChoice = NULL; while (PhaChoiceDialog( hwndDlg, L"Go to Offset", L"Enter an offset:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemEditGotoChoices" )) { ULONG64 offset; if (selectedChoice->Length == 0) continue; if (PhStringToInteger64(&selectedChoice->sr, 0, &offset)) { if (offset >= context->RegionSize) { PhShowError(hwndDlg, L"The offset is too large."); continue; } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); HexEdit_SetSel(context->HexEditHandle, (LONG)offset, (LONG)offset); break; } } } break; case IDC_WRITE: { NTSTATUS status; if (!context->WriteAccess) { HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_READ | PROCESS_VM_WRITE, context->ProcessId ))) { PhShowStatus(hwndDlg, L"Unable to open the process", status, 0); break; } if (context->ProcessHandle) NtClose(context->ProcessHandle); context->ProcessHandle = processHandle; context->WriteAccess = TRUE; } if (!NT_SUCCESS(status = PhWriteVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to write memory", status, 0); } } break; case IDC_REREAD: { NTSTATUS status; if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to read memory", status, 0); } InvalidateRect(context->HexEditHandle, NULL, TRUE); } break; case IDC_BYTESPERROW: if (HIWORD(wParam) == CBN_SELCHANGE) { PPH_STRING bytesPerRowString = PhaGetDlgItemText(hwndDlg, IDC_BYTESPERROW); PH_STRINGREF firstPart; PH_STRINGREF secondPart; ULONG64 bytesPerRow64; if (PhSplitStringRefAtChar(&bytesPerRowString->sr, ' ', &firstPart, &secondPart)) { if (PhStringToInteger64(&firstPart, 10, &bytesPerRow64)) { PhSetIntegerSetting(L"MemEditBytesPerRow", (ULONG)bytesPerRow64); HexEdit_SetBytesPerRow(context->HexEditHandle, (ULONG)bytesPerRow64); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SELECT_OFFSET: { HexEdit_SetEditMode(context->HexEditHandle, EDIT_ASCII); HexEdit_SetSel(context->HexEditHandle, (ULONG)wParam, (ULONG)wParam + (ULONG)lParam); } break; } return FALSE; }
INT_PTR CALLBACK PhpProcessMiniDumpDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PPROCESS_MINIDUMP_CONTEXT context = (PPROCESS_MINIDUMP_CONTEXT)lParam; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); SetDlgItemText(hwndDlg, IDC_PROGRESSTEXT, L"Creating the dump file..."); PhSetWindowStyle(GetDlgItem(hwndDlg, IDC_PROGRESS), PBS_MARQUEE, PBS_MARQUEE); SendMessage(GetDlgItem(hwndDlg, IDC_PROGRESS), PBM_SETMARQUEE, TRUE, 75); context->WindowHandle = hwndDlg; context->ThreadHandle = PhCreateThread(0, PhpProcessMiniDumpThreadStart, context); if (!context->ThreadHandle) { PhShowStatus(hwndDlg, L"Unable to create the minidump thread", 0, GetLastError()); EndDialog(hwndDlg, IDCANCEL); } SetTimer(hwndDlg, 1, 500, NULL); } break; case WM_DESTROY: { PPROCESS_MINIDUMP_CONTEXT context; context = (PPROCESS_MINIDUMP_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); NtClose(context->ThreadHandle); RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: { PPROCESS_MINIDUMP_CONTEXT context = (PPROCESS_MINIDUMP_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE); context->Stop = TRUE; } break; } } break; case WM_TIMER: { if (wParam == 1) { PPROCESS_MINIDUMP_CONTEXT context = (PPROCESS_MINIDUMP_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); ULONG currentTickCount; currentTickCount = GetTickCount(); if (currentTickCount - context->LastTickCount >= 2000) { // No status message update for 2 seconds. SetDlgItemText(hwndDlg, IDC_PROGRESSTEXT, (PWSTR)L"Creating the dump file..."); InvalidateRect(GetDlgItem(hwndDlg, IDC_PROGRESSTEXT), NULL, FALSE); context->LastTickCount = currentTickCount; } } } break; case WM_PH_MINIDUMP_STATUS_UPDATE: { PPROCESS_MINIDUMP_CONTEXT context; context = (PPROCESS_MINIDUMP_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); switch (wParam) { case PH_MINIDUMP_STATUS_UPDATE: SetDlgItemText(hwndDlg, IDC_PROGRESSTEXT, (PWSTR)lParam); InvalidateRect(GetDlgItem(hwndDlg, IDC_PROGRESSTEXT), NULL, FALSE); context->LastTickCount = GetTickCount(); break; case PH_MINIDUMP_ERROR: PhShowStatus(hwndDlg, L"Unable to create the minidump", 0, (ULONG)lParam); break; case PH_MINIDUMP_COMPLETED: EndDialog(hwndDlg, IDOK); break; } } break; } return FALSE; }
VOID PhShowThreadStackDialog( _In_ HWND ParentWindowHandle, _In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ PPH_SYMBOL_PROVIDER SymbolProvider ) { NTSTATUS status; THREAD_STACK_CONTEXT threadStackContext; HANDLE threadHandle = NULL; // If the user is trying to view a system thread stack // but KProcessHacker is not loaded, show an error message. if (ProcessId == SYSTEM_PROCESS_ID && !KphIsConnected()) { PhShowError(ParentWindowHandle, KPH_ERROR_MESSAGE); return; } memset(&threadStackContext, 0, sizeof(THREAD_STACK_CONTEXT)); threadStackContext.ProcessId = ProcessId; threadStackContext.ThreadId = ThreadId; threadStackContext.SymbolProvider = SymbolProvider; if (!NT_SUCCESS(status = PhOpenThread( &threadHandle, THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME, ThreadId ))) { if (KphIsConnected()) { status = PhOpenThread( &threadHandle, ThreadQueryAccess, ThreadId ); } } if (!NT_SUCCESS(status)) { PhShowStatus(ParentWindowHandle, L"Unable to open the thread", status, 0); return; } threadStackContext.ThreadHandle = threadHandle; threadStackContext.List = PhCreateList(10); threadStackContext.NewList = PhCreateList(10); PhInitializeQueuedLock(&threadStackContext.StatusLock); DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_THRDSTACK), ParentWindowHandle, PhpThreadStackDlgProc, (LPARAM)&threadStackContext ); PhSwapReference(&threadStackContext.StatusMessage, NULL); PhDereferenceObject(threadStackContext.NewList); PhDereferenceObject(threadStackContext.List); if (threadStackContext.ThreadHandle) NtClose(threadStackContext.ThreadHandle); }
static INT_PTR CALLBACK PhpThreadStackDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; PTHREAD_STACK_CONTEXT threadStackContext; PPH_STRING title; HWND lvHandle; PPH_LAYOUT_MANAGER layoutManager; threadStackContext = (PTHREAD_STACK_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)threadStackContext); title = PhFormatString(L"Stack - thread %u", (ULONG)threadStackContext->ThreadId); SetWindowText(hwndDlg, title->Buffer); PhDereferenceObject(title); lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 30, L" "); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 300, L"Name"); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhLoadListViewColumnsFromSetting(L"ThreadStackListViewColumns", lvHandle); threadStackContext->ListViewHandle = lvHandle; layoutManager = PhAllocate(sizeof(PH_LAYOUT_MANAGER)); PhInitializeLayoutManager(layoutManager, hwndDlg); SetProp(hwndDlg, L"LayoutManager", (HANDLE)layoutManager); PhAddLayoutItem(layoutManager, lvHandle, NULL, PH_ANCHOR_ALL); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_REFRESH), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 190; rect.bottom = 120; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } PhLoadWindowPlacementFromSetting(NULL, L"ThreadStackWindowSize", hwndDlg); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackInitializing; control.UniqueKey = threadStackContext; control.u.Initializing.ProcessId = threadStackContext->ProcessId; control.u.Initializing.ThreadId = threadStackContext->ThreadId; control.u.Initializing.ThreadHandle = threadStackContext->ThreadHandle; control.u.Initializing.SymbolProvider = threadStackContext->SymbolProvider; control.u.Initializing.CustomWalk = FALSE; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); threadStackContext->CustomWalk = control.u.Initializing.CustomWalk; } status = PhpRefreshThreadStack(hwndDlg, threadStackContext); if (status == STATUS_ABANDONED) EndDialog(hwndDlg, IDCANCEL); else if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to load the stack", status, 0); } break; case WM_DESTROY: { PPH_LAYOUT_MANAGER layoutManager; PTHREAD_STACK_CONTEXT threadStackContext; ULONG i; layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager"); PhDeleteLayoutManager(layoutManager); PhFree(layoutManager); threadStackContext = (PTHREAD_STACK_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackUninitializing; control.UniqueKey = threadStackContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } for (i = 0; i < threadStackContext->List->Count; i++) PhpFreeThreadStackItem(threadStackContext->List->Items[i]); PhSaveListViewColumnsToSetting(L"ThreadStackListViewColumns", GetDlgItem(hwndDlg, IDC_LIST)); PhSaveWindowPlacementToSetting(NULL, L"ThreadStackWindowSize", hwndDlg); RemoveProp(hwndDlg, PhMakeContextAtom()); RemoveProp(hwndDlg, L"LayoutManager"); } break; case WM_COMMAND: { INT id = LOWORD(wParam); switch (id) { case IDCANCEL: // Esc and X button to close case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_REFRESH: { NTSTATUS status; if (!NT_SUCCESS(status = PhpRefreshThreadStack( hwndDlg, (PTHREAD_STACK_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()) ))) { PhShowStatus(hwndDlg, L"Unable to load the stack", status, 0); } } break; case IDC_COPY: { HWND lvHandle; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); if (ListView_GetSelectedCount(lvHandle) == 0) PhSetStateAllListViewItems(lvHandle, LVIS_SELECTED, LVIS_SELECTED); PhCopyListView(lvHandle); SetFocus(lvHandle); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case LVN_GETINFOTIP: { LPNMLVGETINFOTIP getInfoTip = (LPNMLVGETINFOTIP)header; HWND lvHandle; PTHREAD_STACK_CONTEXT threadStackContext; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); threadStackContext = (PTHREAD_STACK_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); if (header->hwndFrom == lvHandle) { PTHREAD_STACK_ITEM stackItem; PPH_THREAD_STACK_FRAME stackFrame; if (PhGetListViewItemParam(lvHandle, getInfoTip->iItem, &stackItem)) { PH_STRING_BUILDER stringBuilder; PPH_STRING fileName; PH_SYMBOL_LINE_INFORMATION lineInfo; stackFrame = &stackItem->StackFrame; PhInitializeStringBuilder(&stringBuilder, 40); // There are no params for kernel-mode stack traces. if ((ULONG_PTR)stackFrame->PcAddress <= PhSystemBasicInformation.MaximumUserModeAddress) { PhAppendFormatStringBuilder( &stringBuilder, L"Parameters: 0x%Ix, 0x%Ix, 0x%Ix, 0x%Ix\n", stackFrame->Params[0], stackFrame->Params[1], stackFrame->Params[2], stackFrame->Params[3] ); } if (PhGetLineFromAddress( threadStackContext->SymbolProvider, (ULONG64)stackFrame->PcAddress, &fileName, NULL, &lineInfo )) { PhAppendFormatStringBuilder( &stringBuilder, L"File: %s: line %u\n", fileName->Buffer, lineInfo.LineNumber ); PhDereferenceObject(fileName); } if (stringBuilder.String->Length != 0) PhRemoveStringBuilder(&stringBuilder, stringBuilder.String->Length / 2 - 1, 1); if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackGetTooltip; control.UniqueKey = threadStackContext; control.u.GetTooltip.StackFrame = stackFrame; control.u.GetTooltip.StringBuilder = &stringBuilder; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } PhCopyListViewInfoTip(getInfoTip, &stringBuilder.String->sr); PhDeleteStringBuilder(&stringBuilder); } } } break; } } break; case WM_SIZE: { PPH_LAYOUT_MANAGER layoutManager; layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager"); PhLayoutManagerLayout(layoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; } return FALSE; }
INT_PTR CALLBACK PhpProcessMiniDumpDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PPROCESS_MINIDUMP_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = (PPROCESS_MINIDUMP_CONTEXT)lParam; PhSetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT, context); } else { context = PhGetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhSetDialogItemText(hwndDlg, IDC_PROGRESSTEXT, L"Creating the dump file..."); PhSetWindowStyle(GetDlgItem(hwndDlg, IDC_PROGRESS), PBS_MARQUEE, PBS_MARQUEE); SendMessage(GetDlgItem(hwndDlg, IDC_PROGRESS), PBM_SETMARQUEE, TRUE, 75); context->WindowHandle = hwndDlg; PhCreateThread2(PhpProcessMiniDumpThreadStart, context); SetTimer(hwndDlg, 1, 500, NULL); } break; case WM_DESTROY: { PhRemoveWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCANCEL: { EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE); context->Stop = TRUE; } break; } } break; case WM_TIMER: { if (wParam == 1) { ULONG64 currentTickCount; currentTickCount = NtGetTickCount64(); if (currentTickCount - context->LastTickCount >= 2000) { // No status message update for 2 seconds. PhSetDialogItemText(hwndDlg, IDC_PROGRESSTEXT, L"Creating the dump file..."); context->LastTickCount = currentTickCount; } } } break; case WM_PH_MINIDUMP_STATUS_UPDATE: { switch (wParam) { case PH_MINIDUMP_STATUS_UPDATE: PhSetDialogItemText(hwndDlg, IDC_PROGRESSTEXT, (PWSTR)lParam); context->LastTickCount = NtGetTickCount64(); break; case PH_MINIDUMP_ERROR: PhShowStatus(hwndDlg, L"Unable to create the minidump", 0, (ULONG)lParam); break; case PH_MINIDUMP_COMPLETED: EndDialog(hwndDlg, IDOK); break; } } break; } return FALSE; }
INT_PTR CALLBACK PhpCreateServiceDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_TYPE), PhServiceTypeStrings, sizeof(PhServiceTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_STARTTYPE), PhServiceStartTypeStrings, sizeof(PhServiceStartTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), PhServiceErrorControlStrings, sizeof(PhServiceErrorControlStrings) / sizeof(WCHAR *)); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Own Process", FALSE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_STARTTYPE), L"Demand Start", FALSE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), L"Ignore", FALSE); if (!PhElevated) { SendMessage(GetDlgItem(hwndDlg, IDOK), BCM_SETSHIELD, 0, TRUE); } SetFocus(GetDlgItem(hwndDlg, IDC_NAME)); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: { EndDialog(hwndDlg, IDCANCEL); } break; case IDOK: { NTSTATUS status = 0; BOOLEAN success = FALSE; SC_HANDLE scManagerHandle; SC_HANDLE serviceHandle; ULONG win32Result = 0; PPH_STRING serviceName; PPH_STRING serviceDisplayName; PPH_STRING serviceTypeString; PPH_STRING serviceStartTypeString; PPH_STRING serviceErrorControlString; ULONG serviceType; ULONG serviceStartType; ULONG serviceErrorControl; PPH_STRING serviceBinaryPath; serviceName = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_NAME))); serviceDisplayName = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_DISPLAYNAME))); serviceTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_TYPE))); serviceStartTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_STARTTYPE))); serviceErrorControlString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_ERRORCONTROL))); serviceType = PhGetServiceTypeInteger(serviceTypeString->Buffer); serviceStartType = PhGetServiceStartTypeInteger(serviceStartTypeString->Buffer); serviceErrorControl = PhGetServiceErrorControlInteger(serviceErrorControlString->Buffer); serviceBinaryPath = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_BINARYPATH))); if (PhElevated) { if (scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) { if (serviceHandle = CreateService( scManagerHandle, serviceName->Buffer, serviceDisplayName->Buffer, SERVICE_CHANGE_CONFIG, serviceType, serviceStartType, serviceErrorControl, serviceBinaryPath->Buffer, NULL, NULL, NULL, NULL, L"" )) { EndDialog(hwndDlg, IDOK); CloseServiceHandle(serviceHandle); success = TRUE; } else { win32Result = GetLastError(); } CloseServiceHandle(scManagerHandle); } else { win32Result = GetLastError(); } } else { if (PhUiConnectToPhSvc(hwndDlg, FALSE)) { status = PhSvcCallCreateService( serviceName->Buffer, serviceDisplayName->Buffer, serviceType, serviceStartType, serviceErrorControl, serviceBinaryPath->Buffer, NULL, NULL, NULL, NULL, L"" ); PhUiDisconnectFromPhSvc(); if (NT_SUCCESS(status)) { EndDialog(hwndDlg, IDOK); success = TRUE; } } else { // User cancelled elevation. success = TRUE; } } if (!success) PhShowStatus(hwndDlg, L"Unable to create the service", status, win32Result); } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Executable files (*.exe;*.sys)", L"*.exe;*.sys" }, { 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_BINARYPATH)); PhSetFileDialogFileName(fileDialog, fileName->Buffer); PhDereferenceObject(fileName); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_BINARYPATH, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; } } break; } return FALSE; }
static INT_PTR CALLBACK PhpInformationDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PWSTR string = (PWSTR)lParam; PPH_LAYOUT_MANAGER layoutManager; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); SetDlgItemText(hwndDlg, IDC_TEXT, string); layoutManager = PhAllocate(sizeof(PH_LAYOUT_MANAGER)); PhInitializeLayoutManager(layoutManager, hwndDlg); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_TEXT), NULL, PH_ANCHOR_ALL); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(layoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 200; rect.bottom = 140; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } SetProp(hwndDlg, L"LayoutManager", (HANDLE)layoutManager); SetProp(hwndDlg, L"String", (HANDLE)string); } break; case WM_DESTROY: { PPH_LAYOUT_MANAGER layoutManager; layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager"); PhDeleteLayoutManager(layoutManager); PhFree(layoutManager); RemoveProp(hwndDlg, L"String"); RemoveProp(hwndDlg, L"LayoutManager"); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_COPY: { HWND editControl; LONG selStart; LONG selEnd; PWSTR buffer; PH_STRINGREF string; editControl = GetDlgItem(hwndDlg, IDC_TEXT); SendMessage(editControl, EM_GETSEL, (WPARAM)&selStart, (LPARAM)&selEnd); buffer = (PWSTR)GetProp(hwndDlg, L"String"); if (selStart == selEnd) { // Select and copy the entire string. PhInitializeStringRefLongHint(&string, buffer); Edit_SetSel(editControl, 0, -1); } else { string.Buffer = buffer + selStart; string.Length = (selEnd - selStart) * 2; } PhSetClipboardString(hwndDlg, &string); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)editControl, TRUE); } break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Text files (*.txt)", L"*.txt" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, L"Information.txt"); if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; fileName = PhGetFileDialogFileName(fileDialog); PhAutoDereferenceObject(fileName); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { PH_STRINGREF string; PhWriteStringAsUtf8FileStream(fileStream, &PhUnicodeByteOrderMark); PhInitializeStringRef(&string, (PWSTR)GetProp(hwndDlg, L"String")); PhWriteStringAsUtf8FileStream(fileStream, &string); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; } } break; case WM_SIZE: { PPH_LAYOUT_MANAGER layoutManager; layoutManager = (PPH_LAYOUT_MANAGER)GetProp(hwndDlg, L"LayoutManager"); PhLayoutManagerLayout(layoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; } return FALSE; }
INT WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ INT nCmdShow ) { LONG result; #ifdef DEBUG PHP_BASE_THREAD_DBG dbg; #endif CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #ifndef DEBUG SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); #endif PhInstanceHandle = (HINSTANCE)NtCurrentPeb()->ImageBaseAddress; if (!NT_SUCCESS(PhInitializePhLib())) return 1; if (!PhInitializeAppSystem()) return 1; PhInitializeCommonControls(); if (PhCurrentTokenQueryHandle) { PTOKEN_USER tokenUser; if (NT_SUCCESS(PhGetTokenUser(PhCurrentTokenQueryHandle, &tokenUser))) { PhCurrentUserName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL); PhFree(tokenUser); } } PhLocalSystemName = PhGetSidFullName(&PhSeLocalSystemSid, TRUE, NULL); // There has been a report of the above call failing. if (!PhLocalSystemName) PhLocalSystemName = PhCreateString(L"NT AUTHORITY\\SYSTEM"); PhApplicationFileName = PhGetApplicationFileName(); PhApplicationDirectory = PhGetApplicationDirectory(); // Just in case if (!PhApplicationFileName) PhApplicationFileName = PhCreateString(L"ProcessHacker.exe"); if (!PhApplicationDirectory) PhApplicationDirectory = PhReferenceEmptyString(); PhpProcessStartupParameters(); PhSettingsInitialization(); PhpEnablePrivileges(); if (PhStartupParameters.RunAsServiceMode) { RtlExitUserProcess(PhRunAsServiceStart(PhStartupParameters.RunAsServiceMode)); } PhpInitializeSettings(); // Activate a previous instance if required. if (PhGetIntegerSetting(L"AllowOnlyOneInstance") && !PhStartupParameters.NewInstance && !PhStartupParameters.ShowOptions && !PhStartupParameters.CommandMode && !PhStartupParameters.PhSvc) { PhActivatePreviousInstance(); } if (PhGetIntegerSetting(L"EnableKph") && !PhStartupParameters.NoKph && !PhIsExecutingInWow64()) PhInitializeKph(); if (PhStartupParameters.CommandMode && PhStartupParameters.CommandType && PhStartupParameters.CommandAction) { NTSTATUS status; status = PhCommandModeStart(); if (!NT_SUCCESS(status) && !PhStartupParameters.Silent) { PhShowStatus(NULL, L"Unable to execute the command", status, 0); } RtlExitUserProcess(status); } #ifdef DEBUG dbg.ClientId = NtCurrentTeb()->ClientId; dbg.StartAddress = wWinMain; dbg.Parameter = NULL; InsertTailList(&PhDbgThreadListHead, &dbg.ListEntry); TlsSetValue(PhDbgThreadDbgTlsIndex, &dbg); #endif PhInitializeAutoPool(&BaseAutoPool); PhEmInitialization(); PhGuiSupportInitialization(); PhTreeNewInitialization(); PhGraphControlInitialization(); PhHexEditInitialization(); PhColorBoxInitialization(); PhSmallIconSize.X = GetSystemMetrics(SM_CXSMICON); PhSmallIconSize.Y = GetSystemMetrics(SM_CYSMICON); PhLargeIconSize.X = GetSystemMetrics(SM_CXICON); PhLargeIconSize.Y = GetSystemMetrics(SM_CYICON); if (PhStartupParameters.ShowOptions) { // Elevated options dialog for changing the value of Replace Task Manager with Process Hacker. PhShowOptionsDialog(PhStartupParameters.WindowHandle); RtlExitUserProcess(STATUS_SUCCESS); } #ifndef DEBUG if (PhIsExecutingInWow64() && !PhStartupParameters.PhSvc) { PhShowWarning( NULL, L"You are attempting to run the 32-bit version of Process Hacker on 64-bit Windows. " L"Most features will not work correctly.\n\n" L"Please run the 64-bit version of Process Hacker instead." ); } #endif PhPluginsEnabled = PhGetIntegerSetting(L"EnablePlugins") && !PhStartupParameters.NoPlugins; if (PhPluginsEnabled) { PhPluginsInitialization(); PhLoadPlugins(); } if (PhStartupParameters.PhSvc) { MSG message; // Turn the feedback cursor off. PostMessage(NULL, WM_NULL, 0, 0); GetMessage(&message, NULL, 0, 0); RtlExitUserProcess(PhSvcMain(NULL, NULL, NULL)); } // Create a mutant for the installer. { HANDLE mutantHandle; OBJECT_ATTRIBUTES oa; UNICODE_STRING mutantName; RtlInitUnicodeString(&mutantName, L"\\BaseNamedObjects\\ProcessHacker2Mutant"); InitializeObjectAttributes( &oa, &mutantName, 0, NULL, NULL ); NtCreateMutant(&mutantHandle, MUTANT_ALL_ACCESS, &oa, FALSE); } // Set priority. { PROCESS_PRIORITY_CLASS priorityClass; priorityClass.Foreground = FALSE; priorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; if (PhStartupParameters.PriorityClass != 0) priorityClass.PriorityClass = (UCHAR)PhStartupParameters.PriorityClass; NtSetInformationProcess(NtCurrentProcess(), ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS)); } if (!PhMainWndInitialization(nCmdShow)) { PhShowError(NULL, L"Unable to initialize the main window."); return 1; } PhDrainAutoPool(&BaseAutoPool); result = PhMainMessageLoop(); RtlExitUserProcess(result); }
INT_PTR CALLBACK PhpLogDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(ListViewHandle, FALSE, TRUE); PhSetControlTheme(ListViewHandle, L"explorer"); PhAddListViewColumn(ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 140, L"Time"); PhAddListViewColumn(ListViewHandle, 1, 1, 1, LVCFMT_LEFT, 260, L"Message"); PhLoadListViewColumnsFromSetting(L"LogListViewColumns", ListViewHandle); PhInitializeLayoutManager(&WindowLayoutManager, hwndDlg); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_LIST), NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_AUTOSCROLL), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_CLEAR), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); MinimumSize.left = 0; MinimumSize.top = 0; MinimumSize.right = 290; MinimumSize.bottom = 150; MapDialogRect(hwndDlg, &MinimumSize); PhLoadWindowPlacementFromSetting(L"LogWindowPosition", L"LogWindowSize", hwndDlg); Button_SetCheck(GetDlgItem(hwndDlg, IDC_AUTOSCROLL), BST_CHECKED); PhRegisterCallback(&PhLoggedCallback, LoggedCallback, NULL, &LoggedRegistration); PhpUpdateLogList(); ListView_EnsureVisible(ListViewHandle, ListViewCount - 1, FALSE); } break; case WM_DESTROY: { PhSaveListViewColumnsToSetting(L"LogListViewColumns", ListViewHandle); PhSaveWindowPlacementToSetting(L"LogWindowPosition", L"LogWindowSize", hwndDlg); PhDeleteLayoutManager(&WindowLayoutManager); PhUnregisterCallback(&PhLoggedCallback, &LoggedRegistration); PhUnregisterDialog(PhLogWindowHandle); PhLogWindowHandle = NULL; } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_CLEAR: { PhClearLogEntries(); PhpUpdateLogList(); } break; case IDC_COPY: { PPH_STRING string; ULONG selectedCount; selectedCount = ListView_GetSelectedCount(ListViewHandle); if (selectedCount == 0) { // User didn't select anything, so copy all items. string = PhpGetStringForSelectedLogEntries(TRUE); PhSetStateAllListViewItems(ListViewHandle, LVIS_SELECTED, LVIS_SELECTED); } else { string = PhpGetStringForSelectedLogEntries(FALSE); } PhSetClipboardStringEx(hwndDlg, string->Buffer, string->Length); PhDereferenceObject(string); SetFocus(ListViewHandle); } break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Text files (*.txt)", L"*.txt" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, L"Process Hacker Log.txt"); if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; PPH_STRING string; fileName = PhGetFileDialogFileName(fileDialog); PhaDereferenceObject(fileName); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { PhWritePhTextHeader(fileStream); string = PhpGetStringForSelectedLogEntries(TRUE); PhWriteStringAsAnsiFileStreamEx(fileStream, string->Buffer, string->Length); PhDereferenceObject(string); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case LVN_GETDISPINFO: { NMLVDISPINFO *dispInfo = (NMLVDISPINFO *)header; PPH_LOG_ENTRY entry; entry = PhGetItemCircularBuffer_PVOID(&PhLogBuffer, ListViewCount - dispInfo->item.iItem - 1); if (dispInfo->item.iSubItem == 0) { if (dispInfo->item.mask & LVIF_TEXT) { SYSTEMTIME systemTime; PPH_STRING dateTime; PhLargeIntegerToLocalSystemTime(&systemTime, &entry->Time); dateTime = PhFormatDateTime(&systemTime); wcsncpy_s(dispInfo->item.pszText, dispInfo->item.cchTextMax, dateTime->Buffer, _TRUNCATE); PhDereferenceObject(dateTime); } } else if (dispInfo->item.iSubItem == 1) { if (dispInfo->item.mask & LVIF_TEXT) { PPH_STRING string; string = PhFormatLogEntry(entry); wcsncpy_s(dispInfo->item.pszText, dispInfo->item.cchTextMax, string->Buffer, _TRUNCATE); PhDereferenceObject(string); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&WindowLayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_LOG_UPDATED: { PhpUpdateLogList(); } break; } return FALSE; }
INT_PTR CALLBACK PhpProcessMemoryDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PPH_MEMORY_CONTEXT memoryContext; HWND tnHandle; if (PhpPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { memoryContext = (PPH_MEMORY_CONTEXT)propPageContext->Context; if (memoryContext) tnHandle = memoryContext->ListContext.TreeNewHandle; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { memoryContext = propPageContext->Context = PhAllocate(PhEmGetObjectSize(EmMemoryContextType, sizeof(PH_MEMORY_CONTEXT))); memset(memoryContext, 0, sizeof(PH_MEMORY_CONTEXT)); memoryContext->ProcessId = processItem->ProcessId; // Initialize the list. tnHandle = GetDlgItem(hwndDlg, IDC_LIST); BringWindowToTop(tnHandle); PhInitializeMemoryList(hwndDlg, tnHandle, &memoryContext->ListContext); TreeNew_SetEmptyText(tnHandle, &PhpLoadingText, 0); memoryContext->LastRunStatus = -1; memoryContext->ErrorMessage = NULL; PhEmCallObjectOperation(EmMemoryContextType, memoryContext, EmObjectCreate); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &memoryContext->ListContext.Cm; treeNewInfo.SystemContext = memoryContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMemoryTreeNewInitializing), &treeNewInfo); } PhLoadSettingsMemoryList(&memoryContext->ListContext); PhSetOptionsMemoryList(&memoryContext->ListContext, TRUE); Button_SetCheck(GetDlgItem(hwndDlg, IDC_HIDEFREEREGIONS), memoryContext->ListContext.HideFreeRegions ? BST_CHECKED : BST_UNCHECKED); PhpRefreshProcessMemoryList(hwndDlg, propPageContext); } break; case WM_DESTROY: { PhEmCallObjectOperation(EmMemoryContextType, memoryContext, EmObjectDelete); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &memoryContext->ListContext.Cm; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMemoryTreeNewUninitializing), &treeNewInfo); } PhSaveSettingsMemoryList(&memoryContext->ListContext); PhDeleteMemoryList(&memoryContext->ListContext); if (memoryContext->MemoryItemListValid) PhDeleteMemoryItemList(&memoryContext->MemoryItemList); PhClearReference(&memoryContext->ErrorMessage); PhFree(memoryContext); PhpPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { if (!propPageContext->LayoutInitialized) { PPH_LAYOUT_ITEM dialogItem; dialogItem = PhAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_STRINGS), dialogItem, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_REFRESH), dialogItem, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddPropPageLayoutItem(hwndDlg, memoryContext->ListContext.TreeNewHandle, dialogItem, PH_ANCHOR_ALL); PhDoPropPageLayout(hwndDlg); propPageContext->LayoutInitialized = TRUE; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_SHOWCONTEXTMENU: { PhShowMemoryContextMenu(hwndDlg, processItem, memoryContext, (PPH_TREENEW_CONTEXT_MENU)lParam); } break; case ID_MEMORY_READWRITEMEMORY: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode && !memoryNode->IsAllocationBase) { if (memoryNode->MemoryItem->State & MEM_COMMIT) { PPH_SHOWMEMORYEDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR)); memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR)); showMemoryEditor->ProcessId = processItem->ProcessId; showMemoryEditor->BaseAddress = memoryNode->MemoryItem->BaseAddress; showMemoryEditor->RegionSize = memoryNode->MemoryItem->RegionSize; showMemoryEditor->SelectOffset = -1; showMemoryEditor->SelectLength = 0; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); } else { PhShowError(hwndDlg, L"Unable to edit the memory region because it is not committed."); } } } break; case ID_MEMORY_SAVE: { NTSTATUS status; HANDLE processHandle; PPH_MEMORY_NODE *memoryNodes; ULONG numberOfMemoryNodes; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_READ, processItem->ProcessId ))) { PhShowStatus(hwndDlg, L"Unable to open the process", status, 0); break; } PhGetSelectedMemoryNodes(&memoryContext->ListContext, &memoryNodes, &numberOfMemoryNodes); if (numberOfMemoryNodes != 0) { static PH_FILETYPE_FILTER filters[] = { { L"Binary files (*.bin)", L"*.bin" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, PhaConcatStrings2(processItem->ProcessName->Buffer, L".bin")->Buffer); if (PhShowFileDialog(hwndDlg, fileDialog)) { PPH_STRING fileName; PPH_FILE_STREAM fileStream; PVOID buffer; ULONG i; ULONG_PTR offset; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { buffer = PhAllocatePage(PAGE_SIZE, NULL); // Go through each selected memory item and append the region contents // to the file. for (i = 0; i < numberOfMemoryNodes; i++) { PPH_MEMORY_NODE memoryNode = memoryNodes[i]; PPH_MEMORY_ITEM memoryItem = memoryNode->MemoryItem; if (!memoryNode->IsAllocationBase && !(memoryItem->State & MEM_COMMIT)) continue; for (offset = 0; offset < memoryItem->RegionSize; offset += PAGE_SIZE) { if (NT_SUCCESS(NtReadVirtualMemory( processHandle, PTR_ADD_OFFSET(memoryItem->BaseAddress, offset), buffer, PAGE_SIZE, NULL ))) { PhWriteFileStream(fileStream, buffer, PAGE_SIZE); } } } PhFreePage(buffer); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } PhFree(memoryNodes); NtClose(processHandle); } break; case ID_MEMORY_CHANGEPROTECTION: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode) { PhReferenceObject(memoryNode->MemoryItem); PhShowMemoryProtectDialog(hwndDlg, processItem, memoryNode->MemoryItem); PhUpdateMemoryNode(&memoryContext->ListContext, memoryNode); PhDereferenceObject(memoryNode->MemoryItem); } } break; case ID_MEMORY_FREE: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode) { PhReferenceObject(memoryNode->MemoryItem); PhUiFreeMemory(hwndDlg, processItem->ProcessId, memoryNode->MemoryItem, TRUE); PhDereferenceObject(memoryNode->MemoryItem); // TODO: somehow update the list } } break; case ID_MEMORY_DECOMMIT: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode) { PhReferenceObject(memoryNode->MemoryItem); PhUiFreeMemory(hwndDlg, processItem->ProcessId, memoryNode->MemoryItem, FALSE); PhDereferenceObject(memoryNode->MemoryItem); } } break; case ID_MEMORY_READWRITEADDRESS: { PPH_STRING selectedChoice = NULL; if (!memoryContext->MemoryItemListValid) break; while (PhaChoiceDialog( hwndDlg, L"Read/Write Address", L"Enter an address:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemoryReadWriteAddressChoices" )) { ULONG64 address64; PVOID address; if (selectedChoice->Length == 0) continue; if (PhStringToInteger64(&selectedChoice->sr, 0, &address64)) { PPH_MEMORY_ITEM memoryItem; address = (PVOID)address64; memoryItem = PhLookupMemoryItemList(&memoryContext->MemoryItemList, address); if (memoryItem) { PPH_SHOWMEMORYEDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR)); memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR)); showMemoryEditor->ProcessId = processItem->ProcessId; showMemoryEditor->BaseAddress = memoryItem->BaseAddress; showMemoryEditor->RegionSize = memoryItem->RegionSize; showMemoryEditor->SelectOffset = (ULONG)((ULONG_PTR)address - (ULONG_PTR)memoryItem->BaseAddress); showMemoryEditor->SelectLength = 0; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); break; } else { PhShowError(hwndDlg, L"Unable to find the memory region for the selected address."); } } } } break; case ID_MEMORY_COPY: { PPH_STRING text; text = PhGetTreeNewText(tnHandle, 0); PhSetClipboardString(tnHandle, &text->sr); PhDereferenceObject(text); } break; case IDC_HIDEFREEREGIONS: { BOOLEAN hide; hide = Button_GetCheck(GetDlgItem(hwndDlg, IDC_HIDEFREEREGIONS)) == BST_CHECKED; PhSetOptionsMemoryList(&memoryContext->ListContext, hide); } break; case IDC_STRINGS: PhShowMemoryStringDialog(hwndDlg, processItem); break; case IDC_REFRESH: PhpRefreshProcessMemoryList(hwndDlg, propPageContext); break; } } break; } return FALSE; }
VOID NTAPI MenuItemCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PPH_PLUGIN_MENU_ITEM menuItem = Parameter; switch (menuItem->Id) { case CRITICAL_MENU_ITEM: { NTSTATUS status; PPH_PROCESS_ITEM processItem = menuItem->Context; HANDLE processHandle; ULONG breakOnTermination; if (NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, processItem->ProcessId))) { if (NT_SUCCESS(status = NtQueryInformationProcess(processHandle, ProcessBreakOnTermination, &breakOnTermination, sizeof(ULONG), NULL))) { if (!breakOnTermination && PhShowConfirmMessage( menuItem->OwnerWindow, L"enable", L"critical status on the process", L"If the process ends, the operating system will shut down immediately.", TRUE )) { breakOnTermination = TRUE; status = NtSetInformationProcess(processHandle, ProcessBreakOnTermination, &breakOnTermination, sizeof(ULONG)); } else if (breakOnTermination && PhShowConfirmMessage( menuItem->OwnerWindow, L"disable", L"critical status on the process", NULL, FALSE )) { breakOnTermination = FALSE; status = NtSetInformationProcess(processHandle, ProcessBreakOnTermination, &breakOnTermination, sizeof(ULONG)); } if (!NT_SUCCESS(status)) PhShowStatus(menuItem->OwnerWindow, L"Unable to set critical status", status, 0); } else { PhShowStatus(menuItem->OwnerWindow, L"Unable to query critical status", status, 0); } NtClose(processHandle); } else { PhShowStatus(menuItem->OwnerWindow, L"Unable to open the process", status, 0); } } break; } }
INT_PTR CALLBACK PhpJobPageProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PJOB_PAGE_CONTEXT jobPageContext; jobPageContext = PhpJobPageHeader(hwndDlg, uMsg, wParam, lParam); if (!jobPageContext) return FALSE; if (jobPageContext->HookProc) { if (jobPageContext->HookProc(hwndDlg, uMsg, wParam, lParam)) return TRUE; } switch (uMsg) { case WM_INITDIALOG: { HANDLE jobHandle; HWND processesLv; HWND limitsLv; processesLv = GetDlgItem(hwndDlg, IDC_PROCESSES); limitsLv = GetDlgItem(hwndDlg, IDC_LIMITS); PhSetListViewStyle(processesLv, FALSE, TRUE); PhSetListViewStyle(limitsLv, FALSE, TRUE); PhSetControlTheme(processesLv, L"explorer"); PhSetControlTheme(limitsLv, L"explorer"); PhAddListViewColumn(processesLv, 0, 0, 0, LVCFMT_LEFT, 240, L"Name"); PhAddListViewColumn(limitsLv, 0, 0, 0, LVCFMT_LEFT, 120, L"Name"); PhAddListViewColumn(limitsLv, 1, 1, 1, LVCFMT_LEFT, 160, L"Value"); SetDlgItemText(hwndDlg, IDC_NAME, L"Unknown"); if (NT_SUCCESS(jobPageContext->OpenObject( &jobHandle, JOB_OBJECT_QUERY, jobPageContext->Context ))) { PPH_STRING jobObjectName = NULL; JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedLimits; JOBOBJECT_BASIC_UI_RESTRICTIONS basicUiRestrictions; // Name PhGetHandleInformation( NtCurrentProcess(), jobHandle, -1, NULL, NULL, NULL, &jobObjectName ); PHA_DEREFERENCE(jobObjectName); if (jobObjectName && jobObjectName->Length == 0) jobObjectName = NULL; SetDlgItemText(hwndDlg, IDC_NAME, PhGetStringOrDefault(jobObjectName, L"(unnamed job)")); // Processes PhpAddJobProcesses(hwndDlg, jobHandle); // Limits if (NT_SUCCESS(PhGetJobExtendedLimits(jobHandle, &extendedLimits))) { ULONG flags = extendedLimits.BasicLimitInformation.LimitFlags; if (flags & JOB_OBJECT_LIMIT_ACTIVE_PROCESS) { WCHAR value[PH_INT32_STR_LEN_1]; PhPrintUInt32(value, extendedLimits.BasicLimitInformation.ActiveProcessLimit); PhpAddLimit(limitsLv, L"Active Processes", value); } if (flags & JOB_OBJECT_LIMIT_AFFINITY) { WCHAR value[PH_PTR_STR_LEN_1]; PhPrintPointer(value, (PVOID)extendedLimits.BasicLimitInformation.Affinity); PhpAddLimit(limitsLv, L"Affinity", value); } if (flags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) { PhpAddLimit(limitsLv, L"Breakaway OK", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION) { PhpAddLimit(limitsLv, L"Die on Unhandled Exception", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_JOB_MEMORY) { PPH_STRING value = PhFormatSize(extendedLimits.JobMemoryLimit, -1); PhpAddLimit(limitsLv, L"Job Memory", value->Buffer); PhDereferenceObject(value); } if (flags & JOB_OBJECT_LIMIT_JOB_TIME) { WCHAR value[PH_TIMESPAN_STR_LEN_1]; PhPrintTimeSpan(value, extendedLimits.BasicLimitInformation.PerJobUserTimeLimit.QuadPart, PH_TIMESPAN_DHMS); PhpAddLimit(limitsLv, L"Job Time", value); } if (flags & JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE) { PhpAddLimit(limitsLv, L"Kill on Job Close", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_PRIORITY_CLASS) { PhpAddLimit(limitsLv, L"Priority Class", PhGetProcessPriorityClassString(extendedLimits.BasicLimitInformation.PriorityClass)); } if (flags & JOB_OBJECT_LIMIT_PROCESS_MEMORY) { PPH_STRING value = PhFormatSize(extendedLimits.ProcessMemoryLimit, -1); PhpAddLimit(limitsLv, L"Process Memory", value->Buffer); PhDereferenceObject(value); } if (flags & JOB_OBJECT_LIMIT_PROCESS_TIME) { WCHAR value[PH_TIMESPAN_STR_LEN_1]; PhPrintTimeSpan(value, extendedLimits.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart, PH_TIMESPAN_DHMS); PhpAddLimit(limitsLv, L"Process Time", value); } if (flags & JOB_OBJECT_LIMIT_SCHEDULING_CLASS) { WCHAR value[PH_INT32_STR_LEN_1]; PhPrintUInt32(value, extendedLimits.BasicLimitInformation.SchedulingClass); PhpAddLimit(limitsLv, L"Scheduling Class", value); } if (flags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK) { PhpAddLimit(limitsLv, L"Silent Breakaway OK", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_WORKINGSET) { PPH_STRING value; value = PhFormatSize(extendedLimits.BasicLimitInformation.MinimumWorkingSetSize, -1); PhpAddLimit(limitsLv, L"Working Set Minimum", value->Buffer); PhDereferenceObject(value); value = PhFormatSize(extendedLimits.BasicLimitInformation.MaximumWorkingSetSize, -1); PhpAddLimit(limitsLv, L"Working Set Maximum", value->Buffer); PhDereferenceObject(value); } } if (NT_SUCCESS(PhGetJobBasicUiRestrictions(jobHandle, &basicUiRestrictions))) { ULONG flags = basicUiRestrictions.UIRestrictionsClass; if (flags & JOB_OBJECT_UILIMIT_DESKTOP) PhpAddLimit(limitsLv, L"Desktop", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_DISPLAYSETTINGS) PhpAddLimit(limitsLv, L"Display Settings", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_EXITWINDOWS) PhpAddLimit(limitsLv, L"Exit Windows", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_GLOBALATOMS) PhpAddLimit(limitsLv, L"Global Atoms", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_HANDLES) PhpAddLimit(limitsLv, L"Handles", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_READCLIPBOARD) PhpAddLimit(limitsLv, L"Read Clipboard", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS) PhpAddLimit(limitsLv, L"System Parameters", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_WRITECLIPBOARD) PhpAddLimit(limitsLv, L"Write Clipboard", L"Limited"); } NtClose(jobHandle); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_TERMINATE: { if (PhShowConfirmMessage( hwndDlg, L"terminate", L"the job", L"Terminating a job will terminate all processes assigned to it.", TRUE )) { NTSTATUS status; HANDLE jobHandle; if (NT_SUCCESS(status = jobPageContext->OpenObject( &jobHandle, JOB_OBJECT_TERMINATE, jobPageContext->Context ))) { status = NtTerminateJobObject(jobHandle, STATUS_SUCCESS); NtClose(jobHandle); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to terminate the job", status, 0); } } break; case IDC_ADD: { NTSTATUS status; HANDLE processId; HANDLE processHandle; HANDLE jobHandle; while (PhShowChooseProcessDialog( hwndDlg, L"Select a process to add to the job permanently.", &processId )) { if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_TERMINATE | PROCESS_SET_QUOTA, processId ))) { if (NT_SUCCESS(status = jobPageContext->OpenObject( &jobHandle, JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_QUERY, jobPageContext->Context ))) { status = NtAssignProcessToJobObject(jobHandle, processHandle); if (NT_SUCCESS(status)) { ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_PROCESSES)); PhpAddJobProcesses(hwndDlg, jobHandle); } NtClose(jobHandle); } NtClose(processHandle); } if (NT_SUCCESS(status)) break; else PhShowStatus(hwndDlg, L"Unable to add the process to the job", status, 0); } } break; case IDC_ADVANCED: { PhpShowJobAdvancedProperties(hwndDlg, jobPageContext); } break; } } break; case WM_NOTIFY: { PhHandleListViewNotifyBehaviors(lParam, GetDlgItem(hwndDlg, IDC_PROCESSES), PH_LIST_VIEW_DEFAULT_1_BEHAVIORS); PhHandleListViewNotifyBehaviors(lParam, GetDlgItem(hwndDlg, IDC_LIMITS), PH_LIST_VIEW_DEFAULT_1_BEHAVIORS); } break; } return FALSE; }
INT_PTR CALLBACK PhpRunAsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PRUNAS_DIALOG_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = (PRUNAS_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PRUNAS_DIALOG_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND typeComboBoxHandle = GetDlgItem(hwndDlg, IDC_TYPE); HWND userNameComboBoxHandle = GetDlgItem(hwndDlg, IDC_USERNAME); ULONG sessionId; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); if (SHAutoComplete_I) { SHAutoComplete_I( GetDlgItem(hwndDlg, IDC_PROGRAM), SHACF_AUTOAPPEND_FORCE_ON | SHACF_AUTOSUGGEST_FORCE_ON | SHACF_FILESYS_ONLY ); } ComboBox_AddString(typeComboBoxHandle, L"Batch"); ComboBox_AddString(typeComboBoxHandle, L"Interactive"); ComboBox_AddString(typeComboBoxHandle, L"Network"); ComboBox_AddString(typeComboBoxHandle, L"New credentials"); ComboBox_AddString(typeComboBoxHandle, L"Service"); PhSelectComboBoxString(typeComboBoxHandle, L"Interactive", FALSE); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\SYSTEM"); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\LOCAL SERVICE"); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\NETWORK SERVICE"); PhpAddAccountsToComboBox(userNameComboBoxHandle); if (NT_SUCCESS(PhGetProcessSessionId(NtCurrentProcess(), &sessionId))) SetDlgItemInt(hwndDlg, IDC_SESSIONID, sessionId, FALSE); SetDlgItemText(hwndDlg, IDC_DESKTOP, L"WinSta0\\Default"); SetDlgItemText(hwndDlg, IDC_PROGRAM, PhaGetStringSetting(L"RunAsProgram")->Buffer); if (!context->ProcessId) { SetDlgItemText(hwndDlg, IDC_USERNAME, PH_AUTO_T(PH_STRING, PhGetStringSetting(L"RunAsUserName"))->Buffer); // Fire the user name changed event so we can fix the logon type. SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_USERNAME, CBN_EDITCHANGE), 0); } else { HANDLE processHandle; HANDLE tokenHandle; PTOKEN_USER user; PPH_STRING userName; if (NT_SUCCESS(PhOpenProcess( &processHandle, ProcessQueryAccess, context->ProcessId ))) { if (NT_SUCCESS(PhOpenProcessToken( processHandle, TOKEN_QUERY, &tokenHandle ))) { if (NT_SUCCESS(PhGetTokenUser(tokenHandle, &user))) { if (userName = PhGetSidFullName(user->User.Sid, TRUE, NULL)) { SetDlgItemText(hwndDlg, IDC_USERNAME, userName->Buffer); PhDereferenceObject(userName); } PhFree(user); } NtClose(tokenHandle); } NtClose(processHandle); } EnableWindow(GetDlgItem(hwndDlg, IDC_USERNAME), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TYPE), FALSE); } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_PROGRAM), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_PROGRAM), 0, -1); //if (!PhGetOwnTokenAttributes().Elevated) // SendMessage(GetDlgItem(hwndDlg, IDOK), BCM_SETSHIELD, 0, TRUE); if (!WINDOWS_HAS_UAC) ShowWindow(GetDlgItem(hwndDlg, IDC_TOGGLEELEVATION), SW_HIDE); } break; case WM_DESTROY: { if (context->DesktopList) PhDereferenceObject(context->DesktopList); RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { NTSTATUS status; PPH_STRING program; PPH_STRING userName; PPH_STRING password; PPH_STRING logonTypeString; ULONG logonType; ULONG sessionId; PPH_STRING desktopName; BOOLEAN useLinkedToken; program = PhaGetDlgItemText(hwndDlg, IDC_PROGRAM); userName = PhaGetDlgItemText(hwndDlg, IDC_USERNAME); logonTypeString = PhaGetDlgItemText(hwndDlg, IDC_TYPE); // Fix up the user name if it doesn't have a domain. if (PhFindCharInString(userName, 0, '\\') == -1) { PSID sid; PPH_STRING newUserName; if (NT_SUCCESS(PhLookupName(&userName->sr, &sid, NULL, NULL))) { if (newUserName = PH_AUTO(PhGetSidFullName(sid, TRUE, NULL))) userName = newUserName; PhFree(sid); } } if (!IsServiceAccount(userName)) password = PhGetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD)); else password = NULL; sessionId = GetDlgItemInt(hwndDlg, IDC_SESSIONID, NULL, FALSE); desktopName = PhaGetDlgItemText(hwndDlg, IDC_DESKTOP); if (WINDOWS_HAS_UAC) useLinkedToken = Button_GetCheck(GetDlgItem(hwndDlg, IDC_TOGGLEELEVATION)) == BST_CHECKED; else useLinkedToken = FALSE; if (PhFindIntegerSiKeyValuePairs( PhpLogonTypePairs, sizeof(PhpLogonTypePairs), logonTypeString->Buffer, &logonType )) { if ( logonType == LOGON32_LOGON_INTERACTIVE && !context->ProcessId && sessionId == NtCurrentPeb()->SessionId && !useLinkedToken ) { // We are eligible to load the user profile. // This must be done here, not in the service, because // we need to be in the target session. PH_CREATE_PROCESS_AS_USER_INFO createInfo; PPH_STRING domainPart; PPH_STRING userPart; PhpSplitUserName(userName->Buffer, &domainPart, &userPart); memset(&createInfo, 0, sizeof(PH_CREATE_PROCESS_AS_USER_INFO)); createInfo.CommandLine = program->Buffer; createInfo.UserName = userPart->Buffer; createInfo.DomainName = domainPart->Buffer; createInfo.Password = PhGetStringOrEmpty(password); // Whenever we can, try not to set the desktop name; it breaks a lot of things. // Note that on XP we must set it, otherwise the program doesn't display correctly. if (WindowsVersion < WINDOWS_VISTA || (desktopName->Length != 0 && !PhEqualString2(desktopName, L"WinSta0\\Default", TRUE))) createInfo.DesktopName = desktopName->Buffer; PhSetDesktopWinStaAccess(); status = PhCreateProcessAsUser( &createInfo, PH_CREATE_PROCESS_WITH_PROFILE, NULL, NULL, NULL ); if (domainPart) PhDereferenceObject(domainPart); if (userPart) PhDereferenceObject(userPart); } else { status = PhExecuteRunAsCommand2( hwndDlg, program->Buffer, userName->Buffer, PhGetStringOrEmpty(password), logonType, context->ProcessId, sessionId, desktopName->Buffer, useLinkedToken ); } } else { status = STATUS_INVALID_PARAMETER; } if (password) { RtlSecureZeroMemory(password->Buffer, password->Length); PhDereferenceObject(password); } if (!NT_SUCCESS(status)) { if (status != STATUS_CANCELLED) PhShowStatus(hwndDlg, L"Unable to start the program", status, 0); } else if (status != STATUS_TIMEOUT) { PhSetStringSetting2(L"RunAsProgram", &program->sr); PhSetStringSetting2(L"RunAsUserName", &userName->sr); EndDialog(hwndDlg, IDOK); } } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Programs (*.exe;*.pif;*.com;*.bat)", L"*.exe;*.pif;*.com;*.bat" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, PhaGetDlgItemText(hwndDlg, IDC_PROGRAM)->Buffer); if (PhShowFileDialog(hwndDlg, fileDialog)) { PPH_STRING fileName; fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_PROGRAM, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; case IDC_USERNAME: { PPH_STRING userName = NULL; if (!context->ProcessId && HIWORD(wParam) == CBN_SELCHANGE) { userName = PH_AUTO(PhGetComboBoxString(GetDlgItem(hwndDlg, IDC_USERNAME), -1)); } else if (!context->ProcessId && ( HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_CLOSEUP )) { userName = PhaGetDlgItemText(hwndDlg, IDC_USERNAME); } if (userName) { if (IsServiceAccount(userName)) { EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE); // Hack for Windows XP if ( PhEqualString2(userName, L"NT AUTHORITY\\SYSTEM", TRUE) && WindowsVersion <= WINDOWS_XP ) { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"New credentials", FALSE); } else { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Service", FALSE); } } else { EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Interactive", FALSE); } } } break; case IDC_SESSIONS: { PPH_EMENU sessionsMenu; PSESSIONIDW sessions; ULONG numberOfSessions; ULONG i; RECT buttonRect; PPH_EMENU_ITEM selectedItem; sessionsMenu = PhCreateEMenu(); if (WinStationEnumerateW(NULL, &sessions, &numberOfSessions)) { for (i = 0; i < numberOfSessions; i++) { PPH_STRING menuString; WINSTATIONINFORMATION winStationInfo; ULONG returnLength; if (!WinStationQueryInformationW( NULL, sessions[i].SessionId, WinStationInformation, &winStationInfo, sizeof(WINSTATIONINFORMATION), &returnLength )) { winStationInfo.Domain[0] = 0; winStationInfo.UserName[0] = 0; } if ( winStationInfo.UserName[0] != 0 && sessions[i].WinStationName[0] != 0 ) { menuString = PhaFormatString( L"%u: %s (%s\\%s)", sessions[i].SessionId, sessions[i].WinStationName, winStationInfo.Domain, winStationInfo.UserName ); } else if (winStationInfo.UserName[0] != 0) { menuString = PhaFormatString( L"%u: %s\\%s", sessions[i].SessionId, winStationInfo.Domain, winStationInfo.UserName ); } else if (sessions[i].WinStationName[0] != 0) { menuString = PhaFormatString( L"%u: %s", sessions[i].SessionId, sessions[i].WinStationName ); } else { menuString = PhaFormatString(L"%u", sessions[i].SessionId); } PhInsertEMenuItem(sessionsMenu, PhCreateEMenuItem(0, 0, menuString->Buffer, NULL, UlongToPtr(sessions[i].SessionId)), -1); } WinStationFreeMemory(sessions); GetWindowRect(GetDlgItem(hwndDlg, IDC_SESSIONS), &buttonRect); selectedItem = PhShowEMenu( sessionsMenu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, buttonRect.right, buttonRect.top ); if (selectedItem) { SetDlgItemInt( hwndDlg, IDC_SESSIONID, PtrToUlong(selectedItem->Context), FALSE ); } PhDestroyEMenu(sessionsMenu); } } break; case IDC_DESKTOPS: { PPH_EMENU desktopsMenu; ULONG i; RECT buttonRect; PPH_EMENU_ITEM selectedItem; desktopsMenu = PhCreateEMenu(); if (!context->DesktopList) context->DesktopList = PhCreateList(10); context->CurrentWinStaName = GetCurrentWinStaName(); EnumDesktops(GetProcessWindowStation(), EnumDesktopsCallback, (LPARAM)context); for (i = 0; i < context->DesktopList->Count; i++) { PhInsertEMenuItem( desktopsMenu, PhCreateEMenuItem(0, 0, ((PPH_STRING)context->DesktopList->Items[i])->Buffer, NULL, NULL), -1 ); } GetWindowRect(GetDlgItem(hwndDlg, IDC_DESKTOPS), &buttonRect); selectedItem = PhShowEMenu( desktopsMenu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, buttonRect.right, buttonRect.top ); if (selectedItem) { SetDlgItemText( hwndDlg, IDC_DESKTOP, selectedItem->Text ); } for (i = 0; i < context->DesktopList->Count; i++) PhDereferenceObject(context->DesktopList->Items[i]); PhClearList(context->DesktopList); PhDereferenceObject(context->CurrentWinStaName); PhDestroyEMenu(desktopsMenu); } break; } } break; } return FALSE; }