246 lines
7.1 KiB
C
246 lines
7.1 KiB
C
|
#include <ntos.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <dbghelp.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <wtypes.h>
|
||
|
#include <ntstatus.dbg>
|
||
|
#include <winerror.dbg>
|
||
|
#include <netevent.h>
|
||
|
#include <netevent.dbg>
|
||
|
|
||
|
#define MAX_TYPE_NAMES 32
|
||
|
|
||
|
ULONG NumberOfTypeNames;
|
||
|
UNICODE_STRING TypeNames[ MAX_TYPE_NAMES ];
|
||
|
|
||
|
PCHAR LargeBuffer1[ 8192 ];
|
||
|
|
||
|
ULONG CompareField;
|
||
|
|
||
|
#define SORT_BY_TYPE_NAME 0
|
||
|
#define SORT_BY_OBJECT_COUNT 1
|
||
|
#define SORT_BY_HANDLE_COUNT 2
|
||
|
#define SORT_BY_PAGED_POOL 3
|
||
|
#define SORT_BY_NONPAGED_POOL 4
|
||
|
#define SORT_BY_NAME_USAGE 5
|
||
|
|
||
|
int __cdecl
|
||
|
CompareTypeInfo(
|
||
|
const void *e1,
|
||
|
const void *e2
|
||
|
);
|
||
|
|
||
|
int __cdecl
|
||
|
CompareTypeInfo(
|
||
|
const void *e1,
|
||
|
const void *e2
|
||
|
)
|
||
|
{
|
||
|
POBJECT_TYPE_INFORMATION p1, p2;
|
||
|
|
||
|
p1 = (POBJECT_TYPE_INFORMATION)e1;
|
||
|
p2 = (POBJECT_TYPE_INFORMATION)e2;
|
||
|
|
||
|
switch (CompareField) {
|
||
|
case SORT_BY_TYPE_NAME:
|
||
|
return RtlCompareUnicodeString( &p1->TypeName, &p2->TypeName, TRUE );
|
||
|
|
||
|
case SORT_BY_OBJECT_COUNT:
|
||
|
return p2->TotalNumberOfObjects - p1->TotalNumberOfObjects;
|
||
|
|
||
|
case SORT_BY_HANDLE_COUNT:
|
||
|
return p2->TotalNumberOfHandles - p1->TotalNumberOfHandles;
|
||
|
|
||
|
case SORT_BY_PAGED_POOL:
|
||
|
return p2->TotalPagedPoolUsage - p1->TotalPagedPoolUsage;
|
||
|
|
||
|
case SORT_BY_NONPAGED_POOL:
|
||
|
return p2->TotalNonPagedPoolUsage - p1->TotalNonPagedPoolUsage;
|
||
|
|
||
|
case SORT_BY_NAME_USAGE:
|
||
|
return p2->TotalNamePoolUsage - p1->TotalNamePoolUsage;
|
||
|
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
_cdecl
|
||
|
main(
|
||
|
int argc,
|
||
|
char *argv[]
|
||
|
)
|
||
|
{
|
||
|
BOOL fShowUsage;
|
||
|
ANSI_STRING AnsiString;
|
||
|
PCHAR s;
|
||
|
NTSTATUS Status;
|
||
|
POBJECT_TYPES_INFORMATION TypesInfo;
|
||
|
POBJECT_TYPE_INFORMATION TypeInfo;
|
||
|
POBJECT_TYPE_INFORMATION TypeInfo1;
|
||
|
ULONG Size, i, j;
|
||
|
ULONG Totals[ 8 ];
|
||
|
|
||
|
fShowUsage = FALSE;
|
||
|
CompareField = SORT_BY_TYPE_NAME;
|
||
|
NumberOfTypeNames = 0;
|
||
|
while (--argc) {
|
||
|
s = *++argv;
|
||
|
if (*s == '-' || *s == '/') {
|
||
|
while (*++s) {
|
||
|
switch( toupper( *s ) ) {
|
||
|
case 'C':
|
||
|
CompareField = SORT_BY_OBJECT_COUNT;
|
||
|
break;
|
||
|
|
||
|
case 'H':
|
||
|
CompareField = SORT_BY_HANDLE_COUNT;
|
||
|
break;
|
||
|
|
||
|
case 'P':
|
||
|
CompareField = SORT_BY_PAGED_POOL;
|
||
|
break;
|
||
|
|
||
|
case 'N':
|
||
|
CompareField = SORT_BY_NONPAGED_POOL;
|
||
|
break;
|
||
|
|
||
|
case 'M':
|
||
|
CompareField = SORT_BY_NAME_USAGE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
fprintf( stderr, "OBJMON: Invalid flag - '%c'\n", *s );
|
||
|
|
||
|
case '?':
|
||
|
fShowUsage = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if (fShowUsage) {
|
||
|
break;
|
||
|
}
|
||
|
else {
|
||
|
if (NumberOfTypeNames >= MAX_TYPE_NAMES) {
|
||
|
fprintf( stderr, "OBJMON: Too many type names specified.\n" );
|
||
|
fShowUsage = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
RtlInitAnsiString( &AnsiString, s );
|
||
|
RtlAnsiStringToUnicodeString( &TypeNames[ NumberOfTypeNames++ ],
|
||
|
&AnsiString,
|
||
|
TRUE
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fShowUsage) {
|
||
|
fprintf( stderr, "usage: OBJMON [-h] [Type Names to display]\n" );
|
||
|
fprintf( stderr, "where: -? - displays this help message.\n" );
|
||
|
fprintf( stderr, " -c - sort by number of objects.\n" );
|
||
|
fprintf( stderr, " -h - sort by number of handles.\n" );
|
||
|
fprintf( stderr, " -p - sort by paged pool usage.\n" );
|
||
|
fprintf( stderr, " -n - sort by nonpaged pool usage.\n" );
|
||
|
fprintf( stderr, " -m - sort by object name usage.\n" );
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
TypesInfo = (POBJECT_TYPES_INFORMATION)LargeBuffer1;
|
||
|
|
||
|
Size = sizeof( LargeBuffer1 );
|
||
|
Status = NtQueryObject( NULL,
|
||
|
ObjectTypesInformation,
|
||
|
TypesInfo,
|
||
|
Size,
|
||
|
&Size
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
fprintf( stderr, "OBJMON: Unable to query type information - %x\n", Status );
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
TypeInfo = (POBJECT_TYPE_INFORMATION)malloc( TypesInfo->NumberOfTypes * sizeof( *TypeInfo ) );
|
||
|
TypeInfo1 = (POBJECT_TYPE_INFORMATION)(((PUCHAR)TypesInfo) + ALIGN_UP( sizeof(*TypesInfo), ULONG_PTR ));
|
||
|
for (i=0; i<TypesInfo->NumberOfTypes; i++) {
|
||
|
TypeInfo[ i ] = *TypeInfo1;
|
||
|
TypeInfo1 = (POBJECT_TYPE_INFORMATION)
|
||
|
((PCHAR)TypeInfo1 + sizeof( *TypeInfo1 ) + ALIGN_UP( TypeInfo1->TypeName.MaximumLength, ULONG_PTR ));
|
||
|
}
|
||
|
|
||
|
qsort( (void *)TypeInfo, TypesInfo->NumberOfTypes, sizeof( *TypeInfo ), CompareTypeInfo );
|
||
|
|
||
|
memset( Totals, 0, sizeof( Totals ) );
|
||
|
printf( "Object Type Count Handles\n" );
|
||
|
for (i=0; i<TypesInfo->NumberOfTypes; i++) {
|
||
|
for (j=0; j<NumberOfTypeNames; j++) {
|
||
|
if (RtlEqualUnicodeString( &TypeInfo[ i ].TypeName,
|
||
|
&TypeNames[ j ],
|
||
|
TRUE
|
||
|
)
|
||
|
) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NumberOfTypeNames == 0 || j < NumberOfTypeNames) {
|
||
|
printf( "%-14wZ %5u %7u\n",
|
||
|
&TypeInfo[ i ].TypeName,
|
||
|
TypeInfo[ i ].TotalNumberOfObjects,
|
||
|
TypeInfo[ i ].TotalNumberOfHandles
|
||
|
);
|
||
|
|
||
|
Totals[ 0 ] += TypeInfo[ i ].TotalNumberOfObjects;
|
||
|
Totals[ 1 ] += TypeInfo[ i ].TotalNumberOfHandles;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
printf( "%-14s %5u %7u\n",
|
||
|
"Totals",
|
||
|
Totals[ 0 ],
|
||
|
Totals[ 1 ]
|
||
|
);
|
||
|
|
||
|
memset( Totals, 0, sizeof( Totals ) );
|
||
|
printf( "\n\nHigh Water marks for above totals.\n" );
|
||
|
printf( "Object Type Count Handles\n" );
|
||
|
for (i=0; i<TypesInfo->NumberOfTypes; i++) {
|
||
|
for (j=0; j<NumberOfTypeNames; j++) {
|
||
|
if (RtlEqualUnicodeString( &TypeInfo[ i ].TypeName,
|
||
|
&TypeNames[ j ],
|
||
|
TRUE
|
||
|
)
|
||
|
) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NumberOfTypeNames == 0 || j < NumberOfTypeNames) {
|
||
|
printf( "%-14wZ %5u %7u\n",
|
||
|
&TypeInfo[ i ].TypeName,
|
||
|
TypeInfo[ i ].HighWaterNumberOfObjects,
|
||
|
TypeInfo[ i ].HighWaterNumberOfHandles
|
||
|
);
|
||
|
|
||
|
Totals[ 0 ] += TypeInfo[ i ].HighWaterNumberOfObjects;
|
||
|
Totals[ 1 ] += TypeInfo[ i ].HighWaterNumberOfHandles;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf( "%-14s %5u %7u\n",
|
||
|
"Totals",
|
||
|
Totals[ 0 ],
|
||
|
Totals[ 1 ]
|
||
|
);
|
||
|
|
||
|
return 0;
|
||
|
}
|