BOOLEAN UpdaterCheckApplicationDirectory( VOID ) { HANDLE fileHandle; PPH_STRING directory; PPH_STRING file; if (UpdaterCheckKphInstallState()) return FALSE; directory = PhGetApplicationDirectory(); file = PhConcatStrings(2, PhGetStringOrEmpty(directory), L"\\processhacker.update"); if (NT_SUCCESS(PhCreateFileWin32( &fileHandle, PhGetString(file), FILE_GENERIC_WRITE | DELETE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE ))) { PhDereferenceObject(file); PhDereferenceObject(directory); NtClose(fileHandle); return TRUE; } PhDereferenceObject(file); PhDereferenceObject(directory); return FALSE; }
VOID ShowLatestVersionDialog( _In_ PPH_UPDATER_CONTEXT Context ) { TASKDIALOGCONFIG config; LARGE_INTEGER time; SYSTEMTIME systemTime = { 0 }; PIMAGE_DOS_HEADER imageDosHeader; PIMAGE_NT_HEADERS imageNtHeader; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_ENABLE_HYPERLINKS | TDF_EXPAND_FOOTER_AREA; config.dwCommonButtons = TDCBF_CLOSE_BUTTON; config.hMainIcon = Context->IconLargeHandle; config.cxWidth = 200; config.pfCallback = FinalTaskDialogCallbackProc; config.lpCallbackData = (LONG_PTR)Context; // HACK imageDosHeader = (PIMAGE_DOS_HEADER)NtCurrentPeb()->ImageBaseAddress; imageNtHeader = (PIMAGE_NT_HEADERS)PTR_ADD_OFFSET(imageDosHeader, imageDosHeader->e_lfanew); RtlSecondsSince1970ToTime(imageNtHeader->FileHeader.TimeDateStamp, &time); PhLargeIntegerToLocalSystemTime(&systemTime, &time); config.pszWindowTitle = L"Process Hacker - Updater"; config.pszMainInstruction = L"You're running the latest version."; config.pszContent = PhaFormatString( L"Version: v%s\r\nCompiled: %s\r\n\r\n<A HREF=\"changelog.txt\">View Changelog</A>", PhGetStringOrEmpty(Context->CurrentVersionString), PhaFormatDateTime(&systemTime)->Buffer )->Buffer; TaskDialogNavigatePage(Context->DialogHandle, &config); }
VOID ShowFileFoundDialog( _In_ PUPLOAD_CONTEXT Context ) { TASKDIALOGCONFIG config; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS; config.dwCommonButtons = TDCBF_CLOSE_BUTTON; config.hMainIcon = Context->IconLargeHandle; config.pszMainInstruction = PhaFormatString( L"%s was last analyzed %s ago", PhGetStringOrEmpty(Context->BaseFileName), PhGetStringOrEmpty(Context->LastAnalysisAgo) )->Buffer; // was last analyzed by VirusTotal on 2016-12-28 05:26:50 UTC (1 hour ago) it was first analyzed by VirusTotal on 2016-12-12 17:08:19 UTC. config.pszContent = PhaFormatString( L"Detection ratio: %s/%s\r\nFirst analyzed: %s\r\nLast analyzed: %s\r\nUpload size: %s\r\n\r\nYou can take a look at the last analysis or upload it again now.", PhGetStringOrEmpty(Context->Detected), PhGetStringOrEmpty(Context->MaxDetected), PhGetStringOrEmpty(Context->FirstAnalysisDate), PhGetStringOrEmpty(Context->LastAnalysisDate), PhGetStringOrEmpty(Context->FileSize) )->Buffer; config.pszVerificationText = L"Remember this selection..."; config.pButtons = TaskDialogButtonArray; config.cButtons = ARRAYSIZE(TaskDialogButtonArray); config.lpCallbackData = (LONG_PTR)Context; config.pfCallback = TaskDialogResultFoundProc; SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config); }
VOID VirusTotalShowErrorDialog( _In_ PUPLOAD_CONTEXT Context ) { TASKDIALOGCONFIG config; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_ENABLE_HYPERLINKS; config.dwCommonButtons = TDCBF_CLOSE_BUTTON; config.hMainIcon = Context->IconLargeHandle; config.pszWindowTitle = PhaFormatString(L"Uploading %s...", PhGetStringOrEmpty(Context->BaseFileName))->Buffer; config.pszMainInstruction = PhaFormatString(L"Error uploading %s...", PhGetStringOrEmpty(Context->BaseFileName))->Buffer; config.pszContent = PhGetStringOrEmpty(Context->ErrorString); config.cxWidth = 200; config.lpCallbackData = (LONG_PTR)Context; config.pfCallback = TaskDialogErrorProc; SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config); }
VOID ShowVirusTotalProgressDialog( _In_ PUPLOAD_CONTEXT Context ) { TASKDIALOGCONFIG config; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_EXPAND_FOOTER_AREA | TDF_ENABLE_HYPERLINKS | TDF_SHOW_PROGRESS_BAR; config.dwCommonButtons = TDCBF_CANCEL_BUTTON; config.hMainIcon = Context->IconLargeHandle; config.pszWindowTitle = PhaFormatString(L"Uploading %s...", PhGetStringOrEmpty(Context->BaseFileName))->Buffer; config.pszMainInstruction = PhaFormatString(L"Uploading %s...", PhGetStringOrEmpty(Context->BaseFileName))->Buffer; config.pszContent = L"Uploaded: ~ of ~ (0%)\r\nSpeed: ~ KB/s"; config.cxWidth = 200; config.lpCallbackData = (LONG_PTR)Context; config.pfCallback = TaskDialogProgressCallbackProc; SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config); }
VOID PhSaveSettingsColumnList( _In_ PWSTR SettingName, _In_ PPH_LIST ColumnSetList ) { ULONG index; PPH_STRING settingsString; PH_STRING_BUILDER stringBuilder; PhInitializeStringBuilder(&stringBuilder, 100); PhAppendFormatStringBuilder( &stringBuilder, L"%lu-", ColumnSetList->Count ); for (index = 0; index < ColumnSetList->Count; index++) { PPH_COLUMN_SET_ENTRY entry = ColumnSetList->Items[index]; if (PhIsNullOrEmptyString(entry->Name)) continue; PhAppendFormatStringBuilder( &stringBuilder, L"%s-%s-%s-", entry->Name->Buffer, PhGetStringOrEmpty(entry->Setting), PhGetStringOrEmpty(entry->Sorting) ); } if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); settingsString = PH_AUTO(PhFinalStringBuilderString(&stringBuilder)); PhSetStringSetting2(SettingName, &settingsString->sr); }
VOID ShowNewerVersionDialog( _In_ PPH_UPDATER_CONTEXT Context ) { TASKDIALOGCONFIG config; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_EXPAND_FOOTER_AREA; config.dwCommonButtons = TDCBF_CLOSE_BUTTON; config.hMainIcon = Context->IconLargeHandle; config.cxWidth = 200; config.pfCallback = FinalTaskDialogCallbackProc; config.lpCallbackData = (LONG_PTR)Context; config.pszWindowTitle = L"Process Hacker - Updater"; config.pszMainInstruction = L"You're running a pre-release build."; config.pszContent = PhaFormatString( L"Pre-release build: v%s\r\n", PhGetStringOrEmpty(Context->CurrentVersionString) )->Buffer; TaskDialogNavigatePage(Context->DialogHandle, &config); }
VOID PhSipNotifyCpuGraph( _In_ ULONG Index, _In_ NMHDR *Header ) { 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_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_USE_LINE_2; PhSiSetColorsGraphDrawInfo(drawInfo, PhCsColorCpuKernel, PhCsColorCpuUser); if (Index == -1) { PhGraphStateGetDrawInfo( &CpuGraphState, getDrawInfo, PhCpuKernelHistory.Count ); if (!CpuGraphState.Valid) { PhCopyCircularBuffer_FLOAT(&PhCpuKernelHistory, CpuGraphState.Data1, drawInfo->LineDataCount); PhCopyCircularBuffer_FLOAT(&PhCpuUserHistory, CpuGraphState.Data2, drawInfo->LineDataCount); CpuGraphState.Valid = TRUE; } } else { PhGraphStateGetDrawInfo( &CpusGraphState[Index], getDrawInfo, PhCpuKernelHistory.Count ); if (!CpusGraphState[Index].Valid) { PhCopyCircularBuffer_FLOAT(&PhCpusKernelHistory[Index], CpusGraphState[Index].Data1, drawInfo->LineDataCount); PhCopyCircularBuffer_FLOAT(&PhCpusUserHistory[Index], CpusGraphState[Index].Data2, drawInfo->LineDataCount); CpusGraphState[Index].Valid = TRUE; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header; if (getTooltipText->Index < getTooltipText->TotalCount) { if (Index == -1) { if (CpuGraphState.TooltipIndex != getTooltipText->Index) { FLOAT cpuKernel; FLOAT cpuUser; cpuKernel = PhGetItemCircularBuffer_FLOAT(&PhCpuKernelHistory, getTooltipText->Index); cpuUser = PhGetItemCircularBuffer_FLOAT(&PhCpuUserHistory, getTooltipText->Index); PhMoveReference(&CpuGraphState.TooltipText, PhFormatString( L"%.2f%%%s\n%s", (cpuKernel + cpuUser) * 100, PhGetStringOrEmpty(PhSipGetMaxCpuString(getTooltipText->Index)), PH_AUTO_T(PH_STRING, PhGetStatisticsTimeString(NULL, getTooltipText->Index))->Buffer )); } getTooltipText->Text = CpuGraphState.TooltipText->sr; } else { if (CpusGraphState[Index].TooltipIndex != getTooltipText->Index) { FLOAT cpuKernel; FLOAT cpuUser; cpuKernel = PhGetItemCircularBuffer_FLOAT(&PhCpusKernelHistory[Index], getTooltipText->Index); cpuUser = PhGetItemCircularBuffer_FLOAT(&PhCpusUserHistory[Index], getTooltipText->Index); PhMoveReference(&CpusGraphState[Index].TooltipText, PhFormatString( L"%.2f%% (K: %.2f%%, U: %.2f%%)%s\n%s", (cpuKernel + cpuUser) * 100, cpuKernel * 100, cpuUser * 100, PhGetStringOrEmpty(PhSipGetMaxCpuString(getTooltipText->Index)), PH_AUTO_T(PH_STRING, PhGetStatisticsTimeString(NULL, getTooltipText->Index))->Buffer )); } getTooltipText->Text = CpusGraphState[Index].TooltipText->sr; } } } break; case GCN_MOUSEEVENT: { PPH_GRAPH_MOUSEEVENT mouseEvent = (PPH_GRAPH_MOUSEEVENT)Header; PPH_PROCESS_RECORD record; record = NULL; if (mouseEvent->Message == WM_LBUTTONDBLCLK && mouseEvent->Index < mouseEvent->TotalCount) { record = PhSipReferenceMaxCpuRecord(mouseEvent->Index); } if (record) { PhShowProcessRecordDialog(CpuDialog, record); PhDereferenceProcessRecord(record); } } break; } }
BOOLEAN EtpGpuSectionCallback( __in PPH_SYSINFO_SECTION Section, __in PH_SYSINFO_SECTION_MESSAGE Message, __in_opt PVOID Parameter1, __in_opt PVOID Parameter2 ) { switch (Message) { case SysInfoDestroy: { if (GpuDialog) { EtpUninitializeGpuDialog(); GpuDialog = NULL; } } return TRUE; case SysInfoTick: { if (GpuDialog) { EtpTickGpuDialog(); } } return TRUE; case SysInfoCreateDialog: { PPH_SYSINFO_CREATE_DIALOG createDialog = Parameter1; createDialog->Instance = PluginInstance->DllBase; createDialog->Template = MAKEINTRESOURCE(IDD_SYSINFO_GPU); createDialog->DialogProc = EtpGpuDialogProc; } return TRUE; case SysInfoGraphGetDrawInfo: { PPH_GRAPH_DRAW_INFO drawInfo = Parameter1; drawInfo->Flags = PH_GRAPH_USE_GRID; Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0); PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, EtGpuNodeHistory.Count); if (!Section->GraphState.Valid) { PhCopyCircularBuffer_FLOAT(&EtGpuNodeHistory, Section->GraphState.Data1, drawInfo->LineDataCount); Section->GraphState.Valid = TRUE; } } return TRUE; case SysInfoGraphGetTooltipText: { PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = Parameter1; FLOAT gpu; gpu = PhGetItemCircularBuffer_FLOAT(&EtGpuNodeHistory, getTooltipText->Index); PhSwapReference2(&Section->GraphState.TooltipText, PhFormatString( L"%.2f%%%s\n%s", gpu * 100, PhGetStringOrEmpty(EtpGetMaxNodeString(getTooltipText->Index)), ((PPH_STRING)PHA_DEREFERENCE(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); getTooltipText->Text = Section->GraphState.TooltipText->sr; } return TRUE; case SysInfoGraphDrawPanel: { PPH_SYSINFO_DRAW_PANEL drawPanel = Parameter1; drawPanel->Title = PhCreateString(L"GPU"); drawPanel->SubTitle = PhFormatString(L"%.2f%%", EtGpuNodeUsage * 100); } return TRUE; } return FALSE; }
NTSTATUS UpdateDownloadThread( _In_ PVOID Parameter ) { BOOLEAN downloadSuccess = FALSE; BOOLEAN hashSuccess = FALSE; BOOLEAN signatureSuccess = FALSE; HANDLE tempFileHandle = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING downloadHostPath = NULL; PPH_STRING downloadUrlPath = NULL; PUPDATER_HASH_CONTEXT hashContext = NULL; USHORT httpPort = 0; LARGE_INTEGER timeNow; LARGE_INTEGER timeStart; ULONG64 timeTicks = 0; ULONG64 timeBitsPerSecond = 0; PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)Parameter; SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Initializing download request..."); if (!PhHttpSocketParseUrl( context->SetupFileDownloadUrl, &downloadHostPath, &downloadUrlPath, &httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Create the local path string. context->SetupFilePath = UpdaterParseDownloadFileName(downloadUrlPath); if (PhIsNullOrEmptyString(context->SetupFilePath)) goto CleanupExit; // Create temporary output file. if (!NT_SUCCESS(PhCreateFileWin32( &tempFileHandle, PhGetString(context->SetupFilePath), FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Connecting..."); if (!PhHttpSocketCreate(&httpContext, NULL)) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, PhGetString(downloadHostPath), httpPort )) { context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketBeginRequest( httpContext, NULL, PhGetString(downloadUrlPath), PH_HTTP_FLAG_REFRESH | (httpPort == PH_HTTP_DEFAULT_HTTPS_PORT ? PH_HTTP_FLAG_SECURE : 0) )) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Sending download request..."); if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) { context->ErrorCode = GetLastError(); goto CleanupExit; } SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)L"Waiting for response..."); if (!PhHttpSocketEndRequest(httpContext)) { context->ErrorCode = GetLastError(); goto CleanupExit; } else { ULONG bytesDownloaded = 0; ULONG downloadedBytes = 0; ULONG contentLength = 0; PPH_STRING status; IO_STATUS_BLOCK isb; BYTE buffer[PAGE_SIZE]; status = PhFormatString(L"Downloading update %s...", PhGetStringOrEmpty(context->Version)); SendMessage(context->DialogHandle, TDM_SET_MARQUEE_PROGRESS_BAR, FALSE, 0); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_MAIN_INSTRUCTION, (LPARAM)status->Buffer); PhDereferenceObject(status); if (!PhHttpSocketQueryHeaderUlong( httpContext, PH_HTTP_QUERY_CONTENT_LENGTH, &contentLength )) { context->ErrorCode = GetLastError(); goto CleanupExit; } // Initialize hash algorithm. if (!(hashContext = UpdaterInitializeHash())) goto CleanupExit; // Zero the buffer. memset(buffer, 0, PAGE_SIZE); // Start the clock. PhQuerySystemTime(&timeStart); // Download the data. while (PhHttpSocketReadData(httpContext, buffer, PAGE_SIZE, &bytesDownloaded)) { // If we get zero bytes, the file was uploaded or there was an error if (bytesDownloaded == 0) break; // If the dialog was closed, just cleanup and exit if (!UpdateDialogThreadHandle) goto CleanupExit; // Update the hash of bytes we downloaded. UpdaterUpdateHash(hashContext, buffer, bytesDownloaded); // Write the downloaded bytes to disk. if (!NT_SUCCESS(NtWriteFile( tempFileHandle, NULL, NULL, NULL, &isb, buffer, bytesDownloaded, NULL, NULL ))) { goto CleanupExit; } downloadedBytes += (DWORD)isb.Information; // Check the number of bytes written are the same we downloaded. if (bytesDownloaded != isb.Information) goto CleanupExit; // Query the current time PhQuerySystemTime(&timeNow); // Calculate the number of ticks timeTicks = (timeNow.QuadPart - timeStart.QuadPart) / PH_TICKS_PER_SEC; timeBitsPerSecond = downloadedBytes / __max(timeTicks, 1); // TODO: Update on timer callback. { FLOAT percent = ((FLOAT)downloadedBytes / contentLength * 100); PPH_STRING totalLength = PhFormatSize(contentLength, -1); PPH_STRING totalDownloaded = PhFormatSize(downloadedBytes, -1); PPH_STRING totalSpeed = PhFormatSize(timeBitsPerSecond, -1); PPH_STRING statusMessage = PhFormatString( L"Downloaded: %s of %s (%.0f%%)\r\nSpeed: %s/s", PhGetStringOrEmpty(totalDownloaded), PhGetStringOrEmpty(totalLength), percent, PhGetStringOrEmpty(totalSpeed) ); SendMessage(context->DialogHandle, TDM_UPDATE_ELEMENT_TEXT, TDE_CONTENT, (LPARAM)statusMessage->Buffer); SendMessage(context->DialogHandle, TDM_SET_PROGRESS_BAR_POS, (WPARAM)percent, 0); PhDereferenceObject(statusMessage); PhDereferenceObject(totalSpeed); PhDereferenceObject(totalLength); PhDereferenceObject(totalDownloaded); } } if (UpdaterVerifyHash(hashContext, context->SetupFileHash)) { hashSuccess = TRUE; } if (UpdaterVerifySignature(hashContext, context->SetupFileSignature)) { signatureSuccess = TRUE; } if (hashSuccess && signatureSuccess) { downloadSuccess = TRUE; } } CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (hashContext) UpdaterDestroyHash(hashContext); if (tempFileHandle) NtClose(tempFileHandle); if (downloadHostPath) PhDereferenceObject(downloadHostPath); if (downloadUrlPath) PhDereferenceObject(downloadUrlPath); if (UpdateDialogThreadHandle) { if (downloadSuccess && hashSuccess && signatureSuccess) { ShowUpdateInstallDialog(context); } else if (downloadSuccess) { if (signatureSuccess) ShowUpdateFailedDialog(context, TRUE, FALSE); else if (hashSuccess) ShowUpdateFailedDialog(context, FALSE, TRUE); else ShowUpdateFailedDialog(context, FALSE, FALSE); } else { ShowUpdateFailedDialog(context, FALSE, FALSE); } } PhDereferenceObject(context); return STATUS_SUCCESS; }
INT_PTR CALLBACK PhpRunAsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PRUNAS_DIALOG_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = (PRUNAS_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PRUNAS_DIALOG_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND typeComboBoxHandle = GetDlgItem(hwndDlg, IDC_TYPE); HWND userNameComboBoxHandle = GetDlgItem(hwndDlg, IDC_USERNAME); ULONG sessionId; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); if (SHAutoComplete_I) { SHAutoComplete_I( GetDlgItem(hwndDlg, IDC_PROGRAM), SHACF_AUTOAPPEND_FORCE_ON | SHACF_AUTOSUGGEST_FORCE_ON | SHACF_FILESYS_ONLY ); } ComboBox_AddString(typeComboBoxHandle, L"Batch"); ComboBox_AddString(typeComboBoxHandle, L"Interactive"); ComboBox_AddString(typeComboBoxHandle, L"Network"); ComboBox_AddString(typeComboBoxHandle, L"New credentials"); ComboBox_AddString(typeComboBoxHandle, L"Service"); PhSelectComboBoxString(typeComboBoxHandle, L"Interactive", FALSE); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\SYSTEM"); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\LOCAL SERVICE"); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\NETWORK SERVICE"); PhpAddAccountsToComboBox(userNameComboBoxHandle); if (NT_SUCCESS(PhGetProcessSessionId(NtCurrentProcess(), &sessionId))) SetDlgItemInt(hwndDlg, IDC_SESSIONID, sessionId, FALSE); SetDlgItemText(hwndDlg, IDC_DESKTOP, L"WinSta0\\Default"); SetDlgItemText(hwndDlg, IDC_PROGRAM, PhaGetStringSetting(L"RunAsProgram")->Buffer); if (!context->ProcessId) { SetDlgItemText(hwndDlg, IDC_USERNAME, PH_AUTO_T(PH_STRING, PhGetStringSetting(L"RunAsUserName"))->Buffer); // Fire the user name changed event so we can fix the logon type. SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_USERNAME, CBN_EDITCHANGE), 0); } else { HANDLE processHandle; HANDLE tokenHandle; PTOKEN_USER user; PPH_STRING userName; if (NT_SUCCESS(PhOpenProcess( &processHandle, ProcessQueryAccess, context->ProcessId ))) { if (NT_SUCCESS(PhOpenProcessToken( processHandle, TOKEN_QUERY, &tokenHandle ))) { if (NT_SUCCESS(PhGetTokenUser(tokenHandle, &user))) { if (userName = PhGetSidFullName(user->User.Sid, TRUE, NULL)) { SetDlgItemText(hwndDlg, IDC_USERNAME, userName->Buffer); PhDereferenceObject(userName); } PhFree(user); } NtClose(tokenHandle); } NtClose(processHandle); } EnableWindow(GetDlgItem(hwndDlg, IDC_USERNAME), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TYPE), FALSE); } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_PROGRAM), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_PROGRAM), 0, -1); //if (!PhGetOwnTokenAttributes().Elevated) // SendMessage(GetDlgItem(hwndDlg, IDOK), BCM_SETSHIELD, 0, TRUE); if (!WINDOWS_HAS_UAC) ShowWindow(GetDlgItem(hwndDlg, IDC_TOGGLEELEVATION), SW_HIDE); } break; case WM_DESTROY: { if (context->DesktopList) PhDereferenceObject(context->DesktopList); RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { NTSTATUS status; PPH_STRING program; PPH_STRING userName; PPH_STRING password; PPH_STRING logonTypeString; ULONG logonType; ULONG sessionId; PPH_STRING desktopName; BOOLEAN useLinkedToken; program = PhaGetDlgItemText(hwndDlg, IDC_PROGRAM); userName = PhaGetDlgItemText(hwndDlg, IDC_USERNAME); logonTypeString = PhaGetDlgItemText(hwndDlg, IDC_TYPE); // Fix up the user name if it doesn't have a domain. if (PhFindCharInString(userName, 0, '\\') == -1) { PSID sid; PPH_STRING newUserName; if (NT_SUCCESS(PhLookupName(&userName->sr, &sid, NULL, NULL))) { if (newUserName = PH_AUTO(PhGetSidFullName(sid, TRUE, NULL))) userName = newUserName; PhFree(sid); } } if (!IsServiceAccount(userName)) password = PhGetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD)); else password = NULL; sessionId = GetDlgItemInt(hwndDlg, IDC_SESSIONID, NULL, FALSE); desktopName = PhaGetDlgItemText(hwndDlg, IDC_DESKTOP); if (WINDOWS_HAS_UAC) useLinkedToken = Button_GetCheck(GetDlgItem(hwndDlg, IDC_TOGGLEELEVATION)) == BST_CHECKED; else useLinkedToken = FALSE; if (PhFindIntegerSiKeyValuePairs( PhpLogonTypePairs, sizeof(PhpLogonTypePairs), logonTypeString->Buffer, &logonType )) { if ( logonType == LOGON32_LOGON_INTERACTIVE && !context->ProcessId && sessionId == NtCurrentPeb()->SessionId && !useLinkedToken ) { // We are eligible to load the user profile. // This must be done here, not in the service, because // we need to be in the target session. PH_CREATE_PROCESS_AS_USER_INFO createInfo; PPH_STRING domainPart; PPH_STRING userPart; PhpSplitUserName(userName->Buffer, &domainPart, &userPart); memset(&createInfo, 0, sizeof(PH_CREATE_PROCESS_AS_USER_INFO)); createInfo.CommandLine = program->Buffer; createInfo.UserName = userPart->Buffer; createInfo.DomainName = domainPart->Buffer; createInfo.Password = PhGetStringOrEmpty(password); // Whenever we can, try not to set the desktop name; it breaks a lot of things. // Note that on XP we must set it, otherwise the program doesn't display correctly. if (WindowsVersion < WINDOWS_VISTA || (desktopName->Length != 0 && !PhEqualString2(desktopName, L"WinSta0\\Default", TRUE))) createInfo.DesktopName = desktopName->Buffer; PhSetDesktopWinStaAccess(); status = PhCreateProcessAsUser( &createInfo, PH_CREATE_PROCESS_WITH_PROFILE, NULL, NULL, NULL ); if (domainPart) PhDereferenceObject(domainPart); if (userPart) PhDereferenceObject(userPart); } else { status = PhExecuteRunAsCommand2( hwndDlg, program->Buffer, userName->Buffer, PhGetStringOrEmpty(password), logonType, context->ProcessId, sessionId, desktopName->Buffer, useLinkedToken ); } } else { status = STATUS_INVALID_PARAMETER; } if (password) { RtlSecureZeroMemory(password->Buffer, password->Length); PhDereferenceObject(password); } if (!NT_SUCCESS(status)) { if (status != STATUS_CANCELLED) PhShowStatus(hwndDlg, L"Unable to start the program", status, 0); } else if (status != STATUS_TIMEOUT) { PhSetStringSetting2(L"RunAsProgram", &program->sr); PhSetStringSetting2(L"RunAsUserName", &userName->sr); EndDialog(hwndDlg, IDOK); } } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Programs (*.exe;*.pif;*.com;*.bat)", L"*.exe;*.pif;*.com;*.bat" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, PhaGetDlgItemText(hwndDlg, IDC_PROGRAM)->Buffer); if (PhShowFileDialog(hwndDlg, fileDialog)) { PPH_STRING fileName; fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_PROGRAM, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; case IDC_USERNAME: { PPH_STRING userName = NULL; if (!context->ProcessId && HIWORD(wParam) == CBN_SELCHANGE) { userName = PH_AUTO(PhGetComboBoxString(GetDlgItem(hwndDlg, IDC_USERNAME), -1)); } else if (!context->ProcessId && ( HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_CLOSEUP )) { userName = PhaGetDlgItemText(hwndDlg, IDC_USERNAME); } if (userName) { if (IsServiceAccount(userName)) { EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE); // Hack for Windows XP if ( PhEqualString2(userName, L"NT AUTHORITY\\SYSTEM", TRUE) && WindowsVersion <= WINDOWS_XP ) { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"New credentials", FALSE); } else { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Service", FALSE); } } else { EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Interactive", FALSE); } } } break; case IDC_SESSIONS: { PPH_EMENU sessionsMenu; PSESSIONIDW sessions; ULONG numberOfSessions; ULONG i; RECT buttonRect; PPH_EMENU_ITEM selectedItem; sessionsMenu = PhCreateEMenu(); if (WinStationEnumerateW(NULL, &sessions, &numberOfSessions)) { for (i = 0; i < numberOfSessions; i++) { PPH_STRING menuString; WINSTATIONINFORMATION winStationInfo; ULONG returnLength; if (!WinStationQueryInformationW( NULL, sessions[i].SessionId, WinStationInformation, &winStationInfo, sizeof(WINSTATIONINFORMATION), &returnLength )) { winStationInfo.Domain[0] = 0; winStationInfo.UserName[0] = 0; } if ( winStationInfo.UserName[0] != 0 && sessions[i].WinStationName[0] != 0 ) { menuString = PhaFormatString( L"%u: %s (%s\\%s)", sessions[i].SessionId, sessions[i].WinStationName, winStationInfo.Domain, winStationInfo.UserName ); } else if (winStationInfo.UserName[0] != 0) { menuString = PhaFormatString( L"%u: %s\\%s", sessions[i].SessionId, winStationInfo.Domain, winStationInfo.UserName ); } else if (sessions[i].WinStationName[0] != 0) { menuString = PhaFormatString( L"%u: %s", sessions[i].SessionId, sessions[i].WinStationName ); } else { menuString = PhaFormatString(L"%u", sessions[i].SessionId); } PhInsertEMenuItem(sessionsMenu, PhCreateEMenuItem(0, 0, menuString->Buffer, NULL, UlongToPtr(sessions[i].SessionId)), -1); } WinStationFreeMemory(sessions); GetWindowRect(GetDlgItem(hwndDlg, IDC_SESSIONS), &buttonRect); selectedItem = PhShowEMenu( sessionsMenu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, buttonRect.right, buttonRect.top ); if (selectedItem) { SetDlgItemInt( hwndDlg, IDC_SESSIONID, PtrToUlong(selectedItem->Context), FALSE ); } PhDestroyEMenu(sessionsMenu); } } break; case IDC_DESKTOPS: { PPH_EMENU desktopsMenu; ULONG i; RECT buttonRect; PPH_EMENU_ITEM selectedItem; desktopsMenu = PhCreateEMenu(); if (!context->DesktopList) context->DesktopList = PhCreateList(10); context->CurrentWinStaName = GetCurrentWinStaName(); EnumDesktops(GetProcessWindowStation(), EnumDesktopsCallback, (LPARAM)context); for (i = 0; i < context->DesktopList->Count; i++) { PhInsertEMenuItem( desktopsMenu, PhCreateEMenuItem(0, 0, ((PPH_STRING)context->DesktopList->Items[i])->Buffer, NULL, NULL), -1 ); } GetWindowRect(GetDlgItem(hwndDlg, IDC_DESKTOPS), &buttonRect); selectedItem = PhShowEMenu( desktopsMenu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, buttonRect.right, buttonRect.top ); if (selectedItem) { SetDlgItemText( hwndDlg, IDC_DESKTOP, selectedItem->Text ); } for (i = 0; i < context->DesktopList->Count; i++) PhDereferenceObject(context->DesktopList->Items[i]); PhClearList(context->DesktopList); PhDereferenceObject(context->CurrentWinStaName); PhDestroyEMenu(desktopsMenu); } break; } } break; } return FALSE; }
VOID EtpNotifyGpuGraph( __in NMHDR *Header ) { 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; GpuSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0); PhGraphStateGetDrawInfo( &GpuGraphState, getDrawInfo, EtGpuNodeHistory.Count ); if (!GpuGraphState.Valid) { PhCopyCircularBuffer_FLOAT(&EtGpuNodeHistory, GpuGraphState.Data1, drawInfo->LineDataCount); GpuGraphState.Valid = TRUE; } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header; if (getTooltipText->Index < getTooltipText->TotalCount) { if (GpuGraphState.TooltipIndex != getTooltipText->Index) { FLOAT gpu; gpu = PhGetItemCircularBuffer_FLOAT(&EtGpuNodeHistory, getTooltipText->Index); PhSwapReference2(&GpuGraphState.TooltipText, PhFormatString( L"%.2f%%%s\n%s", gpu * 100, PhGetStringOrEmpty(EtpGetMaxNodeString(getTooltipText->Index)), ((PPH_STRING)PHA_DEREFERENCE(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); } getTooltipText->Text = GpuGraphState.TooltipText->sr; } } break; case GCN_MOUSEEVENT: { PPH_GRAPH_MOUSEEVENT mouseEvent = (PPH_GRAPH_MOUSEEVENT)Header; PPH_PROCESS_RECORD record; record = NULL; if (mouseEvent->Message == WM_LBUTTONDBLCLK && mouseEvent->Index < mouseEvent->TotalCount) { record = EtpReferenceMaxNodeRecord(mouseEvent->Index); } if (record) { PhShowProcessRecordDialog(GpuDialog, record); PhDereferenceProcessRecord(record); } } break; } }
VOID PhpUpdateThreadDetails( _In_ HWND hwndDlg, _In_ PPH_THREADS_CONTEXT Context, _In_ BOOLEAN Force ) { PPH_THREAD_ITEM *threads; ULONG numberOfThreads; PPH_THREAD_ITEM threadItem; PPH_STRING startModule = NULL; PPH_STRING started = NULL; WCHAR kernelTime[PH_TIMESPAN_STR_LEN_1] = L"N/A"; WCHAR userTime[PH_TIMESPAN_STR_LEN_1] = L"N/A"; PPH_STRING contextSwitches = NULL; PPH_STRING cycles = NULL; PPH_STRING state = NULL; WCHAR priority[PH_INT32_STR_LEN_1] = L"N/A"; WCHAR basePriority[PH_INT32_STR_LEN_1] = L"N/A"; PWSTR ioPriority = L"N/A"; PWSTR pagePriority = L"N/A"; WCHAR idealProcessor[PH_INT32_STR_LEN + 1 + PH_INT32_STR_LEN + 1] = L"N/A"; HANDLE threadHandle; SYSTEMTIME time; IO_PRIORITY_HINT ioPriorityInteger; ULONG pagePriorityInteger; PROCESSOR_NUMBER idealProcessorNumber; ULONG suspendCount; PhGetSelectedThreadItems(&Context->ListContext, &threads, &numberOfThreads); if (numberOfThreads == 1) threadItem = threads[0]; else threadItem = NULL; PhFree(threads); if (numberOfThreads != 1 && !Force) return; if (numberOfThreads == 1) { startModule = threadItem->StartAddressFileName; PhLargeIntegerToLocalSystemTime(&time, &threadItem->CreateTime); started = PhaFormatDateTime(&time); PhPrintTimeSpan(kernelTime, threadItem->KernelTime.QuadPart, PH_TIMESPAN_HMSM); PhPrintTimeSpan(userTime, threadItem->UserTime.QuadPart, PH_TIMESPAN_HMSM); contextSwitches = PhaFormatUInt64(threadItem->ContextSwitchesDelta.Value, TRUE); if (WINDOWS_HAS_CYCLE_TIME) cycles = PhaFormatUInt64(threadItem->CyclesDelta.Value, TRUE); if (threadItem->State != Waiting) { if ((ULONG)threadItem->State < MaximumThreadState) state = PhaCreateString(PhKThreadStateNames[(ULONG)threadItem->State]); else state = PhaCreateString(L"Unknown"); } else { if ((ULONG)threadItem->WaitReason < MaximumWaitReason) state = PhaConcatStrings2(L"Wait:", PhKWaitReasonNames[(ULONG)threadItem->WaitReason]); else state = PhaCreateString(L"Waiting"); } PhPrintInt32(priority, threadItem->Priority); PhPrintInt32(basePriority, threadItem->BasePriority); if (NT_SUCCESS(PhOpenThread(&threadHandle, ThreadQueryAccess, threadItem->ThreadId))) { if (NT_SUCCESS(PhGetThreadIoPriority(threadHandle, &ioPriorityInteger)) && ioPriorityInteger < MaxIoPriorityTypes) { ioPriority = PhIoPriorityHintNames[ioPriorityInteger]; } if (NT_SUCCESS(PhGetThreadPagePriority(threadHandle, &pagePriorityInteger)) && pagePriorityInteger <= MEMORY_PRIORITY_NORMAL) { pagePriority = PhPagePriorityNames[pagePriorityInteger]; } if (NT_SUCCESS(NtQueryInformationThread(threadHandle, ThreadIdealProcessorEx, &idealProcessorNumber, sizeof(PROCESSOR_NUMBER), NULL))) { PH_FORMAT format[3]; PhInitFormatU(&format[0], idealProcessorNumber.Group); PhInitFormatC(&format[1], ':'); PhInitFormatU(&format[2], idealProcessorNumber.Number); PhFormatToBuffer(format, 3, idealProcessor, sizeof(idealProcessor), NULL); } if (threadItem->WaitReason == Suspended && NT_SUCCESS(NtQueryInformationThread(threadHandle, ThreadSuspendCount, &suspendCount, sizeof(ULONG), NULL))) { PH_FORMAT format[4]; PhInitFormatSR(&format[0], state->sr); PhInitFormatS(&format[1], L" ("); PhInitFormatU(&format[2], suspendCount); PhInitFormatS(&format[3], L")"); state = PH_AUTO(PhFormat(format, 4, 30)); } NtClose(threadHandle); } } if (Force) { // These don't change... SetDlgItemText(hwndDlg, IDC_STARTMODULE, PhGetStringOrEmpty(startModule)); EnableWindow(GetDlgItem(hwndDlg, IDC_OPENSTARTMODULE), !!startModule); SetDlgItemText(hwndDlg, IDC_STARTED, PhGetStringOrDefault(started, L"N/A")); } SetDlgItemText(hwndDlg, IDC_KERNELTIME, kernelTime); SetDlgItemText(hwndDlg, IDC_USERTIME, userTime); SetDlgItemText(hwndDlg, IDC_CONTEXTSWITCHES, PhGetStringOrDefault(contextSwitches, L"N/A")); SetDlgItemText(hwndDlg, IDC_CYCLES, PhGetStringOrDefault(cycles, L"N/A")); SetDlgItemText(hwndDlg, IDC_STATE, PhGetStringOrDefault(state, L"N/A")); SetDlgItemText(hwndDlg, IDC_PRIORITY, priority); SetDlgItemText(hwndDlg, IDC_BASEPRIORITY, basePriority); SetDlgItemText(hwndDlg, IDC_IOPRIORITY, ioPriority); SetDlgItemText(hwndDlg, IDC_PAGEPRIORITY, pagePriority); SetDlgItemText(hwndDlg, IDC_IDEALPROCESSOR, idealProcessor); }
VOID ToolbarUpdateGraphsInfo(LPNMHDR Header) { switch (Header->code) { case GCN_GETDRAWINFO: { if (ToolStatusConfig.CpuGraphEnabled && Header->hwndFrom == CpuGraphHandle) { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_LINE_2; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), PhGetIntegerSetting(L"ColorCpuUser")); if (ProcessesUpdatedCount < 2) return; PhGraphStateGetDrawInfo(&CpuGraphState, getDrawInfo, SystemStatistics.CpuUserHistory->Count); if (!CpuGraphState.Valid) { PhCopyCircularBuffer_FLOAT(SystemStatistics.CpuKernelHistory, CpuGraphState.Data1, drawInfo->LineDataCount); PhCopyCircularBuffer_FLOAT(SystemStatistics.CpuUserHistory, CpuGraphState.Data2, drawInfo->LineDataCount); CpuGraphState.Valid = TRUE; } } else if (ToolStatusConfig.MemGraphEnabled && Header->hwndFrom == MemGraphHandle) { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; drawInfo->Flags = PH_GRAPH_USE_GRID_X; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorPhysical"), 0); if (ProcessesUpdatedCount < 2) return; PhGraphStateGetDrawInfo(&MemGraphState, getDrawInfo, SystemStatistics.PhysicalHistory->Count); if (!MemGraphState.Valid) { for (ULONG i = 0; i < drawInfo->LineDataCount; i++) { MemGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(SystemStatistics.PhysicalHistory, i); } PhDivideSinglesBySingle( MemGraphState.Data1, (FLOAT)PhSystemBasicInformation.NumberOfPhysicalPages, drawInfo->LineDataCount ); MemGraphState.Valid = TRUE; } } else if (ToolStatusConfig.CommitGraphEnabled && Header->hwndFrom == CommitGraphHandle) { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; drawInfo->Flags = PH_GRAPH_USE_GRID_X; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorPrivate"), 0); if (ProcessesUpdatedCount < 2) return; PhGraphStateGetDrawInfo(&CommitGraphState, getDrawInfo, SystemStatistics.CommitHistory->Count); if (!CommitGraphState.Valid) { for (ULONG i = 0; i < drawInfo->LineDataCount; i++) { CommitGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(SystemStatistics.CommitHistory, i); } PhDivideSinglesBySingle( CommitGraphState.Data1, (FLOAT)SystemStatistics.Performance->CommitLimit, drawInfo->LineDataCount ); CommitGraphState.Valid = TRUE; } } else if (ToolStatusConfig.IoGraphEnabled && Header->hwndFrom == IoGraphHandle) { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_LINE_2; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite")); if (ProcessesUpdatedCount < 2) return; PhGraphStateGetDrawInfo(&IoGraphState, getDrawInfo, SystemStatistics.IoReadHistory->Count); if (!IoGraphState.Valid) { FLOAT max = 1024 * 1024; // minimum scaling of 1 MB. for (ULONG i = 0; i < drawInfo->LineDataCount; i++) { IoGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG64(SystemStatistics.IoReadHistory, i) + (FLOAT)PhGetItemCircularBuffer_ULONG64(SystemStatistics.IoOtherHistory, i); IoGraphState.Data2[i] = (FLOAT)PhGetItemCircularBuffer_ULONG64(SystemStatistics.IoWriteHistory, i); if (max < IoGraphState.Data1[i] + IoGraphState.Data2[i]) max = IoGraphState.Data1[i] + IoGraphState.Data2[i]; } PhDivideSinglesBySingle(IoGraphState.Data1, max, drawInfo->LineDataCount); PhDivideSinglesBySingle(IoGraphState.Data2, max, drawInfo->LineDataCount); drawInfo->GridHeight = 1 / max; IoGraphState.Valid = TRUE; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header; if (getTooltipText->Index < getTooltipText->TotalCount) { if (ToolStatusConfig.CpuGraphEnabled && Header->hwndFrom == CpuGraphHandle) { if (CpuGraphState.TooltipIndex != getTooltipText->Index) { FLOAT cpuKernel; FLOAT cpuUser; cpuKernel = PhGetItemCircularBuffer_FLOAT(SystemStatistics.CpuKernelHistory, getTooltipText->Index); cpuUser = PhGetItemCircularBuffer_FLOAT(SystemStatistics.CpuUserHistory, getTooltipText->Index); PhMoveReference(&CpuGraphState.TooltipText, PhFormatString( L"%.2f%%%s\n%s", (cpuKernel + cpuUser) * 100, PhGetStringOrEmpty(PhSipGetMaxCpuString(getTooltipText->Index)), ((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); } getTooltipText->Text = CpuGraphState.TooltipText->sr; } else if (ToolStatusConfig.MemGraphEnabled && Header->hwndFrom == MemGraphHandle) { ULONG physicalUsage; physicalUsage = PhGetItemCircularBuffer_ULONG(SystemStatistics.PhysicalHistory, getTooltipText->Index); PhMoveReference(&MemGraphState.TooltipText, PhFormatString( L"Physical Memory: %s\n%s", PhaFormatSize(UInt32x32To64(physicalUsage, PAGE_SIZE), -1)->Buffer, ((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); getTooltipText->Text = MemGraphState.TooltipText->sr; } else if (ToolStatusConfig.CommitGraphEnabled && Header->hwndFrom == CommitGraphHandle) { ULONG commitUsage; commitUsage = PhGetItemCircularBuffer_ULONG(SystemStatistics.CommitHistory, getTooltipText->Index); PhMoveReference(&CommitGraphState.TooltipText, PhFormatString( L"Commit: %s\n%s", PhaFormatSize(UInt32x32To64(commitUsage, PAGE_SIZE), -1)->Buffer, ((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); getTooltipText->Text = CommitGraphState.TooltipText->sr; } else if (ToolStatusConfig.IoGraphEnabled && Header->hwndFrom == IoGraphHandle) { ULONG64 ioRead; ULONG64 ioWrite; ULONG64 ioOther; ioRead = PhGetItemCircularBuffer_ULONG64(SystemStatistics.IoReadHistory, getTooltipText->Index); ioWrite = PhGetItemCircularBuffer_ULONG64(SystemStatistics.IoWriteHistory, getTooltipText->Index); ioOther = PhGetItemCircularBuffer_ULONG64(SystemStatistics.IoOtherHistory, getTooltipText->Index); PhMoveReference(&IoGraphState.TooltipText, PhFormatString( L"R: %s\nW: %s\nO: %s%s\n%s", PhaFormatSize(ioRead, -1)->Buffer, PhaFormatSize(ioWrite, -1)->Buffer, PhaFormatSize(ioOther, -1)->Buffer, PhGetStringOrEmpty(PhSipGetMaxIoString(getTooltipText->Index)), ((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); getTooltipText->Text = IoGraphState.TooltipText->sr; } } } break; case GCN_MOUSEEVENT: { PPH_GRAPH_MOUSEEVENT mouseEvent = (PPH_GRAPH_MOUSEEVENT)Header; PPH_PROCESS_RECORD record = NULL; if (ToolStatusConfig.CpuGraphEnabled && Header->hwndFrom == CpuGraphHandle) { if (mouseEvent->Message == WM_RBUTTONUP) { ShowCustomizeMenu(); } else { if (mouseEvent->Message == WM_LBUTTONDBLCLK && mouseEvent->Index < mouseEvent->TotalCount) { record = PhSipReferenceMaxCpuRecord(mouseEvent->Index); } if (record) { PhShowProcessRecordDialog(PhMainWndHandle, record); PhDereferenceProcessRecord(record); } } } else if (ToolStatusConfig.MemGraphEnabled && Header->hwndFrom == MemGraphHandle) { if (mouseEvent->Message == WM_RBUTTONUP) { ShowCustomizeMenu(); } } else if (ToolStatusConfig.CommitGraphEnabled && Header->hwndFrom == CommitGraphHandle) { if (mouseEvent->Message == WM_RBUTTONUP) { ShowCustomizeMenu(); } } else if (ToolStatusConfig.IoGraphEnabled && Header->hwndFrom == IoGraphHandle) { if (mouseEvent->Message == WM_RBUTTONUP) { ShowCustomizeMenu(); } else { if (mouseEvent->Message == WM_LBUTTONDBLCLK && mouseEvent->Index < mouseEvent->TotalCount) { record = PhSipReferenceMaxIoRecord(mouseEvent->Index); } if (record) { PhShowProcessRecordDialog(PhMainWndHandle, record); PhDereferenceProcessRecord(record); } } } } break; } }
static PPH_STRING PhpaGetSendMessageReceiver( _In_ HANDLE ThreadId ) { static HWND (WINAPI *GetSendMessageReceiver_I)( _In_ HANDLE ThreadId ); HWND windowHandle; ULONG threadId; ULONG processId; CLIENT_ID clientId; PPH_STRING clientIdName; WCHAR windowClass[64]; PPH_STRING windowText; // GetSendMessageReceiver is an undocumented function exported by // user32.dll. It retrieves the handle of the window which a thread // is sending a message to. if (!GetSendMessageReceiver_I) GetSendMessageReceiver_I = PhGetDllProcedureAddress(L"user32.dll", "GetSendMessageReceiver", 0); if (!GetSendMessageReceiver_I) return NULL; windowHandle = GetSendMessageReceiver_I(ThreadId); if (!windowHandle) return NULL; threadId = GetWindowThreadProcessId(windowHandle, &processId); clientId.UniqueProcess = UlongToHandle(processId); clientId.UniqueThread = UlongToHandle(threadId); clientIdName = PH_AUTO(PhGetClientIdName(&clientId)); if (!GetClassName(windowHandle, windowClass, sizeof(windowClass) / sizeof(WCHAR))) windowClass[0] = UNICODE_NULL; windowText = PH_AUTO(PhGetWindowText(windowHandle)); return PhaFormatString(L"Window 0x%Ix (%s): %s \"%s\"", windowHandle, clientIdName->Buffer, windowClass, PhGetStringOrEmpty(windowText)); }
VOID PhShowHandleProperties( _In_ HWND ParentWindowHandle, _In_ HANDLE ProcessId, _In_ PPH_HANDLE_ITEM HandleItem ) { PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) }; PROPSHEETPAGE propSheetPage; HPROPSHEETPAGE pages[16]; HANDLE_PROPERTIES_CONTEXT context; PH_STD_OBJECT_SECURITY stdObjectSecurity; PPH_ACCESS_ENTRY accessEntries; ULONG numberOfAccessEntries; context.ProcessId = ProcessId; context.HandleItem = HandleItem; propSheetHeader.dwFlags = PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP | PSH_PROPTITLE; propSheetHeader.hwndParent = ParentWindowHandle; propSheetHeader.pszCaption = L"Handle"; propSheetHeader.nPages = 0; propSheetHeader.nStartPage = 0; propSheetHeader.phpage = pages; // General page memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE)); propSheetPage.dwSize = sizeof(PROPSHEETPAGE); propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_HNDLGENERAL); propSheetPage.pfnDlgProc = PhpHandleGeneralDlgProc; propSheetPage.lParam = (LPARAM)&context; pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage); // Object-specific page if (!HandleItem->TypeName) { // Dummy } else if (PhEqualString2(HandleItem->TypeName, L"Event", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateEventPage( PhpDuplicateHandleFromProcess, &context ); } else if (PhEqualString2(HandleItem->TypeName, L"EventPair", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateEventPairPage( PhpDuplicateHandleFromProcess, &context ); } else if (PhEqualString2(HandleItem->TypeName, L"Job", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateJobPage( PhpDuplicateHandleFromProcess, &context, NULL ); } else if (PhEqualString2(HandleItem->TypeName, L"Mutant", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateMutantPage( PhpDuplicateHandleFromProcess, &context ); } else if (PhEqualString2(HandleItem->TypeName, L"Section", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateSectionPage( PhpDuplicateHandleFromProcess, &context ); } else if (PhEqualString2(HandleItem->TypeName, L"Semaphore", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateSemaphorePage( PhpDuplicateHandleFromProcess, &context ); } else if (PhEqualString2(HandleItem->TypeName, L"Timer", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateTimerPage( PhpDuplicateHandleFromProcess, &context ); } else if (PhEqualString2(HandleItem->TypeName, L"Token", TRUE)) { pages[propSheetHeader.nPages++] = PhCreateTokenPage( PhpDuplicateHandleFromProcess, &context, NULL ); } // Security page stdObjectSecurity.OpenObject = PhpDuplicateHandleFromProcess; stdObjectSecurity.ObjectType = HandleItem->TypeName->Buffer; stdObjectSecurity.Context = &context; if (PhGetAccessEntries(HandleItem->TypeName->Buffer, &accessEntries, &numberOfAccessEntries)) { pages[propSheetHeader.nPages++] = PhCreateSecurityPage( PhGetStringOrEmpty(HandleItem->BestObjectName), PhStdGetObjectSecurity, PhStdSetObjectSecurity, &stdObjectSecurity, accessEntries, numberOfAccessEntries ); PhFree(accessEntries); } if (PhPluginsEnabled) { PH_PLUGIN_OBJECT_PROPERTIES objectProperties; PH_PLUGIN_HANDLE_PROPERTIES_CONTEXT propertiesContext; propertiesContext.ProcessId = ProcessId; propertiesContext.HandleItem = HandleItem; objectProperties.Parameter = &propertiesContext; objectProperties.NumberOfPages = propSheetHeader.nPages; objectProperties.MaximumNumberOfPages = sizeof(pages) / sizeof(HPROPSHEETPAGE); objectProperties.Pages = pages; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackHandlePropertiesInitializing), &objectProperties); propSheetHeader.nPages = objectProperties.NumberOfPages; } PhModalPropertySheet(&propSheetHeader); }
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; }
HRESULT CALLBACK FinalTaskDialogCallbackProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _In_ LONG_PTR dwRefData ) { PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData; switch (uMsg) { case TDN_NAVIGATED: { if (!UpdaterCheckApplicationDirectory()) { SendMessage(hwndDlg, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, IDYES, TRUE); } } break; case TDN_BUTTON_CLICKED: { INT buttonId = (INT)wParam; if (buttonId == IDRETRY) { ShowCheckForUpdatesDialog(context); return S_FALSE; } else if (buttonId == IDYES) { SHELLEXECUTEINFO info = { sizeof(SHELLEXECUTEINFO) }; PPH_STRING parameters; if (PhIsNullOrEmptyString(context->SetupFilePath)) break; parameters = PH_AUTO(PhGetApplicationDirectory()); parameters = PH_AUTO(PhBufferToHexString((PUCHAR)parameters->Buffer, (ULONG)parameters->Length)); parameters = PH_AUTO(PhConcatStrings(3, L"-update \"", PhGetStringOrEmpty(parameters), L"\"")); info.lpFile = PhGetStringOrEmpty(context->SetupFilePath); info.lpParameters = PhGetString(parameters); info.lpVerb = UpdaterCheckApplicationDirectory() ? NULL : L"runas"; info.nShow = SW_SHOW; info.hwnd = hwndDlg; info.fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOZONECHECKS; ProcessHacker_PrepareForEarlyShutdown(PhMainWndHandle); if (ShellExecuteEx(&info)) { ProcessHacker_Destroy(PhMainWndHandle); } else { ULONG errorCode = GetLastError(); // Install failed, cancel the shutdown. ProcessHacker_CancelEarlyShutdown(PhMainWndHandle); // Show error dialog. if (errorCode != ERROR_CANCELLED) // Ignore UAC decline. { PhShowStatus(hwndDlg, L"Unable to execute the setup.", 0, errorCode); if (context->StartupCheck) ShowAvailableDialog(context); else ShowCheckForUpdatesDialog(context); } return S_FALSE; } } } break; case TDN_HYPERLINK_CLICKED: { TaskDialogLinkClicked(context); return S_FALSE; } break; } return S_OK; }
BOOLEAN PhSipCpuSectionCallback( _In_ PPH_SYSINFO_SECTION Section, _In_ PH_SYSINFO_SECTION_MESSAGE Message, _In_opt_ PVOID Parameter1, _In_opt_ PVOID Parameter2 ) { switch (Message) { case SysInfoCreate: { CpuSection = Section; } return TRUE; case SysInfoDestroy: { if (CpuDialog) { PhSipUninitializeCpuDialog(); CpuDialog = NULL; } } return TRUE; case SysInfoTick: { if (CpuDialog) { PhSipTickCpuDialog(); } } return TRUE; case SysInfoCreateDialog: { PPH_SYSINFO_CREATE_DIALOG createDialog = Parameter1; createDialog->Instance = PhInstanceHandle; createDialog->Template = MAKEINTRESOURCE(IDD_SYSINFO_CPU); createDialog->DialogProc = PhSipCpuDialogProc; } return TRUE; case SysInfoGraphGetDrawInfo: { PPH_GRAPH_DRAW_INFO drawInfo = Parameter1; drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_USE_LINE_2; Section->Parameters->ColorSetupFunction(drawInfo, PhCsColorCpuKernel, PhCsColorCpuUser); PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, PhCpuKernelHistory.Count); if (!Section->GraphState.Valid) { PhCopyCircularBuffer_FLOAT(&PhCpuKernelHistory, Section->GraphState.Data1, drawInfo->LineDataCount); PhCopyCircularBuffer_FLOAT(&PhCpuUserHistory, Section->GraphState.Data2, drawInfo->LineDataCount); Section->GraphState.Valid = TRUE; } } return TRUE; case SysInfoGraphGetTooltipText: { PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = Parameter1; FLOAT cpuKernel; FLOAT cpuUser; cpuKernel = PhGetItemCircularBuffer_FLOAT(&PhCpuKernelHistory, getTooltipText->Index); cpuUser = PhGetItemCircularBuffer_FLOAT(&PhCpuUserHistory, getTooltipText->Index); PhMoveReference(&Section->GraphState.TooltipText, PhFormatString( L"%.2f%%%s\n%s", (cpuKernel + cpuUser) * 100, PhGetStringOrEmpty(PhSipGetMaxCpuString(getTooltipText->Index)), PH_AUTO_T(PH_STRING, PhGetStatisticsTimeString(NULL, getTooltipText->Index))->Buffer )); getTooltipText->Text = Section->GraphState.TooltipText->sr; } return TRUE; case SysInfoGraphDrawPanel: { PPH_SYSINFO_DRAW_PANEL drawPanel = Parameter1; drawPanel->Title = PhCreateString(L"CPU"); drawPanel->SubTitle = PhFormatString(L"%.2f%%", (PhCpuKernelUsage + PhCpuUserUsage) * 100); } return TRUE; } return FALSE; }