PSTR VirusTotalSendHttpRequest( _In_ PPH_BYTES JsonArray ) { HANDLE fileHandle = INVALID_HANDLE_VALUE; HINTERNET httpSessionHandle = NULL; HINTERNET connectHandle = NULL; HINTERNET requestHandle = NULL; PSTR subRequestBuffer = NULL; PPH_STRING phVersion = NULL; PPH_STRING userAgent = NULL; PPH_STRING urlString = NULL; phVersion = PhGetPhVersion(); userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer); if (!(httpSessionHandle = WinHttpOpen( userAgent->Buffer, WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ))) { goto CleanupExit; } if (WindowsVersion >= WINDOWS_8_1) { WinHttpSetOption( httpSessionHandle, WINHTTP_OPTION_DECOMPRESSION, &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, sizeof(ULONG) ); } if (!(connectHandle = WinHttpConnect( httpSessionHandle, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, 0 ))) { goto CleanupExit; } PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlString = PhFormatString( L"%s%s%s%s%S", L"/partners", L"/sysinternals", L"/file-reports", L"?apikey=", resourceString->Buffer ); PhClearReference(&resourceString); if (!(requestHandle = WinHttpOpenRequest( connectHandle, L"POST", PhGetString(urlString), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE ))) { PhClearReference(&urlString); goto CleanupExit; } PhClearReference(&urlString); if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0)) { goto CleanupExit; } if (!WinHttpSendRequest( requestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, JsonArray->Buffer, (ULONG)JsonArray->Length, (ULONG)JsonArray->Length, 0 )) { goto CleanupExit; } if (WinHttpReceiveResponse(requestHandle, NULL)) { BYTE buffer[PAGE_SIZE]; ULONG allocatedLength; ULONG dataLength; ULONG returnLength; allocatedLength = sizeof(buffer); subRequestBuffer = PhAllocate(allocatedLength); dataLength = 0; while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength)) { if (returnLength == 0) break; if (allocatedLength < dataLength + returnLength) { allocatedLength *= 2; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } memcpy(subRequestBuffer + dataLength, buffer, returnLength); dataLength += returnLength; } if (allocatedLength < dataLength + 1) { allocatedLength++; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } // Ensure that the buffer is null-terminated. subRequestBuffer[dataLength] = 0; } CleanupExit: if (requestHandle) WinHttpCloseHandle(requestHandle); if (connectHandle) WinHttpCloseHandle(connectHandle); if (httpSessionHandle) WinHttpCloseHandle(httpSessionHandle); if (JsonArray) PhDereferenceObject(JsonArray); return subRequestBuffer; }
PPH_BYTES VirusTotalSendHttpRequest( _In_ PPH_BYTES JsonArray ) { PPH_BYTES subRequestBuffer = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING versionString = NULL; PPH_STRING userAgentString = NULL; PPH_STRING urlPathString = NULL; versionString = PhGetPhVersion(); userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer); if (!PhHttpSocketCreate(&httpContext, PhGetString(userAgentString))) goto CleanupExit; if (!PhHttpSocketConnect(httpContext, L"www.virustotal.com", PH_HTTP_DEFAULT_HTTPS_PORT)) goto CleanupExit; { PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlPathString = PhFormatString( L"%s%s%s%s%S", L"/partners", L"/sysinternals", L"/file-reports", L"?\x0061\x0070\x0069\x006B\x0065\x0079=", resourceString->Buffer ); PhClearReference(&resourceString); } if (!PhHttpSocketBeginRequest( httpContext, L"POST", urlPathString->Buffer, PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { goto CleanupExit; } if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0)) goto CleanupExit; if (!PhHttpSocketSendRequest(httpContext, JsonArray->Buffer, (ULONG)JsonArray->Length)) goto CleanupExit; if (!PhHttpSocketEndRequest(httpContext)) goto CleanupExit; if (!(subRequestBuffer = PhHttpSocketDownloadString(httpContext, FALSE))) goto CleanupExit; CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); PhClearReference(&urlPathString); PhClearReference(&versionString); PhClearReference(&userAgentString); if (JsonArray) PhDereferenceObject(JsonArray); return subRequestBuffer; }
PVIRUSTOTAL_API_RESPONSE VirusTotalRequestIpAddressReport( _In_ PPH_STRING IpAddress ) { PVIRUSTOTAL_API_RESPONSE result = NULL; PPH_BYTES jsonString = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING versionString = NULL; PPH_STRING userAgentString = NULL; PPH_STRING urlPathString = NULL; PVOID jsonRootObject = NULL; versionString = PhGetPhVersion(); userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer); if (!PhHttpSocketCreate( &httpContext, PhGetString(userAgentString) )) { goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, L"www.virustotal.com", PH_HTTP_DEFAULT_HTTPS_PORT )) { goto CleanupExit; } { PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlPathString = PhFormatString( L"%s%s%s%s%s%S%s%s", L"/vtapi", L"/v2", L"/ip-address", L"/report", L"?\x0061\x0070\x0069\x006B\x0065\x0079=", resourceString->Buffer, L"&ip=", IpAddress->Buffer ); PhClearReference(&resourceString); } if (!PhHttpSocketBeginRequest( httpContext, L"POST", PhGetString(urlPathString), PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { goto CleanupExit; } if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0)) goto CleanupExit; if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) goto CleanupExit; if (!PhHttpSocketEndRequest(httpContext)) goto CleanupExit; if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE))) goto CleanupExit; if (!(jsonRootObject = PhCreateJsonParser(jsonString->Buffer))) goto CleanupExit; result = PhAllocate(sizeof(VIRUSTOTAL_API_RESPONSE)); memset(result, 0, sizeof(VIRUSTOTAL_API_RESPONSE)); //result->ResponseCode = PhGetJsonValueAsLong64(jsonRootObject, "response_code"); //result->StatusMessage = PhGetJsonValueAsString(jsonRootObject, "verbose_msg"); //result->PermaLink = PhGetJsonValueAsString(jsonRootObject, "permalink"); //result->ScanId = PhGetJsonValueAsString(jsonRootObject, "scan_id"); CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (jsonRootObject) PhFreeJsonParser(jsonRootObject); PhClearReference(&jsonString); PhClearReference(&versionString); PhClearReference(&userAgentString); return result; }
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); } }
INT_PTR CALLBACK DotNetAsmPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PASMPAGE_CONTEXT context; if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { context = propPageContext->Context; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { PPH_STRING settings; HWND tnHandle; context = PhAllocate(sizeof(ASMPAGE_CONTEXT)); memset(context, 0, sizeof(ASMPAGE_CONTEXT)); propPageContext->Context = context; context->WindowHandle = hwndDlg; context->ProcessItem = processItem; context->ClrVersions = 0; PhGetProcessIsDotNetEx(processItem->ProcessId, NULL, 0, NULL, &context->ClrVersions); tnHandle = GetDlgItem(hwndDlg, IDC_LIST); context->TnHandle = tnHandle; TreeNew_SetCallback(tnHandle, DotNetAsmTreeNewCallback, context); TreeNew_SetExtendedFlags(tnHandle, TN_FLAG_ITEM_DRAG_SELECT, TN_FLAG_ITEM_DRAG_SELECT); PhSetControlTheme(tnHandle, L"explorer"); SendMessage(TreeNew_GetTooltips(tnHandle), TTM_SETMAXTIPWIDTH, 0, MAXSHORT); PhAddTreeNewColumn(tnHandle, DNATNC_STRUCTURE, TRUE, L"Structure", 240, PH_ALIGN_LEFT, -2, 0); PhAddTreeNewColumn(tnHandle, DNATNC_ID, TRUE, L"ID", 50, PH_ALIGN_RIGHT, 0, DT_RIGHT); PhAddTreeNewColumn(tnHandle, DNATNC_FLAGS, TRUE, L"Flags", 120, PH_ALIGN_LEFT, 1, 0); PhAddTreeNewColumn(tnHandle, DNATNC_PATH, TRUE, L"Path", 600, PH_ALIGN_LEFT, 2, 0); // don't use path ellipsis - the user already has the base file name PhAddTreeNewColumn(tnHandle, DNATNC_NATIVEPATH, TRUE, L"Native image path", 600, PH_ALIGN_LEFT, 3, 0); settings = PhGetStringSetting(SETTING_NAME_ASM_TREE_LIST_COLUMNS); PhCmLoadSettings(tnHandle, &settings->sr); PhDereferenceObject(settings); PhSwapReference(&context->TnErrorMessage, PhCreateString(L"Loading .NET assemblies...")); TreeNew_SetEmptyText(tnHandle, &context->TnErrorMessage->sr, 0); if ( !IsProcessSuspended(processItem->ProcessId) || PhShowMessage(hwndDlg, MB_ICONWARNING | MB_YESNO, L".NET assembly enumeration may not work properly because the process is currently suspended. Do you want to continue?") == IDYES ) { CreateDotNetTraceQueryThread( hwndDlg, context->ClrVersions, processItem->ProcessId ); } else { PhSwapReference(&context->TnErrorMessage, PhCreateString(L"Unable to start the event tracing session because the process is suspended.") ); TreeNew_SetEmptyText(tnHandle, &context->TnErrorMessage->sr, 0); InvalidateRect(tnHandle, NULL, FALSE); } } break; case WM_DESTROY: { PPH_STRING settings; ULONG i; settings = PhCmSaveSettings(context->TnHandle); PhSetStringSetting2(SETTING_NAME_ASM_TREE_LIST_COLUMNS, &settings->sr); PhDereferenceObject(settings); if (context->NodeList) { for (i = 0; i < context->NodeList->Count; i++) DestroyNode(context->NodeList->Items[i]); PhDereferenceObject(context->NodeList); } if (context->NodeRootList) PhDereferenceObject(context->NodeRootList); PhClearReference(&context->TnErrorMessage); PhFree(context); PhPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { PPH_LAYOUT_ITEM dialogItem; if (dialogItem = PhBeginPropPageLayout(hwndDlg, propPageContext)) { PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_LIST), dialogItem, PH_ANCHOR_ALL); PhEndPropPageLayout(hwndDlg, propPageContext); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_COPY: { PPH_STRING text; text = PhGetTreeNewText(context->TnHandle, 0); PhSetClipboardString(context->TnHandle, &text->sr); PhDereferenceObject(text); } break; } } break; case UPDATE_MSG: { ULONG result = (ULONG)wParam; PASMPAGE_QUERY_CONTEXT queryContext = (PASMPAGE_QUERY_CONTEXT)lParam; if (result == 0) { PhSwapReference(&context->NodeList, queryContext->NodeList); PhSwapReference(&context->NodeRootList, queryContext->NodeRootList); DestroyDotNetTraceQuery(queryContext); TreeNew_NodesStructured(context->TnHandle); } else { PhSwapReference(&context->TnErrorMessage, PhConcatStrings2(L"Unable to start the event tracing session: ", PhGetStringOrDefault(PhGetWin32Message(result), L"Unknown error")) ); TreeNew_SetEmptyText(context->TnHandle, &context->TnErrorMessage->sr, 0); InvalidateRect(context->TnHandle, NULL, FALSE); } } break; } return FALSE; }
INT_PTR CALLBACK PhpOptionsGeneralDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND comboBoxHandle; ULONG i; LOGFONT font; PhpPageInit(hwndDlg); comboBoxHandle = GetDlgItem(hwndDlg, IDC_MAXSIZEUNIT); for (i = 0; i < sizeof(PhSizeUnitNames) / sizeof(PWSTR); i++) ComboBox_AddString(comboBoxHandle, PhSizeUnitNames[i]); SetDlgItemText(hwndDlg, IDC_SEARCHENGINE, PhaGetStringSetting(L"SearchEngine")->Buffer); SetDlgItemText(hwndDlg, IDC_PEVIEWER, PhaGetStringSetting(L"ProgramInspectExecutables")->Buffer); if (PhMaxSizeUnit != -1) ComboBox_SetCurSel(comboBoxHandle, PhMaxSizeUnit); else ComboBox_SetCurSel(comboBoxHandle, sizeof(PhSizeUnitNames) / sizeof(PWSTR) - 1); SetDlgItemInt(hwndDlg, IDC_ICONPROCESSES, PhGetIntegerSetting(L"IconProcesses"), FALSE); SetDlgItemCheckForSetting(hwndDlg, IDC_ALLOWONLYONEINSTANCE, L"AllowOnlyOneInstance"); SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEONCLOSE, L"HideOnClose"); SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEONMINIMIZE, L"HideOnMinimize"); SetDlgItemCheckForSetting(hwndDlg, IDC_COLLAPSESERVICES, L"CollapseServicesOnStart"); SetDlgItemCheckForSetting(hwndDlg, IDC_ICONSINGLECLICK, L"IconSingleClick"); SetDlgItemCheckForSetting(hwndDlg, IDC_ICONTOGGLESVISIBILITY, L"IconTogglesVisibility"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEPLUGINS, L"EnablePlugins"); ReadCurrentUserRun(); if (CurrentUserRunPresent) { Button_SetCheck(GetDlgItem(hwndDlg, IDC_STARTATLOGON), BST_CHECKED); if (CurrentUserRunStartHidden) Button_SetCheck(GetDlgItem(hwndDlg, IDC_STARTHIDDEN), BST_CHECKED); } else { EnableWindow(GetDlgItem(hwndDlg, IDC_STARTHIDDEN), FALSE); } // Set the font of the button for a nice preview. if (GetCurrentFont(&font)) { CurrentFontInstance = CreateFontIndirect(&font); if (CurrentFontInstance) SendMessage(GetDlgItem(hwndDlg, IDC_FONT), WM_SETFONT, (WPARAM)CurrentFontInstance, TRUE); } } break; case WM_DESTROY: { if (CurrentFontInstance) DeleteObject(CurrentFontInstance); PhClearReference(&NewFontSelection); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_STARTATLOGON: { EnableWindow(GetDlgItem(hwndDlg, IDC_STARTHIDDEN), Button_GetCheck(GetDlgItem(hwndDlg, IDC_STARTATLOGON)) == BST_CHECKED); } break; case IDC_FONT: { LOGFONT font; CHOOSEFONT chooseFont; if (!GetCurrentFont(&font)) { // Can't get LOGFONT from the existing setting, probably // because the user hasn't ever chosen a font before. // Set the font to something familiar. GetObject((HFONT)SendMessage(PhMainWndHandle, WM_PH_GET_FONT, 0, 0), sizeof(LOGFONT), &font); } memset(&chooseFont, 0, sizeof(CHOOSEFONT)); chooseFont.lStructSize = sizeof(CHOOSEFONT); chooseFont.hwndOwner = hwndDlg; chooseFont.lpLogFont = &font; chooseFont.Flags = CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS; if (ChooseFont(&chooseFont)) { PhMoveReference(&NewFontSelection, PhBufferToHexString((PUCHAR)&font, sizeof(LOGFONT))); // Update the button's font. if (CurrentFontInstance) DeleteObject(CurrentFontInstance); CurrentFontInstance = CreateFontIndirect(&font); SendMessage(GetDlgItem(hwndDlg, IDC_FONT), WM_SETFONT, (WPARAM)CurrentFontInstance, TRUE); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_APPLY: { BOOLEAN startAtLogon; BOOLEAN startHidden; PhSetStringSetting2(L"SearchEngine", &(PhaGetDlgItemText(hwndDlg, IDC_SEARCHENGINE)->sr)); PhSetStringSetting2(L"ProgramInspectExecutables", &(PhaGetDlgItemText(hwndDlg, IDC_PEVIEWER)->sr)); PhSetIntegerSetting(L"MaxSizeUnit", PhMaxSizeUnit = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_MAXSIZEUNIT))); PhSetIntegerSetting(L"IconProcesses", GetDlgItemInt(hwndDlg, IDC_ICONPROCESSES, NULL, FALSE)); SetSettingForDlgItemCheck(hwndDlg, IDC_ALLOWONLYONEINSTANCE, L"AllowOnlyOneInstance"); SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEONCLOSE, L"HideOnClose"); SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEONMINIMIZE, L"HideOnMinimize"); SetSettingForDlgItemCheck(hwndDlg, IDC_COLLAPSESERVICES, L"CollapseServicesOnStart"); SetSettingForDlgItemCheck(hwndDlg, IDC_ICONSINGLECLICK, L"IconSingleClick"); SetSettingForDlgItemCheck(hwndDlg, IDC_ICONTOGGLESVISIBILITY, L"IconTogglesVisibility"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLEPLUGINS, L"EnablePlugins"); startAtLogon = Button_GetCheck(GetDlgItem(hwndDlg, IDC_STARTATLOGON)) == BST_CHECKED; startHidden = Button_GetCheck(GetDlgItem(hwndDlg, IDC_STARTHIDDEN)) == BST_CHECKED; WriteCurrentUserRun(startAtLogon, startHidden); if (NewFontSelection) { PhSetStringSetting2(L"Font", &NewFontSelection->sr); PostMessage(PhMainWndHandle, WM_PH_UPDATE_FONT, 0, 0); } SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); } return TRUE; } } break; } return FALSE; }
INT_PTR CALLBACK PhpOptionsAdvancedDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PhpPageInit(hwndDlg); PhpAdvancedPageLoad(hwndDlg); if (PhStartupParameters.ShowOptions) { // Disable all controls except for Replace Task Manager. EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEWARNINGS), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEKERNELMODEDRIVER), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_HIDEUNNAMEDHANDLES), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLESTAGE2), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLENETWORKRESOLVE), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_PROPAGATECPUUSAGE), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLECYCLECPUUSAGE), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTLABEL), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC), FALSE); } else { if (WindowsVersion < WINDOWS_7) EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLECYCLECPUUSAGE), FALSE); // cycle-based CPU usage not available before Windows 7 } } break; case WM_DESTROY: { PhClearReference(&OldTaskMgrDebugger); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_CHANGE: { HANDLE threadHandle; RECT windowRect; // Save the options so they don't get "overwritten" when // WM_PH_CHILD_EXIT gets sent. PhpAdvancedPageSave(hwndDlg); GetWindowRect(GetParent(hwndDlg), &windowRect); WindowHandleForElevate = hwndDlg; threadHandle = PhCreateThread(0, PhpElevateAdvancedThreadStart, PhFormatString( L"-showoptions -hwnd %Ix -point %u,%u", (ULONG_PTR)GetParent(hwndDlg), windowRect.left + 20, windowRect.top + 20 )); if (threadHandle) NtClose(threadHandle); } break; case IDC_SAMPLECOUNTAUTOMATIC: { EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), Button_GetCheck(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC)) != BST_CHECKED); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_APPLY: { PhpAdvancedPageSave(hwndDlg); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); } return TRUE; } } break; case WM_PH_CHILD_EXIT: { PhpAdvancedPageLoad(hwndDlg); } break; } return FALSE; }
NTSTATUS PhpThreadQueryWorker( _In_ PVOID Parameter ) { PPH_THREAD_QUERY_DATA data = (PPH_THREAD_QUERY_DATA)Parameter; LONG newSymbolsLoading; if (data->ThreadProvider->Terminating) goto Done; newSymbolsLoading = _InterlockedIncrement(&data->ThreadProvider->SymbolsLoading); if (newSymbolsLoading == 1) PhInvokeCallback(&data->ThreadProvider->LoadingStateChangedEvent, (PVOID)TRUE); if (data->ThreadProvider->SymbolsLoadedRunId == 0) PhLoadSymbolsThreadProvider(data->ThreadProvider); data->StartAddressString = PhGetSymbolFromAddress( data->ThreadProvider->SymbolProvider, data->ThreadItem->StartAddress, &data->StartAddressResolveLevel, &data->ThreadItem->StartAddressFileName, NULL, NULL ); if (data->StartAddressResolveLevel == PhsrlAddress && data->ThreadProvider->SymbolsLoadedRunId < data->RunId) { // The process may have loaded new modules, so load symbols for those and try again. PhLoadSymbolsThreadProvider(data->ThreadProvider); PhClearReference(&data->StartAddressString); PhClearReference(&data->ThreadItem->StartAddressFileName); data->StartAddressString = PhGetSymbolFromAddress( data->ThreadProvider->SymbolProvider, data->ThreadItem->StartAddress, &data->StartAddressResolveLevel, &data->ThreadItem->StartAddressFileName, NULL, NULL ); } newSymbolsLoading = _InterlockedDecrement(&data->ThreadProvider->SymbolsLoading); if (newSymbolsLoading == 0) PhInvokeCallback(&data->ThreadProvider->LoadingStateChangedEvent, (PVOID)FALSE); // Check if the process has services - we'll need to know before getting service tag/name // information. if (WINDOWS_HAS_SERVICE_TAGS && !data->ThreadProvider->HasServicesKnown) { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(data->ThreadProvider->ProcessId)) { data->ThreadProvider->HasServices = processItem->ServiceList && processItem->ServiceList->Count != 0; PhDereferenceObject(processItem); } data->ThreadProvider->HasServicesKnown = TRUE; } // Get the service tag, and the service name. if (WINDOWS_HAS_SERVICE_TAGS && data->ThreadProvider->SymbolProvider->IsRealHandle && data->ThreadItem->ThreadHandle) { PVOID serviceTag; if (NT_SUCCESS(PhGetThreadServiceTag( data->ThreadItem->ThreadHandle, data->ThreadProvider->ProcessHandle, &serviceTag ))) { data->ServiceName = PhGetServiceNameFromTag( data->ThreadProvider->ProcessId, serviceTag ); } } Done: RtlInterlockedPushEntrySList(&data->ThreadProvider->QueryListHead, &data->ListEntry); PhDereferenceObject(data->ThreadProvider); return STATUS_SUCCESS; }
VOID PhpFillUmdfDrivers( _In_ PPH_PROCESS_ITEM Process, _Inout_ PPH_STRING_BUILDER Drivers ) { static PH_STRINGREF activeDevices = PH_STRINGREF_INIT(L"ACTIVE_DEVICES"); static PH_STRINGREF currentControlSetEnum = PH_STRINGREF_INIT(L"System\\CurrentControlSet\\Enum\\"); HANDLE processHandle; ULONG flags = 0; PVOID environment; ULONG environmentLength; ULONG enumerationKey; PH_ENVIRONMENT_VARIABLE variable; if (!NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, Process->ProcessId ))) return; #ifdef _WIN64 // Just in case. if (Process->IsWow64) flags |= PH_GET_PROCESS_ENVIRONMENT_WOW64; #endif if (NT_SUCCESS(PhGetProcessEnvironment( processHandle, flags, &environment, &environmentLength ))) { enumerationKey = 0; while (PhEnumProcessEnvironmentVariables(environment, environmentLength, &enumerationKey, &variable)) { PH_STRINGREF part; PH_STRINGREF remainingPart; if (!PhEqualStringRef(&variable.Name, &activeDevices, TRUE)) continue; remainingPart = variable.Value; while (remainingPart.Length != 0) { PhSplitStringRefAtChar(&remainingPart, ';', &part, &remainingPart); if (part.Length != 0) { HANDLE driverKeyHandle; PPH_STRING driverKeyPath; driverKeyPath = PhConcatStringRef2(¤tControlSetEnum, &part); if (NT_SUCCESS(PhOpenKey( &driverKeyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &driverKeyPath->sr, 0 ))) { PPH_STRING deviceDesc; PH_STRINGREF deviceName; PPH_STRING hardwareId; if (deviceDesc = PhQueryRegistryString(driverKeyHandle, L"DeviceDesc")) { PH_STRINGREF firstPart; PH_STRINGREF secondPart; if (PhSplitStringRefAtLastChar(&deviceDesc->sr, ';', &firstPart, &secondPart)) deviceName = secondPart; else deviceName = deviceDesc->sr; } else { PhInitializeStringRef(&deviceName, L"Unknown Device"); } hardwareId = PhQueryRegistryString(driverKeyHandle, L"HardwareID"); PhAppendStringBuilder(Drivers, &StandardIndent); PhAppendStringBuilder(Drivers, &deviceName); if (hardwareId) { PhTrimToNullTerminatorString(hardwareId); if (hardwareId->Length != 0) { PhAppendStringBuilder2(Drivers, L" ("); PhAppendStringBuilder(Drivers, &hardwareId->sr); PhAppendCharStringBuilder(Drivers, ')'); } } PhAppendCharStringBuilder(Drivers, '\n'); PhClearReference(&hardwareId); PhClearReference(&deviceDesc); NtClose(driverKeyHandle); } PhDereferenceObject(driverKeyPath); } } } PhFreePage(environment); } NtClose(processHandle); }
INT_PTR CALLBACK RestartComputerDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PSERVICE_RECOVERY_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = (PSERVICE_RECOVERY_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PSERVICE_RECOVERY_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { SetDlgItemInt(hwndDlg, IDC_RESTARTCOMPAFTER, context->RebootAfter / (1000 * 60), FALSE); // ms to min Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), context->RebootMessage ? BST_CHECKED : BST_UNCHECKED); SetDlgItemText(hwndDlg, IDC_RESTARTMESSAGE, PhGetString(context->RebootMessage)); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_RESTARTCOMPAFTER), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_RESTARTCOMPAFTER), 0, -1); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { context->RebootAfter = GetDlgItemInt(hwndDlg, IDC_RESTARTCOMPAFTER, NULL, FALSE) * 1000 * 60; if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE)) == BST_CHECKED) PhMoveReference(&context->RebootMessage, PhGetWindowText(GetDlgItem(hwndDlg, IDC_RESTARTMESSAGE))); else PhClearReference(&context->RebootMessage); context->Dirty = TRUE; EndDialog(hwndDlg, IDOK); } break; case IDC_USEDEFAULTMESSAGE: { PPH_STRING message; PWSTR computerName; ULONG bufferSize; BOOLEAN allocated = TRUE; // Get the computer name. bufferSize = 64; computerName = PhAllocate((bufferSize + 1) * sizeof(WCHAR)); if (!GetComputerName(computerName, &bufferSize)) { PhFree(computerName); computerName = PhAllocate((bufferSize + 1) * sizeof(WCHAR)); if (!GetComputerName(computerName, &bufferSize)) { PhFree(computerName); computerName = L"(unknown)"; allocated = FALSE; } } // This message is exactly the same as the one in the Services console, // except the double spaces are replaced by single spaces. message = PhFormatString( L"Your computer is connected to the computer named %s. " L"The %s service on %s has ended unexpectedly. " L"%s will restart automatically, and then you can reestablish the connection.", computerName, context->ServiceItem->Name->Buffer, computerName, computerName ); SetDlgItemText(hwndDlg, IDC_RESTARTMESSAGE, message->Buffer); PhDereferenceObject(message); if (allocated) PhFree(computerName); Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), BST_CHECKED); } break; case IDC_RESTARTMESSAGE: { if (HIWORD(wParam) == EN_CHANGE) { // A zero length restart message disables it, so we might as well uncheck the box. Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), GetWindowTextLength(GetDlgItem(hwndDlg, IDC_RESTARTMESSAGE)) != 0 ? BST_CHECKED : BST_UNCHECKED); } } break; } } break; } return FALSE; }
VOID FindNetworkAdapters( _In_ PDV_NETADAPTER_CONTEXT Context ) { if (Context->UseAlternateMethod) { ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_ALL_INTERFACES; ULONG bufferLength = 0; PVOID buffer; if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &bufferLength) != ERROR_BUFFER_OVERFLOW) return; buffer = PhAllocate(bufferLength); memset(buffer, 0, bufferLength); if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, buffer, &bufferLength) == ERROR_SUCCESS) { PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (PIP_ADAPTER_ADDRESSES i = buffer; i; i = i->Next) { PPH_STRING description; if (description = PhCreateString(i->Description)) { AddNetworkAdapterToListView( Context, TRUE, i->IfIndex, i->Luid, PhConvertMultiByteToUtf16(i->AdapterName), description ); PhDereferenceObject(description); } } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); } PhFree(buffer); } else { static PH_STRINGREF devicePathSr = PH_STRINGREF_INIT(L"\\\\.\\"); PPH_LIST deviceList; PWSTR deviceInterfaceList; ULONG deviceInterfaceListLength = 0; PWSTR deviceInterface; if (CM_Get_Device_Interface_List_Size( &deviceInterfaceListLength, (PGUID)&GUID_DEVINTERFACE_NET, NULL, CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES ) != CR_SUCCESS) { return; } deviceInterfaceList = PhAllocate(deviceInterfaceListLength * sizeof(WCHAR)); memset(deviceInterfaceList, 0, deviceInterfaceListLength * sizeof(WCHAR)); if (CM_Get_Device_Interface_List( (PGUID)&GUID_DEVINTERFACE_NET, NULL, deviceInterfaceList, deviceInterfaceListLength, CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES ) != CR_SUCCESS) { PhFree(deviceInterfaceList); return; } deviceList = PH_AUTO(PhCreateList(1)); for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1) { HKEY keyHandle; DEVINST deviceInstanceHandle; PPH_STRING deviceDescription = NULL; if (!QueryNetworkDeviceInterfaceDescription(deviceInterface, &deviceInstanceHandle, &deviceDescription)) continue; if (CM_Open_DevInst_Key( deviceInstanceHandle, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &keyHandle, CM_REGISTRY_SOFTWARE ) == CR_SUCCESS) { PNET_ENUM_ENTRY adapterEntry; HANDLE deviceHandle; adapterEntry = PhAllocate(sizeof(NET_ENUM_ENTRY)); memset(adapterEntry, 0, sizeof(NET_ENUM_ENTRY)); adapterEntry->DeviceGuid = PhQueryRegistryString(keyHandle, L"NetCfgInstanceId"); adapterEntry->DeviceInterface = PhConcatStringRef2(&devicePathSr, &adapterEntry->DeviceGuid->sr); adapterEntry->DeviceLuid.Info.IfType = PhQueryRegistryUlong64(keyHandle, L"*IfType"); adapterEntry->DeviceLuid.Info.NetLuidIndex = PhQueryRegistryUlong64(keyHandle, L"NetLuidIndex"); if (NT_SUCCESS(PhCreateFileWin32( &deviceHandle, PhGetString(adapterEntry->DeviceInterface), FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { PPH_STRING adapterName; // Try query the full adapter name adapterName = NetworkAdapterQueryName(deviceHandle, adapterEntry->DeviceGuid); if (adapterName) adapterEntry->DeviceName = adapterName; adapterEntry->DevicePresent = TRUE; NtClose(deviceHandle); } if (!adapterEntry->DeviceName) adapterEntry->DeviceName = PhCreateString2(&deviceDescription->sr); PhAddItemList(deviceList, adapterEntry); NtClose(keyHandle); } PhClearReference(&deviceDescription); } // Cleanup. PhFree(deviceInterfaceList); // Sort the entries qsort(deviceList->Items, deviceList->Count, sizeof(PVOID), AdapterEntryCompareFunction); PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (ULONG i = 0; i < deviceList->Count; i++) { PNET_ENUM_ENTRY entry = deviceList->Items[i]; AddNetworkAdapterToListView( Context, entry->DevicePresent, 0, entry->DeviceLuid, entry->DeviceGuid, entry->DeviceName ); if (entry->DeviceName) PhDereferenceObject(entry->DeviceName); if (entry->DeviceInterface) PhDereferenceObject(entry->DeviceInterface); // Note: DeviceGuid is disposed by WM_DESTROY. PhFree(entry); } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); } // HACK: Show all unknown devices. PhAcquireQueuedLockShared(&NetworkAdaptersListLock); for (ULONG i = 0; i < NetworkAdaptersList->Count; i++) { ULONG index = ULONG_MAX; BOOLEAN found = FALSE; PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]); if (!entry) continue; while ((index = PhFindListViewItemByFlags( Context->ListViewHandle, index, LVNI_ALL )) != ULONG_MAX) { PDV_NETADAPTER_ID param; if (PhGetListViewItemParam(Context->ListViewHandle, index, ¶m)) { if (EquivalentNetAdapterId(param, &entry->AdapterId)) { found = TRUE; } } } if (!found) { PPH_STRING description; MIB_IF_ROW2 interfaceRow; memset(&interfaceRow, 0, sizeof(MIB_IF_ROW2)); interfaceRow.InterfaceLuid = entry->AdapterId.InterfaceLuid; interfaceRow.InterfaceIndex = entry->AdapterId.InterfaceIndex; // HACK: Try query the description from the interface entry (if it exists). if (GetIfEntry2(&interfaceRow) == NO_ERROR) description = PhCreateString(interfaceRow.Description); else description = PhCreateString(L"Unknown network adapter"); if (description) { AddNetworkAdapterToListView( Context, FALSE, entry->AdapterId.InterfaceIndex, entry->AdapterId.InterfaceLuid, entry->AdapterId.InterfaceGuid, description ); PhDereferenceObject(description); } } PhDereferenceObjectDeferDelete(entry); } PhReleaseQueuedLockShared(&NetworkAdaptersListLock); }
INT_PTR CALLBACK EspServiceRecoveryDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PSERVICE_RECOVERY_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(SERVICE_RECOVERY_CONTEXT)); memset(context, 0, sizeof(SERVICE_RECOVERY_CONTEXT)); SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PSERVICE_RECOVERY_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam; context->ServiceItem = serviceItem; EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE)); EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_SECONDFAILURE)); EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES)); status = EspLoadRecoveryInfo(hwndDlg, context); if (status == STATUS_SOME_NOT_MAPPED) { if (context->NumberOfActions > 3) { PhShowWarning( hwndDlg, L"The service has %lu failure actions configured, but this program only supports editing 3. " L"If you save the recovery information using this program, the additional failure actions will be lost.", context->NumberOfActions ); } } else if (!NT_SUCCESS(status)) { SetDlgItemText(hwndDlg, IDC_RESETFAILCOUNT, L"0"); if (WindowsVersion >= WINDOWS_VISTA) { context->EnableFlagCheckBox = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS), TRUE); } PhShowWarning(hwndDlg, L"Unable to query service recovery information: %s", ((PPH_STRING)PhAutoDereferenceObject(PhGetNtMessage(status)))->Buffer); } EspFixControls(hwndDlg, context); context->Ready = TRUE; } break; case WM_DESTROY: { PhClearReference(&context->RebootMessage); PhFree(context); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_FIRSTFAILURE: case IDC_SECONDFAILURE: case IDC_SUBSEQUENTFAILURES: { if (HIWORD(wParam) == CBN_SELCHANGE) { EspFixControls(hwndDlg, context); } } break; case IDC_RESTARTCOMPUTEROPTIONS: { DialogBoxParam( PluginInstance->DllBase, MAKEINTRESOURCE(IDD_RESTARTCOMP), hwndDlg, RestartComputerDlgProc, (LPARAM)context ); } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Executable files (*.exe;*.cmd;*.bat)", L"*.exe;*.cmd;*.bat" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhaGetDlgItemText(hwndDlg, IDC_RUNPROGRAM); PhSetFileDialogFileName(fileDialog, fileName->Buffer); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_RUNPROGRAM, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; case IDC_ENABLEFORERRORSTOPS: { context->Dirty = TRUE; } break; } switch (HIWORD(wParam)) { case EN_CHANGE: case CBN_SELCHANGE: { if (context->Ready) context->Dirty = TRUE; } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_KILLACTIVE: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); } return TRUE; case PSN_APPLY: { NTSTATUS status; PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; ULONG restartServiceAfter; SERVICE_FAILURE_ACTIONS failureActions; SC_ACTION actions[3]; ULONG i; BOOLEAN enableRestart = FALSE; SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); if (!context->Dirty) { return TRUE; } // Build the failure actions structure. failureActions.dwResetPeriod = GetDlgItemInt(hwndDlg, IDC_RESETFAILCOUNT, NULL, FALSE) * 60 * 60 * 24; failureActions.lpRebootMsg = PhGetStringOrEmpty(context->RebootMessage); failureActions.lpCommand = PhaGetDlgItemText(hwndDlg, IDC_RUNPROGRAM)->Buffer; failureActions.cActions = 3; failureActions.lpsaActions = actions; actions[0].Type = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE)); actions[1].Type = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_SECONDFAILURE)); actions[2].Type = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES)); restartServiceAfter = GetDlgItemInt(hwndDlg, IDC_RESTARTSERVICEAFTER, NULL, FALSE) * 1000 * 60; for (i = 0; i < 3; i++) { switch (actions[i].Type) { case SC_ACTION_RESTART: actions[i].Delay = restartServiceAfter; enableRestart = TRUE; break; case SC_ACTION_REBOOT: actions[i].Delay = context->RebootAfter; break; case SC_ACTION_RUN_COMMAND: actions[i].Delay = 0; break; } } // Try to save the changes. serviceHandle = PhOpenService( serviceItem->Name->Buffer, SERVICE_CHANGE_CONFIG | (enableRestart ? SERVICE_START : 0) // SC_ACTION_RESTART requires SERVICE_START ); if (serviceHandle) { if (ChangeServiceConfig2( serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, &failureActions )) { if (context->EnableFlagCheckBox) { SERVICE_FAILURE_ACTIONS_FLAG failureActionsFlag; failureActionsFlag.fFailureActionsOnNonCrashFailures = Button_GetCheck(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS)) == BST_CHECKED; ChangeServiceConfig2( serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, &failureActionsFlag ); } CloseServiceHandle(serviceHandle); } else { CloseServiceHandle(serviceHandle); goto ErrorCase; } } else { if (GetLastError() == ERROR_ACCESS_DENIED && !PhElevated) { // Elevate using phsvc. if (PhUiConnectToPhSvc(hwndDlg, FALSE)) { if (NT_SUCCESS(status = PhSvcCallChangeServiceConfig2( serviceItem->Name->Buffer, SERVICE_CONFIG_FAILURE_ACTIONS, &failureActions ))) { if (context->EnableFlagCheckBox) { SERVICE_FAILURE_ACTIONS_FLAG failureActionsFlag; failureActionsFlag.fFailureActionsOnNonCrashFailures = Button_GetCheck(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS)) == BST_CHECKED; PhSvcCallChangeServiceConfig2( serviceItem->Name->Buffer, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, &failureActionsFlag ); } } PhUiDisconnectFromPhSvc(); if (!NT_SUCCESS(status)) { SetLastError(PhNtStatusToDosError(status)); goto ErrorCase; } } else { // User cancelled elevation. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } } else { goto ErrorCase; } } return TRUE; ErrorCase: if (PhShowMessage( hwndDlg, MB_ICONERROR | MB_RETRYCANCEL, L"Unable to change service recovery information: %s", ((PPH_STRING)PhAutoDereferenceObject(PhGetWin32Message(GetLastError())))->Buffer ) == IDRETRY) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } } return TRUE; } } break; } return FALSE; }
NTSTATUS EspLoadRecoveryInfo( _In_ HWND hwndDlg, _In_ PSERVICE_RECOVERY_CONTEXT Context ) { NTSTATUS status = STATUS_SUCCESS; SC_HANDLE serviceHandle; LPSERVICE_FAILURE_ACTIONS failureActions; SERVICE_FAILURE_ACTIONS_FLAG failureActionsFlag; SC_ACTION_TYPE lastType; ULONG returnLength; ULONG i; if (!(serviceHandle = PhOpenService(Context->ServiceItem->Name->Buffer, SERVICE_QUERY_CONFIG))) return NTSTATUS_FROM_WIN32(GetLastError()); if (!(failureActions = PhQueryServiceVariableSize(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS))) { CloseServiceHandle(serviceHandle); return NTSTATUS_FROM_WIN32(GetLastError()); } // Failure action types Context->NumberOfActions = failureActions->cActions; if (failureActions->cActions != 0 && failureActions->cActions != 3) status = STATUS_SOME_NOT_MAPPED; // If failure actions are not defined for a particular fail count, the // last failure action is used. Here we duplicate this behaviour when there // are fewer than 3 failure actions. lastType = SC_ACTION_NONE; ServiceActionToComboBox(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE), failureActions->cActions >= 1 ? (lastType = failureActions->lpsaActions[0].Type) : lastType); ServiceActionToComboBox(GetDlgItem(hwndDlg, IDC_SECONDFAILURE), failureActions->cActions >= 2 ? (lastType = failureActions->lpsaActions[1].Type) : lastType); ServiceActionToComboBox(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES), failureActions->cActions >= 3 ? (lastType = failureActions->lpsaActions[2].Type) : lastType); // Reset fail count after SetDlgItemInt(hwndDlg, IDC_RESETFAILCOUNT, failureActions->dwResetPeriod / (60 * 60 * 24), FALSE); // s to days // Restart service after SetDlgItemText(hwndDlg, IDC_RESTARTSERVICEAFTER, L"1"); for (i = 0; i < failureActions->cActions; i++) { if (failureActions->lpsaActions[i].Type == SC_ACTION_RESTART) { if (failureActions->lpsaActions[i].Delay != 0) { SetDlgItemInt(hwndDlg, IDC_RESTARTSERVICEAFTER, failureActions->lpsaActions[i].Delay / (1000 * 60), FALSE); // ms to min } break; } } // Enable actions for stops with errors // This is Vista and above only. if (WindowsVersion >= WINDOWS_VISTA && QueryServiceConfig2( serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, (BYTE *)&failureActionsFlag, sizeof(SERVICE_FAILURE_ACTIONS_FLAG), &returnLength )) { Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS), failureActionsFlag.fFailureActionsOnNonCrashFailures ? BST_CHECKED : BST_UNCHECKED); Context->EnableFlagCheckBox = TRUE; } else { Context->EnableFlagCheckBox = FALSE; } // Restart computer options Context->RebootAfter = 1 * 1000 * 60; for (i = 0; i < failureActions->cActions; i++) { if (failureActions->lpsaActions[i].Type == SC_ACTION_REBOOT) { if (failureActions->lpsaActions[i].Delay != 0) Context->RebootAfter = failureActions->lpsaActions[i].Delay; break; } } if (failureActions->lpRebootMsg && failureActions->lpRebootMsg[0] != 0) PhMoveReference(&Context->RebootMessage, PhCreateString(failureActions->lpRebootMsg)); else PhClearReference(&Context->RebootMessage); // Run program SetDlgItemText(hwndDlg, IDC_RUNPROGRAM, failureActions->lpCommand); PhFree(failureActions); CloseServiceHandle(serviceHandle); return status; }
PVIRUSTOTAL_FILE_REPORT_RESULT VirusTotalSendHttpFileReportRequest( _In_ PPH_STRING FileHash ) { NTSTATUS status = STATUS_SUCCESS; HANDLE fileHandle = INVALID_HANDLE_VALUE; HINTERNET httpSessionHandle = NULL; HINTERNET connectHandle = NULL; HINTERNET requestHandle = NULL; PSTR subRequestBuffer = NULL; PPH_STRING phVersion = NULL; PPH_STRING userAgent = NULL; PPH_STRING urlString = NULL; phVersion = PhGetPhVersion(); userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer); if (!(httpSessionHandle = WinHttpOpen( userAgent->Buffer, WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ))) { goto CleanupExit; } if (WindowsVersion >= WINDOWS_8_1) { WinHttpSetOption( httpSessionHandle, WINHTTP_OPTION_DECOMPRESSION, &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, sizeof(ULONG) ); } if (!(connectHandle = WinHttpConnect( httpSessionHandle, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, 0 ))) { goto CleanupExit; } PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlString = PhFormatString( L"%s%s%s%s%S%s%s", L"/vtapi", L"/v2", L"/file", L"/report", L"?apikey=", resourceString->Buffer, L"&resource=", PhGetString(FileHash) ); PhClearReference(&resourceString); if (!(requestHandle = WinHttpOpenRequest( connectHandle, L"POST", PhGetString(urlString), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE ))) { goto CleanupExit; } if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0)) goto CleanupExit; if (!WinHttpSendRequest( requestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0 )) { goto CleanupExit; } if (WinHttpReceiveResponse(requestHandle, NULL)) { BYTE buffer[PAGE_SIZE]; ULONG allocatedLength; ULONG dataLength; ULONG returnLength; allocatedLength = sizeof(buffer); subRequestBuffer = PhAllocate(allocatedLength); dataLength = 0; while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength)) { if (returnLength == 0) break; if (allocatedLength < dataLength + returnLength) { allocatedLength *= 2; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } memcpy(subRequestBuffer + dataLength, buffer, returnLength); dataLength += returnLength; } if (allocatedLength < dataLength + 1) { allocatedLength++; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } subRequestBuffer[dataLength] = 0; } CleanupExit: PhClearReference(&urlString); if (requestHandle) WinHttpCloseHandle(requestHandle); if (connectHandle) WinHttpCloseHandle(connectHandle); if (httpSessionHandle) WinHttpCloseHandle(httpSessionHandle); PVOID jsonRootObject; //PVOID jsonScanObject; PVIRUSTOTAL_FILE_REPORT_RESULT result; if (!(jsonRootObject = CreateJsonParser(subRequestBuffer))) goto CleanupExit; if (!GetJsonValueAsUlong(jsonRootObject, "response_code")) goto CleanupExit; result = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); memset(result, 0, sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); result->Total = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "total"), FALSE); result->Positives = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "positives"), FALSE); result->Resource = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "resource")); result->ScanId = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_id")); result->Md5 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "md5")); result->Sha1 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha1")); result->Sha256 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha256")); result->ScanDate = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_date")); result->Permalink = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "permalink")); result->StatusMessage = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "verbose_msg")); //if (jsonScanObject = JsonGetObject(jsonRootObject, "scans")) //{ // PPH_LIST jsonArrayList; // // if (jsonArrayList = JsonGetObjectArrayList(jsonScanObject)) // { // result->ScanResults = PhCreateList(jsonArrayList->Count); // // for (ULONG i = 0; i < jsonArrayList->Count; i++) // { // PJSON_ARRAY_LIST_OBJECT object = jsonArrayList->Items[i]; // //BOOLEAN detected = GetJsonValueAsBool(object->Entry, "detected") == TRUE; // //PSTR version = GetJsonValueAsString(object->Entry, "version"); // //PSTR result = GetJsonValueAsString(object->Entry, "result"); // //PSTR update = GetJsonValueAsString(object->Entry, "update"); // // PhFree(object); // } // // PhDereferenceObject(jsonArrayList); // } //} return result; }
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; }
PPH_STRING PhGetServiceTooltipText( _In_ PPH_SERVICE_ITEM Service ) { PH_STRING_BUILDER stringBuilder; SC_HANDLE serviceHandle; PhInitializeStringBuilder(&stringBuilder, 200); if (serviceHandle = PhOpenService(Service->Name->Buffer, SERVICE_QUERY_CONFIG)) { PPH_STRING fileName; PPH_STRING description; // File information if (fileName = PhGetServiceRelevantFileName(&Service->Name->sr, serviceHandle)) { PH_IMAGE_VERSION_INFO versionInfo; PPH_STRING versionInfoText; if (PhInitializeImageVersionInfo( &versionInfo, fileName->Buffer )) { versionInfoText = PhFormatImageVersionInfo( fileName, &versionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(versionInfoText)) { PhAppendStringBuilder2(&stringBuilder, L"File:\n"); PhAppendStringBuilder(&stringBuilder, &versionInfoText->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } PhClearReference(&versionInfoText); PhDeleteImageVersionInfo(&versionInfo); } PhDereferenceObject(fileName); } // Description if (description = PhGetServiceDescription(serviceHandle)) { PhAppendStringBuilder2(&stringBuilder, L"Description:\n "); PhAppendStringBuilder(&stringBuilder, &description->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); PhDereferenceObject(description); } CloseServiceHandle(serviceHandle); } // Remove the trailing newline. if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); return PhFinalStringBuilderString(&stringBuilder); }
NTSTATUS LoadDb( VOID ) { NTSTATUS status; HANDLE fileHandle; LARGE_INTEGER fileSize; mxml_node_t *topNode; mxml_node_t *currentNode; status = PhCreateFileWin32( &fileHandle, ObjectDbPath->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) return status; if (NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize)) && fileSize.QuadPart == 0) { // A blank file is OK. There are no objects to load. NtClose(fileHandle); return status; } topNode = mxmlLoadFd(NULL, fileHandle, MXML_OPAQUE_CALLBACK); NtClose(fileHandle); if (!topNode) return STATUS_FILE_CORRUPT_ERROR; if (topNode->type != MXML_ELEMENT) { mxmlDelete(topNode); return STATUS_FILE_CORRUPT_ERROR; } LockDb(); for (currentNode = topNode->child; currentNode; currentNode = currentNode->next) { PDB_OBJECT object = NULL; PPH_STRING tag = NULL; PPH_STRING name = NULL; PPH_STRING priorityClass = NULL; PPH_STRING ioPriorityPlusOne = NULL; PPH_STRING comment = NULL; PPH_STRING backColor = NULL; PPH_STRING collapse = NULL; PPH_STRING affinityMask = NULL; if (currentNode->type == MXML_ELEMENT && currentNode->value.element.num_attrs >= 2) { for (INT i = 0; i < currentNode->value.element.num_attrs; i++) { if (_stricmp(currentNode->value.element.attrs[i].name, "tag") == 0) PhMoveReference(&tag, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "name") == 0) PhMoveReference(&name, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "priorityclass") == 0) PhMoveReference(&priorityClass, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "iopriorityplusone") == 0) PhMoveReference(&ioPriorityPlusOne, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "backcolor") == 0) PhMoveReference(&backColor, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "collapse") == 0) PhMoveReference(&collapse, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "affinity") == 0) PhMoveReference(&affinityMask, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); } } comment = GetOpaqueXmlNodeText(currentNode); if (tag && name && comment) { ULONG64 tagInteger; ULONG64 priorityClassInteger = 0; ULONG64 ioPriorityPlusOneInteger = 0; PhStringToInteger64(&tag->sr, 10, &tagInteger); if (priorityClass) PhStringToInteger64(&priorityClass->sr, 10, &priorityClassInteger); if (ioPriorityPlusOne) PhStringToInteger64(&ioPriorityPlusOne->sr, 10, &ioPriorityPlusOneInteger); object = CreateDbObject((ULONG)tagInteger, &name->sr, comment); object->PriorityClass = (ULONG)priorityClassInteger; object->IoPriorityPlusOne = (ULONG)ioPriorityPlusOneInteger; } // NOTE: These items are handled separately to maintain compatibility with previous versions of the database. if (object && backColor) { ULONG64 backColorInteger = ULONG_MAX; PhStringToInteger64(&backColor->sr, 10, &backColorInteger); object->BackColor = (COLORREF)backColorInteger; } if (object && collapse) { ULONG64 collapseInteger = 0; PhStringToInteger64(&collapse->sr, 10, &collapseInteger); object->Collapse = !!collapseInteger; } if (object && affinityMask) { ULONG64 affinityInteger = 0; PhStringToInteger64(&affinityMask->sr, 10, &affinityInteger); object->AffinityMask = (ULONG)affinityInteger; } PhClearReference(&tag); PhClearReference(&name); PhClearReference(&priorityClass); PhClearReference(&ioPriorityPlusOne); PhClearReference(&comment); PhClearReference(&backColor); PhClearReference(&collapse); PhClearReference(&affinityMask); } UnlockDb(); mxmlDelete(topNode); return STATUS_SUCCESS; }
INT_PTR CALLBACK PhpColumnSetEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PCOLUMNSET_DIALOG_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(COLUMNSET_DIALOG_CONTEXT)); memset(context, 0, sizeof(COLUMNSET_DIALOG_CONTEXT)); context->SettingName = PhCreateString((PWSTR)lParam); SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } else { context = (PCOLUMNSET_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { context->DialogHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_COLUMNSETLIST); context->RenameButtonHandle = GetDlgItem(hwndDlg, IDC_RENAME); context->MoveUpButtonHandle = GetDlgItem(hwndDlg, IDC_MOVEUP); context->MoveDownButtonHandle = GetDlgItem(hwndDlg, IDC_MOVEDOWN); context->RemoveButtonHandle = GetDlgItem(hwndDlg, IDC_REMOVE); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE); PhSetControlTheme(context->ListViewHandle, L"explorer"); PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 250, L"Name"); PhSetExtendedListView(context->ListViewHandle); context->ColumnSetList = PhInitializeColumnSetList(PhGetString(context->SettingName)); for (ULONG i = 0; i < context->ColumnSetList->Count; i++) { PPH_COLUMN_SET_ENTRY entry = context->ColumnSetList->Items[i]; PhAddListViewItem(context->ListViewHandle, MAXINT, entry->Name->Buffer, entry); } Button_Enable(context->RenameButtonHandle, FALSE); Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); Button_Enable(context->RemoveButtonHandle, FALSE); } break; case WM_DESTROY: { PhDeleteColumnSetList(context->ColumnSetList); RemoveProp(hwndDlg, PhMakeContextAtom()); PhFree(context); } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { if (context->LabelEditActive) break; PhSaveSettingsColumnList(PhGetString(context->SettingName), context->ColumnSetList); EndDialog(hwndDlg, IDOK); } break; case IDC_RENAME: { INT lvItemIndex; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1) { SetFocus(context->ListViewHandle); ListView_EditLabel(context->ListViewHandle, lvItemIndex); } } break; case IDC_MOVEUP: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; PhpMoveSelectedListViewItemUp(context->ListViewHandle); lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhInsertItemList(context->ColumnSetList, lvItemIndex, entry); } } } break; case IDC_MOVEDOWN: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; PhpMoveSelectedListViewItemDown(context->ListViewHandle); lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhInsertItemList(context->ColumnSetList, lvItemIndex, entry); } } } break; case IDC_REMOVE: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhRemoveListViewItem(context->ListViewHandle, lvItemIndex); PhClearReference(&entry->Name); PhClearReference(&entry->Setting); PhClearReference(&entry->Sorting); PhFree(entry); } SetFocus(context->ListViewHandle); ListView_SetItemState(context->ListViewHandle, 0, LVNI_SELECTED, LVNI_SELECTED); //ListView_EnsureVisible(context->ListViewHandle, 0, FALSE); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_DBLCLK: { INT lvItemIndex; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1) { SetFocus(context->ListViewHandle); ListView_EditLabel(context->ListViewHandle, lvItemIndex); } } break; case LVN_ITEMCHANGED: { LPNMLISTVIEW listview = (LPNMLISTVIEW)lParam; INT index; INT lvItemIndex; INT count; index = listview->iItem; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); count = ListView_GetItemCount(context->ListViewHandle); if (count == 0 || index == -1 || lvItemIndex == -1) { Button_Enable(context->RenameButtonHandle, FALSE); Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); Button_Enable(context->RemoveButtonHandle, FALSE); break; } if (index != lvItemIndex) break; if (index == 0 && count == 1) { // First and last item Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); } else if (index == (count - 1)) { // Last item Button_Enable(context->MoveUpButtonHandle, TRUE); Button_Enable(context->MoveDownButtonHandle, FALSE); } else if (index == 0) { // First item Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, TRUE); } else { Button_Enable(context->MoveUpButtonHandle, TRUE); Button_Enable(context->MoveDownButtonHandle, TRUE); } Button_Enable(context->RenameButtonHandle, TRUE); Button_Enable(context->RemoveButtonHandle, TRUE); } break; case LVN_BEGINLABELEDIT: context->LabelEditActive = TRUE; break; case LVN_ENDLABELEDIT: { LV_DISPINFO* lvinfo = (LV_DISPINFO*)lParam; if (lvinfo->item.iItem != -1 && lvinfo->item.pszText) { BOOLEAN found = FALSE; PPH_COLUMN_SET_ENTRY entry; ULONG index; for (ULONG i = 0; i < context->ColumnSetList->Count; i++) { entry = context->ColumnSetList->Items[i]; if (PhEqualStringRef2(&entry->Name->sr, lvinfo->item.pszText, FALSE)) { found = TRUE; break; } } if (!found && PhGetListViewItemParam(context->ListViewHandle, lvinfo->item.iItem, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhMoveReference(&entry->Name, PhCreateString(lvinfo->item.pszText)); ListView_SetItemText(context->ListViewHandle, lvinfo->item.iItem, 0, lvinfo->item.pszText); } } } context->LabelEditActive = FALSE; } break; } } break; } return FALSE; }
VOID PhpAdvancedPageLoad( _In_ HWND hwndDlg ) { HWND changeButton; SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEWARNINGS, L"EnableWarnings"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEKERNELMODEDRIVER, L"EnableKph"); SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEUNNAMEDHANDLES, L"HideUnnamedHandles"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLESTAGE2, L"EnableStage2"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLENETWORKRESOLVE, L"EnableNetworkResolve"); SetDlgItemCheckForSetting(hwndDlg, IDC_PROPAGATECPUUSAGE, L"PropagateCpuUsage"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS, L"EnableInstantTooltips"); if (WindowsVersion >= WINDOWS_7) SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLECYCLECPUUSAGE, L"EnableCycleCpuUsage"); SetDlgItemInt(hwndDlg, IDC_SAMPLECOUNT, PhGetIntegerSetting(L"SampleCount"), FALSE); SetDlgItemCheckForSetting(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC, L"SampleCountAutomatic"); if (PhGetIntegerSetting(L"SampleCountAutomatic")) EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), FALSE); // Replace Task Manager changeButton = GetDlgItem(hwndDlg, IDC_CHANGE); if (PhGetOwnTokenAttributes().Elevated) { ShowWindow(changeButton, SW_HIDE); } else { SendMessage(changeButton, BCM_SETSHIELD, 0, TRUE); } { HANDLE taskmgrKeyHandle = NULL; ULONG disposition; BOOLEAN success = FALSE; BOOLEAN alreadyReplaced = FALSE; // See if we can write to the key. if (NT_SUCCESS(PhCreateKey( &taskmgrKeyHandle, KEY_READ | KEY_WRITE, PH_KEY_LOCAL_MACHINE, &TaskMgrImageOptionsKeyName, 0, 0, &disposition ))) { success = TRUE; } if (taskmgrKeyHandle || NT_SUCCESS(PhOpenKey( &taskmgrKeyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &TaskMgrImageOptionsKeyName, 0 ))) { PhClearReference(&OldTaskMgrDebugger); if (OldTaskMgrDebugger = PhQueryRegistryString(taskmgrKeyHandle, L"Debugger")) { alreadyReplaced = PathMatchesPh(OldTaskMgrDebugger); } NtClose(taskmgrKeyHandle); } if (!success) EnableWindow(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER), FALSE); OldReplaceTaskMgr = alreadyReplaced; Button_SetCheck(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER), alreadyReplaced ? BST_CHECKED : BST_UNCHECKED); } }
VOID PhShowThreadStackDialog( _In_ HWND ParentWindowHandle, _In_ HANDLE ProcessId, _In_ HANDLE ThreadId, _In_ PPH_THREAD_PROVIDER ThreadProvider ) { 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, PH_KPH_ERROR_MESSAGE); return; } memset(&threadStackContext, 0, sizeof(THREAD_STACK_CONTEXT)); threadStackContext.ProcessId = ProcessId; threadStackContext.ThreadId = ThreadId; threadStackContext.ThreadProvider = ThreadProvider; threadStackContext.SymbolProvider = ThreadProvider->SymbolProvider; if (!NT_SUCCESS(status = PhOpenThread( &threadHandle, THREAD_QUERY_INFORMATION | 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 ); PhClearReference(&threadStackContext.StatusMessage); PhDereferenceObject(threadStackContext.NewList); PhDereferenceObject(threadStackContext.List); if (threadStackContext.ThreadHandle) NtClose(threadStackContext.ThreadHandle); }
INT_PTR CALLBACK PhpProcessMitigationPolicyDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMITIGATION_POLICY_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = (PMITIGATION_POLICY_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PMITIGATION_POLICY_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) { RemoveProp(hwndDlg, L"Context"); } } if (context == NULL) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PROCESS_MITIGATION_POLICY policy; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); context->ListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 350, L"Policy"); PhSetExtendedListView(lvHandle); for (policy = 0; policy < MaxProcessMitigationPolicy; policy++) { PMITIGATION_POLICY_ENTRY entry = &context->Entries[policy]; if (!entry->ShortDescription) continue; PhAddListViewItem(lvHandle, MAXINT, entry->ShortDescription->Buffer, entry); } if (context->SystemDllInitBlock && RTL_CONTAINS_FIELD(context->SystemDllInitBlock, context->SystemDllInitBlock->Size, MitigationOptionsMap)) { if (context->SystemDllInitBlock->MitigationOptionsMap.Map[0] & PROCESS_CREATION_MITIGATION_POLICY2_LOADER_INTEGRITY_CONTINUITY_ALWAYS_ON) { PMITIGATION_POLICY_ENTRY entry; entry = PhAllocate(sizeof(MITIGATION_POLICY_ENTRY)); entry->NonStandard = TRUE; entry->ShortDescription = PhCreateString(L"Loader Integrity"); entry->LongDescription = PhCreateString(L"OS signing levels for depenedent module loads are enabled."); PhAddListViewItem(lvHandle, MAXINT, entry->ShortDescription->Buffer, entry); } if (context->SystemDllInitBlock->MitigationOptionsMap.Map[0] & PROCESS_CREATION_MITIGATION_POLICY2_MODULE_TAMPERING_PROTECTION_ALWAYS_ON) { PMITIGATION_POLICY_ENTRY entry; entry = PhAllocate(sizeof(MITIGATION_POLICY_ENTRY)); entry->NonStandard = TRUE; entry->ShortDescription = PhCreateString(L"Module Tampering"); entry->LongDescription = PhCreateString(L"Module Tampering protection is enabled."); PhAddListViewItem(lvHandle, MAXINT, entry->ShortDescription->Buffer, entry); } } ExtendedListView_SortItems(lvHandle); ExtendedListView_SetColumnWidth(lvHandle, 0, ELVSCW_AUTOSIZE_REMAININGSPACE); ListView_SetItemState(lvHandle, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)lvHandle, TRUE); } break; case WM_DESTROY: { ULONG index = -1; while ((index = PhFindListViewItemByFlags( context->ListViewHandle, index, LVNI_ALL )) != -1) { PMITIGATION_POLICY_ENTRY entry; if (PhGetListViewItemParam(context->ListViewHandle, index, &entry)) { if (entry->NonStandard) { PhClearReference(&entry->ShortDescription); PhClearReference(&entry->LongDescription); PhFree(entry); } } } } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; HWND lvHandle = GetDlgItem(hwndDlg, IDC_LIST); switch (header->code) { case LVN_ITEMCHANGED: { if (header->hwndFrom == lvHandle) { PWSTR description; if (ListView_GetSelectedCount(lvHandle) == 1) description = ((PMITIGATION_POLICY_ENTRY)PhGetSelectedListViewItemParam(lvHandle))->LongDescription->Buffer; else description = L""; SetDlgItemText(hwndDlg, IDC_DESCRIPTION, description); } } break; } PhHandleListViewNotifyForCopy(lParam, lvHandle); } break; } return FALSE; }
INT_PTR CALLBACK EtpGpuNodesDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { ULONG i; HFONT font; PPH_STRING nodeString; RECT labelRect; RECT tempRect; ULONG numberOfRows; ULONG numberOfColumns; WindowHandle = hwndDlg; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhInitializeLayoutManager(&LayoutManager, hwndDlg); PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); LayoutMargin = PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_LAYOUT), NULL, PH_ANCHOR_ALL)->Margin; PhRegisterCallback(&PhProcessesUpdatedEvent, ProcessesUpdatedCallback, NULL, &ProcessesUpdatedCallbackRegistration); GraphHandle = PhAllocate(sizeof(HWND) * EtGpuTotalNodeCount); CheckBoxHandle = PhAllocate(sizeof(HWND) * EtGpuTotalNodeCount); GraphState = PhAllocate(sizeof(PH_GRAPH_STATE) * EtGpuTotalNodeCount); font = (HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0); for (i = 0; i < EtGpuTotalNodeCount; i++) { nodeString = PhFormatString(L"Node %lu", i); GraphHandle[i] = CreateWindow( PH_GRAPH_CLASSNAME, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 3, 3, hwndDlg, NULL, NULL, NULL ); Graph_SetTooltip(GraphHandle[i], TRUE); CheckBoxHandle[i] = CreateWindow( WC_BUTTON, nodeString->Buffer, WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX, 0, 0, 3, 3, hwndDlg, NULL, NULL, NULL ); SendMessage(CheckBoxHandle[i], WM_SETFONT, (WPARAM)font, FALSE); PhInitializeGraphState(&GraphState[i]); PhDereferenceObject(nodeString); } // Calculate the minimum size. numberOfRows = (ULONG)sqrt(EtGpuTotalNodeCount); numberOfColumns = (EtGpuTotalNodeCount + numberOfRows - 1) / numberOfRows; MinimumSize.left = 0; MinimumSize.top = 0; MinimumSize.right = 45; MinimumSize.bottom = 60; MapDialogRect(hwndDlg, &MinimumSize); MinimumSize.right += (MinimumSize.right + GRAPH_PADDING) * numberOfColumns; MinimumSize.bottom += (MinimumSize.bottom + GRAPH_PADDING) * numberOfRows; GetWindowRect(GetDlgItem(hwndDlg, IDC_INSTRUCTION), &labelRect); MapWindowPoints(NULL, hwndDlg, (POINT *)&labelRect, 2); labelRect.right += GetSystemMetrics(SM_CXFRAME) * 2; tempRect.left = 0; tempRect.top = 0; tempRect.right = 7; tempRect.bottom = 0; MapDialogRect(hwndDlg, &tempRect); labelRect.right += tempRect.right; if (MinimumSize.right < labelRect.right) MinimumSize.right = labelRect.right; SetWindowPos(hwndDlg, NULL, 0, 0, MinimumSize.right, MinimumSize.bottom, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); EtpLoadNodeBitMap(); } break; case WM_DESTROY: { ULONG i; EtpSaveNodeBitMap(); PhUnregisterCallback(&PhProcessesUpdatedEvent, &ProcessesUpdatedCallbackRegistration); for (i = 0; i < EtGpuTotalNodeCount; i++) { PhDeleteGraphState(&GraphState[i]); } PhFree(GraphHandle); PhFree(CheckBoxHandle); PhFree(GraphState); PhDeleteLayoutManager(&LayoutManager); } break; case WM_SIZE: { HDWP deferHandle; RECT clientRect; RECT checkBoxRect; ULONG numberOfRows = (ULONG)sqrt(EtGpuTotalNodeCount); ULONG numberOfColumns = (EtGpuTotalNodeCount + numberOfRows - 1) / numberOfRows; ULONG numberOfYPaddings = numberOfRows - 1; ULONG numberOfXPaddings = numberOfColumns - 1; ULONG cellHeight; ULONG y; ULONG cellWidth; ULONG x; ULONG i; PhLayoutManagerLayout(&LayoutManager); deferHandle = BeginDeferWindowPos(EtGpuTotalNodeCount * 2); GetClientRect(hwndDlg, &clientRect); GetClientRect(GetDlgItem(hwndDlg, IDC_EXAMPLE), &checkBoxRect); cellHeight = (clientRect.bottom - LayoutMargin.top - LayoutMargin.bottom - GRAPH_PADDING * numberOfYPaddings) / numberOfRows; y = LayoutMargin.top; i = 0; for (ULONG row = 0; row < numberOfRows; ++row) { // Give the last row the remaining space; the height we calculated might be off by a few // pixels due to integer division. if (row == numberOfRows - 1) cellHeight = clientRect.bottom - LayoutMargin.bottom - y; cellWidth = (clientRect.right - LayoutMargin.left - LayoutMargin.right - GRAPH_PADDING * numberOfXPaddings) / numberOfColumns; x = LayoutMargin.left; for (ULONG column = 0; column < numberOfColumns; column++) { // Give the last cell the remaining space; the width we calculated might be off by a few // pixels due to integer division. if (column == numberOfColumns - 1) cellWidth = clientRect.right - LayoutMargin.right - x; if (i < EtGpuTotalNodeCount) { deferHandle = DeferWindowPos( deferHandle, GraphHandle[i], NULL, x, y, cellWidth, cellHeight - checkBoxRect.bottom - CHECKBOX_PADDING, SWP_NOACTIVATE | SWP_NOZORDER ); deferHandle = DeferWindowPos( deferHandle, CheckBoxHandle[i], NULL, x, y + cellHeight - checkBoxRect.bottom, cellWidth, checkBoxRect.bottom, SWP_NOACTIVATE | SWP_NOZORDER ); i++; } x += cellWidth + GRAPH_PADDING; } y += cellHeight + GRAPH_PADDING; } EndDeferWindowPos(deferHandle); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: { EndDialog(hwndDlg, IDOK); } break; } } break; case WM_NOTIFY: { NMHDR *header = (NMHDR *)lParam; ULONG i; switch (header->code) { case GCN_GETDRAWINFO: { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; drawInfo->Flags = PH_GRAPH_USE_GRID; SysInfoParameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0); for (i = 0; i < EtGpuTotalNodeCount; i++) { if (header->hwndFrom == GraphHandle[i]) { PhGraphStateGetDrawInfo( &GraphState[i], getDrawInfo, EtGpuNodesHistory[i].Count ); if (!GraphState[i].Valid) { PhCopyCircularBuffer_FLOAT(&EtGpuNodesHistory[i], GraphState[i].Data1, drawInfo->LineDataCount); GraphState[i].Valid = TRUE; } break; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)header; if (getTooltipText->Index < getTooltipText->TotalCount) { for (i = 0; i < EtGpuTotalNodeCount; i++) { if (header->hwndFrom == GraphHandle[i]) { if (GraphState[i].TooltipIndex != getTooltipText->Index) { FLOAT gpu; ULONG adapterIndex; PPH_STRING adapterDescription; gpu = PhGetItemCircularBuffer_FLOAT(&EtGpuNodesHistory[i], getTooltipText->Index); adapterIndex = EtGetGpuAdapterIndexFromNodeIndex(i); if (adapterIndex != -1) { adapterDescription = EtGetGpuAdapterDescription(adapterIndex); if (adapterDescription && adapterDescription->Length == 0) PhClearReference(&adapterDescription); if (!adapterDescription) adapterDescription = PhFormatString(L"Adapter %lu", adapterIndex); } else { adapterDescription = PhCreateString(L"Unknown Adapter"); } PhMoveReference(&GraphState[i].TooltipText, PhFormatString( L"Node %lu on %s\n%.2f%%\n%s", i, adapterDescription->Buffer, gpu * 100, ((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); PhDereferenceObject(adapterDescription); } getTooltipText->Text = GraphState[i].TooltipText->sr; break; } } } } break; } } break; case UPDATE_MSG: { ULONG i; for (i = 0; i < EtGpuTotalNodeCount; i++) { GraphState[i].Valid = FALSE; GraphState[i].TooltipIndex = -1; Graph_MoveGrid(GraphHandle[i], 1); Graph_Draw(GraphHandle[i]); Graph_UpdateTooltip(GraphHandle[i]); InvalidateRect(GraphHandle[i], NULL, FALSE); } } break; } return FALSE; }
static INT_PTR CALLBACK PhpFindObjectsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhFindObjectsListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_RESULTS); PhInitializeLayoutManager(&WindowLayoutManager, hwndDlg); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_FILTER), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_REGEX), NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, lvHandle, NULL, PH_ANCHOR_ALL); MinimumSize.left = 0; MinimumSize.top = 0; MinimumSize.right = 150; MinimumSize.bottom = 100; MapDialogRect(hwndDlg, &MinimumSize); PhRegisterDialog(hwndDlg); PhLoadWindowPlacementFromSetting(L"FindObjWindowPosition", L"FindObjWindowSize", hwndDlg); PhSetListViewStyle(lvHandle, TRUE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Process"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Type"); PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 200, L"Name"); PhAddListViewColumn(lvHandle, 3, 3, 3, LVCFMT_LEFT, 80, L"Handle"); PhSetExtendedListView(lvHandle); ExtendedListView_SetSortFast(lvHandle, TRUE); ExtendedListView_SetCompareFunction(lvHandle, 0, PhpObjectProcessCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 1, PhpObjectTypeCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 2, PhpObjectNameCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 3, PhpObjectHandleCompareFunction); PhLoadListViewColumnsFromSetting(L"FindObjListViewColumns", lvHandle); Button_SetCheck(GetDlgItem(hwndDlg, IDC_REGEX), PhGetIntegerSetting(L"FindObjRegex") ? BST_CHECKED : BST_UNCHECKED); } break; case WM_DESTROY: { PhSetIntegerSetting(L"FindObjRegex", Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED); PhSaveWindowPlacementToSetting(L"FindObjWindowPosition", L"FindObjWindowSize", hwndDlg); PhSaveListViewColumnsToSetting(L"FindObjListViewColumns", PhFindObjectsListViewHandle); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_FILTER), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_FILTER), 0, -1); } break; case WM_CLOSE: { ShowWindow(hwndDlg, SW_HIDE); // IMPORTANT // Set the result to 0 so the default dialog message // handler doesn't invoke IDCANCEL, which will send // WM_CLOSE, creating an infinite loop. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0); } return TRUE; case WM_SETCURSOR: { if (SearchThreadHandle) { SetCursor(LoadCursor(NULL, IDC_WAIT)); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); return TRUE; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDOK: { // Don't continue if the user requested cancellation. if (SearchStop) break; if (!SearchThreadHandle) { ULONG i; PhMoveReference(&SearchString, PhGetWindowText(GetDlgItem(hwndDlg, IDC_FILTER))); if (SearchRegexCompiledExpression) { pcre2_code_free(SearchRegexCompiledExpression); SearchRegexCompiledExpression = NULL; } if (SearchRegexMatchData) { pcre2_match_data_free(SearchRegexMatchData); SearchRegexMatchData = NULL; } if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED) { int errorCode; PCRE2_SIZE errorOffset; SearchRegexCompiledExpression = pcre2_compile( SearchString->Buffer, SearchString->Length / sizeof(WCHAR), PCRE2_CASELESS | PCRE2_DOTALL, &errorCode, &errorOffset, NULL ); if (!SearchRegexCompiledExpression) { PhShowError(hwndDlg, L"Unable to compile the regular expression: \"%s\" at position %zu.", PhGetStringOrDefault(PH_AUTO(PhPcre2GetErrorMessage(errorCode)), L"Unknown error"), errorOffset ); break; } SearchRegexMatchData = pcre2_match_data_create_from_pattern(SearchRegexCompiledExpression, NULL); } // Clean up previous results. ListView_DeleteAllItems(PhFindObjectsListViewHandle); if (SearchResults) { for (i = 0; i < SearchResults->Count; i++) { PPHP_OBJECT_SEARCH_RESULT searchResult = SearchResults->Items[i]; PhDereferenceObject(searchResult->TypeName); PhDereferenceObject(searchResult->Name); if (searchResult->ProcessName) PhDereferenceObject(searchResult->ProcessName); PhFree(searchResult); } PhDereferenceObject(SearchResults); } // Start the search. SearchResults = PhCreateList(128); SearchResultsAddIndex = 0; SearchThreadHandle = PhCreateThread(0, PhpFindObjectsThreadStart, NULL); if (!SearchThreadHandle) { PhClearReference(&SearchResults); break; } SetDlgItemText(hwndDlg, IDOK, L"Cancel"); SetCursor(LoadCursor(NULL, IDC_WAIT)); } else { SearchStop = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); } } break; case IDCANCEL: { SendMessage(hwndDlg, WM_CLOSE, 0, 0); } break; case ID_OBJECT_CLOSE: { PPHP_OBJECT_SEARCH_RESULT *results; ULONG numberOfResults; ULONG i; PhGetSelectedListViewItemParams( PhFindObjectsListViewHandle, &results, &numberOfResults ); if (numberOfResults != 0 && PhShowConfirmMessage( hwndDlg, L"close", numberOfResults == 1 ? L"the selected handle" : L"the selected handles", L"Closing handles may cause system instability and data corruption.", FALSE )) { for (i = 0; i < numberOfResults; i++) { NTSTATUS status; HANDLE processHandle; if (results[i]->ResultType != HandleSearchResult) continue; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, results[i]->ProcessId ))) { if (NT_SUCCESS(status = PhDuplicateObject( processHandle, results[i]->Handle, NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE ))) { PhRemoveListViewItem(PhFindObjectsListViewHandle, PhFindListViewItemByParam(PhFindObjectsListViewHandle, 0, results[i])); } NtClose(processHandle); } if (!NT_SUCCESS(status)) { if (!PhShowContinueStatus(hwndDlg, PhaFormatString(L"Unable to close \"%s\"", results[i]->Name->Buffer)->Buffer, status, 0 )) break; } } } PhFree(results); } break; case ID_HANDLE_OBJECTPROPERTIES1: case ID_HANDLE_OBJECTPROPERTIES2: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { PH_HANDLE_ITEM_INFO info; info.ProcessId = result->ProcessId; info.Handle = result->Handle; info.TypeName = result->TypeName; info.BestObjectName = result->Name; if (LOWORD(wParam) == ID_HANDLE_OBJECTPROPERTIES1) PhShowHandleObjectProperties1(hwndDlg, &info); else PhShowHandleObjectProperties2(hwndDlg, &info); } } break; case ID_OBJECT_GOTOOWNINGPROCESS: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { PPH_PROCESS_NODE processNode; if (processNode = PhFindProcessNode(result->ProcessId)) { ProcessHacker_SelectTabPage(PhMainWndHandle, 0); ProcessHacker_SelectProcessNode(PhMainWndHandle, processNode); ProcessHacker_ToggleVisible(PhMainWndHandle, TRUE); } } } break; case ID_OBJECT_PROPERTIES: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { if (result->ResultType == HandleSearchResult) { PPH_HANDLE_ITEM handleItem; handleItem = PhCreateHandleItem(&result->Info); handleItem->BestObjectName = handleItem->ObjectName = result->Name; PhReferenceObjectEx(result->Name, 2); handleItem->TypeName = result->TypeName; PhReferenceObject(result->TypeName); PhShowHandleProperties( hwndDlg, result->ProcessId, handleItem ); PhDereferenceObject(handleItem); } else { // DLL or Mapped File. Just show file properties. PhShellProperties(hwndDlg, result->Name->Buffer); } } } break; case ID_OBJECT_COPY: { PhCopyListView(PhFindObjectsListViewHandle); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_DBLCLK: { if (header->hwndFrom == PhFindObjectsListViewHandle) { SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_PROPERTIES, 0); } } break; case LVN_KEYDOWN: { if (header->hwndFrom == PhFindObjectsListViewHandle) { LPNMLVKEYDOWN keyDown = (LPNMLVKEYDOWN)header; switch (keyDown->wVKey) { case 'C': if (GetKeyState(VK_CONTROL) < 0) SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_COPY, 0); break; case 'A': if (GetKeyState(VK_CONTROL) < 0) PhSetStateAllListViewItems(PhFindObjectsListViewHandle, LVIS_SELECTED, LVIS_SELECTED); break; case VK_DELETE: SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_CLOSE, 0); break; } } } break; } } break; case WM_CONTEXTMENU: { if ((HWND)wParam == PhFindObjectsListViewHandle) { POINT point; PPHP_OBJECT_SEARCH_RESULT *results; ULONG numberOfResults; point.x = (SHORT)LOWORD(lParam); point.y = (SHORT)HIWORD(lParam); if (point.x == -1 && point.y == -1) PhGetListViewContextMenuPoint((HWND)wParam, &point); PhGetSelectedListViewItemParams(PhFindObjectsListViewHandle, &results, &numberOfResults); if (numberOfResults != 0) { PPH_EMENU menu; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_FINDOBJ), 0); PhSetFlagsEMenuItem(menu, ID_OBJECT_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT); PhpInitializeFindObjMenu(menu, results, numberOfResults); PhShowEMenu( menu, hwndDlg, PH_EMENU_SHOW_SEND_COMMAND | PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y ); PhDestroyEMenu(menu); } PhFree(results); } } break; case WM_SIZE: { PhLayoutManagerLayout(&WindowLayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SEARCH_UPDATE: { HWND lvHandle; ULONG i; lvHandle = GetDlgItem(hwndDlg, IDC_RESULTS); ExtendedListView_SetRedraw(lvHandle, FALSE); PhAcquireQueuedLockExclusive(&SearchResultsLock); for (i = SearchResultsAddIndex; i < SearchResults->Count; i++) { PPHP_OBJECT_SEARCH_RESULT searchResult = SearchResults->Items[i]; CLIENT_ID clientId; PPH_PROCESS_ITEM processItem; PPH_STRING clientIdName; INT lvItemIndex; clientId.UniqueProcess = searchResult->ProcessId; clientId.UniqueThread = NULL; processItem = PhReferenceProcessItem(clientId.UniqueProcess); clientIdName = PhGetClientIdNameEx(&clientId, processItem ? processItem->ProcessName : NULL); lvItemIndex = PhAddListViewItem( lvHandle, MAXINT, clientIdName->Buffer, searchResult ); PhDereferenceObject(clientIdName); if (processItem) { PhSetReference(&searchResult->ProcessName, processItem->ProcessName); PhDereferenceObject(processItem); } else { searchResult->ProcessName = NULL; } PhSetListViewSubItem(lvHandle, lvItemIndex, 1, searchResult->TypeName->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 2, searchResult->Name->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 3, searchResult->HandleString); } SearchResultsAddIndex = i; PhReleaseQueuedLockExclusive(&SearchResultsLock); ExtendedListView_SetRedraw(lvHandle, TRUE); } break; case WM_PH_SEARCH_FINISHED: { NTSTATUS handleSearchStatus = (NTSTATUS)wParam; // Add any un-added items. SendMessage(hwndDlg, WM_PH_SEARCH_UPDATE, 0, 0); NtWaitForSingleObject(SearchThreadHandle, FALSE, NULL); NtClose(SearchThreadHandle); SearchThreadHandle = NULL; SearchStop = FALSE; ExtendedListView_SortItems(GetDlgItem(hwndDlg, IDC_RESULTS)); SetDlgItemText(hwndDlg, IDOK, L"Find"); EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (handleSearchStatus == STATUS_INSUFFICIENT_RESOURCES) { PhShowWarning( hwndDlg, L"Unable to search for handles because the total number of handles on the system is too large. " L"Please check if there are any processes with an extremely large number of handles open." ); } } break; } return FALSE; }
VOID DeleteNetAdapterId( _Inout_ PDV_NETADAPTER_ID Id ) { PhClearReference(&Id->InterfaceGuid); }
NTSTATUS PhpServiceNonPollThreadStart( _In_ PVOID Parameter ) { ULONG result; SC_HANDLE scManagerHandle; LPENUM_SERVICE_STATUS_PROCESS services; ULONG numberOfServices; ULONG i; PLIST_ENTRY listEntry; PPHP_SERVICE_NOTIFY_CONTEXT notifyContext; if (!NT_SUCCESS(NtCreateEvent(&PhpNonPollEventHandle, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE))) { PhpNonPollActive = FALSE; PhpNonPollGate = 1; return STATUS_UNSUCCESSFUL; } while (TRUE) { scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); if (!scManagerHandle) goto ErrorExit; InitializeListHead(&PhpNonPollServiceListHead); InitializeListHead(&PhpNonPollServicePendingListHead); if (!(services = PhEnumServices(scManagerHandle, 0, 0, &numberOfServices))) goto ErrorExit; for (i = 0; i < numberOfServices; i++) { SC_HANDLE serviceHandle; if (serviceHandle = OpenService(scManagerHandle, services[i].lpServiceName, SERVICE_QUERY_STATUS)) { notifyContext = PhAllocate(sizeof(PHP_SERVICE_NOTIFY_CONTEXT)); memset(notifyContext, 0, sizeof(PHP_SERVICE_NOTIFY_CONTEXT)); notifyContext->ServiceHandle = serviceHandle; notifyContext->State = SnNotify; InsertTailList(&PhpNonPollServicePendingListHead, ¬ifyContext->ListEntry); } } PhFree(services); notifyContext = PhAllocate(sizeof(PHP_SERVICE_NOTIFY_CONTEXT)); memset(notifyContext, 0, sizeof(PHP_SERVICE_NOTIFY_CONTEXT)); notifyContext->ServiceHandle = scManagerHandle; notifyContext->IsServiceManager = TRUE; notifyContext->State = SnNotify; InsertTailList(&PhpNonPollServicePendingListHead, ¬ifyContext->ListEntry); while (TRUE) { BOOLEAN lagging = FALSE; listEntry = PhpNonPollServicePendingListHead.Flink; while (listEntry != &PhpNonPollServicePendingListHead) { notifyContext = CONTAINING_RECORD(listEntry, PHP_SERVICE_NOTIFY_CONTEXT, ListEntry); listEntry = listEntry->Flink; switch (notifyContext->State) { case SnNone: break; case SnAdding: notifyContext->ServiceHandle = OpenService(scManagerHandle, notifyContext->ServiceName->Buffer, SERVICE_QUERY_STATUS); if (!notifyContext->ServiceHandle) { RemoveEntryList(¬ifyContext->ListEntry); PhpDestroyServiceNotifyContext(notifyContext); continue; } PhClearReference(¬ifyContext->ServiceName); notifyContext->State = SnNotify; goto NotifyCase; case SnRemoving: RemoveEntryList(¬ifyContext->ListEntry); PhpDestroyServiceNotifyContext(notifyContext); break; case SnNotify: NotifyCase: memset(¬ifyContext->Buffer, 0, sizeof(SERVICE_NOTIFY)); notifyContext->Buffer.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; notifyContext->Buffer.pfnNotifyCallback = PhpServiceNonPollScNotifyCallback; notifyContext->Buffer.pContext = notifyContext; result = NotifyServiceStatusChangeW_I( notifyContext->ServiceHandle, notifyContext->IsServiceManager ? (SERVICE_NOTIFY_CREATED | SERVICE_NOTIFY_DELETED) : (SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_START_PENDING | SERVICE_NOTIFY_STOP_PENDING | SERVICE_NOTIFY_RUNNING | SERVICE_NOTIFY_CONTINUE_PENDING | SERVICE_NOTIFY_PAUSE_PENDING | SERVICE_NOTIFY_PAUSED | SERVICE_NOTIFY_DELETE_PENDING), ¬ifyContext->Buffer ); switch (result) { case ERROR_SUCCESS: notifyContext->State = SnNone; RemoveEntryList(¬ifyContext->ListEntry); InsertTailList(&PhpNonPollServiceListHead, ¬ifyContext->ListEntry); break; case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING: // We are lagging behind. Re-open the handle to the SCM as soon as possible. lagging = TRUE; break; case ERROR_SERVICE_MARKED_FOR_DELETE: default: RemoveEntryList(¬ifyContext->ListEntry); PhpDestroyServiceNotifyContext(notifyContext); break; } break; } } while (NtWaitForSingleObject(PhpNonPollEventHandle, TRUE, NULL) != STATUS_WAIT_0) NOTHING; if (lagging) break; } // Execute all pending callbacks. NtTestAlert(); listEntry = PhpNonPollServiceListHead.Flink; while (listEntry != &PhpNonPollServiceListHead) { notifyContext = CONTAINING_RECORD(listEntry, PHP_SERVICE_NOTIFY_CONTEXT, ListEntry); listEntry = listEntry->Flink; PhpDestroyServiceNotifyContext(notifyContext); } listEntry = PhpNonPollServicePendingListHead.Flink; while (listEntry != &PhpNonPollServicePendingListHead) { notifyContext = CONTAINING_RECORD(listEntry, PHP_SERVICE_NOTIFY_CONTEXT, ListEntry); listEntry = listEntry->Flink; PhpDestroyServiceNotifyContext(notifyContext); } CloseServiceHandle(scManagerHandle); } NtClose(PhpNonPollEventHandle); return STATUS_SUCCESS; ErrorExit: PhpNonPollActive = FALSE; PhpNonPollGate = 1; NtClose(PhpNonPollEventHandle); return STATUS_UNSUCCESSFUL; }
PPH_STRING BrowseForFolder( _In_opt_ HWND DialogHandle, _In_opt_ PCWSTR Title ) { PPH_STRING folderPath = NULL; if (WINDOWS_HAS_IFILEDIALOG) { PVOID fileDialog; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogOptions(fileDialog, PH_FILEDIALOG_PICKFOLDERS); if (PhShowFileDialog(DialogHandle, fileDialog)) { PPH_STRING folderPath; PPH_STRING fileDialogFolderPath = PhGetFileDialogFileName(fileDialog); folderPath = PhCreateStringEx(fileDialogFolderPath->Buffer, fileDialogFolderPath->Length * 2); // Ensure the folder path ends with a slash // We must make sure the install path ends with a backslash since // this string is wcscat' with our zip extraction paths. PathAddBackslash(folderPath->Buffer); PhTrimToNullTerminatorString(folderPath); PhFreeFileDialog(fileDialog); return folderPath; } } else { PIDLIST_ABSOLUTE shellItemId; BROWSEINFO browseInformation; memset(&browseInformation, 0, sizeof(BROWSEINFO)); browseInformation.hwndOwner = DialogHandle; browseInformation.lpszTitle = Title; browseInformation.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; // Caller needs to call OleInitialize() before using BIF_NEWDIALOGSTYLE? if (shellItemId = SHBrowseForFolder(&browseInformation)) { folderPath = PhCreateStringEx(NULL, MAX_PATH * 2); if (SHGetPathFromIDList(shellItemId, folderPath->Buffer)) { // Ensure the folder path ends with a slash // We must make sure the install path ends with a backslash since // this string is wcscat' with our zip extraction paths. PathAddBackslash(folderPath->Buffer); PhTrimToNullTerminatorString(folderPath); } else { PhClearReference(&folderPath); } CoTaskMemFree(shellItemId); } } return folderPath; }
PVIRUSTOTAL_FILE_REPORT VirusTotalRequestFileReport( _In_ PPH_STRING FileHash ) { PVIRUSTOTAL_FILE_REPORT result = NULL; PPH_BYTES jsonString = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING versionString = NULL; PPH_STRING userAgentString = NULL; PPH_STRING urlPathString = NULL; PVOID jsonRootObject = NULL; PVOID jsonScanObject; versionString = PhGetPhVersion(); userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer); if (!PhHttpSocketCreate( &httpContext, PhGetString(userAgentString) )) { goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, L"www.virustotal.com", PH_HTTP_DEFAULT_HTTPS_PORT )) { goto CleanupExit; } { PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlPathString = PhFormatString( L"%s%s%s%s%s%S%s%s", L"/vtapi", L"/v2", L"/file", L"/report", L"?\x0061\x0070\x0069\x006B\x0065\x0079=", resourceString->Buffer, L"&resource=", FileHash->Buffer ); PhClearReference(&resourceString); } if (!PhHttpSocketBeginRequest( httpContext, L"POST", PhGetString(urlPathString), PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { goto CleanupExit; } if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0)) goto CleanupExit; if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) goto CleanupExit; if (!PhHttpSocketEndRequest(httpContext)) goto CleanupExit; if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE))) goto CleanupExit; if (!(jsonRootObject = PhCreateJsonParser(jsonString->Buffer))) goto CleanupExit; result = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT)); memset(result, 0, sizeof(VIRUSTOTAL_FILE_REPORT)); result->ResponseCode = PhGetJsonValueAsLong64(jsonRootObject, "response_code"); result->StatusMessage = PhGetJsonValueAsString(jsonRootObject, "verbose_msg"); result->PermaLink = PhGetJsonValueAsString(jsonRootObject, "permalink"); result->ScanDate = PhGetJsonValueAsString(jsonRootObject, "scan_date"); result->ScanId = PhGetJsonValueAsString(jsonRootObject, "scan_id"); result->Total = PhFormatUInt64(PhGetJsonValueAsLong64(jsonRootObject, "total"), FALSE); result->Positives = PhFormatUInt64(PhGetJsonValueAsLong64(jsonRootObject, "positives"), FALSE); //result->Md5 = PhGetJsonValueAsString(jsonRootObject, "md5"); //result->Sha1 = PhGetJsonValueAsString(jsonRootObject, "sha1"); //result->Sha256 = PhGetJsonValueAsString(jsonRootObject, "sha256"); if (jsonScanObject = PhGetJsonObject(jsonRootObject, "scans")) { PPH_LIST jsonArrayList; if (jsonArrayList = PhGetJsonObjectAsArrayList(jsonScanObject)) { result->ScanResults = PhCreateList(jsonArrayList->Count); for (ULONG i = 0; i < jsonArrayList->Count; i++) { PVIRUSTOTAL_FILE_REPORT_RESULT entry; PJSON_ARRAY_LIST_OBJECT object = jsonArrayList->Items[i]; entry = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); memset(entry, 0, sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); entry->Vendor = PhConvertUtf8ToUtf16(object->Key); entry->Detected = PhGetJsonObjectBool(object->Entry, "detected"); entry->EngineVersion = PhGetJsonValueAsString(object->Entry, "version"); entry->DetectionName = PhGetJsonValueAsString(object->Entry, "result"); entry->DatabaseDate = PhGetJsonValueAsString(object->Entry, "update"); PhAddItemList(result->ScanResults, entry); PhFree(object); } PhDereferenceObject(jsonArrayList); } } CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (jsonRootObject) PhFreeJsonParser(jsonRootObject); PhClearReference(&jsonString); PhClearReference(&versionString); PhClearReference(&userAgentString); return result; }
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 DeleteDiskId( _Inout_ PDV_DISK_ID Id ) { PhClearReference(&Id->DevicePath); }
VOID DiskDrivesUpdate( VOID ) { static ULONG runCount = 0; // MUST keep in sync with runCount in process provider PhAcquireQueuedLockShared(&DiskDrivesListLock); for (ULONG i = 0; i < DiskDrivesList->Count; i++) { HANDLE deviceHandle; PDV_DISK_ENTRY entry; entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]); if (!entry) continue; if (NT_SUCCESS(DiskDriveCreateHandle(&deviceHandle, entry->Id.DevicePath))) { DISK_PERFORMANCE diskPerformance; if (NT_SUCCESS(DiskDriveQueryStatistics(deviceHandle, &diskPerformance))) { ULONG64 readTime; ULONG64 writeTime; ULONG64 idleTime; ULONG readCount; ULONG writeCount; ULONG64 queryTime; PhUpdateDelta(&entry->BytesReadDelta, diskPerformance.BytesRead.QuadPart); PhUpdateDelta(&entry->BytesWrittenDelta, diskPerformance.BytesWritten.QuadPart); PhUpdateDelta(&entry->ReadTimeDelta, diskPerformance.ReadTime.QuadPart); PhUpdateDelta(&entry->WriteTimeDelta, diskPerformance.WriteTime.QuadPart); PhUpdateDelta(&entry->IdleTimeDelta, diskPerformance.IdleTime.QuadPart); PhUpdateDelta(&entry->ReadCountDelta, diskPerformance.ReadCount); PhUpdateDelta(&entry->WriteCountDelta, diskPerformance.WriteCount); PhUpdateDelta(&entry->QueryTimeDelta, diskPerformance.QueryTime.QuadPart); readTime = entry->ReadTimeDelta.Delta; writeTime = entry->WriteTimeDelta.Delta; idleTime = entry->IdleTimeDelta.Delta; readCount = entry->ReadCountDelta.Delta; writeCount = entry->WriteCountDelta.Delta; queryTime = entry->QueryTimeDelta.Delta; if (readCount + writeCount != 0) entry->ResponseTime = ((FLOAT)readTime + (FLOAT)writeTime) / (readCount + writeCount); else entry->ResponseTime = 0; if (queryTime != 0) entry->ActiveTime = (FLOAT)(queryTime - idleTime) / queryTime * 100; else entry->ActiveTime = 0.0f; if (entry->ActiveTime > 100.f) entry->ActiveTime = 0.f; if (entry->ActiveTime < 0.f) entry->ActiveTime = 0.f; entry->QueueDepth = diskPerformance.QueueDepth; entry->SplitCount = diskPerformance.SplitCount; entry->DiskIndex = diskPerformance.StorageDeviceNumber; entry->DevicePresent = TRUE; } else { // Disk has been disconnected or dismounted. PhInitializeDelta(&entry->BytesReadDelta); PhInitializeDelta(&entry->BytesWrittenDelta); PhInitializeDelta(&entry->ReadTimeDelta); PhInitializeDelta(&entry->WriteTimeDelta); PhInitializeDelta(&entry->IdleTimeDelta); PhInitializeDelta(&entry->ReadCountDelta); PhInitializeDelta(&entry->WriteCountDelta); PhInitializeDelta(&entry->QueryTimeDelta); entry->ResponseTime = 0; entry->ActiveTime = 0.0f; entry->QueueDepth = 0; entry->SplitCount = 0; entry->DiskIndex = ULONG_MAX; entry->DevicePresent = FALSE; PhClearReference(&entry->DiskIndexName); } if (runCount > 1) { // Delay the first query for the disk name, index and type. // 1) This information is not needed until the user opens the sysinfo window. // 2) Try not to query this information while opening the sysinfo window (e.g. delay). // 3) Try not to query this information during startup (e.g. delay). // // Note: If the user opens the Sysinfo window before we query the disk info, // we have a second check in diskgraph.c that queries the information on demand. DiskDriveUpdateDeviceInfo(deviceHandle, entry); } NtClose(deviceHandle); } else { // Disk has been disconnected or dismounted. PhInitializeDelta(&entry->BytesReadDelta); PhInitializeDelta(&entry->BytesWrittenDelta); PhInitializeDelta(&entry->ReadTimeDelta); PhInitializeDelta(&entry->WriteTimeDelta); PhInitializeDelta(&entry->IdleTimeDelta); PhInitializeDelta(&entry->ReadCountDelta); PhInitializeDelta(&entry->WriteCountDelta); PhInitializeDelta(&entry->QueryTimeDelta); entry->ResponseTime = 0; entry->ActiveTime = 0.0f; entry->QueueDepth = 0; entry->SplitCount = 0; entry->DiskIndex = ULONG_MAX; entry->DevicePresent = FALSE; PhClearReference(&entry->DiskIndexName); } if (!entry->HaveFirstSample) { // The first sample must be zero. entry->BytesReadDelta.Delta = 0; entry->BytesWrittenDelta.Delta = 0; entry->HaveFirstSample = TRUE; } if (runCount != 0) { PhAddItemCircularBuffer_ULONG64(&entry->ReadBuffer, entry->BytesReadDelta.Delta); PhAddItemCircularBuffer_ULONG64(&entry->WriteBuffer, entry->BytesWrittenDelta.Delta); } PhDereferenceObjectDeferDelete(entry); } PhReleaseQueuedLockShared(&DiskDrivesListLock); runCount++; }