|
|
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
poolmon.c
Abstract:
This module contains the NT/Win32 Pool Monitor
Author:
Lou Perazzoli (loup) 13-Sep-1993
Revision History:
--*/
#include "perfmtrp.h"
#include <search.h>
#include <malloc.h>
#include <limits.h>
#include <stdlib.h>
//
// the amount of memory to increase the size
// of the buffer for NtQuerySystemInformation at each step
//
#define BUFFER_SIZE_STEP 65536
#define CPU_USAGE 0
#define QUOTAS 1
#define TAG 0
#define ALLOC 1
#define FREE 2
#define DIFF 3
#define BYTES 4
#define EACH 5
#define LIGHT 6
#define NONPAGED 0
#define PAGED 1
#define BOTH 2
UCHAR *PoolType[] = { "Nonp ", "Paged" };
PUCHAR LargeBuffer1 = NULL; PUCHAR LargeBuffer2 = NULL;
size_t LargeBuffer1Size = 0; size_t LargeBuffer2Size = 0;
typedef struct _POOLMON_OUT { union { UCHAR Tag[4]; ULONG TagUlong; }; UCHAR NullByte; BOOLEAN Changed; ULONG Type; SIZE_T Allocs; SIZE_T AllocsDiff; SIZE_T Frees; SIZE_T FreesDiff; SIZE_T Allocs_Frees; SIZE_T Used; SIZE_T UsedDiff; SIZE_T Each; } POOLMON_OUT, *PPOOLMON_OUT;
POOLMON_OUT OutBuffer[2000];
ULONG DisplayType = BOTH; ULONG SortBy = TAG; ULONG Paren;
ULONG DelayTimeMsec = 5000;
BOOLEAN Interactive; ULONG NumberOfInputRecords; INPUT_RECORD InputRecord; HANDLE InputHandle; HANDLE OriginalOutputHandle; HANDLE OutputHandle; DWORD OriginalInputMode; WORD NormalAttribute; WORD HighlightAttribute; ULONG NumberOfCols; ULONG NumberOfRows; ULONG NumberOfDetailLines; SIZE_T FirstDetailLine; CONSOLE_SCREEN_BUFFER_INFO OriginalConsoleInfo; ULONG NoHighlight;
BOOLEAN DisplayTotals = FALSE; POOLMON_OUT Totals[2];
typedef struct _FILTER { union { UCHAR Tag[4]; ULONG TagUlong; }; BOOLEAN Exclude; } FILTER, *PFILTER;
#define MAX_FILTER 64
FILTER Filter[MAX_FILTER]; ULONG FilterCount = 0;
VOID ShowHelpPopup( VOID );
int __cdecl ulcomp(const void *e1,const void *e2);
int __cdecl ulcomp(const void *e1,const void *e2) { LONG_PTR u1;
switch (SortBy) { case TAG:
u1 = ((PUCHAR)e1)[0] - ((PUCHAR)e2)[0]; if (u1 != 0) { return u1 > 0 ? 1 : -1; } u1 = ((PUCHAR)e1)[1] - ((PUCHAR)e2)[1]; if (u1 != 0) { return u1 > 0 ? 1 : -1; } u1 = ((PUCHAR)e1)[2] - ((PUCHAR)e2)[2]; if (u1 != 0) { return u1 > 0 ? 1 : -1; } u1 = ((PUCHAR)e1)[3] - ((PUCHAR)e2)[3]; if (u1 == 0) { return 0; } else { return u1 > 0 ? 1 : -1; } break;
case ALLOC: if (Paren & 1) { u1 = ((PPOOLMON_OUT)e2)->AllocsDiff - ((PPOOLMON_OUT)e1)->AllocsDiff; } else { u1 = ((PPOOLMON_OUT)e2)->Allocs - ((PPOOLMON_OUT)e1)->Allocs; } if (u1 == 0) { return 0; } else { return u1 > 0 ? 1 : -1; } break;
case FREE: if (Paren & 1) { u1 = ((PPOOLMON_OUT)e2)->FreesDiff - ((PPOOLMON_OUT)e1)->FreesDiff; } else { u1 = ((PPOOLMON_OUT)e2)->Frees - ((PPOOLMON_OUT)e1)->Frees; } if (u1 == 0) { return 0; } else { return u1 > 0 ? 1 : -1; } break;
case BYTES: if (Paren & 1) { u1 = ((PPOOLMON_OUT)e2)->UsedDiff - ((PPOOLMON_OUT)e1)->UsedDiff; } else { u1 = ((PPOOLMON_OUT)e2)->Used - ((PPOOLMON_OUT)e1)->Used; } if (u1 == 0) { return 0; } else { return u1 > 0 ? 1 : -1; } break;
case DIFF: u1 = ((PPOOLMON_OUT)e2)->Allocs_Frees - ((PPOOLMON_OUT)e1)->Allocs_Frees; if (u1 == 0) { return 0; } else { return u1 > 0 ? 1 : -1; } break;
case EACH: u1 = ((PPOOLMON_OUT)e2)->Each - ((PPOOLMON_OUT)e1)->Each; if (u1 == 0) { return 0; } else { return u1 > 0 ? 1 : -1; } break;
default: return(0); break; } }
BOOLEAN CheckSingleFilter ( PCHAR Tag, PCHAR Filter ) { ULONG i; CHAR tc; CHAR fc;
for ( i = 0; i < 4; i++ ) { tc = *Tag++; fc = *Filter++; if ( fc == '*' ) return TRUE; if ( fc == '?' ) continue; if ( tc != fc ) return FALSE; } return TRUE; }
BOOLEAN CheckFilters ( PSYSTEM_POOLTAG TagInfo ) { BOOLEAN pass; ULONG i; PCHAR tag;
//
// If there are no filters, all tags pass.
//
if ( FilterCount == 0 ) { return TRUE; }
//
// There are filters. If the first filter excludes tags, then any
// tag not explicitly mentioned passes. If the first filter includes
// tags, then any tag not explicitly mentioned fails.
//
if ( Filter[0].Exclude ) { pass = TRUE; } else { pass = FALSE; }
tag = TagInfo->Tag; for ( i = 0; i < FilterCount; i++ ) { if ( CheckSingleFilter( tag, (PCHAR)&Filter[i].Tag ) ) { pass = !Filter[i].Exclude; } }
return pass; }
VOID AddFilter ( BOOLEAN Exclude, PCHAR FilterString ) { PFILTER f; PCHAR p; ULONG i;
if ( FilterCount == MAX_FILTER ) { printf( "Too many filters specified. Limit is %d\n", MAX_FILTER ); return; }
f = &Filter[FilterCount]; p = f->Tag;
for ( i = 0; i < 4; i++ ) { if ( *FilterString == 0 ) break; *p++ = *FilterString++; } for ( ; i < 4; i++ ) { *p++ = ' '; }
f->Exclude = Exclude; FilterCount++;
return; }
VOID ParseArgs ( int argc, char *argv[] ) { char *p; BOOLEAN exclude;
argc--; argv++;
while ( argc-- > 0 ) { p = *argv++; if ( *p == '-' || *p == '/' ) { p++; exclude = TRUE; switch ( tolower(*p) ) { case 'i': exclude = FALSE; case 'x': p++; if ( strlen(p) == 0 ) { printf( "missing filter string\n" ); ExitProcess( 1 ); } else if ( strlen(p) <= sizeof(ULONG) ) { AddFilter( exclude, p ); } else { printf( "filter string too long: %s\n", p ); ExitProcess( 1 ); } break; case 'e': DisplayTotals = TRUE; break; case 't': SortBy = TAG; break; case 'a': SortBy = ALLOC; break; case 'u': case 'b': SortBy = BYTES; break; case 'f': SortBy = FREE; break; case 'd': SortBy = DIFF; break; case 'm': SortBy = EACH;
case 'l': NoHighlight = 1 - NoHighlight; break;
case 'p': DisplayType += 1; if (DisplayType > BOTH) { DisplayType = NONPAGED; } break; case '(': case ')': Paren += 1; break; default: printf( "unknown switch: %s\n", p ); ExitProcess( 2 ); } } else { printf( "unknown switch: %s\n", p ); ExitProcess( 2 ); } }
return; }
BOOL WriteConsoleLine( HANDLE OutputHandle, WORD LineNumber, LPSTR Text, BOOL Highlight ) { COORD WriteCoord; DWORD NumberWritten; DWORD TextLength;
WriteCoord.X = 0; WriteCoord.Y = LineNumber; if (!FillConsoleOutputCharacter( OutputHandle, ' ', NumberOfCols, WriteCoord, &NumberWritten ) ) { return FALSE; }
if (!FillConsoleOutputAttribute( OutputHandle, (WORD)((Highlight && !NoHighlight) ? HighlightAttribute : NormalAttribute), NumberOfCols, WriteCoord, &NumberWritten ) ) { return FALSE; }
if (Text == NULL || (TextLength = strlen( Text )) == 0) { return TRUE; } else { return WriteConsoleOutputCharacter( OutputHandle, Text, TextLength, WriteCoord, &NumberWritten ); } }
NTSTATUS QueryPoolTagInformationIterative( PUCHAR *CurrentBuffer, size_t *CurrentBufferSize ) { size_t NewBufferSize; NTSTATUS ReturnedStatus = STATUS_SUCCESS;
if( CurrentBuffer == NULL || CurrentBufferSize == NULL ) {
return STATUS_INVALID_PARAMETER;
}
//
// there is no buffer allocated yet
//
if( *CurrentBufferSize == 0 || *CurrentBuffer == NULL ) {
NewBufferSize = sizeof( UCHAR ) * BUFFER_SIZE_STEP;
*CurrentBuffer = (PUCHAR) malloc( NewBufferSize );
if( *CurrentBuffer != NULL ) {
*CurrentBufferSize = NewBufferSize; } else {
//
// insufficient memory
//
ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
//
// iterate by buffer's size
//
while( *CurrentBuffer != NULL ) {
ReturnedStatus = NtQuerySystemInformation ( SystemPoolTagInformation, *CurrentBuffer, (ULONG)*CurrentBufferSize, NULL );
if( ! NT_SUCCESS(ReturnedStatus) ) {
//
// free the current buffer
//
free( *CurrentBuffer ); *CurrentBuffer = NULL;
if (ReturnedStatus == STATUS_INFO_LENGTH_MISMATCH) {
//
// try with a greater buffer size
//
NewBufferSize = *CurrentBufferSize + BUFFER_SIZE_STEP;
*CurrentBuffer = (PUCHAR) malloc( NewBufferSize );
if( *CurrentBuffer != NULL ) {
//
// allocated new buffer
//
*CurrentBufferSize = NewBufferSize;
} else {
//
// insufficient memory
//
ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
*CurrentBufferSize = 0;
}
} else {
*CurrentBufferSize = 0;
}
} else {
//
// NtQuerySystemInformation returned success
//
break;
} }
return ReturnedStatus; }
int __cdecl main( int argc, char *argv[] ) {
NTSTATUS Status; ULONG LastCount = 0; SYSTEM_BASIC_INFORMATION BasicInfo; SYSTEM_PERFORMANCE_INFORMATION PerfInfo; PSYSTEM_POOLTAG_INFORMATION PoolInfo; PSYSTEM_POOLTAG_INFORMATION PoolInfoOld; PUCHAR *PreviousBuffer; PUCHAR *CurrentBuffer; PUCHAR *TempBuffer; size_t *PreviousBufferSize; size_t *CurrentBufferSize; size_t *TempBufferSize; BOOLEAN DoHelp; BOOLEAN DoQuit; SIZE_T NumberOfPoolTags; SIZE_T i; UCHAR LastKey; PPOOLMON_OUT Out; LONG ScrollDelta; WORD DisplayLine, LastDetailRow; CHAR OutputBuffer[ 512 ];
DoHelp = FALSE; DoQuit = FALSE; Interactive = TRUE;
ParseArgs( argc, argv );
InputHandle = GetStdHandle( STD_INPUT_HANDLE ); OriginalOutputHandle = GetStdHandle( STD_OUTPUT_HANDLE ); if (Interactive) { if (InputHandle == NULL || OriginalOutputHandle == NULL || !GetConsoleMode( InputHandle, &OriginalInputMode ) ) { Interactive = FALSE; } else { OutputHandle = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CONSOLE_TEXTMODE_BUFFER, NULL ); if (OutputHandle == NULL || !GetConsoleScreenBufferInfo( OriginalOutputHandle, &OriginalConsoleInfo ) || !SetConsoleScreenBufferSize( OutputHandle, OriginalConsoleInfo.dwSize ) || !SetConsoleActiveScreenBuffer( OutputHandle ) || !SetConsoleMode( InputHandle, 0 ) ) { if (OutputHandle != NULL) { CloseHandle( OutputHandle ); OutputHandle = NULL; }
Interactive = FALSE; } else { NormalAttribute = 0x1F; HighlightAttribute = 0x71; NumberOfCols = OriginalConsoleInfo.dwSize.X; NumberOfRows = OriginalConsoleInfo.dwSize.Y; NumberOfDetailLines = NumberOfRows; } } }
NtQuerySystemInformation( SystemBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL );
if (GetPriorityClass(GetCurrentProcess()) == NORMAL_PRIORITY_CLASS) { SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); }
PreviousBuffer = &LargeBuffer2; // NULL at this point
PreviousBufferSize = &LargeBuffer2Size; // 0 at this point
CurrentBuffer = &LargeBuffer1; // NULL at this point
CurrentBufferSize = &LargeBuffer1Size; // 0 at this point
while(TRUE) { Status = NtQuerySystemInformation( SystemPerformanceInformation, &PerfInfo, sizeof(PerfInfo), NULL );
if ( !NT_SUCCESS(Status) ) { printf("Query perf Failed (returned: %lx)\n", Status); break; }
Status = QueryPoolTagInformationIterative( CurrentBuffer, CurrentBufferSize );
if ( !NT_SUCCESS(Status) ) { printf("Query pooltags failed (returned: %lx)\n" "Did you remember to enable pool tagging with gflags.exe and reboot?\n", Status); break; }
//
// Calculate pool tags and display information.
//
//
PoolInfo = (PSYSTEM_POOLTAG_INFORMATION)( *CurrentBuffer ); i = PoolInfo->Count; PoolInfoOld = (PSYSTEM_POOLTAG_INFORMATION)( *PreviousBuffer );
DisplayLine = 0; sprintf( OutputBuffer, " Memory:%8ldK Avail:%8ldK PageFlts:%6ld InRam Krnl:%5ldK P:%5ldK", BasicInfo.NumberOfPhysicalPages*(BasicInfo.PageSize/1024), PerfInfo.AvailablePages*(BasicInfo.PageSize/1024), PerfInfo.PageFaultCount - LastCount, (PerfInfo.ResidentSystemCodePage + PerfInfo.ResidentSystemDriverPage)*(BasicInfo.PageSize/1024), (PerfInfo.ResidentPagedPoolPage)*(BasicInfo.PageSize/1024) ); WriteConsoleLine( OutputHandle, DisplayLine++, OutputBuffer, FALSE );
LastCount = PerfInfo.PageFaultCount; sprintf( OutputBuffer, " Commit:%7ldK Limit:%7ldK Peak:%7ldK Pool N:%5ldK P:%5ldK", PerfInfo.CommittedPages*(BasicInfo.PageSize/1024), PerfInfo.CommitLimit*(BasicInfo.PageSize/1024), PerfInfo.PeakCommitment*(BasicInfo.PageSize/1024), PerfInfo.NonPagedPoolPages*(BasicInfo.PageSize/1024), PerfInfo.PagedPoolPages*(BasicInfo.PageSize/1024) ); WriteConsoleLine( OutputHandle, DisplayLine++, OutputBuffer, FALSE );
WriteConsoleLine( OutputHandle, DisplayLine++, " Tag Type Allocs Frees Diff Bytes Per Alloc", FALSE ); WriteConsoleLine( OutputHandle, DisplayLine++, NULL, FALSE );
Out = &OutBuffer[0]; if (DisplayTotals) { RtlZeroMemory( Totals, sizeof(POOLMON_OUT)*2 ); }
for (i = 0; i < (int)PoolInfo->Count; i++) {
if ( !CheckFilters(&PoolInfo->TagInfo[i]) ) { continue; }
if ((PoolInfo->TagInfo[i].NonPagedAllocs != 0) && (DisplayType != PAGED)) {
Out->Allocs = PoolInfo->TagInfo[i].NonPagedAllocs; Out->Frees = PoolInfo->TagInfo[i].NonPagedFrees; Out->Used = PoolInfo->TagInfo[i].NonPagedUsed; Out->Allocs_Frees = PoolInfo->TagInfo[i].NonPagedAllocs - PoolInfo->TagInfo[i].NonPagedFrees; Out->TagUlong = PoolInfo->TagInfo[i].TagUlong; Out->Type = NONPAGED; Out->Changed = FALSE; Out->NullByte = '\0';
if (PoolInfoOld != NULL && PoolInfoOld->Count > i && PoolInfoOld->TagInfo[i].TagUlong == PoolInfo->TagInfo[i].TagUlong ) { Out->AllocsDiff = PoolInfo->TagInfo[i].NonPagedAllocs - PoolInfoOld->TagInfo[i].NonPagedAllocs; Out->FreesDiff = PoolInfo->TagInfo[i].NonPagedFrees - PoolInfoOld->TagInfo[i].NonPagedFrees; Out->UsedDiff = PoolInfo->TagInfo[i].NonPagedUsed - PoolInfoOld->TagInfo[i].NonPagedUsed; if (Out->AllocsDiff != 0 || Out->FreesDiff != 0 || Out->UsedDiff != 0 ) { Out->Changed = TRUE; } } else { Out->AllocsDiff = 0; Out->UsedDiff = 0; Out->FreesDiff = 0; } Out->Each = Out->Used / (Out->Allocs_Frees?Out->Allocs_Frees:1); if (DisplayTotals) { Totals[NONPAGED].Allocs += Out->Allocs; Totals[NONPAGED].AllocsDiff += Out->AllocsDiff; Totals[NONPAGED].Frees += Out->Frees; Totals[NONPAGED].FreesDiff += Out->FreesDiff; Totals[NONPAGED].Allocs_Frees += Out->Allocs_Frees; Totals[NONPAGED].Used += Out->Used; Totals[NONPAGED].UsedDiff += Out->UsedDiff; } Out += 1; }
if ((PoolInfo->TagInfo[i].PagedAllocs != 0) && (DisplayType != NONPAGED)) {
Out->Allocs = PoolInfo->TagInfo[i].PagedAllocs; Out->Frees = PoolInfo->TagInfo[i].PagedFrees; Out->Used = PoolInfo->TagInfo[i].PagedUsed; Out->Allocs_Frees = PoolInfo->TagInfo[i].PagedAllocs - PoolInfo->TagInfo[i].PagedFrees; Out->TagUlong = PoolInfo->TagInfo[i].TagUlong; Out->Type = PAGED; Out->Changed = FALSE; Out->NullByte = '\0';
if (PoolInfoOld != NULL && PoolInfoOld->Count > i && PoolInfoOld->TagInfo[i].TagUlong == PoolInfo->TagInfo[i].TagUlong ) { Out->AllocsDiff = PoolInfo->TagInfo[i].PagedAllocs - PoolInfoOld->TagInfo[i].PagedAllocs; Out->FreesDiff = PoolInfo->TagInfo[i].PagedFrees - PoolInfoOld->TagInfo[i].PagedFrees; Out->UsedDiff = PoolInfo->TagInfo[i].PagedUsed - PoolInfoOld->TagInfo[i].PagedUsed; if (Out->AllocsDiff != 0 || Out->FreesDiff != 0 || Out->UsedDiff != 0 ) { Out->Changed = TRUE; } } else { Out->AllocsDiff = 0; Out->UsedDiff = 0; Out->FreesDiff = 0; } Out->Each = Out->Used / (Out->Allocs_Frees?Out->Allocs_Frees:1); if (DisplayTotals) { Totals[PAGED].Allocs += Out->Allocs; Totals[PAGED].AllocsDiff += Out->AllocsDiff; Totals[PAGED].Frees += Out->Frees; Totals[PAGED].FreesDiff += Out->FreesDiff; Totals[PAGED].Allocs_Frees += Out->Allocs_Frees; Totals[PAGED].Used += Out->Used; Totals[PAGED].UsedDiff += Out->UsedDiff; } Out += 1; } } //end for
//
// Sort the running working set buffer
//
NumberOfPoolTags = Out - &OutBuffer[0]; qsort((void *)&OutBuffer, (size_t)NumberOfPoolTags, (size_t)sizeof(POOLMON_OUT), ulcomp);
LastDetailRow = (WORD)(NumberOfRows - (DisplayTotals ? (DisplayType == BOTH ? 3 : 2) : 0)); for (i = FirstDetailLine; i < NumberOfPoolTags; i++) { if (DisplayLine >= LastDetailRow) { break; }
sprintf( OutputBuffer, " %4s %5s %9ld (%4ld) %9ld (%4ld) %8ld %7ld (%6ld) %6ld", OutBuffer[i].Tag, PoolType[OutBuffer[i].Type], OutBuffer[i].Allocs, OutBuffer[i].AllocsDiff, OutBuffer[i].Frees, OutBuffer[i].FreesDiff, OutBuffer[i].Allocs_Frees, OutBuffer[i].Used, OutBuffer[i].UsedDiff, OutBuffer[i].Each ); WriteConsoleLine( OutputHandle, DisplayLine++, OutputBuffer, OutBuffer[i].Changed ); OutBuffer[i].Changed = FALSE; }
if (DisplayTotals) { WriteConsoleLine( OutputHandle, DisplayLine++, NULL, FALSE ); for (i = 0; i < 2; i++) { if ( (int)DisplayType == i || DisplayType == BOTH ) { sprintf( OutputBuffer, "Total %5s %9ld (%4ld) %9ld (%4ld) %8ld %7ld (%6ld) %6ld", PoolType[i], Totals[i].Allocs, Totals[i].AllocsDiff, Totals[i].Frees, Totals[i].FreesDiff, Totals[i].Allocs_Frees, Totals[i].Used, Totals[i].UsedDiff, Totals[i].Each ); WriteConsoleLine( OutputHandle, DisplayLine++, OutputBuffer, FALSE ); } } }
TempBuffer = PreviousBuffer; TempBufferSize = PreviousBufferSize;
PreviousBuffer = CurrentBuffer; PreviousBufferSize = CurrentBufferSize;
CurrentBuffer = TempBuffer; CurrentBufferSize = TempBufferSize;
while (WaitForSingleObject( InputHandle, DelayTimeMsec ) == STATUS_WAIT_0) { //
// Check for input record
//
if (ReadConsoleInput( InputHandle, &InputRecord, 1, &NumberOfInputRecords ) && InputRecord.EventType == KEY_EVENT && InputRecord.Event.KeyEvent.bKeyDown ) { LastKey = InputRecord.Event.KeyEvent.uChar.AsciiChar; if (LastKey < ' ') { ScrollDelta = 0; if (LastKey == 'C'-'A'+1) { DoQuit = TRUE; } else switch (InputRecord.Event.KeyEvent.wVirtualKeyCode) { case VK_ESCAPE: DoQuit = TRUE; break;
case VK_PRIOR: ScrollDelta = -(LONG)(InputRecord.Event.KeyEvent.wRepeatCount * NumberOfDetailLines); break;
case VK_NEXT: ScrollDelta = InputRecord.Event.KeyEvent.wRepeatCount * NumberOfDetailLines; break;
case VK_UP: ScrollDelta = -InputRecord.Event.KeyEvent.wRepeatCount; break;
case VK_DOWN: ScrollDelta = InputRecord.Event.KeyEvent.wRepeatCount; break;
case VK_HOME: FirstDetailLine = 0; break;
case VK_END: FirstDetailLine = NumberOfPoolTags - NumberOfDetailLines; break; }
if (ScrollDelta != 0) { if (ScrollDelta < 0) { if (FirstDetailLine <= (ULONG)-ScrollDelta) { FirstDetailLine = 0; } else { FirstDetailLine += ScrollDelta; } } else { FirstDetailLine += ScrollDelta; if (FirstDetailLine >= (NumberOfPoolTags - NumberOfDetailLines)) { FirstDetailLine = NumberOfPoolTags - NumberOfDetailLines; } } } } else { switch (toupper( LastKey )) { case 'Q': //
// Go to the bottom of the current screen when
// we quit.
//
DoQuit = TRUE; break;
case 'T': SortBy = TAG; FirstDetailLine = 0; break;
case 'A': SortBy = ALLOC; FirstDetailLine = 0; break;
case 'U': case 'B': SortBy = BYTES; FirstDetailLine = 0; break;
case 'F': SortBy = FREE; FirstDetailLine = 0; break;
case 'D': SortBy = DIFF; FirstDetailLine = 0; break;
case 'M': SortBy = EACH; FirstDetailLine = 0; break;
case 'L':
NoHighlight = 1 - NoHighlight; break;
case 'P': DisplayType += 1; if (DisplayType > BOTH) { DisplayType = NONPAGED; } FirstDetailLine = 0; break;
case 'X': case '(': case ')':
Paren += 1; break;
case 'E': DisplayTotals = !DisplayTotals; FirstDetailLine = 0; break;
case 'H': case '?': DoHelp = TRUE; break;
} }
break; } }
if (DoQuit) { break; }
if (DoHelp) { DoHelp = FALSE; ShowHelpPopup(); } }
if (Interactive) { SetConsoleActiveScreenBuffer( OriginalOutputHandle ); SetConsoleMode( InputHandle, OriginalInputMode ); CloseHandle( OutputHandle ); }
ExitProcess( 0 ); return 0; }
VOID ShowHelpPopup( VOID ) { HANDLE PopupHandle; WORD n;
PopupHandle = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CONSOLE_TEXTMODE_BUFFER, NULL ); if (PopupHandle == NULL) { return; }
SetConsoleActiveScreenBuffer( PopupHandle );
n = 0;
WriteConsoleLine( PopupHandle, n++, NULL, FALSE ); WriteConsoleLine( PopupHandle, n++, " Poolmon Help", FALSE ); WriteConsoleLine( PopupHandle, n++, NULL, FALSE ); WriteConsoleLine( PopupHandle, n++, " columns:", FALSE ); WriteConsoleLine( PopupHandle, n++, " Tag is the 4 byte tag given to the pool allocation", FALSE ); WriteConsoleLine( PopupHandle, n++, " Type is paged or nonp(aged)", FALSE ); WriteConsoleLine( PopupHandle, n++, " Allocs is count of all alloctions", FALSE ); WriteConsoleLine( PopupHandle, n++, " ( ) is difference in Allocs column from last update", FALSE ); WriteConsoleLine( PopupHandle, n++, " Frees is count of all frees", FALSE ); WriteConsoleLine( PopupHandle, n++, " ( ) difference in Frees column from last update", FALSE ); WriteConsoleLine( PopupHandle, n++, " Diff is (Allocs - Frees)", FALSE ); WriteConsoleLine( PopupHandle, n++, " Bytes is the total bytes consumed in pool", FALSE ); WriteConsoleLine( PopupHandle, n++, " ( ) difference in Bytes column from last update", FALSE ); WriteConsoleLine( PopupHandle, n++, " Per Alloc is (Bytes / Diff)", FALSE ); WriteConsoleLine( PopupHandle, n++, NULL, FALSE ); WriteConsoleLine( PopupHandle, n++, " switches: ", FALSE ); WriteConsoleLine( PopupHandle, n++, " ? or h - gives this help", FALSE ); WriteConsoleLine( PopupHandle, n++, " q - quits", FALSE ); WriteConsoleLine( PopupHandle, n++, " p - toggles default pool display between both, paged, and nonpaged", FALSE ); WriteConsoleLine( PopupHandle, n++, " e - toggles totals lines on and off", FALSE ); WriteConsoleLine( PopupHandle, n++, " l - toggles highlighting of changed lines on and off", FALSE ); WriteConsoleLine( PopupHandle, n++, NULL, FALSE ); WriteConsoleLine( PopupHandle, n++, " sorting switches:", FALSE ); WriteConsoleLine( PopupHandle, n++, " t - tag a - allocations", FALSE ); WriteConsoleLine( PopupHandle, n++, " f - frees d - difference", FALSE ); WriteConsoleLine( PopupHandle, n++, " b - bytes m - per alloc", FALSE ); WriteConsoleLine( PopupHandle, n++, " (u is the same as b)", FALSE ); WriteConsoleLine( PopupHandle, n++, NULL, FALSE ); WriteConsoleLine( PopupHandle, n++, " ) - toggles sort between primary tag and value in ( )", FALSE ); WriteConsoleLine( PopupHandle, n++, NULL, FALSE ); WriteConsoleLine( PopupHandle, n++, " command line switches", FALSE ); WriteConsoleLine( PopupHandle, n++, " -i<tag> - list only matching tags", FALSE ); WriteConsoleLine( PopupHandle, n++, " -x<tag> - list everything except matching tags", FALSE ); WriteConsoleLine( PopupHandle, n++, " <tag> can include * and ?", FALSE ); WriteConsoleLine( PopupHandle, n++, " -peltafdbum) - as listed above", FALSE ); WriteConsoleLine( PopupHandle, n++, NULL, FALSE ); WriteConsoleLine( PopupHandle, n++, NULL, FALSE );
while (TRUE) { if (WaitForSingleObject( InputHandle, DelayTimeMsec ) == STATUS_WAIT_0 && ReadConsoleInput( InputHandle, &InputRecord, 1, &NumberOfInputRecords ) && InputRecord.EventType == KEY_EVENT && InputRecord.Event.KeyEvent.bKeyDown && InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE ) { break; } }
SetConsoleActiveScreenBuffer( OutputHandle ); CloseHandle( PopupHandle ); return; }
|