diff --git a/2.x/trunk/CHANGELOG.txt b/2.x/trunk/CHANGELOG.txt index 496093486..a06e15b38 100644 --- a/2.x/trunk/CHANGELOG.txt +++ b/2.x/trunk/CHANGELOG.txt @@ -10,6 +10,8 @@ Process Hacker * Extended header context menu * Removed tooltip text truncation * Updated ExtendedTools plugin: + * Added Hard Faults, Hard Faults Delta and Peak Threads + columns to process tree list * Added Firewall Status column * Improved cycle-based CPU usage calculation * FIXED: diff --git a/2.x/trunk/ProcessHacker/include/uimodels.h b/2.x/trunk/ProcessHacker/include/uimodels.h index 1b41f99ff..eeffde39e 100644 --- a/2.x/trunk/ProcessHacker/include/uimodels.h +++ b/2.x/trunk/ProcessHacker/include/uimodels.h @@ -259,10 +259,10 @@ typedef struct _PH_PROCESS_NODE PPH_STRING PeakVirtualSizeText; PPH_STRING PageFaultsText; WCHAR BasePriorityText[PH_INT32_STR_LEN_1]; - WCHAR ThreadsText[PH_INT32_STR_LEN_1]; - WCHAR HandlesText[PH_INT32_STR_LEN_1]; - WCHAR GdiHandlesText[PH_INT32_STR_LEN_1]; - WCHAR UserHandlesText[PH_INT32_STR_LEN_1]; + WCHAR ThreadsText[PH_INT32_STR_LEN_1 + 3]; + WCHAR HandlesText[PH_INT32_STR_LEN_1 + 3]; + WCHAR GdiHandlesText[PH_INT32_STR_LEN_1 + 3]; + WCHAR UserHandlesText[PH_INT32_STR_LEN_1 + 3]; PPH_STRING IoRoRateText; PPH_STRING IoWRateText; WCHAR PagePriorityText[PH_INT32_STR_LEN_1]; diff --git a/2.x/trunk/ProcessHacker/proctree.c b/2.x/trunk/ProcessHacker/proctree.c index 116340dc5..82a1c9a21 100644 --- a/2.x/trunk/ProcessHacker/proctree.c +++ b/2.x/trunk/ProcessHacker/proctree.c @@ -636,6 +636,35 @@ static VOID PhpNeedGraphContext( GraphOldBitmap = SelectObject(GraphContext, GraphBitmap); } +static BOOLEAN PhpFormatInt32GroupDigits( + __in ULONG Value, + __out_bcount(BufferLength) PWCHAR Buffer, + __in ULONG BufferLength, + __out_opt PPH_STRINGREF String + ) +{ + PH_FORMAT format; + SIZE_T returnLength; + + PhInitFormatU(&format, Value); + format.Type |= FormatGroupDigits; + + if (PhFormatToBuffer(&format, 1, Buffer, BufferLength, &returnLength)) + { + if (String) + { + String->Buffer = Buffer; + String->Length = (USHORT)(returnLength - sizeof(WCHAR)); + } + + return TRUE; + } + else + { + return FALSE; + } +} + static FLOAT PhpCalculateInclusiveCpuUsage( __in PPH_PROCESS_NODE ProcessNode ) @@ -1812,22 +1841,18 @@ BOOLEAN NTAPI PhpProcessTreeNewCallback( PhInitializeStringRef(&getCellText->Text, node->BasePriorityText); break; case PHPRTLC_THREADS: - PhPrintUInt32(node->ThreadsText, processItem->NumberOfThreads); - PhInitializeStringRef(&getCellText->Text, node->ThreadsText); + PhpFormatInt32GroupDigits(processItem->NumberOfThreads, node->ThreadsText, sizeof(node->ThreadsText), &getCellText->Text); break; case PHPRTLC_HANDLES: - PhPrintUInt32(node->HandlesText, processItem->NumberOfHandles); - PhInitializeStringRef(&getCellText->Text, node->HandlesText); + PhpFormatInt32GroupDigits(processItem->NumberOfHandles, node->HandlesText, sizeof(node->HandlesText), &getCellText->Text); break; case PHPRTLC_GDIHANDLES: PhpUpdateProcessNodeGdiUserHandles(node); - PhPrintUInt32(node->GdiHandlesText, node->GdiHandles); - PhInitializeStringRef(&getCellText->Text, node->GdiHandlesText); + PhpFormatInt32GroupDigits(node->GdiHandles, node->GdiHandlesText, sizeof(node->GdiHandlesText), &getCellText->Text); break; case PHPRTLC_USERHANDLES: PhpUpdateProcessNodeGdiUserHandles(node); - PhPrintUInt32(node->UserHandlesText, node->UserHandles); - PhInitializeStringRef(&getCellText->Text, node->UserHandlesText); + PhpFormatInt32GroupDigits(node->UserHandles, node->UserHandlesText, sizeof(node->UserHandlesText), &getCellText->Text); break; case PHPRTLC_IORORATE: { diff --git a/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt b/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt index 4c913a6a0..9522d87e0 100644 --- a/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt +++ b/2.x/trunk/plugins/ExtendedTools/CHANGELOG.txt @@ -1,5 +1,7 @@ 1.5 - * Added Firewall Status column + * Added Hard Faults, Hard Faults Delta and Peak Threads columns + to process tree list + * Added Firewall Status column to network list 1.4 * Added ETW columns for processes and network connections diff --git a/2.x/trunk/plugins/ExtendedTools/etwstat.c b/2.x/trunk/plugins/ExtendedTools/etwstat.c index 4a3858924..83cef31b3 100644 --- a/2.x/trunk/plugins/ExtendedTools/etwstat.c +++ b/2.x/trunk/plugins/ExtendedTools/etwstat.c @@ -221,7 +221,7 @@ static VOID NTAPI ProcessesUpdatedCallback( PhUpdateDelta(&EtNetworkSendDelta, EtpNetworkSendRaw); // Update per-process statistics. - // Note: no lock is needed because we only ever modify the hashtable on this same thread. + // Note: no lock is needed because we only ever modify the list on this same thread. listEntry = EtProcessBlockListHead.Flink; @@ -252,12 +252,6 @@ static VOID NTAPI ProcessesUpdatedCallback( maxNetworkBlock = block; } - // Invalidate all text. - - PhAcquireQueuedLockExclusive(&block->TextCacheLock); - memset(block->TextCacheValid, 0, sizeof(block->TextCacheValid)); - PhReleaseQueuedLockExclusive(&block->TextCacheLock); - listEntry = listEntry->Flink; } @@ -318,7 +312,7 @@ static VOID NTAPI NetworkItemsUpdatedCallback( // blocks to all fall one update interval behind, however. // Update per-connection statistics. - // Note: no lock is needed because we only ever modify the hashtable on this same thread. + // Note: no lock is needed because we only ever modify the list on this same thread. listEntry = EtNetworkBlockListHead.Flink; @@ -343,12 +337,6 @@ static VOID NTAPI NetworkItemsUpdatedCallback( ProcessHacker_Invoke(PhMainWndHandle, EtpInvalidateNetworkNode, block->NetworkItem); } - // Invalidate all text. - - PhAcquireQueuedLockExclusive(&block->TextCacheLock); - memset(block->TextCacheValid, 0, sizeof(block->TextCacheValid)); - PhReleaseQueuedLockExclusive(&block->TextCacheLock); - listEntry = listEntry->Flink; } } diff --git a/2.x/trunk/plugins/ExtendedTools/exttools.h b/2.x/trunk/plugins/ExtendedTools/exttools.h index fef543981..b7510a3e2 100644 --- a/2.x/trunk/plugins/ExtendedTools/exttools.h +++ b/2.x/trunk/plugins/ExtendedTools/exttools.h @@ -49,7 +49,10 @@ VOID EtEtwProcessPropertiesInitializing( #define ETPRTNC_NETWORKRECEIVEBYTESDELTA 18 #define ETPRTNC_NETWORKSENDBYTESDELTA 19 #define ETPRTNC_NETWORKTOTALBYTESDELTA 20 -#define ETPRTNC_MAXIMUM 20 +#define ETPRTNC_HARDFAULTS 21 +#define ETPRTNC_HARDFAULTSDELTA 22 +#define ETPRTNC_PEAKTHREADS 23 +#define ETPRTNC_MAXIMUM 23 VOID EtEtwProcessTreeNewInitializing( __in PVOID Parameter @@ -192,6 +195,8 @@ typedef struct _ET_PROCESS_BLOCK PH_UINT32_DELTA NetworkSendDelta; PH_UINT32_DELTA NetworkSendRawDelta; + PH_UINT32_DELTA HardFaultsDelta; + PH_QUEUED_LOCK TextCacheLock; PPH_STRING TextCache[ETPRTNC_MAXIMUM + 1]; BOOLEAN TextCacheValid[ETPRTNC_MAXIMUM + 1]; diff --git a/2.x/trunk/plugins/ExtendedTools/main.c b/2.x/trunk/plugins/ExtendedTools/main.c index dd1eb7e3d..26e55b5a7 100644 --- a/2.x/trunk/plugins/ExtendedTools/main.c +++ b/2.x/trunk/plugins/ExtendedTools/main.c @@ -88,6 +88,16 @@ VOID NTAPI NetworkTreeNewInitializingCallback( __in_opt PVOID Context ); +VOID NTAPI ProcessesUpdatedCallback( + __in_opt PVOID Parameter, + __in_opt PVOID Context + ); + +VOID NTAPI NetworkItemsUpdatedCallback( + __in_opt PVOID Parameter, + __in_opt PVOID Context + ); + VOID NTAPI ProcessItemCreateCallback( __in PVOID Object, __in PH_EM_OBJECT_TYPE ObjectType, @@ -130,6 +140,8 @@ PH_CALLBACK_REGISTRATION ThreadMenuInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION ModuleMenuInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION ProcessTreeNewInitializingCallbackRegistration; PH_CALLBACK_REGISTRATION NetworkTreeNewInitializingCallbackRegistration; +PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration; +PH_CALLBACK_REGISTRATION NetworkItemsUpdatedCallbackRegistration; static HANDLE ModuleProcessId; @@ -235,6 +247,19 @@ LOGICAL DllMain( &NetworkTreeNewInitializingCallbackRegistration ); + PhRegisterCallback( + &PhProcessesUpdatedEvent, + ProcessesUpdatedCallback, + NULL, + &ProcessesUpdatedCallbackRegistration + ); + PhRegisterCallback( + &PhNetworkItemsUpdatedEvent, + NetworkItemsUpdatedCallback, + NULL, + &NetworkItemsUpdatedCallbackRegistration + ); + InitializeListHead(&EtProcessBlockListHead); InitializeListHead(&EtNetworkBlockListHead); @@ -505,6 +530,62 @@ VOID NTAPI NetworkTreeNewInitializingCallback( EtEtwNetworkTreeNewInitializing(Parameter); } +static VOID NTAPI ProcessesUpdatedCallback( + __in_opt PVOID Parameter, + __in_opt PVOID Context + ) +{ + PLIST_ENTRY listEntry; + + // Note: no lock is needed because we only ever modify the list on this same thread. + + listEntry = EtProcessBlockListHead.Flink; + + while (listEntry != &EtProcessBlockListHead) + { + PET_PROCESS_BLOCK block; + + block = CONTAINING_RECORD(listEntry, ET_PROCESS_BLOCK, ListEntry); + + PhUpdateDelta(&block->HardFaultsDelta, block->ProcessItem->HardFaultCount); + + // Invalidate all text. + + PhAcquireQueuedLockExclusive(&block->TextCacheLock); + memset(block->TextCacheValid, 0, sizeof(block->TextCacheValid)); + PhReleaseQueuedLockExclusive(&block->TextCacheLock); + + listEntry = listEntry->Flink; + } +} + +static VOID NTAPI NetworkItemsUpdatedCallback( + __in_opt PVOID Parameter, + __in_opt PVOID Context + ) +{ + PLIST_ENTRY listEntry; + + // Note: no lock is needed because we only ever modify the list on this same thread. + + listEntry = EtNetworkBlockListHead.Flink; + + while (listEntry != &EtNetworkBlockListHead) + { + PET_NETWORK_BLOCK block; + + block = CONTAINING_RECORD(listEntry, ET_NETWORK_BLOCK, ListEntry); + + // Invalidate all text. + + PhAcquireQueuedLockExclusive(&block->TextCacheLock); + memset(block->TextCacheValid, 0, sizeof(block->TextCacheValid)); + PhReleaseQueuedLockExclusive(&block->TextCacheLock); + + listEntry = listEntry->Flink; + } +} + PET_PROCESS_BLOCK EtGetProcessBlock( __in PPH_PROCESS_ITEM ProcessItem ) diff --git a/2.x/trunk/plugins/ExtendedTools/treeext.c b/2.x/trunk/plugins/ExtendedTools/treeext.c index 4e0685baa..842b7ad4d 100644 --- a/2.x/trunk/plugins/ExtendedTools/treeext.c +++ b/2.x/trunk/plugins/ExtendedTools/treeext.c @@ -107,7 +107,10 @@ VOID EtEtwProcessTreeNewInitializing( { ETPRTNC_NETWORKSENDSDELTA, L"Network Sends Delta", 70, PH_ALIGN_RIGHT, DT_RIGHT, TRUE }, { ETPRTNC_NETWORKRECEIVEBYTESDELTA, L"Network Receive Bytes Delta", 70, PH_ALIGN_RIGHT, DT_RIGHT, TRUE }, { ETPRTNC_NETWORKSENDBYTESDELTA, L"Network Send Bytes Delta", 70, PH_ALIGN_RIGHT, DT_RIGHT, TRUE }, - { ETPRTNC_NETWORKTOTALBYTESDELTA, L"Network Total Bytes Delta", 70, PH_ALIGN_RIGHT, DT_RIGHT, TRUE } + { ETPRTNC_NETWORKTOTALBYTESDELTA, L"Network Total Bytes Delta", 70, PH_ALIGN_RIGHT, DT_RIGHT, TRUE }, + { ETPRTNC_HARDFAULTS, L"Hard Faults", 70, PH_ALIGN_RIGHT, DT_RIGHT, TRUE }, + { ETPRTNC_HARDFAULTSDELTA, L"Hard Faults Delta", 70, PH_ALIGN_RIGHT, DT_RIGHT, TRUE }, + { ETPRTNC_PEAKTHREADS, L"Peak Threads", 45, PH_ALIGN_RIGHT, DT_RIGHT, TRUE } }; PPH_PLUGIN_TREENEW_INFORMATION treeNewInfo = Parameter; @@ -228,6 +231,16 @@ VOID EtEtwProcessTreeNewMessage( if (block->NetworkReceiveRawDelta.Delta + block->NetworkSendRawDelta.Delta != 0) text = PhFormatSize(block->NetworkReceiveRawDelta.Delta + block->NetworkSendRawDelta.Delta, -1); break; + case ETPRTNC_HARDFAULTS: + text = PhFormatUInt64(block->HardFaultsDelta.Value, TRUE); + break; + case ETPRTNC_HARDFAULTSDELTA: + if (block->HardFaultsDelta.Delta != 0) + text = PhFormatUInt64(block->HardFaultsDelta.Delta, TRUE); + break; + case ETPRTNC_PEAKTHREADS: + text = PhFormatUInt64(block->ProcessItem->PeakNumberOfThreads, TRUE); + break; } if (text) @@ -323,6 +336,15 @@ LONG EtpProcessTreeNewSortFunction( case ETPRTNC_NETWORKTOTALBYTESDELTA: result = uintcmp(block1->NetworkReceiveRawDelta.Delta + block1->NetworkSendRawDelta.Delta, block2->NetworkReceiveRawDelta.Delta + block2->NetworkSendRawDelta.Delta); break; + case ETPRTNC_HARDFAULTS: + result = uintcmp(block1->HardFaultsDelta.Value, block2->HardFaultsDelta.Value); + break; + case ETPRTNC_HARDFAULTSDELTA: + result = uintcmp(block1->HardFaultsDelta.Delta, block2->HardFaultsDelta.Delta); + break; + case ETPRTNC_PEAKTHREADS: + result = uintcmp(block1->ProcessItem->PeakNumberOfThreads, block2->ProcessItem->PeakNumberOfThreads); + break; } return result;