static PPH_STRING NetworkAdapterQueryLinkSpeed( _In_ HANDLE DeviceHandle ) { NDIS_OID opcode; IO_STATUS_BLOCK isb; NDIS_CO_LINK_SPEED result; // https://msdn.microsoft.com/en-us/library/windows/hardware/ff569593.aspx opcode = OID_GEN_LINK_SPEED; // OID_GEN_CO_LINK_SPEED memset(&result, 0, sizeof(NDIS_CO_LINK_SPEED)); if (NT_SUCCESS(NtDeviceIoControlFile( DeviceHandle, NULL, NULL, NULL, &isb, IOCTL_NDIS_QUERY_GLOBAL_STATS, &opcode, sizeof(NDIS_OID), &result, sizeof(result) ))) { return PhFormatSize(UInt32x32To64(result.Outbound, NDIS_UNIT_OF_MEASUREMENT) / BITS_IN_ONE_BYTE, -1); } return PhReferenceEmptyString(); }
PPH_STRING DiskDriveQueryGeometry( _In_ HANDLE DeviceHandle ) { IO_STATUS_BLOCK isb; DISK_GEOMETRY result; memset(&result, 0, sizeof(DISK_GEOMETRY)); if (NT_SUCCESS(NtDeviceIoControlFile( DeviceHandle, NULL, NULL, NULL, &isb, IOCTL_DISK_GET_DRIVE_GEOMETRY, // https://msdn.microsoft.com/en-us/library/aa365169.aspx NULL, 0, &result, sizeof(result) ))) { // TODO: This doesn't return total capacity like Task Manager. return PhFormatSize(result.Cylinders.QuadPart * result.TracksPerCylinder * result.SectorsPerTrack * result.BytesPerSector, -1); } return PhReferenceEmptyString(); }
INT_PTR CALLBACK PhpJobPageProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PJOB_PAGE_CONTEXT jobPageContext; jobPageContext = PhpJobPageHeader(hwndDlg, uMsg, wParam, lParam); if (!jobPageContext) return FALSE; if (jobPageContext->HookProc) { if (jobPageContext->HookProc(hwndDlg, uMsg, wParam, lParam)) return TRUE; } switch (uMsg) { case WM_INITDIALOG: { HANDLE jobHandle; HWND processesLv; HWND limitsLv; processesLv = GetDlgItem(hwndDlg, IDC_PROCESSES); limitsLv = GetDlgItem(hwndDlg, IDC_LIMITS); PhSetListViewStyle(processesLv, FALSE, TRUE); PhSetListViewStyle(limitsLv, FALSE, TRUE); PhSetControlTheme(processesLv, L"explorer"); PhSetControlTheme(limitsLv, L"explorer"); PhAddListViewColumn(processesLv, 0, 0, 0, LVCFMT_LEFT, 240, L"Name"); PhAddListViewColumn(limitsLv, 0, 0, 0, LVCFMT_LEFT, 120, L"Name"); PhAddListViewColumn(limitsLv, 1, 1, 1, LVCFMT_LEFT, 160, L"Value"); SetDlgItemText(hwndDlg, IDC_NAME, L"Unknown"); if (NT_SUCCESS(jobPageContext->OpenObject( &jobHandle, JOB_OBJECT_QUERY, jobPageContext->Context ))) { PPH_STRING jobObjectName = NULL; JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedLimits; JOBOBJECT_BASIC_UI_RESTRICTIONS basicUiRestrictions; // Name PhGetHandleInformation( NtCurrentProcess(), jobHandle, -1, NULL, NULL, NULL, &jobObjectName ); PHA_DEREFERENCE(jobObjectName); if (jobObjectName && jobObjectName->Length == 0) jobObjectName = NULL; SetDlgItemText(hwndDlg, IDC_NAME, PhGetStringOrDefault(jobObjectName, L"(unnamed job)")); // Processes PhpAddJobProcesses(hwndDlg, jobHandle); // Limits if (NT_SUCCESS(PhGetJobExtendedLimits(jobHandle, &extendedLimits))) { ULONG flags = extendedLimits.BasicLimitInformation.LimitFlags; if (flags & JOB_OBJECT_LIMIT_ACTIVE_PROCESS) { WCHAR value[PH_INT32_STR_LEN_1]; PhPrintUInt32(value, extendedLimits.BasicLimitInformation.ActiveProcessLimit); PhpAddLimit(limitsLv, L"Active Processes", value); } if (flags & JOB_OBJECT_LIMIT_AFFINITY) { WCHAR value[PH_PTR_STR_LEN_1]; PhPrintPointer(value, (PVOID)extendedLimits.BasicLimitInformation.Affinity); PhpAddLimit(limitsLv, L"Affinity", value); } if (flags & JOB_OBJECT_LIMIT_BREAKAWAY_OK) { PhpAddLimit(limitsLv, L"Breakaway OK", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION) { PhpAddLimit(limitsLv, L"Die on Unhandled Exception", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_JOB_MEMORY) { PPH_STRING value = PhFormatSize(extendedLimits.JobMemoryLimit, -1); PhpAddLimit(limitsLv, L"Job Memory", value->Buffer); PhDereferenceObject(value); } if (flags & JOB_OBJECT_LIMIT_JOB_TIME) { WCHAR value[PH_TIMESPAN_STR_LEN_1]; PhPrintTimeSpan(value, extendedLimits.BasicLimitInformation.PerJobUserTimeLimit.QuadPart, PH_TIMESPAN_DHMS); PhpAddLimit(limitsLv, L"Job Time", value); } if (flags & JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE) { PhpAddLimit(limitsLv, L"Kill on Job Close", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_PRIORITY_CLASS) { PhpAddLimit(limitsLv, L"Priority Class", PhGetProcessPriorityClassString(extendedLimits.BasicLimitInformation.PriorityClass)); } if (flags & JOB_OBJECT_LIMIT_PROCESS_MEMORY) { PPH_STRING value = PhFormatSize(extendedLimits.ProcessMemoryLimit, -1); PhpAddLimit(limitsLv, L"Process Memory", value->Buffer); PhDereferenceObject(value); } if (flags & JOB_OBJECT_LIMIT_PROCESS_TIME) { WCHAR value[PH_TIMESPAN_STR_LEN_1]; PhPrintTimeSpan(value, extendedLimits.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart, PH_TIMESPAN_DHMS); PhpAddLimit(limitsLv, L"Process Time", value); } if (flags & JOB_OBJECT_LIMIT_SCHEDULING_CLASS) { WCHAR value[PH_INT32_STR_LEN_1]; PhPrintUInt32(value, extendedLimits.BasicLimitInformation.SchedulingClass); PhpAddLimit(limitsLv, L"Scheduling Class", value); } if (flags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK) { PhpAddLimit(limitsLv, L"Silent Breakaway OK", L"Enabled"); } if (flags & JOB_OBJECT_LIMIT_WORKINGSET) { PPH_STRING value; value = PhFormatSize(extendedLimits.BasicLimitInformation.MinimumWorkingSetSize, -1); PhpAddLimit(limitsLv, L"Working Set Minimum", value->Buffer); PhDereferenceObject(value); value = PhFormatSize(extendedLimits.BasicLimitInformation.MaximumWorkingSetSize, -1); PhpAddLimit(limitsLv, L"Working Set Maximum", value->Buffer); PhDereferenceObject(value); } } if (NT_SUCCESS(PhGetJobBasicUiRestrictions(jobHandle, &basicUiRestrictions))) { ULONG flags = basicUiRestrictions.UIRestrictionsClass; if (flags & JOB_OBJECT_UILIMIT_DESKTOP) PhpAddLimit(limitsLv, L"Desktop", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_DISPLAYSETTINGS) PhpAddLimit(limitsLv, L"Display Settings", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_EXITWINDOWS) PhpAddLimit(limitsLv, L"Exit Windows", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_GLOBALATOMS) PhpAddLimit(limitsLv, L"Global Atoms", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_HANDLES) PhpAddLimit(limitsLv, L"Handles", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_READCLIPBOARD) PhpAddLimit(limitsLv, L"Read Clipboard", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS) PhpAddLimit(limitsLv, L"System Parameters", L"Limited"); if (flags & JOB_OBJECT_UILIMIT_WRITECLIPBOARD) PhpAddLimit(limitsLv, L"Write Clipboard", L"Limited"); } NtClose(jobHandle); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_TERMINATE: { if (PhShowConfirmMessage( hwndDlg, L"terminate", L"the job", L"Terminating a job will terminate all processes assigned to it.", TRUE )) { NTSTATUS status; HANDLE jobHandle; if (NT_SUCCESS(status = jobPageContext->OpenObject( &jobHandle, JOB_OBJECT_TERMINATE, jobPageContext->Context ))) { status = NtTerminateJobObject(jobHandle, STATUS_SUCCESS); NtClose(jobHandle); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to terminate the job", status, 0); } } break; case IDC_ADD: { NTSTATUS status; HANDLE processId; HANDLE processHandle; HANDLE jobHandle; while (PhShowChooseProcessDialog( hwndDlg, L"Select a process to add to the job permanently.", &processId )) { if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_TERMINATE | PROCESS_SET_QUOTA, processId ))) { if (NT_SUCCESS(status = jobPageContext->OpenObject( &jobHandle, JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_QUERY, jobPageContext->Context ))) { status = NtAssignProcessToJobObject(jobHandle, processHandle); if (NT_SUCCESS(status)) { ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_PROCESSES)); PhpAddJobProcesses(hwndDlg, jobHandle); } NtClose(jobHandle); } NtClose(processHandle); } if (NT_SUCCESS(status)) break; else PhShowStatus(hwndDlg, L"Unable to add the process to the job", status, 0); } } break; case IDC_ADVANCED: { PhpShowJobAdvancedProperties(hwndDlg, jobPageContext); } break; } } break; case WM_NOTIFY: { PhHandleListViewNotifyBehaviors(lParam, GetDlgItem(hwndDlg, IDC_PROCESSES), PH_LIST_VIEW_DEFAULT_1_BEHAVIORS); PhHandleListViewNotifyBehaviors(lParam, GetDlgItem(hwndDlg, IDC_LIMITS), PH_LIST_VIEW_DEFAULT_1_BEHAVIORS); } break; } return FALSE; }
INT_PTR CALLBACK UpdaterWndProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { LOGFONT lHeaderFont = { 0 }; // load the PH main icon using the 'magic' resource id. HANDLE hPhIcon = LoadImage( GetModuleHandle(NULL), MAKEINTRESOURCE(PHAPP_IDI_PROCESSHACKER), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_SHARED ); // Set our initial state as download PhUpdaterState = Download; // Set the window icon. SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hPhIcon); lHeaderFont.lfHeight = -15; lHeaderFont.lfWeight = FW_MEDIUM; lHeaderFont.lfQuality = CLEARTYPE_QUALITY | ANTIALIASED_QUALITY; // We don't check if Segoe exists, CreateFontIndirect does this for us. wcscpy_s( lHeaderFont.lfFaceName, _countof(lHeaderFont.lfFaceName), L"Segoe UI" ); // Create the font handle. FontHandle = CreateFontIndirectW(&lHeaderFont); // Set the header font. SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), WM_SETFONT, (WPARAM)FontHandle, FALSE); // Center the update window on PH if visible and not mimimized else center on desktop. PhCenterWindow(hwndDlg, (IsWindowVisible(GetParent(hwndDlg)) && !IsIconic(GetParent(hwndDlg))) ? GetParent(hwndDlg) : NULL); // Create our update check thread. UpdateCheckThreadHandle = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)CheckUpdateThreadStart, hwndDlg); } break; case WM_SHOWDIALOG: { if (IsIconic(hwndDlg)) ShowWindow(hwndDlg, SW_RESTORE); else ShowWindow(hwndDlg, SW_SHOW); SetForegroundWindow(hwndDlg); } break; case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: { HDC hDC = (HDC)wParam; HWND hwndChild = (HWND)lParam; // Check for our static label and change the color. if (GetDlgCtrlID(hwndChild) == IDC_MESSAGE) { SetTextColor(hDC, RGB(19, 112, 171)); } // Set a transparent background for the control backcolor. SetBkMode(hDC, TRANSPARENT); // set window background color. return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: { PostQuitMessage(0); } break; case IDC_DOWNLOAD: { switch (PhUpdaterState) { case Download: { if (PhInstalledUsingSetup()) { // Start our Downloader thread DownloadThreadHandle = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)DownloadUpdateThreadStart, hwndDlg); } else { // Let the user handle non-setup installation, show the homepage and close this dialog. PhShellExecute(hwndDlg, L"http://processhacker.sourceforge.net/downloads.php", NULL); PostQuitMessage(0); } } break; case Install: { SHELLEXECUTEINFO info = { sizeof(SHELLEXECUTEINFO) }; info.lpFile = SetupFilePath->Buffer; info.lpVerb = L"runas"; info.nShow = SW_SHOW; info.hwnd = hwndDlg; ProcessHacker_PrepareForEarlyShutdown(PhMainWndHandle); if (!ShellExecuteEx(&info)) { // Install failed, cancel the shutdown. ProcessHacker_CancelEarlyShutdown(PhMainWndHandle); // Set button text for next action Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Retry"); } else { ProcessHacker_Destroy(PhMainWndHandle); } } break; } } break; } break; } break; case WM_UPDATE: { if (IsUpdating) { DWORD time_taken; DWORD download_speed; //DWORD time_remain = (MulDiv(time_taken, contentLength, bytesDownloaded) - time_taken); int percent; PPH_STRING dlRemaningBytes; PPH_STRING dlLength; PPH_STRING dlSpeed; PPH_STRING statusText; PhAcquireQueuedLockExclusive(&Lock); time_taken = (GetTickCount() - timeTransferred); download_speed = (bytesDownloaded / max(time_taken, 1)); percent = MulDiv(100, bytesDownloaded, contentLength); dlRemaningBytes = PhFormatSize(bytesDownloaded, -1); dlLength = PhFormatSize(contentLength, -1); dlSpeed = PhFormatSize(download_speed * 1024, -1); LastUpdateTime = GetTickCount(); PhReleaseQueuedLockExclusive(&Lock); statusText = PhFormatString( L"%s (%d%%) of %s @ %s/s", dlRemaningBytes->Buffer, percent, dlLength->Buffer, dlSpeed->Buffer ); SetDlgItemText(hwndDlg, IDC_STATUS, statusText->Buffer); SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETPOS, percent, 0); PhDereferenceObject(statusText); PhDereferenceObject(dlSpeed); PhDereferenceObject(dlLength); PhDereferenceObject(dlRemaningBytes); IsUpdating = FALSE; } } break; } return FALSE; }
INT_PTR CALLBACK EtpGpuPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PET_GPU_CONTEXT context; if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { context = propPageContext->Context; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { ULONG sampleCount; sampleCount = PhGetIntegerSetting(L"SampleCount"); context = PhAllocate(sizeof(ET_GPU_CONTEXT)); memset(context, 0, sizeof(ET_GPU_CONTEXT)); context->WindowHandle = hwndDlg; context->Block = EtGetProcessBlock(processItem); context->Enabled = TRUE; context->GpuGroupBox = GetDlgItem(hwndDlg, IDC_GROUPGPU); context->MemGroupBox = GetDlgItem(hwndDlg, IDC_GROUPMEM); context->SharedGroupBox = GetDlgItem(hwndDlg, IDC_GROUPSHARED); propPageContext->Context = context; PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhInitializeGraphState(&context->GpuGraphState); PhInitializeGraphState(&context->MemoryGraphState); PhInitializeGraphState(&context->MemorySharedGraphState); PhInitializeCircularBuffer_FLOAT(&context->GpuHistory, sampleCount); PhInitializeCircularBuffer_ULONG(&context->MemoryHistory, sampleCount); PhInitializeCircularBuffer_ULONG(&context->MemorySharedHistory, sampleCount); GpuPropCreateGraphs(context); GpuPropCreatePanel(context); GpuPropUpdateInfo(context); GpuPropUpdatePanel(context); PhRegisterCallback( &PhProcessesUpdatedEvent, ProcessesUpdatedHandler, context, &context->ProcessesUpdatedRegistration ); } break; case WM_DESTROY: { PhDeleteLayoutManager(&context->LayoutManager); PhDeleteGraphState(&context->GpuGraphState); PhDeleteGraphState(&context->MemoryGraphState); PhDeleteGraphState(&context->MemorySharedGraphState); PhDeleteCircularBuffer_FLOAT(&context->GpuHistory); PhDeleteCircularBuffer_ULONG(&context->MemoryHistory); PhDeleteCircularBuffer_ULONG(&context->MemorySharedHistory); if (context->GpuGraphHandle) DestroyWindow(context->GpuGraphHandle); if (context->MemGraphHandle) DestroyWindow(context->MemGraphHandle); if (context->SharedGraphHandle) DestroyWindow(context->SharedGraphHandle); if (context->PanelHandle) DestroyWindow(context->PanelHandle); PhUnregisterCallback(&PhProcessesUpdatedEvent, &context->ProcessesUpdatedRegistration); PhFree(context); PhPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { if (PhBeginPropPageLayout(hwndDlg, propPageContext)) PhEndPropPageLayout(hwndDlg, propPageContext); } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_SETACTIVE: context->Enabled = TRUE; break; case PSN_KILLACTIVE: context->Enabled = FALSE; break; case GCN_GETDRAWINFO: { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; if (header->hwndFrom == context->GpuGraphHandle) { if (PhGetIntegerSetting(L"GraphShowText")) { HDC hdc; PhMoveReference(&context->GpuGraphState.Text, PhFormatString( L"%.2f%%", context->CurrentGpuUsage * 100 )); hdc = Graph_GetBufferedContext(context->GpuGraphHandle); SelectObject(hdc, PhApplicationFont); PhSetGraphText(hdc, drawInfo, &context->GpuGraphState.Text->sr, &NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT); } else { drawInfo->Text.Buffer = NULL; } drawInfo->Flags = PH_GRAPH_USE_GRID; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0); PhGraphStateGetDrawInfo(&context->GpuGraphState, getDrawInfo, context->GpuHistory.Count); if (!context->GpuGraphState.Valid) { PhCopyCircularBuffer_FLOAT(&context->GpuHistory, context->GpuGraphState.Data1, drawInfo->LineDataCount); context->GpuGraphState.Valid = TRUE; } } else if (header->hwndFrom == context->MemGraphHandle) { if (PhGetIntegerSetting(L"GraphShowText")) { HDC hdc; PhMoveReference(&context->MemoryGraphState.Text, PhFormatString( L"%s", PhaFormatSize(UInt32x32To64(context->CurrentMemUsage, PAGE_SIZE), -1)->Buffer )); hdc = Graph_GetBufferedContext(context->MemGraphHandle); SelectObject(hdc, PhApplicationFont); PhSetGraphText( hdc, drawInfo, &context->MemoryGraphState.Text->sr, &NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT ); } else { drawInfo->Text.Buffer = NULL; } drawInfo->Flags = PH_GRAPH_USE_GRID; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorPhysical"), 0); PhGraphStateGetDrawInfo( &context->MemoryGraphState, getDrawInfo, context->MemoryHistory.Count ); if (!context->MemoryGraphState.Valid) { ULONG i = 0; for (i = 0; i < drawInfo->LineDataCount; i++) { context->MemoryGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&context->MemoryHistory, i); } if (EtGpuDedicatedLimit != 0) { PhDivideSinglesBySingle( context->MemoryGraphState.Data1, (FLOAT)EtGpuDedicatedLimit / PAGE_SIZE, drawInfo->LineDataCount ); } context->MemoryGraphState.Valid = TRUE; } } else if (header->hwndFrom == context->SharedGraphHandle) { if (PhGetIntegerSetting(L"GraphShowText")) { HDC hdc; PhMoveReference(&context->MemorySharedGraphState.Text, PhFormatString( L"%s", PhaFormatSize(UInt32x32To64(context->CurrentMemSharedUsage, PAGE_SIZE), -1)->Buffer )); hdc = Graph_GetBufferedContext(context->SharedGraphHandle); SelectObject(hdc, PhApplicationFont); PhSetGraphText(hdc, drawInfo, &context->MemorySharedGraphState.Text->sr, &NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT); } else { drawInfo->Text.Buffer = NULL; } drawInfo->Flags = PH_GRAPH_USE_GRID; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorPrivate"), 0); PhGraphStateGetDrawInfo( &context->MemorySharedGraphState, getDrawInfo, context->MemorySharedHistory.Count ); if (!context->MemorySharedGraphState.Valid) { ULONG i = 0; for (i = 0; i < drawInfo->LineDataCount; i++) { context->MemorySharedGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&context->MemorySharedHistory, i); } if (EtGpuSharedLimit != 0) { PhDivideSinglesBySingle( context->MemorySharedGraphState.Data1, (FLOAT)EtGpuSharedLimit / PAGE_SIZE, drawInfo->LineDataCount ); } context->MemorySharedGraphState.Valid = TRUE; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)lParam; if (getTooltipText->Index < getTooltipText->TotalCount) { if (header->hwndFrom == context->GpuGraphHandle) { if (context->GpuGraphState.TooltipIndex != getTooltipText->Index) { FLOAT gpuUsage = PhGetItemCircularBuffer_FLOAT( &context->GpuHistory, getTooltipText->Index ); PhMoveReference(&context->GpuGraphState.TooltipText, PhFormatString( L"%.2f%%", gpuUsage * 100 )); } getTooltipText->Text = context->GpuGraphState.TooltipText->sr; } else if (header->hwndFrom == context->MemGraphHandle) { if (context->MemoryGraphState.TooltipIndex != getTooltipText->Index) { ULONG gpuMemory = PhGetItemCircularBuffer_ULONG( &context->MemoryHistory, getTooltipText->Index ); PhMoveReference(&context->MemoryGraphState.TooltipText, PhFormatSize(UInt32x32To64(gpuMemory, PAGE_SIZE), -1) ); } getTooltipText->Text = context->MemoryGraphState.TooltipText->sr; } else if (header->hwndFrom == context->SharedGraphHandle) { if (context->MemorySharedGraphState.TooltipIndex != getTooltipText->Index) { ULONG gpuSharedMemory = PhGetItemCircularBuffer_ULONG( &context->MemorySharedHistory, getTooltipText->Index ); PhMoveReference(&context->MemorySharedGraphState.TooltipText, PhFormatSize(UInt32x32To64(gpuSharedMemory, PAGE_SIZE), -1) ); } getTooltipText->Text = context->MemorySharedGraphState.TooltipText->sr; } } } break; } } break; case MSG_UPDATE: { GpuPropUpdateInfo(context); GpuPropUpdateGraphs(context); GpuPropUpdatePanel(context); } break; case WM_SIZE: { GpuPropLayoutGraphs(context); } break; } return FALSE; }
INT_PTR CALLBACK PhpProcessHeapsDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PPROCESS_HEAPS_CONTEXT context = NULL; if (uMsg != WM_INITDIALOG) { context = (PPROCESS_HEAPS_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PPROCESS_HEAPS_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; ULONG i; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); context->ListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Address"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 120, L"Used"); PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 120, L"Committed"); PhAddListViewColumn(lvHandle, 3, 3, 3, LVCFMT_LEFT, 80, L"Entries"); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhSetExtendedListView(lvHandle); ExtendedListView_SetContext(lvHandle, context); ExtendedListView_SetCompareFunction(lvHandle, 0, PhpHeapAddressCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 1, PhpHeapUsedCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 2, PhpHeapCommittedCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 3, PhpHeapEntriesCompareFunction); ExtendedListView_SetItemFontFunction(lvHandle, PhpHeapFontFunction); for (i = 0; i < context->ProcessHeaps->NumberOfHeaps; i++) { PRTL_HEAP_INFORMATION heapInfo = &context->ProcessHeaps->Heaps[i]; WCHAR addressString[PH_PTR_STR_LEN_1]; INT lvItemIndex; PPH_STRING usedString; PPH_STRING committedString; PPH_STRING numberOfEntriesString; PhPrintPointer(addressString, heapInfo->BaseAddress); lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, addressString, heapInfo); usedString = PhFormatSize(heapInfo->BytesAllocated, -1); committedString = PhFormatSize(heapInfo->BytesCommitted, -1); numberOfEntriesString = PhFormatUInt64(heapInfo->NumberOfEntries, TRUE); PhSetListViewSubItem(lvHandle, lvItemIndex, 1, usedString->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 2, committedString->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 3, numberOfEntriesString->Buffer); PhDereferenceObject(usedString); PhDereferenceObject(committedString); PhDereferenceObject(numberOfEntriesString); } ExtendedListView_SortItems(lvHandle); } break; case WM_DESTROY: { RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_SIZESINBYTES: { BOOLEAN sizesInBytes = Button_GetCheck(GetDlgItem(hwndDlg, IDC_SIZESINBYTES)) == BST_CHECKED; INT index = -1; ExtendedListView_SetRedraw(context->ListViewHandle, FALSE); while ((index = ListView_GetNextItem(context->ListViewHandle, index, LVNI_ALL)) != -1) { PRTL_HEAP_INFORMATION heapInfo; PPH_STRING usedString; PPH_STRING committedString; if (PhGetListViewItemParam(context->ListViewHandle, index, &heapInfo)) { usedString = PhFormatSize(heapInfo->BytesAllocated, sizesInBytes ? 0 : -1); committedString = PhFormatSize(heapInfo->BytesCommitted, sizesInBytes ? 0 : -1); PhSetListViewSubItem(context->ListViewHandle, index, 1, usedString->Buffer); PhSetListViewSubItem(context->ListViewHandle, index, 2, committedString->Buffer); PhDereferenceObject(usedString); PhDereferenceObject(committedString); } } ExtendedListView_SetRedraw(context->ListViewHandle, TRUE); } break; } } break; case WM_NOTIFY: { PhHandleListViewNotifyForCopy(lParam, context->ListViewHandle); } break; case WM_CONTEXTMENU: { if ((HWND)wParam == context->ListViewHandle) { POINT point; PRTL_HEAP_INFORMATION heapInfo; PPH_EMENU menu; INT selectedCount; PPH_EMENU_ITEM menuItem; point.x = (SHORT)LOWORD(lParam); point.y = (SHORT)HIWORD(lParam); if (point.x == -1 && point.y == -1) PhGetListViewContextMenuPoint((HWND)wParam, &point); selectedCount = ListView_GetSelectedCount(context->ListViewHandle); heapInfo = PhGetSelectedListViewItemParam(context->ListViewHandle); if (selectedCount != 0) { menu = PhCreateEMenu(); PhInsertEMenuItem(menu, PhCreateEMenuItem(selectedCount != 1 ? PH_EMENU_DISABLED : 0, 1, L"Destroy", NULL, NULL), -1); PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 2, L"Copy\bCtrl+C", NULL, NULL), -1); menuItem = PhShowEMenu(menu, context->ListViewHandle, PH_EMENU_SHOW_LEFTRIGHT | PH_EMENU_SHOW_NONOTIFY, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y); if (menuItem) { switch (menuItem->Id) { case 1: if (PhUiDestroyHeap(hwndDlg, context->ProcessItem->ProcessId, heapInfo->BaseAddress)) ListView_DeleteItem(context->ListViewHandle, PhFindListViewItemByParam(context->ListViewHandle, -1, heapInfo)); break; case 2: PhCopyListView(context->ListViewHandle); break; } } PhDestroyEMenu(menu); } } } break; } REFLECT_MESSAGE_DLG(hwndDlg, context->ListViewHandle, uMsg, wParam, lParam); return FALSE; }
BOOLEAN EtpRefreshUnloadedDlls( __in HWND hwndDlg, __in PUNLOADED_DLLS_CONTEXT Context ) { NTSTATUS status; PULONG elementSize; PULONG elementCount; PVOID eventTrace; HANDLE processHandle = NULL; ULONG eventTraceSize; ULONG capturedElementSize; ULONG capturedElementCount; PVOID capturedEventTracePointer; PVOID capturedEventTrace = NULL; ULONG i; PVOID currentEvent; HWND lvHandle; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); ListView_DeleteAllItems(lvHandle); RtlGetUnloadEventTraceEx(&elementSize, &elementCount, &eventTrace); if (!NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_VM_READ, Context->ProcessItem->ProcessId))) goto CleanupExit; // We have the pointers for the unload event trace information. // Since ntdll is loaded at the same base address across all processes, // we can read the information in. if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, elementSize, &capturedElementSize, sizeof(ULONG), NULL ))) goto CleanupExit; if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, elementCount, &capturedElementCount, sizeof(ULONG), NULL ))) goto CleanupExit; if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, eventTrace, &capturedEventTracePointer, sizeof(PVOID), NULL ))) goto CleanupExit; if (!capturedEventTracePointer) goto CleanupExit; // no events if (capturedElementCount > 0x4000) capturedElementCount = 0x4000; eventTraceSize = capturedElementSize * capturedElementCount; capturedEventTrace = PhAllocateSafe(eventTraceSize); if (!capturedEventTrace) { status = STATUS_NO_MEMORY; goto CleanupExit; } if (!NT_SUCCESS(status = PhReadVirtualMemory( processHandle, capturedEventTracePointer, capturedEventTrace, eventTraceSize, NULL ))) goto CleanupExit; currentEvent = capturedEventTrace; ExtendedListView_SetRedraw(lvHandle, FALSE); for (i = 0; i < capturedElementCount; i++) { PRTL_UNLOAD_EVENT_TRACE rtlEvent = currentEvent; INT lvItemIndex; WCHAR buffer[128]; PPH_STRING string; LARGE_INTEGER time; SYSTEMTIME systemTime; if (!rtlEvent->BaseAddress) break; PhPrintUInt32(buffer, rtlEvent->Sequence); lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, buffer, rtlEvent); // Name if (PhCopyUnicodeStringZ(rtlEvent->ImageName, sizeof(rtlEvent->ImageName) / sizeof(WCHAR), buffer, sizeof(buffer) / sizeof(WCHAR), NULL)) { PhSetListViewSubItem(lvHandle, lvItemIndex, 1, buffer); } // Base Address PhPrintPointer(buffer, rtlEvent->BaseAddress); PhSetListViewSubItem(lvHandle, lvItemIndex, 2, buffer); // Size string = PhFormatSize(rtlEvent->SizeOfImage, -1); PhSetListViewSubItem(lvHandle, lvItemIndex, 3, string->Buffer); PhDereferenceObject(string); // Time Stamp RtlSecondsSince1970ToTime(rtlEvent->TimeDateStamp, &time); PhLargeIntegerToLocalSystemTime(&systemTime, &time); string = PhFormatDateTime(&systemTime); PhSetListViewSubItem(lvHandle, lvItemIndex, 4, string->Buffer); PhDereferenceObject(string); // Checksum PhPrintPointer(buffer, UlongToPtr(rtlEvent->CheckSum)); PhSetListViewSubItem(lvHandle, lvItemIndex, 5, buffer); currentEvent = PTR_ADD_OFFSET(currentEvent, capturedElementSize); } ExtendedListView_SortItems(lvHandle); ExtendedListView_SetRedraw(lvHandle, TRUE); if (Context->CapturedEventTrace) PhFree(Context->CapturedEventTrace); Context->CapturedEventTrace = capturedEventTrace; CleanupExit: if (processHandle) NtClose(processHandle); if (NT_SUCCESS(status)) { return TRUE; } else { PhShowStatus(hwndDlg, L"Unable to retrieve unload event trace information", status, 0); 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; }
BOOLEAN QueryUpdateData( _Inout_ PPH_UPDATER_CONTEXT Context ) { BOOLEAN success = FALSE; PPH_HTTP_CONTEXT httpContext = NULL; PPH_BYTES jsonString = NULL; PVOID jsonObject = NULL; if (!PhHttpSocketCreate(&httpContext, NULL)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, L"wj32.org", PH_HTTP_DEFAULT_HTTPS_PORT )) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketBeginRequest( httpContext, NULL, L"/processhacker/nightly.php?phupdater", PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { Context->ErrorCode = GetLastError(); goto CleanupExit; } { PPH_STRING versionHeader; PPH_STRING windowsHeader; if (versionHeader = UpdateVersionString()) { PhHttpSocketAddRequestHeaders(httpContext, versionHeader->Buffer, (ULONG)versionHeader->Length / sizeof(WCHAR)); PhDereferenceObject(versionHeader); } if (windowsHeader = UpdateWindowsString()) { PhHttpSocketAddRequestHeaders(httpContext, windowsHeader->Buffer, (ULONG)windowsHeader->Length / sizeof(WCHAR)); PhDereferenceObject(windowsHeader); } } if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketEndRequest(httpContext)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE))) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!(jsonObject = PhCreateJsonParser(jsonString->Buffer))) goto CleanupExit; Context->Version = PhGetJsonValueAsString(jsonObject, "version"); Context->RelDate = PhGetJsonValueAsString(jsonObject, "updated"); Context->SetupFileDownloadUrl = PhGetJsonValueAsString(jsonObject, "setup_url"); Context->SetupFileLength = PhFormatSize(PhGetJsonValueAsLong64(jsonObject, "setup_length"), 2); Context->SetupFileHash = PhGetJsonValueAsString(jsonObject, "setup_hash"); Context->SetupFileSignature = PhGetJsonValueAsString(jsonObject, "setup_sig"); Context->BuildMessage = PhGetJsonValueAsString(jsonObject, "changelog"); PhFreeJsonParser(jsonObject); if (PhIsNullOrEmptyString(Context->Version)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->RelDate)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileDownloadUrl)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileLength)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileHash)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileSignature)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->BuildMessage)) goto CleanupExit; success = TRUE; CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (jsonString) PhDereferenceObject(jsonString); if (success && !PhIsNullOrEmptyString(Context->BuildMessage)) { PH_STRING_BUILDER sb; PhInitializeStringBuilder(&sb, 0x100); for (SIZE_T i = 0; i < Context->BuildMessage->Length / sizeof(WCHAR); i++) { if (Context->BuildMessage->Data[i] == '\n') PhAppendStringBuilder2(&sb, L"\r\n"); else PhAppendCharStringBuilder(&sb, Context->BuildMessage->Data[i]); } PhMoveReference(&Context->BuildMessage, PhFinalStringBuilderString(&sb)); } return success; }