static BOOLEAN NTAPI PhpWalkThreadStackCallback( _In_ PPH_THREAD_STACK_FRAME StackFrame, _In_opt_ PVOID Context ) { PTHREAD_STACK_CONTEXT threadStackContext = (PTHREAD_STACK_CONTEXT)Context; PPH_STRING symbol; PTHREAD_STACK_ITEM item; if (threadStackContext->StopWalk) return FALSE; PhAcquireQueuedLockExclusive(&threadStackContext->StatusLock); PhMoveReference(&threadStackContext->StatusMessage, PhFormatString(L"Processing frame %u...", threadStackContext->NewList->Count)); PhReleaseQueuedLockExclusive(&threadStackContext->StatusLock); PostMessage(threadStackContext->ProgressWindowHandle, WM_PH_STATUS_UPDATE, 0, 0); symbol = PhGetSymbolFromAddress( threadStackContext->SymbolProvider, (ULONG64)StackFrame->PcAddress, NULL, NULL, NULL, NULL ); if (symbol && (StackFrame->Flags & PH_THREAD_STACK_FRAME_I386) && !(StackFrame->Flags & PH_THREAD_STACK_FRAME_FPO_DATA_PRESENT)) { PhMoveReference(&symbol, PhConcatStrings2(symbol->Buffer, L" (No unwind info)")); } item = PhAllocate(sizeof(THREAD_STACK_ITEM)); item->StackFrame = *StackFrame; item->Index = threadStackContext->NewList->Count; if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackResolveSymbol; control.UniqueKey = threadStackContext; control.u.ResolveSymbol.StackFrame = StackFrame; control.u.ResolveSymbol.Symbol = symbol; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); symbol = control.u.ResolveSymbol.Symbol; } item->Symbol = symbol; PhAddItemList(threadStackContext->NewList, item); return TRUE; }
VOID PhSaveSettingsColumnSet( _In_ PWSTR SettingName, _In_ PPH_STRING ColumnSetName, _In_ PPH_STRING TreeListSettings, _In_ PPH_STRING TreeSortSettings ) { ULONG index; BOOLEAN found = FALSE; PPH_LIST columnSetList; columnSetList = PhInitializeColumnSetList(SettingName); for (index = 0; index < columnSetList->Count; index++) { PPH_COLUMN_SET_ENTRY entry = columnSetList->Items[index]; if (PhEqualString(entry->Name, ColumnSetName, FALSE)) { PhReferenceObject(TreeListSettings); PhReferenceObject(TreeSortSettings); PhMoveReference(&entry->Setting, TreeListSettings); PhMoveReference(&entry->Sorting, TreeSortSettings); found = TRUE; break; } } if (!found) { PPH_COLUMN_SET_ENTRY entry; PhReferenceObject(ColumnSetName); PhReferenceObject(TreeListSettings); PhReferenceObject(TreeSortSettings); entry = PhAllocate(sizeof(PH_COLUMN_SET_ENTRY)); entry->Name = ColumnSetName; entry->Setting = TreeListSettings; entry->Sorting = TreeSortSettings; PhAddItemList(columnSetList, entry); } PhSaveSettingsColumnList(SettingName, columnSetList); PhDeleteColumnSetList(columnSetList); }
VOID AddNetworkAdapterToListView( _In_ PDV_NETADAPTER_CONTEXT Context, _In_ BOOLEAN AdapterPresent, _In_ IF_INDEX IfIndex, _In_ IF_LUID Luid, _In_ PPH_STRING Guid, _In_ PPH_STRING Description ) { DV_NETADAPTER_ID adapterId; INT lvItemIndex; BOOLEAN found = FALSE; PDV_NETADAPTER_ID newId = NULL; InitializeNetAdapterId(&adapterId, IfIndex, Luid, Guid); for (ULONG i = 0; i < NetworkAdaptersList->Count; i++) { PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]); if (!entry) continue; if (EquivalentNetAdapterId(&entry->AdapterId, &adapterId)) { newId = PhAllocate(sizeof(DV_NETADAPTER_ID)); CopyNetAdapterId(newId, &entry->AdapterId); if (entry->UserReference) found = TRUE; } PhDereferenceObjectDeferDelete(entry); if (newId) break; } if (!newId) { newId = PhAllocate(sizeof(DV_NETADAPTER_ID)); CopyNetAdapterId(newId, &adapterId); PhMoveReference(&newId->InterfaceGuid, Guid); } lvItemIndex = PhAddListViewGroupItem( Context->ListViewHandle, AdapterPresent ? 0 : 1, MAXINT, Description->Buffer, newId ); if (found) ListView_SetCheckState(Context->ListViewHandle, lvItemIndex, TRUE); DeleteNetAdapterId(&adapterId); }
static NTSTATUS PhpRefreshThreadStack( _In_ HWND hwnd, _In_ PTHREAD_STACK_CONTEXT ThreadStackContext ) { ULONG i; ThreadStackContext->StopWalk = FALSE; PhMoveReference(&ThreadStackContext->StatusMessage, PhCreateString(L"Loading stack...")); DialogBoxParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_PROGRESS), hwnd, PhpThreadStackProgressDlgProc, (LPARAM)ThreadStackContext ); if (!ThreadStackContext->StopWalk && NT_SUCCESS(ThreadStackContext->WalkStatus)) { for (i = 0; i < ThreadStackContext->List->Count; i++) PhpFreeThreadStackItem(ThreadStackContext->List->Items[i]); PhDereferenceObject(ThreadStackContext->List); ThreadStackContext->List = ThreadStackContext->NewList; ThreadStackContext->NewList = PhCreateList(10); SendMessage(ThreadStackContext->ListViewHandle, WM_SETREDRAW, FALSE, 0); ListView_DeleteAllItems(ThreadStackContext->ListViewHandle); for (i = 0; i < ThreadStackContext->List->Count; i++) { PTHREAD_STACK_ITEM item = ThreadStackContext->List->Items[i]; INT lvItemIndex; WCHAR integerString[PH_INT32_STR_LEN_1]; PhPrintUInt32(integerString, item->Index); lvItemIndex = PhAddListViewItem(ThreadStackContext->ListViewHandle, MAXINT, integerString, item); PhSetListViewSubItem(ThreadStackContext->ListViewHandle, lvItemIndex, 1, PhGetStringOrDefault(item->Symbol, L"???")); } SendMessage(ThreadStackContext->ListViewHandle, WM_SETREDRAW, TRUE, 0); InvalidateRect(ThreadStackContext->ListViewHandle, NULL, FALSE); } else { for (i = 0; i < ThreadStackContext->NewList->Count; i++) PhpFreeThreadStackItem(ThreadStackContext->NewList->Items[i]); PhClearList(ThreadStackContext->NewList); } if (ThreadStackContext->StopWalk) return STATUS_ABANDONED; return ThreadStackContext->WalkStatus; }
VOID AddDiskDriveToListView( _In_ PDV_DISK_OPTIONS_CONTEXT Context, _In_ BOOLEAN DiskPresent, _In_ PPH_STRING DiskPath, _In_ PPH_STRING DiskName ) { DV_DISK_ID adapterId; INT lvItemIndex; BOOLEAN found = FALSE; PDV_DISK_ID newId = NULL; InitializeDiskId(&adapterId, DiskPath); for (ULONG i = 0; i < DiskDrivesList->Count; i++) { PDV_DISK_ENTRY entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]); if (!entry) continue; if (EquivalentDiskId(&entry->Id, &adapterId)) { newId = PhAllocate(sizeof(DV_DISK_ID)); CopyDiskId(newId, &entry->Id); if (entry->UserReference) found = TRUE; } PhDereferenceObjectDeferDelete(entry); if (newId) break; } if (!newId) { newId = PhAllocate(sizeof(DV_DISK_ID)); CopyDiskId(newId, &adapterId); PhMoveReference(&newId->DevicePath, DiskPath); } lvItemIndex = AddListViewItemGroupId( Context->ListViewHandle, DiskPresent ? 0 : 1, MAXINT, DiskName->Buffer, newId ); if (found) ListView_SetItemState(Context->ListViewHandle, lvItemIndex, ITEM_CHECKED, LVIS_STATEIMAGEMASK); DeleteDiskId(&adapterId); }
static VOID AddNetworkAdapterToListView( _In_ PDV_NETADAPTER_CONTEXT Context, _In_ PIP_ADAPTER_ADDRESSES Adapter ) { DV_NETADAPTER_ID adapterId; INT lvItemIndex; BOOLEAN found = FALSE; PDV_NETADAPTER_ID newId = NULL; InitializeNetAdapterId(&adapterId, Adapter->IfIndex, Adapter->Luid, NULL); for (ULONG i = 0; i < NetworkAdaptersList->Count; i++) { PDV_NETADAPTER_ENTRY entry = PhReferenceObjectSafe(NetworkAdaptersList->Items[i]); if (!entry) continue; if (EquivalentNetAdapterId(&entry->Id, &adapterId)) { newId = PhAllocate(sizeof(DV_NETADAPTER_ID)); CopyNetAdapterId(newId, &entry->Id); found = TRUE; } PhDereferenceObjectDeferDelete(entry); if (newId) break; } if (!newId) { newId = PhAllocate(sizeof(DV_NETADAPTER_ID)); CopyNetAdapterId(newId, &adapterId); PhMoveReference(&newId->InterfaceGuid, PhConvertMultiByteToUtf16(Adapter->AdapterName)); } lvItemIndex = PhAddListViewItem( Context->ListViewHandle, MAXINT, Adapter->Description, newId ); if (found) ListView_SetItemState(Context->ListViewHandle, lvItemIndex, ITEM_CHECKED, LVIS_STATEIMAGEMASK); DeleteNetAdapterId(&adapterId); }
VOID PhpRefreshProcessMemoryList( _In_ HWND hwndDlg, _In_ PPH_PROCESS_PROPPAGECONTEXT PropPageContext ) { PPH_MEMORY_CONTEXT memoryContext = PropPageContext->Context; if (memoryContext->MemoryItemListValid) { PhDeleteMemoryItemList(&memoryContext->MemoryItemList); memoryContext->MemoryItemListValid = FALSE; } memoryContext->LastRunStatus = PhQueryMemoryItemList( memoryContext->ProcessId, PH_QUERY_MEMORY_REGION_TYPE | PH_QUERY_MEMORY_WS_COUNTERS, &memoryContext->MemoryItemList ); if (NT_SUCCESS(memoryContext->LastRunStatus)) { if (PhPluginsEnabled) { PH_PLUGIN_MEMORY_ITEM_LIST_CONTROL control; control.Type = PluginMemoryItemListInitialized; control.u.Initialized.List = &memoryContext->MemoryItemList; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMemoryItemListControl), &control); } memoryContext->MemoryItemListValid = TRUE; TreeNew_SetEmptyText(memoryContext->ListContext.TreeNewHandle, &EmptyMemoryText, 0); PhReplaceMemoryList(&memoryContext->ListContext, &memoryContext->MemoryItemList); } else { PPH_STRING message; message = PhGetStatusMessage(memoryContext->LastRunStatus, 0); PhMoveReference(&memoryContext->ErrorMessage, PhFormatString(L"Unable to query memory information:\n%s", PhGetStringOrDefault(message, L"Unknown error."))); PhClearReference(&message); TreeNew_SetEmptyText(memoryContext->ListContext.TreeNewHandle, &memoryContext->ErrorMessage->sr, 0); PhReplaceMemoryList(&memoryContext->ListContext, NULL); } }
static PPH_STRING GenerateCacheName( _In_ PDNS_RECORD Record ) { PDNS_RECORD record = Record; PPH_STRING result; result = PhCreateString(record->pName); record = record->pNext; while (record) { PhMoveReference( &result, PhFormatString(L"%s, %s", result->Buffer, record->pName) ); record = record->pNext; } return result; }
VOID EtDiskProcessFileEvent( _In_ PET_ETW_FILE_EVENT Event ) { PH_KEY_VALUE_PAIR pair; PPH_KEY_VALUE_PAIR realPair; if (!EtDiskEnabled) return; if (Event->Type == EtEtwFileCreateType || Event->Type == EtEtwFileRundownType) { pair.Key = Event->FileObject; pair.Value = NULL; PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock); realPair = PhAddEntryHashtableEx(EtFileNameHashtable, &pair, NULL); PhMoveReference(&realPair->Value, PhCreateString2(&Event->FileName)); PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock); } else if (Event->Type == EtEtwFileDeleteType) { pair.Key = Event->FileObject; PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock); realPair = PhFindEntryHashtable(EtFileNameHashtable, &pair); if (realPair) { PhDereferenceObject(realPair->Value); PhRemoveEntryHashtable(EtFileNameHashtable, &pair); } PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock); } }
NTSTATUS LoadDb( VOID ) { NTSTATUS status; HANDLE fileHandle; LARGE_INTEGER fileSize; mxml_node_t *topNode; mxml_node_t *currentNode; status = PhCreateFileWin32( &fileHandle, ObjectDbPath->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) return status; if (NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize)) && fileSize.QuadPart == 0) { // A blank file is OK. There are no objects to load. NtClose(fileHandle); return status; } topNode = mxmlLoadFd(NULL, fileHandle, MXML_OPAQUE_CALLBACK); NtClose(fileHandle); if (!topNode) return STATUS_FILE_CORRUPT_ERROR; if (topNode->type != MXML_ELEMENT) { mxmlDelete(topNode); return STATUS_FILE_CORRUPT_ERROR; } LockDb(); for (currentNode = topNode->child; currentNode; currentNode = currentNode->next) { PDB_OBJECT object = NULL; PPH_STRING tag = NULL; PPH_STRING name = NULL; PPH_STRING priorityClass = NULL; PPH_STRING ioPriorityPlusOne = NULL; PPH_STRING comment = NULL; PPH_STRING backColor = NULL; PPH_STRING collapse = NULL; PPH_STRING affinityMask = NULL; if (currentNode->type == MXML_ELEMENT && currentNode->value.element.num_attrs >= 2) { for (INT i = 0; i < currentNode->value.element.num_attrs; i++) { if (_stricmp(currentNode->value.element.attrs[i].name, "tag") == 0) PhMoveReference(&tag, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "name") == 0) PhMoveReference(&name, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "priorityclass") == 0) PhMoveReference(&priorityClass, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "iopriorityplusone") == 0) PhMoveReference(&ioPriorityPlusOne, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "backcolor") == 0) PhMoveReference(&backColor, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "collapse") == 0) PhMoveReference(&collapse, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "affinity") == 0) PhMoveReference(&affinityMask, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); } } comment = GetOpaqueXmlNodeText(currentNode); if (tag && name && comment) { ULONG64 tagInteger; ULONG64 priorityClassInteger = 0; ULONG64 ioPriorityPlusOneInteger = 0; PhStringToInteger64(&tag->sr, 10, &tagInteger); if (priorityClass) PhStringToInteger64(&priorityClass->sr, 10, &priorityClassInteger); if (ioPriorityPlusOne) PhStringToInteger64(&ioPriorityPlusOne->sr, 10, &ioPriorityPlusOneInteger); object = CreateDbObject((ULONG)tagInteger, &name->sr, comment); object->PriorityClass = (ULONG)priorityClassInteger; object->IoPriorityPlusOne = (ULONG)ioPriorityPlusOneInteger; } // NOTE: These items are handled separately to maintain compatibility with previous versions of the database. if (object && backColor) { ULONG64 backColorInteger = ULONG_MAX; PhStringToInteger64(&backColor->sr, 10, &backColorInteger); object->BackColor = (COLORREF)backColorInteger; } if (object && collapse) { ULONG64 collapseInteger = 0; PhStringToInteger64(&collapse->sr, 10, &collapseInteger); object->Collapse = !!collapseInteger; } if (object && affinityMask) { ULONG64 affinityInteger = 0; PhStringToInteger64(&affinityMask->sr, 10, &affinityInteger); object->AffinityMask = (ULONG)affinityInteger; } PhClearReference(&tag); PhClearReference(&name); PhClearReference(&priorityClass); PhClearReference(&ioPriorityPlusOne); PhClearReference(&comment); PhClearReference(&backColor); PhClearReference(&collapse); PhClearReference(&affinityMask); } UnlockDb(); mxmlDelete(topNode); return STATUS_SUCCESS; }
VOID EtpNotifySharedGraph( _In_ NMHDR *Header ) { switch (Header->code) { case GCN_GETDRAWINFO: { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; ULONG i; drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y; GpuSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorPhysical"), 0); PhGraphStateGetDrawInfo( &SharedGraphState, getDrawInfo, EtGpuSharedHistory.Count ); if (!SharedGraphState.Valid) { for (i = 0; i < drawInfo->LineDataCount; i++) { SharedGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtGpuSharedHistory, i); } if (EtGpuSharedLimit != 0) { // Scale the data. PhDivideSinglesBySingle( SharedGraphState.Data1, (FLOAT)EtGpuSharedLimit / PAGE_SIZE, drawInfo->LineDataCount ); } SharedGraphState.Valid = TRUE; } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header; if (getTooltipText->Index < getTooltipText->TotalCount) { if (SharedGraphState.TooltipIndex != getTooltipText->Index) { ULONG usedPages; usedPages = PhGetItemCircularBuffer_ULONG(&EtGpuSharedHistory, getTooltipText->Index); PhMoveReference(&SharedGraphState.TooltipText, PhFormatString( L"Shared Memory: %s\n%s", PhaFormatSize(UInt32x32To64(usedPages, PAGE_SIZE), -1)->Buffer, ((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); } getTooltipText->Text = SharedGraphState.TooltipText->sr; } } break; } }
BOOLEAN EtpGpuSysInfoSectionCallback( _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_X | PH_GRAPH_USE_GRID_Y; 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); PhMoveReference(&Section->GraphState.TooltipText, PhFormatString( L"%.2f%%%s\n%s", gpu * 100, PhGetStringOrEmpty(EtpGetMaxNodeString(getTooltipText->Index)), ((PPH_STRING)PH_AUTO(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; }
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_X | PH_GRAPH_USE_GRID_Y; 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); PhMoveReference(&GpuGraphState.TooltipText, PhFormatString( L"%.2f%%%s\n%s", gpu * 100, PhGetStringOrEmpty(EtpGetMaxNodeString(getTooltipText->Index)), ((PPH_STRING)PH_AUTO(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 PhSipNotifyPhysicalGraph( _In_ NMHDR *Header ) { switch (Header->code) { case GCN_GETDRAWINFO: { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; ULONG i; drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y; PhSiSetColorsGraphDrawInfo(drawInfo, PhCsColorPhysical, 0); PhGraphStateGetDrawInfo( &PhysicalGraphState, getDrawInfo, PhPhysicalHistory.Count ); if (!PhysicalGraphState.Valid) { for (i = 0; i < drawInfo->LineDataCount; i++) { PhysicalGraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&PhPhysicalHistory, i); } if (PhSystemBasicInformation.NumberOfPhysicalPages != 0) { // Scale the data. PhDivideSinglesBySingle( PhysicalGraphState.Data1, (FLOAT)PhSystemBasicInformation.NumberOfPhysicalPages, drawInfo->LineDataCount ); } PhysicalGraphState.Valid = TRUE; } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header; if (getTooltipText->Index < getTooltipText->TotalCount) { if (PhysicalGraphState.TooltipIndex != getTooltipText->Index) { ULONG usedPages; usedPages = PhGetItemCircularBuffer_ULONG(&PhPhysicalHistory, getTooltipText->Index); PhMoveReference(&PhysicalGraphState.TooltipText, PhFormatString( L"Physical memory: %s\n%s", PhaFormatSize(UInt32x32To64(usedPages, PAGE_SIZE), -1)->Buffer, PH_AUTO_T(PH_STRING, PhGetStatisticsTimeString(NULL, getTooltipText->Index))->Buffer )); } getTooltipText->Text = PhysicalGraphState.TooltipText->sr; } } break; } }
static VOID PhpRefreshProcessList( _In_ HWND hwndDlg, _In_ PCHOOSE_PROCESS_DIALOG_CONTEXT Context ) { NTSTATUS status; HWND lvHandle; PVOID processes; PSYSTEM_PROCESS_INFORMATION process; lvHandle = Context->ListViewHandle; ListView_DeleteAllItems(lvHandle); ImageList_RemoveAll(Context->ImageList); if (!NT_SUCCESS(status = PhEnumProcesses(&processes))) { PhShowStatus(hwndDlg, L"Unable to enumerate processes", status, 0); return; } ExtendedListView_SetRedraw(lvHandle, FALSE); process = PH_FIRST_PROCESS(processes); do { INT lvItemIndex; PPH_STRING name; HANDLE processHandle; PPH_STRING fileName = NULL; HICON icon = NULL; WCHAR processIdString[PH_INT32_STR_LEN_1]; PPH_STRING userName = NULL; INT imageIndex; if (process->UniqueProcessId != SYSTEM_IDLE_PROCESS_ID) name = PhCreateStringFromUnicodeString(&process->ImageName); else name = PhCreateString(SYSTEM_IDLE_PROCESS_NAME); lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, name->Buffer, process->UniqueProcessId); PhDereferenceObject(name); if (NT_SUCCESS(PhOpenProcess(&processHandle, ProcessQueryAccess, process->UniqueProcessId))) { HANDLE tokenHandle; PTOKEN_USER user; if (!WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID) PhGetProcessImageFileName(processHandle, &fileName); if (NT_SUCCESS(PhOpenProcessToken(&tokenHandle, TOKEN_QUERY, processHandle))) { if (NT_SUCCESS(PhGetTokenUser(tokenHandle, &user))) { userName = PhGetSidFullName(user->User.Sid, TRUE, NULL); PhFree(user); } NtClose(tokenHandle); } NtClose(processHandle); } if (process->UniqueProcessId == SYSTEM_IDLE_PROCESS_ID && !userName && PhLocalSystemName) PhSetReference(&userName, PhLocalSystemName); if (WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID) PhGetProcessImageFileNameByProcessId(process->UniqueProcessId, &fileName); if (process->UniqueProcessId == SYSTEM_PROCESS_ID) fileName = PhGetKernelFileName(); if (fileName) PhMoveReference(&fileName, PhGetFileName(fileName)); icon = PhGetFileShellIcon(PhGetString(fileName), L".exe", FALSE); // Icon if (icon) { imageIndex = ImageList_AddIcon(Context->ImageList, icon); PhSetListViewItemImageIndex(Context->ListViewHandle, lvItemIndex, imageIndex); DestroyIcon(icon); } // PID PhPrintUInt32(processIdString, HandleToUlong(process->UniqueProcessId)); PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 1, processIdString); // User Name PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 2, PhGetString(userName)); if (userName) PhDereferenceObject(userName); if (fileName) PhDereferenceObject(fileName); } while (process = PH_NEXT_PROCESS(process)); PhFree(processes); ExtendedListView_SortItems(lvHandle); ExtendedListView_SetRedraw(lvHandle, TRUE); }
INT_PTR CALLBACK PhpColumnSetEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PCOLUMNSET_DIALOG_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = PhAllocate(sizeof(COLUMNSET_DIALOG_CONTEXT)); memset(context, 0, sizeof(COLUMNSET_DIALOG_CONTEXT)); context->SettingName = PhCreateString((PWSTR)lParam); SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } else { context = (PCOLUMNSET_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { context->DialogHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_COLUMNSETLIST); context->RenameButtonHandle = GetDlgItem(hwndDlg, IDC_RENAME); context->MoveUpButtonHandle = GetDlgItem(hwndDlg, IDC_MOVEUP); context->MoveDownButtonHandle = GetDlgItem(hwndDlg, IDC_MOVEDOWN); context->RemoveButtonHandle = GetDlgItem(hwndDlg, IDC_REMOVE); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE); PhSetControlTheme(context->ListViewHandle, L"explorer"); PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 250, L"Name"); PhSetExtendedListView(context->ListViewHandle); context->ColumnSetList = PhInitializeColumnSetList(PhGetString(context->SettingName)); for (ULONG i = 0; i < context->ColumnSetList->Count; i++) { PPH_COLUMN_SET_ENTRY entry = context->ColumnSetList->Items[i]; PhAddListViewItem(context->ListViewHandle, MAXINT, entry->Name->Buffer, entry); } Button_Enable(context->RenameButtonHandle, FALSE); Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); Button_Enable(context->RemoveButtonHandle, FALSE); } break; case WM_DESTROY: { PhDeleteColumnSetList(context->ColumnSetList); RemoveProp(hwndDlg, PhMakeContextAtom()); PhFree(context); } break; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { if (context->LabelEditActive) break; PhSaveSettingsColumnList(PhGetString(context->SettingName), context->ColumnSetList); EndDialog(hwndDlg, IDOK); } break; case IDC_RENAME: { INT lvItemIndex; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1) { SetFocus(context->ListViewHandle); ListView_EditLabel(context->ListViewHandle, lvItemIndex); } } break; case IDC_MOVEUP: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; PhpMoveSelectedListViewItemUp(context->ListViewHandle); lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhInsertItemList(context->ColumnSetList, lvItemIndex, entry); } } } break; case IDC_MOVEDOWN: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; PhpMoveSelectedListViewItemDown(context->ListViewHandle); lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhInsertItemList(context->ColumnSetList, lvItemIndex, entry); } } } break; case IDC_REMOVE: { INT lvItemIndex; PPH_COLUMN_SET_ENTRY entry; ULONG index; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1 && PhGetListViewItemParam(context->ListViewHandle, lvItemIndex, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhRemoveItemList(context->ColumnSetList, index); PhRemoveListViewItem(context->ListViewHandle, lvItemIndex); PhClearReference(&entry->Name); PhClearReference(&entry->Setting); PhClearReference(&entry->Sorting); PhFree(entry); } SetFocus(context->ListViewHandle); ListView_SetItemState(context->ListViewHandle, 0, LVNI_SELECTED, LVNI_SELECTED); //ListView_EnsureVisible(context->ListViewHandle, 0, FALSE); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_DBLCLK: { INT lvItemIndex; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); if (lvItemIndex != -1) { SetFocus(context->ListViewHandle); ListView_EditLabel(context->ListViewHandle, lvItemIndex); } } break; case LVN_ITEMCHANGED: { LPNMLISTVIEW listview = (LPNMLISTVIEW)lParam; INT index; INT lvItemIndex; INT count; index = listview->iItem; lvItemIndex = ListView_GetNextItem(context->ListViewHandle, -1, LVNI_SELECTED); count = ListView_GetItemCount(context->ListViewHandle); if (count == 0 || index == -1 || lvItemIndex == -1) { Button_Enable(context->RenameButtonHandle, FALSE); Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); Button_Enable(context->RemoveButtonHandle, FALSE); break; } if (index != lvItemIndex) break; if (index == 0 && count == 1) { // First and last item Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, FALSE); } else if (index == (count - 1)) { // Last item Button_Enable(context->MoveUpButtonHandle, TRUE); Button_Enable(context->MoveDownButtonHandle, FALSE); } else if (index == 0) { // First item Button_Enable(context->MoveUpButtonHandle, FALSE); Button_Enable(context->MoveDownButtonHandle, TRUE); } else { Button_Enable(context->MoveUpButtonHandle, TRUE); Button_Enable(context->MoveDownButtonHandle, TRUE); } Button_Enable(context->RenameButtonHandle, TRUE); Button_Enable(context->RemoveButtonHandle, TRUE); } break; case LVN_BEGINLABELEDIT: context->LabelEditActive = TRUE; break; case LVN_ENDLABELEDIT: { LV_DISPINFO* lvinfo = (LV_DISPINFO*)lParam; if (lvinfo->item.iItem != -1 && lvinfo->item.pszText) { BOOLEAN found = FALSE; PPH_COLUMN_SET_ENTRY entry; ULONG index; for (ULONG i = 0; i < context->ColumnSetList->Count; i++) { entry = context->ColumnSetList->Items[i]; if (PhEqualStringRef2(&entry->Name->sr, lvinfo->item.pszText, FALSE)) { found = TRUE; break; } } if (!found && PhGetListViewItemParam(context->ListViewHandle, lvinfo->item.iItem, (PVOID *)&entry)) { index = PhFindItemList(context->ColumnSetList, entry); if (index != -1) { PhMoveReference(&entry->Name, PhCreateString(lvinfo->item.pszText)); ListView_SetItemText(context->ListViewHandle, lvinfo->item.iItem, 0, lvinfo->item.pszText); } } } context->LabelEditActive = FALSE; } break; } } break; } return FALSE; }
VOID ProcessesUpdatedCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { static ULONG ProcessesUpdatedCount = 0; PLIST_ENTRY listEntry; if (!VirusTotalScanningEnabled) return; if (ProcessesUpdatedCount < 2) { ProcessesUpdatedCount++; return; } listEntry = ProcessListHead.Flink; while (listEntry != &ProcessListHead) { PPROCESS_EXTENSION extension; PPH_STRING filePath = NULL; extension = CONTAINING_RECORD(listEntry, PROCESS_EXTENSION, ListEntry); if (extension->ProcessItem) { filePath = extension->ProcessItem->FileName; } else if (extension->ModuleItem) { filePath = extension->ModuleItem->FileName; } else if (extension->ServiceItem) { if (extension->FilePath) { filePath = extension->FilePath; } else { PPH_STRING serviceFileName = NULL; PPH_STRING serviceBinaryPath = NULL; if (NT_SUCCESS(QueryServiceFileName( &extension->ServiceItem->Name->sr, &serviceFileName, &serviceBinaryPath ))) { PhMoveReference(&extension->FilePath, serviceFileName); if (serviceBinaryPath) PhDereferenceObject(serviceBinaryPath); } filePath = extension->FilePath; } } if (!PhIsNullOrEmptyString(filePath)) { if (!extension->ResultValid) { PPROCESS_DB_OBJECT object; if (object = FindProcessDbObject(&filePath->sr)) { extension->Stage1 = TRUE; extension->ResultValid = TRUE; extension->Positives = object->Positives; PhSwapReference(&extension->VirusTotalResult, object->Result); } } if (!extension->Stage1) { if (!VirusTotalGetCachedResult(filePath)) { VirusTotalAddCacheResult(filePath, extension); } extension->Stage1 = TRUE; } } listEntry = listEntry->Flink; } }
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; }
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; } }
INT_PTR CALLBACK EtpGpuNodesDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { ULONG i; HFONT font; PPH_STRING nodeString; RECT labelRect; RECT tempRect; ULONG numberOfRows; ULONG numberOfColumns; WindowHandle = hwndDlg; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhInitializeLayoutManager(&LayoutManager, hwndDlg); PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); LayoutMargin = PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_LAYOUT), NULL, PH_ANCHOR_ALL)->Margin; PhRegisterCallback(&PhProcessesUpdatedEvent, ProcessesUpdatedCallback, NULL, &ProcessesUpdatedCallbackRegistration); GraphHandle = PhAllocate(sizeof(HWND) * EtGpuTotalNodeCount); CheckBoxHandle = PhAllocate(sizeof(HWND) * EtGpuTotalNodeCount); GraphState = PhAllocate(sizeof(PH_GRAPH_STATE) * EtGpuTotalNodeCount); font = (HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0); for (i = 0; i < EtGpuTotalNodeCount; i++) { nodeString = PhFormatString(L"Node %lu", i); GraphHandle[i] = CreateWindow( PH_GRAPH_CLASSNAME, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 3, 3, hwndDlg, NULL, NULL, NULL ); Graph_SetTooltip(GraphHandle[i], TRUE); CheckBoxHandle[i] = CreateWindow( WC_BUTTON, nodeString->Buffer, WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX, 0, 0, 3, 3, hwndDlg, NULL, NULL, NULL ); SendMessage(CheckBoxHandle[i], WM_SETFONT, (WPARAM)font, FALSE); PhInitializeGraphState(&GraphState[i]); PhDereferenceObject(nodeString); } // Calculate the minimum size. numberOfRows = (ULONG)sqrt(EtGpuTotalNodeCount); numberOfColumns = (EtGpuTotalNodeCount + numberOfRows - 1) / numberOfRows; MinimumSize.left = 0; MinimumSize.top = 0; MinimumSize.right = 45; MinimumSize.bottom = 60; MapDialogRect(hwndDlg, &MinimumSize); MinimumSize.right += (MinimumSize.right + GRAPH_PADDING) * numberOfColumns; MinimumSize.bottom += (MinimumSize.bottom + GRAPH_PADDING) * numberOfRows; GetWindowRect(GetDlgItem(hwndDlg, IDC_INSTRUCTION), &labelRect); MapWindowPoints(NULL, hwndDlg, (POINT *)&labelRect, 2); labelRect.right += GetSystemMetrics(SM_CXFRAME) * 2; tempRect.left = 0; tempRect.top = 0; tempRect.right = 7; tempRect.bottom = 0; MapDialogRect(hwndDlg, &tempRect); labelRect.right += tempRect.right; if (MinimumSize.right < labelRect.right) MinimumSize.right = labelRect.right; SetWindowPos(hwndDlg, NULL, 0, 0, MinimumSize.right, MinimumSize.bottom, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); EtpLoadNodeBitMap(); } break; case WM_DESTROY: { ULONG i; EtpSaveNodeBitMap(); PhUnregisterCallback(&PhProcessesUpdatedEvent, &ProcessesUpdatedCallbackRegistration); for (i = 0; i < EtGpuTotalNodeCount; i++) { PhDeleteGraphState(&GraphState[i]); } PhFree(GraphHandle); PhFree(CheckBoxHandle); PhFree(GraphState); PhDeleteLayoutManager(&LayoutManager); } break; case WM_SIZE: { HDWP deferHandle; RECT clientRect; RECT checkBoxRect; ULONG numberOfRows = (ULONG)sqrt(EtGpuTotalNodeCount); ULONG numberOfColumns = (EtGpuTotalNodeCount + numberOfRows - 1) / numberOfRows; ULONG numberOfYPaddings = numberOfRows - 1; ULONG numberOfXPaddings = numberOfColumns - 1; ULONG cellHeight; ULONG y; ULONG cellWidth; ULONG x; ULONG i; PhLayoutManagerLayout(&LayoutManager); deferHandle = BeginDeferWindowPos(EtGpuTotalNodeCount * 2); GetClientRect(hwndDlg, &clientRect); GetClientRect(GetDlgItem(hwndDlg, IDC_EXAMPLE), &checkBoxRect); cellHeight = (clientRect.bottom - LayoutMargin.top - LayoutMargin.bottom - GRAPH_PADDING * numberOfYPaddings) / numberOfRows; y = LayoutMargin.top; i = 0; for (ULONG row = 0; row < numberOfRows; ++row) { // Give the last row the remaining space; the height we calculated might be off by a few // pixels due to integer division. if (row == numberOfRows - 1) cellHeight = clientRect.bottom - LayoutMargin.bottom - y; cellWidth = (clientRect.right - LayoutMargin.left - LayoutMargin.right - GRAPH_PADDING * numberOfXPaddings) / numberOfColumns; x = LayoutMargin.left; for (ULONG column = 0; column < numberOfColumns; column++) { // Give the last cell the remaining space; the width we calculated might be off by a few // pixels due to integer division. if (column == numberOfColumns - 1) cellWidth = clientRect.right - LayoutMargin.right - x; if (i < EtGpuTotalNodeCount) { deferHandle = DeferWindowPos( deferHandle, GraphHandle[i], NULL, x, y, cellWidth, cellHeight - checkBoxRect.bottom - CHECKBOX_PADDING, SWP_NOACTIVATE | SWP_NOZORDER ); deferHandle = DeferWindowPos( deferHandle, CheckBoxHandle[i], NULL, x, y + cellHeight - checkBoxRect.bottom, cellWidth, checkBoxRect.bottom, SWP_NOACTIVATE | SWP_NOZORDER ); i++; } x += cellWidth + GRAPH_PADDING; } y += cellHeight + GRAPH_PADDING; } EndDeferWindowPos(deferHandle); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: { EndDialog(hwndDlg, IDOK); } break; } } break; case WM_NOTIFY: { NMHDR *header = (NMHDR *)lParam; ULONG i; switch (header->code) { case GCN_GETDRAWINFO: { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; drawInfo->Flags = PH_GRAPH_USE_GRID; SysInfoParameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0); for (i = 0; i < EtGpuTotalNodeCount; i++) { if (header->hwndFrom == GraphHandle[i]) { PhGraphStateGetDrawInfo( &GraphState[i], getDrawInfo, EtGpuNodesHistory[i].Count ); if (!GraphState[i].Valid) { PhCopyCircularBuffer_FLOAT(&EtGpuNodesHistory[i], GraphState[i].Data1, drawInfo->LineDataCount); GraphState[i].Valid = TRUE; } break; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)header; if (getTooltipText->Index < getTooltipText->TotalCount) { for (i = 0; i < EtGpuTotalNodeCount; i++) { if (header->hwndFrom == GraphHandle[i]) { if (GraphState[i].TooltipIndex != getTooltipText->Index) { FLOAT gpu; ULONG adapterIndex; PPH_STRING adapterDescription; gpu = PhGetItemCircularBuffer_FLOAT(&EtGpuNodesHistory[i], getTooltipText->Index); adapterIndex = EtGetGpuAdapterIndexFromNodeIndex(i); if (adapterIndex != -1) { adapterDescription = EtGetGpuAdapterDescription(adapterIndex); if (adapterDescription && adapterDescription->Length == 0) PhClearReference(&adapterDescription); if (!adapterDescription) adapterDescription = PhFormatString(L"Adapter %lu", adapterIndex); } else { adapterDescription = PhCreateString(L"Unknown Adapter"); } PhMoveReference(&GraphState[i].TooltipText, PhFormatString( L"Node %lu on %s\n%.2f%%\n%s", i, adapterDescription->Buffer, gpu * 100, ((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); PhDereferenceObject(adapterDescription); } getTooltipText->Text = GraphState[i].TooltipText->sr; break; } } } } break; } } break; case UPDATE_MSG: { ULONG i; for (i = 0; i < EtGpuTotalNodeCount; i++) { GraphState[i].Valid = FALSE; GraphState[i].TooltipIndex = -1; Graph_MoveGrid(GraphHandle[i], 1); Graph_Draw(GraphHandle[i]); Graph_UpdateTooltip(GraphHandle[i]); InvalidateRect(GraphHandle[i], NULL, FALSE); } } break; } return FALSE; }
static INT_PTR CALLBACK NetworkPingWndProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PNETWORK_OUTPUT_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = (PNETWORK_OUTPUT_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context"); } if (context == NULL) return FALSE; switch (uMsg) { case WM_INITDIALOG: { PH_RECTANGLE windowRectangle; PPH_LAYOUT_ITEM panelItem; // We have already set the group boxes to have WS_EX_TRANSPARENT to fix // the drawing issue that arises when using WS_CLIPCHILDREN. However // in removing the flicker from the graphs the group boxes will now flicker. // It's a good tradeoff since no one stares at the group boxes. PhSetWindowStyle(hwndDlg, WS_CLIPCHILDREN, WS_CLIPCHILDREN); context->WindowHandle = hwndDlg; context->ParentHandle = GetParent(hwndDlg); context->StatusHandle = GetDlgItem(hwndDlg, IDC_MAINTEXT); context->MaxPingTimeout = PhGetIntegerSetting(SETTING_NAME_PING_TIMEOUT); windowRectangle.Position = PhGetIntegerPairSetting(SETTING_NAME_PING_WINDOW_POSITION); windowRectangle.Size = PhGetIntegerPairSetting(SETTING_NAME_PING_WINDOW_SIZE); // Create the font handle. context->FontHandle = InitializeFont(context->StatusHandle); // Create the graph control. context->PingGraphHandle = CreateWindow( PH_GRAPH_CLASSNAME, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 3, 3, hwndDlg, NULL, NULL, NULL ); Graph_SetTooltip(context->PingGraphHandle, TRUE); // Load the Process Hacker icon. context->IconHandle = (HICON)LoadImage( NtCurrentPeb()->ImageBaseAddress, MAKEINTRESOURCE(PHAPP_IDI_PROCESSHACKER), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_SHARED ); // Set window icon. if (context->IconHandle) SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)context->IconHandle); // Initialize the WorkQueue with a maximum of 20 threads (fix pinging slow-links with a high interval update). PhInitializeWorkQueue(&context->PingWorkQueue, 0, 20, 5000); PhInitializeGraphState(&context->PingGraphState); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhInitializeCircularBuffer_ULONG(&context->PingHistory, PhGetIntegerSetting(L"SampleCount")); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_PANEL), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_AVG), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_MIN), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_MAX), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PINGS_SENT), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PINGS_LOST), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BAD_HASH), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ANON_ADDR), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT); panelItem = PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PING_LAYOUT), NULL, PH_ANCHOR_ALL); PhAddLayoutItemEx(&context->LayoutManager, context->PingGraphHandle, NULL, PH_ANCHOR_ALL, panelItem->Margin); // Load window settings. if (windowRectangle.Position.X == 0 || windowRectangle.Position.Y == 0) PhCenterWindow(hwndDlg, GetParent(hwndDlg)); else { PhLoadWindowPlacementFromSetting(SETTING_NAME_PING_WINDOW_POSITION, SETTING_NAME_PING_WINDOW_SIZE, hwndDlg); } // Initialize window layout. PhLayoutManagerLayout(&context->LayoutManager); // Convert IP Address to string format. if (context->IpAddress.Type == PH_IPV4_NETWORK_TYPE) { RtlIpv4AddressToString(&context->IpAddress.InAddr, context->IpAddressString); } else { RtlIpv6AddressToString(&context->IpAddress.In6Addr, context->IpAddressString); } SetWindowText(hwndDlg, PhaFormatString(L"Ping %s", context->IpAddressString)->Buffer); SetWindowText(context->StatusHandle, PhaFormatString(L"Pinging %s with 32 bytes of data:", context->IpAddressString)->Buffer); PhRegisterCallback( PhGetGeneralCallback(GeneralCallbackProcessesUpdated), NetworkPingUpdateHandler, context, &context->ProcessesUpdatedRegistration ); } return TRUE; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: PostQuitMessage(0); break; } } break; case WM_DESTROY: { PhUnregisterCallback( PhGetGeneralCallback(GeneralCallbackProcessesUpdated), &context->ProcessesUpdatedRegistration ); PhSaveWindowPlacementToSetting( SETTING_NAME_PING_WINDOW_POSITION, SETTING_NAME_PING_WINDOW_SIZE, hwndDlg ); if (context->PingGraphHandle) DestroyWindow(context->PingGraphHandle); if (context->IconHandle) DestroyIcon(context->IconHandle); if (context->FontHandle) DeleteObject(context->FontHandle); PhDeleteWorkQueue(&context->PingWorkQueue); PhDeleteGraphState(&context->PingGraphState); PhDeleteLayoutManager(&context->LayoutManager); RemoveProp(hwndDlg, L"Context"); PhFree(context); } break; case WM_SIZE: PhLayoutManagerLayout(&context->LayoutManager); break; case WM_SIZING: PhResizingMinimumSize((PRECT)lParam, wParam, 420, 250); 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_MAINTEXT) { 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); } break; case WM_PING_UPDATE: { ULONG i = 0; ULONG maxGraphHeight = 0; ULONG pingAvgValue = 0; PhNetworkPingUpdateGraph(context); for (i = 0; i < context->PingHistory.Count; i++) { maxGraphHeight = maxGraphHeight + PhGetItemCircularBuffer_ULONG(&context->PingHistory, i); pingAvgValue = maxGraphHeight / context->PingHistory.Count; } SetDlgItemText(hwndDlg, IDC_ICMP_AVG, PhaFormatString( L"Average: %lums", pingAvgValue)->Buffer); SetDlgItemText(hwndDlg, IDC_ICMP_MIN, PhaFormatString( L"Minimum: %lums", context->PingMinMs)->Buffer); SetDlgItemText(hwndDlg, IDC_ICMP_MAX, PhaFormatString( L"Maximum: %lums", context->PingMaxMs)->Buffer); SetDlgItemText(hwndDlg, IDC_PINGS_SENT, PhaFormatString( L"Pings Sent: %lu", context->PingSentCount)->Buffer); SetDlgItemText(hwndDlg, IDC_PINGS_LOST, PhaFormatString( L"Pings Lost: %lu (%.0f%%)", context->PingLossCount, ((FLOAT)context->PingLossCount / context->PingSentCount * 100) )->Buffer); SetDlgItemText(hwndDlg, IDC_BAD_HASH, PhaFormatString( L"Bad Hashes: %lu", context->HashFailCount)->Buffer); SetDlgItemText(hwndDlg, IDC_ANON_ADDR, PhaFormatString( L"Anon Replies: %lu", context->UnknownAddrCount)->Buffer); } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case GCN_GETDRAWINFO: { PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header; PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), PhGetIntegerSetting(L"ColorCpuUser")); if (header->hwndFrom == context->PingGraphHandle) { if (PhGetIntegerSetting(L"GraphShowText")) { HDC hdc = Graph_GetBufferedContext(context->PingGraphHandle); PhMoveReference(&context->PingGraphState.Text, PhFormatString(L"Ping: %lums", context->CurrentPingMs) ); SelectObject(hdc, PhApplicationFont); PhSetGraphText(hdc, drawInfo, &context->PingGraphState.Text->sr, &NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT); } else { drawInfo->Text.Buffer = NULL; } PhGraphStateGetDrawInfo( &context->PingGraphState, getDrawInfo, context->PingHistory.Count ); if (!context->PingGraphState.Valid) { ULONG i; FLOAT max = 0; for (i = 0; i < drawInfo->LineDataCount; i++) { FLOAT data1; context->PingGraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG(&context->PingHistory, i); if (max < data1) max = data1; } // Minimum scaling of timeout (1000ms default). if (max < (FLOAT)context->MaxPingTimeout) max = (FLOAT)context->MaxPingTimeout; // Scale the data. PhxfDivideSingle2U( context->PingGraphState.Data1, max, drawInfo->LineDataCount ); context->PingGraphState.Valid = TRUE; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)lParam; if (getTooltipText->Index < getTooltipText->TotalCount) { if (header->hwndFrom == context->PingGraphHandle) { if (context->PingGraphState.TooltipIndex != getTooltipText->Index) { ULONG pingMs = PhGetItemCircularBuffer_ULONG(&context->PingHistory, getTooltipText->Index); PhMoveReference(&context->PingGraphState.TooltipText, PhFormatString(L"Ping: %lums", pingMs) ); } getTooltipText->Text = context->PingGraphState.TooltipText->sr; } } } break; } } 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 PhpOptionsGeneralDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND comboBoxHandle; ULONG i; LOGFONT font; PhpPageInit(hwndDlg); comboBoxHandle = GetDlgItem(hwndDlg, IDC_MAXSIZEUNIT); for (i = 0; i < sizeof(PhSizeUnitNames) / sizeof(PWSTR); i++) ComboBox_AddString(comboBoxHandle, PhSizeUnitNames[i]); SetDlgItemText(hwndDlg, IDC_SEARCHENGINE, PhaGetStringSetting(L"SearchEngine")->Buffer); SetDlgItemText(hwndDlg, IDC_PEVIEWER, PhaGetStringSetting(L"ProgramInspectExecutables")->Buffer); if (PhMaxSizeUnit != -1) ComboBox_SetCurSel(comboBoxHandle, PhMaxSizeUnit); else ComboBox_SetCurSel(comboBoxHandle, sizeof(PhSizeUnitNames) / sizeof(PWSTR) - 1); SetDlgItemInt(hwndDlg, IDC_ICONPROCESSES, PhGetIntegerSetting(L"IconProcesses"), FALSE); SetDlgItemCheckForSetting(hwndDlg, IDC_ALLOWONLYONEINSTANCE, L"AllowOnlyOneInstance"); SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEONCLOSE, L"HideOnClose"); SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEONMINIMIZE, L"HideOnMinimize"); SetDlgItemCheckForSetting(hwndDlg, IDC_COLLAPSESERVICES, L"CollapseServicesOnStart"); SetDlgItemCheckForSetting(hwndDlg, IDC_ICONSINGLECLICK, L"IconSingleClick"); SetDlgItemCheckForSetting(hwndDlg, IDC_ICONTOGGLESVISIBILITY, L"IconTogglesVisibility"); SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEPLUGINS, L"EnablePlugins"); ReadCurrentUserRun(); if (CurrentUserRunPresent) { Button_SetCheck(GetDlgItem(hwndDlg, IDC_STARTATLOGON), BST_CHECKED); if (CurrentUserRunStartHidden) Button_SetCheck(GetDlgItem(hwndDlg, IDC_STARTHIDDEN), BST_CHECKED); } else { EnableWindow(GetDlgItem(hwndDlg, IDC_STARTHIDDEN), FALSE); } // Set the font of the button for a nice preview. if (GetCurrentFont(&font)) { CurrentFontInstance = CreateFontIndirect(&font); if (CurrentFontInstance) SendMessage(GetDlgItem(hwndDlg, IDC_FONT), WM_SETFONT, (WPARAM)CurrentFontInstance, TRUE); } } break; case WM_DESTROY: { if (CurrentFontInstance) DeleteObject(CurrentFontInstance); PhClearReference(&NewFontSelection); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_STARTATLOGON: { EnableWindow(GetDlgItem(hwndDlg, IDC_STARTHIDDEN), Button_GetCheck(GetDlgItem(hwndDlg, IDC_STARTATLOGON)) == BST_CHECKED); } break; case IDC_FONT: { LOGFONT font; CHOOSEFONT chooseFont; if (!GetCurrentFont(&font)) { // Can't get LOGFONT from the existing setting, probably // because the user hasn't ever chosen a font before. // Set the font to something familiar. GetObject((HFONT)SendMessage(PhMainWndHandle, WM_PH_GET_FONT, 0, 0), sizeof(LOGFONT), &font); } memset(&chooseFont, 0, sizeof(CHOOSEFONT)); chooseFont.lStructSize = sizeof(CHOOSEFONT); chooseFont.hwndOwner = hwndDlg; chooseFont.lpLogFont = &font; chooseFont.Flags = CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS; if (ChooseFont(&chooseFont)) { PhMoveReference(&NewFontSelection, PhBufferToHexString((PUCHAR)&font, sizeof(LOGFONT))); // Update the button's font. if (CurrentFontInstance) DeleteObject(CurrentFontInstance); CurrentFontInstance = CreateFontIndirect(&font); SendMessage(GetDlgItem(hwndDlg, IDC_FONT), WM_SETFONT, (WPARAM)CurrentFontInstance, TRUE); } } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_APPLY: { BOOLEAN startAtLogon; BOOLEAN startHidden; PhSetStringSetting2(L"SearchEngine", &(PhaGetDlgItemText(hwndDlg, IDC_SEARCHENGINE)->sr)); PhSetStringSetting2(L"ProgramInspectExecutables", &(PhaGetDlgItemText(hwndDlg, IDC_PEVIEWER)->sr)); PhSetIntegerSetting(L"MaxSizeUnit", PhMaxSizeUnit = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_MAXSIZEUNIT))); PhSetIntegerSetting(L"IconProcesses", GetDlgItemInt(hwndDlg, IDC_ICONPROCESSES, NULL, FALSE)); SetSettingForDlgItemCheck(hwndDlg, IDC_ALLOWONLYONEINSTANCE, L"AllowOnlyOneInstance"); SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEONCLOSE, L"HideOnClose"); SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEONMINIMIZE, L"HideOnMinimize"); SetSettingForDlgItemCheck(hwndDlg, IDC_COLLAPSESERVICES, L"CollapseServicesOnStart"); SetSettingForDlgItemCheck(hwndDlg, IDC_ICONSINGLECLICK, L"IconSingleClick"); SetSettingForDlgItemCheck(hwndDlg, IDC_ICONTOGGLESVISIBILITY, L"IconTogglesVisibility"); SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLEPLUGINS, L"EnablePlugins"); startAtLogon = Button_GetCheck(GetDlgItem(hwndDlg, IDC_STARTATLOGON)) == BST_CHECKED; startHidden = Button_GetCheck(GetDlgItem(hwndDlg, IDC_STARTHIDDEN)) == BST_CHECKED; WriteCurrentUserRun(startAtLogon, startHidden); if (NewFontSelection) { PhSetStringSetting2(L"Font", &NewFontSelection->sr); PostMessage(PhMainWndHandle, WM_PH_UPDATE_FONT, 0, 0); } SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); } return TRUE; } } break; } return FALSE; }
VOID PhpThreadProviderUpdate( _In_ PPH_THREAD_PROVIDER ThreadProvider, _In_ PVOID ProcessInformation ) { PPH_THREAD_PROVIDER threadProvider = ThreadProvider; PSYSTEM_PROCESS_INFORMATION process; SYSTEM_PROCESS_INFORMATION localProcess; PSYSTEM_THREAD_INFORMATION threads; ULONG numberOfThreads; ULONG i; process = PhFindProcessInformation(ProcessInformation, threadProvider->ProcessId); if (!process) { // The process doesn't exist anymore. Pretend it does but // has no threads. process = &localProcess; process->NumberOfThreads = 0; } threads = process->Threads; numberOfThreads = process->NumberOfThreads; // System Idle Process has one thread per CPU. // They all have a TID of 0, but we can't have // multiple TIDs, so we'll assign unique TIDs. if (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID) { for (i = 0; i < numberOfThreads; i++) { threads[i].ClientId.UniqueThread = UlongToHandle(i); } } // Look for dead threads. { PPH_LIST threadsToRemove = NULL; ULONG enumerationKey = 0; PPH_THREAD_ITEM *threadItem; while (PhEnumHashtable(threadProvider->ThreadHashtable, (PVOID *)&threadItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the thread still exists. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; if ((*threadItem)->ThreadId == thread->ClientId.UniqueThread) { found = TRUE; break; } } if (!found) { // Raise the thread removed event. PhInvokeCallback(&threadProvider->ThreadRemovedEvent, *threadItem); if (!threadsToRemove) threadsToRemove = PhCreateList(2); PhAddItemList(threadsToRemove, *threadItem); } } if (threadsToRemove) { PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); for (i = 0; i < threadsToRemove->Count; i++) { PhpRemoveThreadItem( threadProvider, (PPH_THREAD_ITEM)threadsToRemove->Items[i] ); } PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); PhDereferenceObject(threadsToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_THREAD_QUERY_DATA data; entry = RtlInterlockedFlushSList(&threadProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_THREAD_QUERY_DATA, ListEntry); entry = entry->Next; if (data->StartAddressResolveLevel == PhsrlFunction && data->StartAddressString) { PhSwapReference(&data->ThreadItem->StartAddressString, data->StartAddressString); data->ThreadItem->StartAddressResolveLevel = data->StartAddressResolveLevel; } PhMoveReference(&data->ThreadItem->ServiceName, data->ServiceName); data->ThreadItem->JustResolved = TRUE; if (data->StartAddressString) PhDereferenceObject(data->StartAddressString); PhDereferenceObject(data->ThreadItem); PhFree(data); } } // Look for new threads and update existing ones. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; PPH_THREAD_ITEM threadItem; threadItem = PhReferenceThreadItem(threadProvider, thread->ClientId.UniqueThread); if (!threadItem) { PVOID startAddress = NULL; threadItem = PhCreateThreadItem(thread->ClientId.UniqueThread); threadItem->CreateTime = thread->CreateTime; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; threadItem->WaitReason = thread->WaitReason; // Try to open a handle to the thread. if (!NT_SUCCESS(PhOpenThread( &threadItem->ThreadHandle, THREAD_QUERY_INFORMATION, threadItem->ThreadId ))) { PhOpenThread( &threadItem->ThreadHandle, ThreadQueryAccess, threadItem->ThreadId ); } // Get the cycle count. if (WINDOWS_HAS_CYCLE_TIME) { ULONG64 cycles; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); } } // Initialize the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Try to get the start address. if (threadItem->ThreadHandle) { NtQueryInformationThread( threadItem->ThreadHandle, ThreadQuerySetWin32StartAddress, &startAddress, sizeof(PVOID), NULL ); } if (!startAddress) startAddress = thread->StartAddress; threadItem->StartAddress = (ULONG64)startAddress; // Get the Win32 priority. threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadProvider->SymbolsLoadedRunId != 0) { threadItem->StartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); } if (!threadItem->StartAddressString) { threadItem->StartAddressResolveLevel = PhsrlAddress; threadItem->StartAddressString = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer( threadItem->StartAddressString->Buffer, (PVOID)threadItem->StartAddress ); PhTrimToNullTerminatorString(threadItem->StartAddressString); } PhpQueueThreadQuery(threadProvider, threadItem); // Is it a GUI thread? if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { threadItem->IsGuiThread = win32Thread != NULL; } } else { GUITHREADINFO info = { sizeof(GUITHREADINFO) }; threadItem->IsGuiThread = !!GetGUIThreadInfo(HandleToUlong(threadItem->ThreadId), &info); } // Add the thread item to the hashtable. PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); PhAddEntryHashtable(threadProvider->ThreadHashtable, &threadItem); PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); // Raise the thread added event. PhInvokeCallback(&threadProvider->ThreadAddedEvent, threadItem); } else { BOOLEAN modified = FALSE; if (threadItem->JustResolved) modified = TRUE; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; if (threadItem->WaitReason != thread->WaitReason) { threadItem->WaitReason = thread->WaitReason; modified = TRUE; } // If the resolve level is only at address, it probably // means symbols weren't loaded the last time we // tried to get the start address. Try again. if (threadItem->StartAddressResolveLevel == PhsrlAddress) { if (threadProvider->SymbolsLoadedRunId != 0) { PPH_STRING newStartAddressString; newStartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); PhMoveReference( &threadItem->StartAddressString, newStartAddressString ); modified = TRUE; } } // If we couldn't resolve the start address to a // module+offset, use the StartAddress instead // of the Win32StartAddress and try again. // Note that we check the resolve level again // because we may have changed it in the previous // block. if (threadItem->JustResolved && threadItem->StartAddressResolveLevel == PhsrlAddress) { if (threadItem->StartAddress != (ULONG64)thread->StartAddress) { threadItem->StartAddress = (ULONG64)thread->StartAddress; PhpQueueThreadQuery(threadProvider, threadItem); } } // Update the context switch count. { ULONG oldDelta; oldDelta = threadItem->ContextSwitchesDelta.Delta; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); if (threadItem->ContextSwitchesDelta.Delta != oldDelta) { modified = TRUE; } } // Update the cycle count. if (WINDOWS_HAS_CYCLE_TIME) { ULONG64 cycles; ULONG64 oldDelta; oldDelta = threadItem->CyclesDelta.Delta; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); if (threadItem->CyclesDelta.Delta != oldDelta) { modified = TRUE; } } } // Update the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Update the CPU usage. // If the cycle time isn't available, we'll fall back to using the CPU time. if (WINDOWS_HAS_CYCLE_TIME && PhEnableCycleCpuUsage && (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID || threadItem->ThreadHandle)) { threadItem->CpuUsage = (FLOAT)threadItem->CyclesDelta.Delta / PhCpuTotalCycleDelta; } else { threadItem->CpuUsage = (FLOAT)(threadItem->CpuKernelDelta.Delta + threadItem->CpuUserDelta.Delta) / (PhCpuKernelDelta.Delta + PhCpuUserDelta.Delta + PhCpuIdleDelta.Delta); } // Update the Win32 priority. { LONG oldPriorityWin32 = threadItem->PriorityWin32; threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadItem->PriorityWin32 != oldPriorityWin32) { modified = TRUE; } } // Update the GUI thread status. if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = win32Thread != NULL; if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } } else { GUITHREADINFO info = { sizeof(GUITHREADINFO) }; BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = !!GetGUIThreadInfo(HandleToUlong(threadItem->ThreadId), &info); if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } threadItem->JustResolved = FALSE; if (modified) { // Raise the thread modified event. PhInvokeCallback(&threadProvider->ThreadModifiedEvent, threadItem); } PhDereferenceObject(threadItem); } } PhInvokeCallback(&threadProvider->UpdatedEvent, NULL); threadProvider->RunId++; }
static INT_PTR CALLBACK PhpFindObjectsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhFindObjectsListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_RESULTS); PhInitializeLayoutManager(&WindowLayoutManager, hwndDlg); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_FILTER), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_REGEX), NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, lvHandle, NULL, PH_ANCHOR_ALL); MinimumSize.left = 0; MinimumSize.top = 0; MinimumSize.right = 150; MinimumSize.bottom = 100; MapDialogRect(hwndDlg, &MinimumSize); PhRegisterDialog(hwndDlg); PhLoadWindowPlacementFromSetting(L"FindObjWindowPosition", L"FindObjWindowSize", hwndDlg); PhSetListViewStyle(lvHandle, TRUE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Process"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Type"); PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 200, L"Name"); PhAddListViewColumn(lvHandle, 3, 3, 3, LVCFMT_LEFT, 80, L"Handle"); PhSetExtendedListView(lvHandle); ExtendedListView_SetSortFast(lvHandle, TRUE); ExtendedListView_SetCompareFunction(lvHandle, 0, PhpObjectProcessCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 1, PhpObjectTypeCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 2, PhpObjectNameCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 3, PhpObjectHandleCompareFunction); PhLoadListViewColumnsFromSetting(L"FindObjListViewColumns", lvHandle); Button_SetCheck(GetDlgItem(hwndDlg, IDC_REGEX), PhGetIntegerSetting(L"FindObjRegex") ? BST_CHECKED : BST_UNCHECKED); } break; case WM_DESTROY: { PhSetIntegerSetting(L"FindObjRegex", Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED); PhSaveWindowPlacementToSetting(L"FindObjWindowPosition", L"FindObjWindowSize", hwndDlg); PhSaveListViewColumnsToSetting(L"FindObjListViewColumns", PhFindObjectsListViewHandle); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_FILTER), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_FILTER), 0, -1); } break; case WM_CLOSE: { ShowWindow(hwndDlg, SW_HIDE); // IMPORTANT // Set the result to 0 so the default dialog message // handler doesn't invoke IDCANCEL, which will send // WM_CLOSE, creating an infinite loop. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0); } return TRUE; case WM_SETCURSOR: { if (SearchThreadHandle) { SetCursor(LoadCursor(NULL, IDC_WAIT)); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); return TRUE; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDOK: { // Don't continue if the user requested cancellation. if (SearchStop) break; if (!SearchThreadHandle) { ULONG i; PhMoveReference(&SearchString, PhGetWindowText(GetDlgItem(hwndDlg, IDC_FILTER))); if (SearchRegexCompiledExpression) { pcre2_code_free(SearchRegexCompiledExpression); SearchRegexCompiledExpression = NULL; } if (SearchRegexMatchData) { pcre2_match_data_free(SearchRegexMatchData); SearchRegexMatchData = NULL; } if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED) { int errorCode; PCRE2_SIZE errorOffset; SearchRegexCompiledExpression = pcre2_compile( SearchString->Buffer, SearchString->Length / sizeof(WCHAR), PCRE2_CASELESS | PCRE2_DOTALL, &errorCode, &errorOffset, NULL ); if (!SearchRegexCompiledExpression) { PhShowError(hwndDlg, L"Unable to compile the regular expression: \"%s\" at position %zu.", PhGetStringOrDefault(PH_AUTO(PhPcre2GetErrorMessage(errorCode)), L"Unknown error"), errorOffset ); break; } SearchRegexMatchData = pcre2_match_data_create_from_pattern(SearchRegexCompiledExpression, NULL); } // Clean up previous results. ListView_DeleteAllItems(PhFindObjectsListViewHandle); if (SearchResults) { for (i = 0; i < SearchResults->Count; i++) { PPHP_OBJECT_SEARCH_RESULT searchResult = SearchResults->Items[i]; PhDereferenceObject(searchResult->TypeName); PhDereferenceObject(searchResult->Name); if (searchResult->ProcessName) PhDereferenceObject(searchResult->ProcessName); PhFree(searchResult); } PhDereferenceObject(SearchResults); } // Start the search. SearchResults = PhCreateList(128); SearchResultsAddIndex = 0; SearchThreadHandle = PhCreateThread(0, PhpFindObjectsThreadStart, NULL); if (!SearchThreadHandle) { PhClearReference(&SearchResults); break; } SetDlgItemText(hwndDlg, IDOK, L"Cancel"); SetCursor(LoadCursor(NULL, IDC_WAIT)); } else { SearchStop = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); } } break; case IDCANCEL: { SendMessage(hwndDlg, WM_CLOSE, 0, 0); } break; case ID_OBJECT_CLOSE: { PPHP_OBJECT_SEARCH_RESULT *results; ULONG numberOfResults; ULONG i; PhGetSelectedListViewItemParams( PhFindObjectsListViewHandle, &results, &numberOfResults ); if (numberOfResults != 0 && PhShowConfirmMessage( hwndDlg, L"close", numberOfResults == 1 ? L"the selected handle" : L"the selected handles", L"Closing handles may cause system instability and data corruption.", FALSE )) { for (i = 0; i < numberOfResults; i++) { NTSTATUS status; HANDLE processHandle; if (results[i]->ResultType != HandleSearchResult) continue; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, results[i]->ProcessId ))) { if (NT_SUCCESS(status = PhDuplicateObject( processHandle, results[i]->Handle, NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE ))) { PhRemoveListViewItem(PhFindObjectsListViewHandle, PhFindListViewItemByParam(PhFindObjectsListViewHandle, 0, results[i])); } NtClose(processHandle); } if (!NT_SUCCESS(status)) { if (!PhShowContinueStatus(hwndDlg, PhaFormatString(L"Unable to close \"%s\"", results[i]->Name->Buffer)->Buffer, status, 0 )) break; } } } PhFree(results); } break; case ID_HANDLE_OBJECTPROPERTIES1: case ID_HANDLE_OBJECTPROPERTIES2: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { PH_HANDLE_ITEM_INFO info; info.ProcessId = result->ProcessId; info.Handle = result->Handle; info.TypeName = result->TypeName; info.BestObjectName = result->Name; if (LOWORD(wParam) == ID_HANDLE_OBJECTPROPERTIES1) PhShowHandleObjectProperties1(hwndDlg, &info); else PhShowHandleObjectProperties2(hwndDlg, &info); } } break; case ID_OBJECT_GOTOOWNINGPROCESS: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { PPH_PROCESS_NODE processNode; if (processNode = PhFindProcessNode(result->ProcessId)) { ProcessHacker_SelectTabPage(PhMainWndHandle, 0); ProcessHacker_SelectProcessNode(PhMainWndHandle, processNode); ProcessHacker_ToggleVisible(PhMainWndHandle, TRUE); } } } break; case ID_OBJECT_PROPERTIES: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { if (result->ResultType == HandleSearchResult) { PPH_HANDLE_ITEM handleItem; handleItem = PhCreateHandleItem(&result->Info); handleItem->BestObjectName = handleItem->ObjectName = result->Name; PhReferenceObjectEx(result->Name, 2); handleItem->TypeName = result->TypeName; PhReferenceObject(result->TypeName); PhShowHandleProperties( hwndDlg, result->ProcessId, handleItem ); PhDereferenceObject(handleItem); } else { // DLL or Mapped File. Just show file properties. PhShellProperties(hwndDlg, result->Name->Buffer); } } } break; case ID_OBJECT_COPY: { PhCopyListView(PhFindObjectsListViewHandle); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_DBLCLK: { if (header->hwndFrom == PhFindObjectsListViewHandle) { SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_PROPERTIES, 0); } } break; case LVN_KEYDOWN: { if (header->hwndFrom == PhFindObjectsListViewHandle) { LPNMLVKEYDOWN keyDown = (LPNMLVKEYDOWN)header; switch (keyDown->wVKey) { case 'C': if (GetKeyState(VK_CONTROL) < 0) SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_COPY, 0); break; case 'A': if (GetKeyState(VK_CONTROL) < 0) PhSetStateAllListViewItems(PhFindObjectsListViewHandle, LVIS_SELECTED, LVIS_SELECTED); break; case VK_DELETE: SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_CLOSE, 0); break; } } } break; } } break; case WM_CONTEXTMENU: { if ((HWND)wParam == PhFindObjectsListViewHandle) { POINT point; PPHP_OBJECT_SEARCH_RESULT *results; ULONG numberOfResults; point.x = (SHORT)LOWORD(lParam); point.y = (SHORT)HIWORD(lParam); if (point.x == -1 && point.y == -1) PhGetListViewContextMenuPoint((HWND)wParam, &point); PhGetSelectedListViewItemParams(PhFindObjectsListViewHandle, &results, &numberOfResults); if (numberOfResults != 0) { PPH_EMENU menu; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_FINDOBJ), 0); PhSetFlagsEMenuItem(menu, ID_OBJECT_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT); PhpInitializeFindObjMenu(menu, results, numberOfResults); PhShowEMenu( menu, hwndDlg, PH_EMENU_SHOW_SEND_COMMAND | PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y ); PhDestroyEMenu(menu); } PhFree(results); } } break; case WM_SIZE: { PhLayoutManagerLayout(&WindowLayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SEARCH_UPDATE: { HWND lvHandle; ULONG i; lvHandle = GetDlgItem(hwndDlg, IDC_RESULTS); ExtendedListView_SetRedraw(lvHandle, FALSE); PhAcquireQueuedLockExclusive(&SearchResultsLock); for (i = SearchResultsAddIndex; i < SearchResults->Count; i++) { PPHP_OBJECT_SEARCH_RESULT searchResult = SearchResults->Items[i]; CLIENT_ID clientId; PPH_PROCESS_ITEM processItem; PPH_STRING clientIdName; INT lvItemIndex; clientId.UniqueProcess = searchResult->ProcessId; clientId.UniqueThread = NULL; processItem = PhReferenceProcessItem(clientId.UniqueProcess); clientIdName = PhGetClientIdNameEx(&clientId, processItem ? processItem->ProcessName : NULL); lvItemIndex = PhAddListViewItem( lvHandle, MAXINT, clientIdName->Buffer, searchResult ); PhDereferenceObject(clientIdName); if (processItem) { PhSetReference(&searchResult->ProcessName, processItem->ProcessName); PhDereferenceObject(processItem); } else { searchResult->ProcessName = NULL; } PhSetListViewSubItem(lvHandle, lvItemIndex, 1, searchResult->TypeName->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 2, searchResult->Name->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 3, searchResult->HandleString); } SearchResultsAddIndex = i; PhReleaseQueuedLockExclusive(&SearchResultsLock); ExtendedListView_SetRedraw(lvHandle, TRUE); } break; case WM_PH_SEARCH_FINISHED: { NTSTATUS handleSearchStatus = (NTSTATUS)wParam; // Add any un-added items. SendMessage(hwndDlg, WM_PH_SEARCH_UPDATE, 0, 0); NtWaitForSingleObject(SearchThreadHandle, FALSE, NULL); NtClose(SearchThreadHandle); SearchThreadHandle = NULL; SearchStop = FALSE; ExtendedListView_SortItems(GetDlgItem(hwndDlg, IDC_RESULTS)); SetDlgItemText(hwndDlg, IDOK, L"Find"); EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (handleSearchStatus == STATUS_INSUFFICIENT_RESOURCES) { PhShowWarning( hwndDlg, L"Unable to search for handles because the total number of handles on the system is too large. " L"Please check if there are any processes with an extremely large number of handles open." ); } } break; } return FALSE; }
INT_PTR CALLBACK EtwDiskNetworkPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PET_DISKNET_CONTEXT context; if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { context = propPageContext->Context; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { ULONG sampleCount; // We have already set the group boxes to have WS_EX_TRANSPARENT to fix // the drawing issue that arises when using WS_CLIPCHILDREN. However // in removing the flicker from the graphs the group boxes will now flicker. // It's a good tradeoff since no one stares at the group boxes. PhSetWindowStyle(hwndDlg, WS_CLIPCHILDREN, WS_CLIPCHILDREN); sampleCount = PhGetIntegerSetting(L"SampleCount"); context = PhAllocateZero(sizeof(ET_DISKNET_CONTEXT)); context->WindowHandle = hwndDlg; context->Block = EtGetProcessBlock(processItem); context->Enabled = TRUE; context->DiskGroupBox = GetDlgItem(hwndDlg, IDC_GROUPDISK); context->NetworkGroupBox = GetDlgItem(hwndDlg, IDC_GROUPNETWORK); propPageContext->Context = context; PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhInitializeGraphState(&context->DiskGraphState); PhInitializeGraphState(&context->NetworkGraphState); PhInitializeCircularBuffer_ULONG64(&context->DiskReadHistory, sampleCount); PhInitializeCircularBuffer_ULONG64(&context->DiskWriteHistory, sampleCount); PhInitializeCircularBuffer_ULONG64(&context->NetworkSendHistory, sampleCount); PhInitializeCircularBuffer_ULONG64(&context->NetworkReceiveHistory, sampleCount); EtwDiskNetworkCreateGraphs(context); EtwDiskNetworkCreatePanel(context); EtwDiskNetworkUpdateInfo(context); EtwDiskNetworkUpdatePanel(context); PhRegisterCallback( PhGetGeneralCallback(GeneralCallbackProcessProviderUpdatedEvent), EtwDiskNetworkUpdateHandler, context, &context->ProcessesUpdatedRegistration ); PhInitializeWindowTheme(hwndDlg, !!PhGetIntegerSetting(L"EnableThemeSupport")); } break; case WM_DESTROY: { PhDeleteLayoutManager(&context->LayoutManager); PhDeleteGraphState(&context->DiskGraphState); PhDeleteGraphState(&context->NetworkGraphState); PhDeleteCircularBuffer_ULONG64(&context->DiskReadHistory); PhDeleteCircularBuffer_ULONG64(&context->DiskWriteHistory); PhDeleteCircularBuffer_ULONG64(&context->NetworkSendHistory); PhDeleteCircularBuffer_ULONG64(&context->NetworkReceiveHistory); if (context->DiskGraphHandle) DestroyWindow(context->DiskGraphHandle); if (context->NetworkGraphHandle) DestroyWindow(context->NetworkGraphHandle); if (context->PanelHandle) DestroyWindow(context->PanelHandle); PhUnregisterCallback(PhGetGeneralCallback(GeneralCallbackProcessProviderUpdatedEvent), &context->ProcessesUpdatedRegistration); PhFree(context); } 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->DiskGraphHandle) { if (PhGetIntegerSetting(L"GraphShowText")) { HDC hdc; PhMoveReference(&context->DiskGraphState.Text, PhFormatString( L"R: %s, W: %s", PhaFormatSize(context->CurrentDiskRead, ULONG_MAX)->Buffer, PhaFormatSize(context->CurrentDiskWrite, ULONG_MAX)->Buffer )); hdc = Graph_GetBufferedContext(context->DiskGraphHandle); SelectObject(hdc, PhApplicationFont); PhSetGraphText(hdc, drawInfo, &context->DiskGraphState.Text->sr, &NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT); } else { drawInfo->Text.Buffer = NULL; } drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_LABEL_MAX_Y | PH_GRAPH_USE_LINE_2; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite")); PhGraphStateGetDrawInfo(&context->DiskGraphState, getDrawInfo, context->DiskReadHistory.Count); if (!context->DiskGraphState.Valid) { FLOAT max = 0; for (ULONG i = 0; i < drawInfo->LineDataCount; i++) { FLOAT data1; FLOAT data2; context->DiskGraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->DiskReadHistory, i); context->DiskGraphState.Data2[i] = data2 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->DiskWriteHistory, i); if (max < data1 + data2) max = data1 + data2; } // Minimum scaling of 1 MB. //if (max < 1024 * 1024) // max = 1024 * 1024; if (max != 0) { // Scale the data. PhDivideSinglesBySingle( context->DiskGraphState.Data1, max, drawInfo->LineDataCount ); PhDivideSinglesBySingle( context->DiskGraphState.Data2, max, drawInfo->LineDataCount ); } drawInfo->LabelYFunction = PhSiSizeLabelYFunction; drawInfo->LabelYFunctionParameter = max; context->DiskGraphState.Valid = TRUE; } } else if (header->hwndFrom == context->NetworkGraphHandle) { if (PhGetIntegerSetting(L"GraphShowText")) { HDC hdc; PhMoveReference(&context->NetworkGraphState.Text, PhFormatString( L"R: %s, S: %s", PhaFormatSize(context->CurrentNetworkReceive, ULONG_MAX)->Buffer, PhaFormatSize(context->CurrentNetworkSend, ULONG_MAX)->Buffer )); hdc = Graph_GetBufferedContext(context->NetworkGraphHandle); SelectObject(hdc, PhApplicationFont); PhSetGraphText(hdc, drawInfo, &context->NetworkGraphState.Text->sr, &NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT); } else { drawInfo->Text.Buffer = NULL; } drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y | PH_GRAPH_LABEL_MAX_Y | PH_GRAPH_USE_LINE_2; PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite")); PhGraphStateGetDrawInfo(&context->NetworkGraphState, getDrawInfo, context->NetworkSendHistory.Count); if (!context->NetworkGraphState.Valid) { FLOAT max = 0; for (ULONG i = 0; i < drawInfo->LineDataCount; i++) { FLOAT data1; FLOAT data2; context->NetworkGraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->NetworkReceiveHistory, i); context->NetworkGraphState.Data2[i] = data2 = (FLOAT)PhGetItemCircularBuffer_ULONG64(&context->NetworkSendHistory, i); if (max < data1 + data2) max = data1 + data2; } // Minimum scaling of 1 MB. //if (max < 1024 * 1024) // max = 1024 * 1024; if (max != 0) { // Scale the data. PhDivideSinglesBySingle( context->NetworkGraphState.Data1, max, drawInfo->LineDataCount ); PhDivideSinglesBySingle( context->NetworkGraphState.Data2, max, drawInfo->LineDataCount ); } drawInfo->LabelYFunction = PhSiSizeLabelYFunction; drawInfo->LabelYFunctionParameter = max; context->NetworkGraphState.Valid = TRUE; } } } break; case GCN_GETTOOLTIPTEXT: { PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)lParam; if (getTooltipText->Index < getTooltipText->TotalCount) { if (header->hwndFrom == context->DiskGraphHandle) { if (context->DiskGraphState.TooltipIndex != getTooltipText->Index) { ULONG64 diskRead = PhGetItemCircularBuffer_ULONG64( &context->DiskReadHistory, getTooltipText->Index ); ULONG64 diskWrite = PhGetItemCircularBuffer_ULONG64( &context->DiskWriteHistory, getTooltipText->Index ); PhMoveReference(&context->DiskGraphState.TooltipText, PhFormatString( L"R: %s\nW: %s\n%s", PhaFormatSize(diskRead, ULONG_MAX)->Buffer, PhaFormatSize(diskWrite, ULONG_MAX)->Buffer, ((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); } getTooltipText->Text = PhGetStringRef(context->DiskGraphState.TooltipText); } else if (header->hwndFrom == context->NetworkGraphHandle) { if (context->NetworkGraphState.TooltipIndex != getTooltipText->Index) { ULONG64 networkSend = PhGetItemCircularBuffer_ULONG64( &context->NetworkSendHistory, getTooltipText->Index ); ULONG64 networkReceive = PhGetItemCircularBuffer_ULONG64( &context->NetworkReceiveHistory, getTooltipText->Index ); PhMoveReference(&context->NetworkGraphState.TooltipText, PhFormatString( L"S: %s\nR: %s\n%s", PhaFormatSize(networkSend, ULONG_MAX)->Buffer, PhaFormatSize(networkReceive, ULONG_MAX)->Buffer, ((PPH_STRING)PH_AUTO(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer )); } getTooltipText->Text = PhGetStringRef(context->NetworkGraphState.TooltipText); } } } break; } } break; case ET_WM_UPDATE: { if (context->Enabled) { EtwDiskNetworkUpdateInfo(context); EtwDiskNetworkUpdateGraphs(context); EtwDiskNetworkUpdatePanel(context); } } break; case WM_SIZE: { EtwDiskNetworkLayoutGraphs(context); } break; } return FALSE; }
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; } }
BOOLEAN PhSipMemorySectionCallback( _In_ PPH_SYSINFO_SECTION Section, _In_ PH_SYSINFO_SECTION_MESSAGE Message, _In_opt_ PVOID Parameter1, _In_opt_ PVOID Parameter2 ) { switch (Message) { case SysInfoCreate: { MemorySection = Section; } return TRUE; case SysInfoDestroy: { if (MemoryDialog) { PhSipUninitializeMemoryDialog(); MemoryDialog = NULL; } } break; case SysInfoTick: { if (MemoryDialog) { PhSipTickMemoryDialog(); } } return TRUE; case SysInfoCreateDialog: { PPH_SYSINFO_CREATE_DIALOG createDialog = Parameter1; createDialog->Instance = PhInstanceHandle; createDialog->Template = MAKEINTRESOURCE(IDD_SYSINFO_MEM); createDialog->DialogProc = PhSipMemoryDialogProc; } return TRUE; case SysInfoGraphGetDrawInfo: { PPH_GRAPH_DRAW_INFO drawInfo = Parameter1; ULONG i; if (PhGetIntegerSetting(L"ShowCommitInSummary")) { drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y; Section->Parameters->ColorSetupFunction(drawInfo, PhCsColorPrivate, 0); PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, PhCommitHistory.Count); if (!Section->GraphState.Valid) { for (i = 0; i < drawInfo->LineDataCount; i++) { Section->GraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&PhCommitHistory, i); } if (PhPerfInformation.CommitLimit != 0) { // Scale the data. PhDivideSinglesBySingle( Section->GraphState.Data1, (FLOAT)PhPerfInformation.CommitLimit, drawInfo->LineDataCount ); } Section->GraphState.Valid = TRUE; } } else { drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y; Section->Parameters->ColorSetupFunction(drawInfo, PhCsColorPhysical, 0); PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, PhPhysicalHistory.Count); if (!Section->GraphState.Valid) { for (i = 0; i < drawInfo->LineDataCount; i++) { Section->GraphState.Data1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&PhPhysicalHistory, i); } if (PhSystemBasicInformation.NumberOfPhysicalPages != 0) { // Scale the data. PhDivideSinglesBySingle( Section->GraphState.Data1, (FLOAT)PhSystemBasicInformation.NumberOfPhysicalPages, drawInfo->LineDataCount ); } Section->GraphState.Valid = TRUE; } } } return TRUE; case SysInfoGraphGetTooltipText: { PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = Parameter1; ULONG usedPages; if (PhGetIntegerSetting(L"ShowCommitInSummary")) { usedPages = PhGetItemCircularBuffer_ULONG(&PhCommitHistory, getTooltipText->Index); PhMoveReference(&Section->GraphState.TooltipText, PhFormatString( L"Commit charge: %s\n%s", PhaFormatSize(UInt32x32To64(usedPages, PAGE_SIZE), -1)->Buffer, PH_AUTO_T(PH_STRING, PhGetStatisticsTimeString(NULL, getTooltipText->Index))->Buffer )); getTooltipText->Text = Section->GraphState.TooltipText->sr; } else { usedPages = PhGetItemCircularBuffer_ULONG(&PhPhysicalHistory, getTooltipText->Index); PhMoveReference(&Section->GraphState.TooltipText, PhFormatString( L"Physical memory: %s\n%s", PhaFormatSize(UInt32x32To64(usedPages, PAGE_SIZE), -1)->Buffer, 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; ULONG totalPages; ULONG usedPages; if (PhGetIntegerSetting(L"ShowCommitInSummary")) { totalPages = PhPerfInformation.CommitLimit; usedPages = PhPerfInformation.CommittedPages; } else { totalPages = PhSystemBasicInformation.NumberOfPhysicalPages; usedPages = totalPages - PhPerfInformation.AvailablePages; } drawPanel->Title = PhCreateString(L"Memory"); drawPanel->SubTitle = PhFormatString( L"%.0f%%\n%s / %s", (FLOAT)usedPages * 100 / totalPages, PhSipFormatSizeWithPrecision(UInt32x32To64(usedPages, PAGE_SIZE), 1)->Buffer, PhSipFormatSizeWithPrecision(UInt32x32To64(totalPages, PAGE_SIZE), 1)->Buffer ); drawPanel->SubTitleOverflow = PhFormatString( L"%.0f%%\n%s", (FLOAT)usedPages * 100 / totalPages, PhSipFormatSizeWithPrecision(UInt32x32To64(usedPages, PAGE_SIZE), 1)->Buffer ); } return TRUE; } return FALSE; }
VOID NTAPI DotNetEventCallback( _In_ PEVENT_RECORD EventRecord ) { PASMPAGE_QUERY_CONTEXT context = EventRecord->UserContext; PEVENT_HEADER eventHeader = &EventRecord->EventHeader; PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; if (UlongToHandle(eventHeader->ProcessId) == context->ProcessId) { // .NET 4.0+ switch (eventDescriptor->Id) { case RuntimeInformationDCStart: { PRuntimeInformationRundown data = EventRecord->UserData; PDNA_NODE node; PPH_STRING startupFlagsString; PPH_STRING startupModeString; // Check for duplicates. if (FindClrNode(context, data->ClrInstanceID)) break; node = AddNode(context); node->Type = DNA_TYPE_CLR; node->u.Clr.ClrInstanceID = data->ClrInstanceID; node->u.Clr.DisplayName = PhFormatString(L"CLR v%u.%u.%u.%u", data->VMMajorVersion, data->VMMinorVersion, data->VMBuildNumber, data->VMQfeNumber); node->StructureText = node->u.Clr.DisplayName->sr; node->IdText = PhFormatString(L"%u", data->ClrInstanceID); startupFlagsString = FlagsToString(data->StartupFlags, StartupFlagsMap, sizeof(StartupFlagsMap)); startupModeString = FlagsToString(data->StartupMode, StartupModeMap, sizeof(StartupModeMap)); if (startupFlagsString->Length != 0 && startupModeString->Length != 0) { node->FlagsText = PhConcatStrings(3, startupFlagsString->Buffer, L", ", startupModeString->Buffer); PhDereferenceObject(startupFlagsString); PhDereferenceObject(startupModeString); } else if (startupFlagsString->Length != 0) { node->FlagsText = startupFlagsString; PhDereferenceObject(startupModeString); } else if (startupModeString->Length != 0) { node->FlagsText = startupModeString; PhDereferenceObject(startupFlagsString); } if (data->CommandLine[0]) node->PathText = PhCreateString(data->CommandLine); PhAddItemList(context->NodeRootList, node); } break; case AppDomainDCStart_V1: { PAppDomainLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T appDomainNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; appDomainNameLength = PhCountStringZ(data->AppDomainName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AppDomainLoadUnloadRundown_V1, AppDomainName) + appDomainNameLength + sizeof(WCHAR) + sizeof(ULONG)); // Find the CLR node to add the AppDomain node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) { // Check for duplicates. if (FindAppDomainNode(parentNode, data->AppDomainID)) break; node = AddNode(context); node->Type = DNA_TYPE_APPDOMAIN; node->u.AppDomain.AppDomainID = data->AppDomainID; node->u.AppDomain.DisplayName = PhConcatStrings2(L"AppDomain: ", data->AppDomainName); node->StructureText = node->u.AppDomain.DisplayName->sr; node->IdText = PhFormatString(L"%I64u", data->AppDomainID); node->FlagsText = FlagsToString(data->AppDomainFlags, AppDomainFlagsMap, sizeof(AppDomainFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case AssemblyDCStart_V1: { PAssemblyLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T fullyQualifiedAssemblyNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; PH_STRINGREF remainingPart; fullyQualifiedAssemblyNameLength = PhCountStringZ(data->FullyQualifiedAssemblyName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AssemblyLoadUnloadRundown_V1, FullyQualifiedAssemblyName) + fullyQualifiedAssemblyNameLength + sizeof(WCHAR)); // Find the AppDomain node to add the Assembly node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) parentNode = FindAppDomainNode(parentNode, data->AppDomainID); if (parentNode) { // Check for duplicates. if (FindAssemblyNode(parentNode, data->AssemblyID)) break; node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->u.Assembly.AssemblyID = data->AssemblyID; node->u.Assembly.FullyQualifiedAssemblyName = PhCreateStringEx(data->FullyQualifiedAssemblyName, fullyQualifiedAssemblyNameLength); // Display only the assembly name, not the whole fully qualified name. if (!PhSplitStringRefAtChar(&node->u.Assembly.FullyQualifiedAssemblyName->sr, ',', &node->StructureText, &remainingPart)) node->StructureText = node->u.Assembly.FullyQualifiedAssemblyName->sr; node->IdText = PhFormatString(L"%I64u", data->AssemblyID); node->FlagsText = FlagsToString(data->AssemblyFlags, AssemblyFlagsMap, sizeof(AssemblyFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case ModuleDCStart_V1: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; USHORT clrInstanceID; PDNA_NODE node; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)moduleNativePath + moduleNativePathLength + sizeof(WCHAR)); // Find the Assembly node to set the path on. node = FindClrNode(context, clrInstanceID); if (node) node = FindAssemblyNode2(node, data->AssemblyID); if (node) { PhMoveReference(&node->PathText, PhCreateStringEx(moduleILPath, moduleILPathLength)); if (moduleNativePathLength != 0) PhMoveReference(&node->NativePathText, PhCreateStringEx(moduleNativePath, moduleNativePathLength)); } } break; case DCStartComplete_V1: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } // .NET 2.0 if (eventDescriptor->Id == 0) { switch (eventDescriptor->Opcode) { case CLR_MODULEDCSTART_OPCODE: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; PDNA_NODE node; ULONG_PTR indexOfBackslash; ULONG_PTR indexOfLastDot; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); if (context->ClrV2Node && (moduleILPathLength != 0 || moduleNativePathLength != 0)) { node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->FlagsText = FlagsToString(data->ModuleFlags, ModuleFlagsMap, sizeof(ModuleFlagsMap)); node->PathText = PhCreateStringEx(moduleILPath, moduleILPathLength); if (moduleNativePathLength != 0) node->NativePathText = PhCreateStringEx(moduleNativePath, moduleNativePathLength); // Use the name between the last backslash and the last dot for the structure column text. // (E.g. C:\...\AcmeSoft.BigLib.dll -> AcmeSoft.BigLib) indexOfBackslash = PhFindLastCharInString(node->PathText, 0, '\\'); indexOfLastDot = PhFindLastCharInString(node->PathText, 0, '.'); if (indexOfBackslash != -1) { node->StructureText.Buffer = node->PathText->Buffer + indexOfBackslash + 1; if (indexOfLastDot != -1 && indexOfLastDot > indexOfBackslash) { node->StructureText.Length = (indexOfLastDot - indexOfBackslash - 1) * sizeof(WCHAR); } else { node->StructureText.Length = node->PathText->Length - indexOfBackslash * sizeof(WCHAR) - sizeof(WCHAR); } } else { node->StructureText = node->PathText->sr; } PhAddItemList(context->ClrV2Node->Children, node); } } break; case CLR_METHODDC_DCSTARTCOMPLETE_OPCODE: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } } } }
BOOLEAN EtpDiskListSectionCallback( _In_ struct _PH_MINIINFO_LIST_SECTION *ListSection, _In_ PH_MINIINFO_LIST_SECTION_MESSAGE Message, _In_opt_ PVOID Parameter1, _In_opt_ PVOID Parameter2 ) { switch (Message) { case MiListSectionTick: { PH_FORMAT format[4]; PhInitFormatS(&format[0], L"Disk R: "); PhInitFormatSize(&format[1], EtDiskReadDelta.Delta); format[1].Type |= FormatUsePrecision; format[1].Precision = 0; PhInitFormatS(&format[2], L" W: "); PhInitFormatSize(&format[3], EtDiskWriteDelta.Delta); format[3].Type |= FormatUsePrecision; format[3].Precision = 0; ListSection->Section->Parameters->SetSectionText(ListSection->Section, PhAutoDereferenceObject(PhFormat(format, 4, 50))); } break; case MiListSectionSortProcessList: { PPH_MINIINFO_LIST_SECTION_SORT_LIST sortList = Parameter1; qsort(sortList->List->Items, sortList->List->Count, sizeof(PPH_PROCESS_NODE), EtpDiskListSectionProcessCompareFunction); } return TRUE; case MiListSectionAssignSortData: { PPH_MINIINFO_LIST_SECTION_ASSIGN_SORT_DATA assignSortData = Parameter1; PPH_LIST processes = assignSortData->ProcessGroup->Processes; ULONG64 diskReadDelta = 0; ULONG64 diskWriteDelta = 0; ULONG i; for (i = 0; i < processes->Count; i++) { PPH_PROCESS_ITEM processItem = processes->Items[i]; PET_PROCESS_BLOCK block = EtGetProcessBlock(processItem); diskReadDelta += block->DiskReadRawDelta.Delta; diskWriteDelta += block->DiskWriteRawDelta.Delta; } assignSortData->SortData->UserData[0] = diskReadDelta; assignSortData->SortData->UserData[1] = diskWriteDelta; } return TRUE; case MiListSectionSortGroupList: { PPH_MINIINFO_LIST_SECTION_SORT_LIST sortList = Parameter1; qsort(sortList->List->Items, sortList->List->Count, sizeof(PPH_MINIINFO_LIST_SECTION_SORT_DATA), EtpDiskListSectionNodeCompareFunction); } return TRUE; case MiListSectionGetUsageText: { PPH_MINIINFO_LIST_SECTION_GET_USAGE_TEXT getUsageText = Parameter1; PPH_LIST processes = getUsageText->ProcessGroup->Processes; ULONG64 diskReadDelta = getUsageText->SortData->UserData[0]; ULONG64 diskWriteDelta = getUsageText->SortData->UserData[1]; PH_FORMAT format[1]; PhInitFormatSize(&format[0], diskReadDelta + diskWriteDelta); PhMoveReference(&getUsageText->Line1, PhFormat(format, 1, 16)); } return TRUE; } return FALSE; }