822 lines
22 KiB
C
822 lines
22 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1991 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
pstat.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains the Windows NT process/thread status display.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Lou Perazzoli (LouP) 25-Oct-1991
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <assert.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
#include <time.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#define BUFFER_SIZE 64*1024
|
||
|
#define MAX_BUFFER_SIZE 10*1024*1024
|
||
|
|
||
|
VOID
|
||
|
PrintLoadedDrivers(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
ULONG CurrentBufferSize;
|
||
|
|
||
|
UCHAR *StateTable[] = {
|
||
|
"Initialized",
|
||
|
"Ready",
|
||
|
"Running",
|
||
|
"Standby",
|
||
|
"Terminated",
|
||
|
"Wait:",
|
||
|
"Transition",
|
||
|
"Unknown",
|
||
|
"Unknown",
|
||
|
"Unknown",
|
||
|
"Unknown",
|
||
|
"Unknown"
|
||
|
};
|
||
|
|
||
|
UCHAR *WaitTable[] = {
|
||
|
"Executive",
|
||
|
"FreePage",
|
||
|
"PageIn",
|
||
|
"PoolAllocation",
|
||
|
"DelayExecution",
|
||
|
"Suspended",
|
||
|
"UserRequest",
|
||
|
"Executive",
|
||
|
"FreePage",
|
||
|
"PageIn",
|
||
|
"PoolAllocation",
|
||
|
"DelayExecution",
|
||
|
"Suspended",
|
||
|
"UserRequest",
|
||
|
"EventPairHigh",
|
||
|
"EventPairLow",
|
||
|
"LpcReceive",
|
||
|
"LpcReply",
|
||
|
"VirtualMemory",
|
||
|
"PageOut",
|
||
|
"Spare1",
|
||
|
"Spare2",
|
||
|
"Spare3",
|
||
|
"Spare4",
|
||
|
"Spare5",
|
||
|
"Spare6",
|
||
|
"Spare7",
|
||
|
"Unknown",
|
||
|
"Unknown",
|
||
|
"Unknown"
|
||
|
};
|
||
|
|
||
|
UCHAR *Empty = " ";
|
||
|
|
||
|
BOOLEAN fUserOnly = TRUE;
|
||
|
BOOLEAN fSystemOnly = TRUE;
|
||
|
BOOLEAN fVerbose = FALSE;
|
||
|
BOOLEAN fPrintIt;
|
||
|
|
||
|
int
|
||
|
__cdecl
|
||
|
main(
|
||
|
int argc,
|
||
|
char *argv[]
|
||
|
)
|
||
|
{
|
||
|
|
||
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
|
||
|
PSYSTEM_THREAD_INFORMATION ThreadInfo;
|
||
|
PUCHAR LargeBuffer1;
|
||
|
NTSTATUS status;
|
||
|
NTSTATUS Status;
|
||
|
ULONG i;
|
||
|
ULONG TotalOffset = 0;
|
||
|
TIME_FIELDS UserTime;
|
||
|
TIME_FIELDS KernelTime;
|
||
|
TIME_FIELDS UpTime;
|
||
|
SYSTEM_BASIC_INFORMATION BasicInfo;
|
||
|
SYSTEM_TIMEOFDAY_INFORMATION TimeOfDayInfo;
|
||
|
PSYSTEM_PAGEFILE_INFORMATION PageFileInfo;
|
||
|
LARGE_INTEGER Time;
|
||
|
LPSTR lpstrCmd;
|
||
|
CHAR ch;
|
||
|
ANSI_STRING pname;
|
||
|
SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
|
||
|
SYSTEM_FILECACHE_INFORMATION FileCache;
|
||
|
SIZE_T SumCommit;
|
||
|
SIZE_T SumWorkingSet;
|
||
|
|
||
|
SetFileApisToOEM();
|
||
|
lpstrCmd = GetCommandLine();
|
||
|
if( lpstrCmd != NULL ) {
|
||
|
CharToOem( lpstrCmd, lpstrCmd );
|
||
|
}
|
||
|
|
||
|
|
||
|
LargeBuffer1 = VirtualAlloc (NULL,
|
||
|
MAX_BUFFER_SIZE,
|
||
|
MEM_RESERVE,
|
||
|
PAGE_READWRITE);
|
||
|
if (LargeBuffer1 == NULL) {
|
||
|
printf("Memory allocation failed\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (VirtualAlloc (LargeBuffer1,
|
||
|
BUFFER_SIZE,
|
||
|
MEM_COMMIT,
|
||
|
PAGE_READWRITE) == NULL) {
|
||
|
printf("Memory commit failed\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
CurrentBufferSize = BUFFER_SIZE;
|
||
|
|
||
|
do
|
||
|
ch = *lpstrCmd++;
|
||
|
while (ch != ' ' && ch != '\t' && ch != '\0');
|
||
|
while (ch == ' ' || ch == '\t')
|
||
|
ch = *lpstrCmd++;
|
||
|
while (ch == '-') {
|
||
|
ch = *lpstrCmd++;
|
||
|
|
||
|
// process multiple switch characters as needed
|
||
|
|
||
|
do {
|
||
|
switch (ch) {
|
||
|
|
||
|
case 'U':
|
||
|
case 'u':
|
||
|
fUserOnly = TRUE;
|
||
|
fSystemOnly = FALSE;
|
||
|
ch = *lpstrCmd++;
|
||
|
break;
|
||
|
|
||
|
case 'S':
|
||
|
case 's':
|
||
|
fUserOnly = FALSE;
|
||
|
fSystemOnly = TRUE;
|
||
|
ch = *lpstrCmd++;
|
||
|
break;
|
||
|
|
||
|
case 'V':
|
||
|
case 'v':
|
||
|
fVerbose = TRUE;
|
||
|
ch = *lpstrCmd++;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("bad switch '%c'\n", ch);
|
||
|
ExitProcess(1);
|
||
|
}
|
||
|
}
|
||
|
while (ch != ' ' && ch != '\t' && ch != '\0');
|
||
|
|
||
|
// skip over any following white space
|
||
|
|
||
|
while (ch == ' ' || ch == '\t')
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
|
||
|
|
||
|
status = NtQuerySystemInformation(
|
||
|
SystemBasicInformation,
|
||
|
&BasicInfo,
|
||
|
sizeof(SYSTEM_BASIC_INFORMATION),
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
printf("Query info failed %lx\n",status);
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
status = NtQuerySystemInformation(
|
||
|
SystemTimeOfDayInformation,
|
||
|
&TimeOfDayInfo,
|
||
|
sizeof(SYSTEM_TIMEOFDAY_INFORMATION),
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
printf("Query info failed %lx\n",status);
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
Time.QuadPart = TimeOfDayInfo.CurrentTime.QuadPart -
|
||
|
TimeOfDayInfo.BootTime.QuadPart;
|
||
|
|
||
|
RtlTimeToElapsedTimeFields ( &Time, &UpTime);
|
||
|
|
||
|
printf("Pstat version 0.3: memory: %4ld kb uptime:%3ld %2ld:%02ld:%02ld.%03ld \n\n",
|
||
|
BasicInfo.NumberOfPhysicalPages * (BasicInfo.PageSize/1024),
|
||
|
UpTime.Day,
|
||
|
UpTime.Hour,
|
||
|
UpTime.Minute,
|
||
|
UpTime.Second,
|
||
|
UpTime.Milliseconds);
|
||
|
|
||
|
PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)LargeBuffer1;
|
||
|
status = NtQuerySystemInformation(
|
||
|
SystemPageFileInformation,
|
||
|
PageFileInfo,
|
||
|
CurrentBufferSize,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS(status)) {
|
||
|
|
||
|
//
|
||
|
// Print out the page file information.
|
||
|
//
|
||
|
|
||
|
if (PageFileInfo->TotalSize == 0) {
|
||
|
printf("no page files in use\n");
|
||
|
} else {
|
||
|
for (; ; ) {
|
||
|
printf("PageFile: %wZ\n", &PageFileInfo->PageFileName);
|
||
|
printf("\tCurrent Size: %6ld kb Total Used: %6ld kb Peak Used %6ld kb\n",
|
||
|
PageFileInfo->TotalSize*(BasicInfo.PageSize/1024),
|
||
|
PageFileInfo->TotalInUse*(BasicInfo.PageSize/1024),
|
||
|
PageFileInfo->PeakUsage*(BasicInfo.PageSize/1024));
|
||
|
if (PageFileInfo->NextEntryOffset == 0) {
|
||
|
break;
|
||
|
}
|
||
|
PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)(
|
||
|
(PCHAR)PageFileInfo + PageFileInfo->NextEntryOffset);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
retry:
|
||
|
status = NtQuerySystemInformation(
|
||
|
SystemProcessInformation,
|
||
|
LargeBuffer1,
|
||
|
CurrentBufferSize,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (status == STATUS_INFO_LENGTH_MISMATCH) {
|
||
|
|
||
|
//
|
||
|
// Increase buffer size.
|
||
|
//
|
||
|
|
||
|
CurrentBufferSize += 8192;
|
||
|
|
||
|
if (VirtualAlloc (LargeBuffer1,
|
||
|
CurrentBufferSize,
|
||
|
MEM_COMMIT,
|
||
|
PAGE_READWRITE) == NULL) {
|
||
|
printf("Memory commit failed\n");
|
||
|
return 0;
|
||
|
}
|
||
|
goto retry;
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
printf("Query info failed %lx\n",status);
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// display pmon style process output, then detailed output that includes
|
||
|
// per thread stuff
|
||
|
//
|
||
|
|
||
|
TotalOffset = 0;
|
||
|
SumCommit = 0;
|
||
|
SumWorkingSet = 0;
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
||
|
while (TRUE) {
|
||
|
SumCommit += ProcessInfo->PrivatePageCount / 1024;
|
||
|
SumWorkingSet += ProcessInfo->WorkingSetSize / 1024;
|
||
|
if (ProcessInfo->NextEntryOffset == 0) {
|
||
|
break;
|
||
|
}
|
||
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
||
|
}
|
||
|
|
||
|
Status = NtQuerySystemInformation(
|
||
|
SystemPerformanceInformation,
|
||
|
&PerfInfo,
|
||
|
sizeof(PerfInfo),
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if ( !NT_SUCCESS(Status) ) {
|
||
|
printf("Query perf Failed %lx\n",Status);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Status = NtQuerySystemInformation(
|
||
|
SystemFileCacheInformation,
|
||
|
&FileCache,
|
||
|
sizeof(FileCache),
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if ( !NT_SUCCESS(Status) ) {
|
||
|
printf("Query file cache Failed %lx\n",Status);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
NtQuerySystemInformation(
|
||
|
SystemBasicInformation,
|
||
|
&BasicInfo,
|
||
|
sizeof(BasicInfo),
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
SumWorkingSet += FileCache.CurrentSize/1024;
|
||
|
printf (
|
||
|
"\n Memory:%7ldK Avail:%7ldK TotalWs:%7ldK InRam Kernel:%5ldK P:%5ldK\n",
|
||
|
BasicInfo.NumberOfPhysicalPages*(BasicInfo.PageSize/1024),
|
||
|
PerfInfo.AvailablePages*(BasicInfo.PageSize/1024),
|
||
|
SumWorkingSet,
|
||
|
(PerfInfo.ResidentSystemCodePage + PerfInfo.ResidentSystemDriverPage)*(BasicInfo.PageSize/1024),
|
||
|
(PerfInfo.ResidentPagedPoolPage)*(BasicInfo.PageSize/1024)
|
||
|
);
|
||
|
printf(
|
||
|
" Commit:%7ldK/%7ldK Limit:%7ldK Peak:%7ldK Pool N:%5ldK P:%5ldK\n",
|
||
|
PerfInfo.CommittedPages*(BasicInfo.PageSize/1024),
|
||
|
SumCommit,
|
||
|
PerfInfo.CommitLimit*(BasicInfo.PageSize/1024),
|
||
|
PerfInfo.PeakCommitment*(BasicInfo.PageSize/1024),
|
||
|
PerfInfo.NonPagedPoolPages*(BasicInfo.PageSize/1024),
|
||
|
PerfInfo.PagedPoolPages*(BasicInfo.PageSize/1024)
|
||
|
);
|
||
|
TotalOffset = 0;
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
||
|
printf("\n");
|
||
|
|
||
|
|
||
|
printf(" User Time Kernel Time Ws Faults Commit Pri Hnd Thd Pid Name\n");
|
||
|
|
||
|
printf(" %6ld %8ld %s\n",
|
||
|
FileCache.CurrentSize/1024,
|
||
|
FileCache.PageFaultCount,
|
||
|
"File Cache"
|
||
|
);
|
||
|
while (TRUE) {
|
||
|
|
||
|
pname.Buffer = NULL;
|
||
|
if ( ProcessInfo->ImageName.Buffer ) {
|
||
|
RtlUnicodeStringToAnsiString(&pname,(PUNICODE_STRING)&ProcessInfo->ImageName,TRUE);
|
||
|
}
|
||
|
|
||
|
RtlTimeToElapsedTimeFields ( &ProcessInfo->UserTime, &UserTime);
|
||
|
RtlTimeToElapsedTimeFields ( &ProcessInfo->KernelTime, &KernelTime);
|
||
|
|
||
|
printf("%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
|
||
|
UserTime.Hour,
|
||
|
UserTime.Minute,
|
||
|
UserTime.Second,
|
||
|
UserTime.Milliseconds,
|
||
|
KernelTime.Hour,
|
||
|
KernelTime.Minute,
|
||
|
KernelTime.Second,
|
||
|
KernelTime.Milliseconds
|
||
|
);
|
||
|
|
||
|
printf("%6ld %8ld %7ld",
|
||
|
ProcessInfo->WorkingSetSize / 1024,
|
||
|
ProcessInfo->PageFaultCount,
|
||
|
ProcessInfo->PrivatePageCount / 1024
|
||
|
);
|
||
|
|
||
|
printf(" %2ld %4ld %3ld %3ld %s\n",
|
||
|
ProcessInfo->BasePriority,
|
||
|
ProcessInfo->HandleCount,
|
||
|
ProcessInfo->NumberOfThreads,
|
||
|
HandleToUlong(ProcessInfo->UniqueProcessId),
|
||
|
ProcessInfo->UniqueProcessId == 0 ? "Idle Process" : (
|
||
|
ProcessInfo->ImageName.Buffer ? pname.Buffer : "System")
|
||
|
);
|
||
|
|
||
|
if ( pname.Buffer ) {
|
||
|
RtlFreeAnsiString(&pname);
|
||
|
}
|
||
|
|
||
|
if (ProcessInfo->NextEntryOffset == 0) {
|
||
|
break;
|
||
|
}
|
||
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Beginning of normal old style pstat output
|
||
|
//
|
||
|
|
||
|
TotalOffset = 0;
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)LargeBuffer1;
|
||
|
printf("\n");
|
||
|
while (TRUE) {
|
||
|
fPrintIt = FALSE;
|
||
|
if ( (ProcessInfo->ImageName.Buffer && fUserOnly) ||
|
||
|
(ProcessInfo->ImageName.Buffer==NULL && fSystemOnly) ) {
|
||
|
|
||
|
fPrintIt = TRUE;
|
||
|
|
||
|
pname.Buffer = NULL;
|
||
|
if ( ProcessInfo->ImageName.Buffer ) {
|
||
|
RtlUnicodeStringToAnsiString(&pname,(PUNICODE_STRING)&ProcessInfo->ImageName,TRUE);
|
||
|
}
|
||
|
printf("pid:%3lx pri:%2ld Hnd:%5ld Pf:%7ld Ws:%7ldK %s\n",
|
||
|
HandleToUlong(ProcessInfo->UniqueProcessId),
|
||
|
ProcessInfo->BasePriority,
|
||
|
ProcessInfo->HandleCount,
|
||
|
ProcessInfo->PageFaultCount,
|
||
|
ProcessInfo->WorkingSetSize / 1024,
|
||
|
ProcessInfo->UniqueProcessId == 0 ? "Idle Process" : (
|
||
|
ProcessInfo->ImageName.Buffer ? pname.Buffer : "System")
|
||
|
);
|
||
|
|
||
|
if ( pname.Buffer ) {
|
||
|
RtlFreeAnsiString(&pname);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
i = 0;
|
||
|
ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
|
||
|
if (ProcessInfo->NumberOfThreads) {
|
||
|
printf(" tid pri Ctx Swtch StrtAddr User Time Kernel Time State\n");
|
||
|
}
|
||
|
while (i < ProcessInfo->NumberOfThreads) {
|
||
|
RtlTimeToElapsedTimeFields ( &ThreadInfo->UserTime, &UserTime);
|
||
|
|
||
|
RtlTimeToElapsedTimeFields ( &ThreadInfo->KernelTime, &KernelTime);
|
||
|
if ( fPrintIt ) {
|
||
|
|
||
|
printf(" %3lx %2ld %9ld %p",
|
||
|
ProcessInfo->UniqueProcessId == 0 ? 0 : HandleToUlong(ThreadInfo->ClientId.UniqueThread),
|
||
|
ProcessInfo->UniqueProcessId == 0 ? 0 : ThreadInfo->Priority,
|
||
|
ThreadInfo->ContextSwitches,
|
||
|
ProcessInfo->UniqueProcessId == 0 ? 0 : ThreadInfo->StartAddress
|
||
|
);
|
||
|
|
||
|
printf(" %2ld:%02ld:%02ld.%03ld %2ld:%02ld:%02ld.%03ld",
|
||
|
UserTime.Hour,
|
||
|
UserTime.Minute,
|
||
|
UserTime.Second,
|
||
|
UserTime.Milliseconds,
|
||
|
KernelTime.Hour,
|
||
|
KernelTime.Minute,
|
||
|
KernelTime.Second,
|
||
|
KernelTime.Milliseconds
|
||
|
);
|
||
|
|
||
|
printf(" %s%s\n",
|
||
|
StateTable[ThreadInfo->ThreadState],
|
||
|
(ThreadInfo->ThreadState == 5) ?
|
||
|
WaitTable[ThreadInfo->WaitReason] : Empty
|
||
|
);
|
||
|
}
|
||
|
ThreadInfo += 1;
|
||
|
i += 1;
|
||
|
}
|
||
|
if (ProcessInfo->NextEntryOffset == 0) {
|
||
|
break;
|
||
|
}
|
||
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
|
||
|
if ( fPrintIt ) {
|
||
|
printf("\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PrintLoadedDrivers();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
typedef struct _MODULE_DATA {
|
||
|
ULONG CodeSize;
|
||
|
ULONG DataSize;
|
||
|
ULONG BssSize;
|
||
|
ULONG RoDataSize;
|
||
|
ULONG ImportDataSize;
|
||
|
ULONG ExportDataSize;
|
||
|
ULONG ResourceDataSize;
|
||
|
ULONG PagedSize;
|
||
|
ULONG InitSize;
|
||
|
ULONG CheckSum;
|
||
|
ULONG TimeDateStamp;
|
||
|
} MODULE_DATA, *PMODULE_DATA;
|
||
|
|
||
|
typedef struct _LOADED_IMAGE {
|
||
|
PUCHAR MappedAddress;
|
||
|
PIMAGE_NT_HEADERS FileHeader;
|
||
|
PIMAGE_SECTION_HEADER LastRvaSection;
|
||
|
int NumberOfSections;
|
||
|
PIMAGE_SECTION_HEADER Sections;
|
||
|
} LOADED_IMAGE, *PLOADED_IMAGE;
|
||
|
|
||
|
|
||
|
VOID
|
||
|
SumModuleData(
|
||
|
PMODULE_DATA Sum,
|
||
|
PMODULE_DATA Current
|
||
|
)
|
||
|
{
|
||
|
Sum->CodeSize += Current->CodeSize;
|
||
|
Sum->DataSize += Current->DataSize;
|
||
|
Sum->BssSize += Current->BssSize;
|
||
|
Sum->RoDataSize += Current->RoDataSize;
|
||
|
Sum->ImportDataSize += Current->ImportDataSize;
|
||
|
Sum->ExportDataSize += Current->ExportDataSize;
|
||
|
Sum->ResourceDataSize += Current->ResourceDataSize;
|
||
|
Sum->PagedSize += Current->PagedSize;
|
||
|
Sum->InitSize += Current->InitSize;
|
||
|
}
|
||
|
VOID
|
||
|
PrintModuleSeperator(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
printf("------------------------------------------------------------------------------\n");
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PrintModuleHeader(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
printf(" ModuleName Load Addr Code Data Paged LinkDate\n");
|
||
|
PrintModuleSeperator();
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PrintModuleLine(
|
||
|
LPSTR ModuleName,
|
||
|
PMODULE_DATA Current,
|
||
|
PRTL_PROCESS_MODULE_INFORMATION Module
|
||
|
)
|
||
|
{
|
||
|
if ( Module ) {
|
||
|
printf("%12s %p %7d %7d %7d %s",
|
||
|
ModuleName,
|
||
|
Module->ImageBase,
|
||
|
Current->CodeSize,
|
||
|
Current->DataSize,
|
||
|
Current->PagedSize,
|
||
|
Current->TimeDateStamp ? ctime((time_t *)&Current->TimeDateStamp) : "\n"
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
printf("%12s %7d %7d %7d\n",
|
||
|
ModuleName,
|
||
|
Current->CodeSize,
|
||
|
Current->DataSize,
|
||
|
Current->PagedSize
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
GetModuleData(
|
||
|
HANDLE hFile,
|
||
|
PMODULE_DATA Mod
|
||
|
)
|
||
|
{
|
||
|
HANDLE hMappedFile;
|
||
|
PIMAGE_DOS_HEADER DosHeader;
|
||
|
LOADED_IMAGE LoadedImage;
|
||
|
ULONG SectionAlignment;
|
||
|
PIMAGE_SECTION_HEADER Section;
|
||
|
int i;
|
||
|
ULONG Size;
|
||
|
|
||
|
hMappedFile = CreateFileMapping(
|
||
|
hFile,
|
||
|
NULL,
|
||
|
PAGE_READONLY,
|
||
|
0,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
if ( !hMappedFile ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LoadedImage.MappedAddress = MapViewOfFile(
|
||
|
hMappedFile,
|
||
|
FILE_MAP_READ,
|
||
|
0,
|
||
|
0,
|
||
|
0
|
||
|
);
|
||
|
CloseHandle(hMappedFile);
|
||
|
|
||
|
if ( !LoadedImage.MappedAddress ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Everything is mapped. Now check the image and find nt image headers
|
||
|
//
|
||
|
|
||
|
DosHeader = (PIMAGE_DOS_HEADER)LoadedImage.MappedAddress;
|
||
|
|
||
|
if ( DosHeader->e_magic != IMAGE_DOS_SIGNATURE ) {
|
||
|
UnmapViewOfFile(LoadedImage.MappedAddress);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LoadedImage.FileHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew);
|
||
|
|
||
|
if ( LoadedImage.FileHeader->Signature != IMAGE_NT_SIGNATURE ) {
|
||
|
UnmapViewOfFile(LoadedImage.MappedAddress);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LoadedImage.NumberOfSections = LoadedImage.FileHeader->FileHeader.NumberOfSections;
|
||
|
LoadedImage.Sections = (PIMAGE_SECTION_HEADER)((ULONG_PTR)LoadedImage.FileHeader + sizeof(IMAGE_NT_HEADERS));
|
||
|
LoadedImage.LastRvaSection = LoadedImage.Sections;
|
||
|
|
||
|
//
|
||
|
// Walk through the sections and tally the dater
|
||
|
//
|
||
|
|
||
|
SectionAlignment = LoadedImage.FileHeader->OptionalHeader.SectionAlignment;
|
||
|
|
||
|
for(Section = LoadedImage.Sections,i=0; i<LoadedImage.NumberOfSections; i++,Section++) {
|
||
|
Size = Section->Misc.VirtualSize;
|
||
|
|
||
|
if (Size == 0) {
|
||
|
Size = Section->SizeOfRawData;
|
||
|
}
|
||
|
|
||
|
Size = (Size + SectionAlignment - 1) & ~(SectionAlignment - 1);
|
||
|
|
||
|
if (!_strnicmp(Section->Name,"PAGE", 4 )) {
|
||
|
Mod->PagedSize += Size;
|
||
|
}
|
||
|
else if (!_stricmp(Section->Name,"INIT" )) {
|
||
|
Mod->InitSize += Size;
|
||
|
}
|
||
|
else if (!_stricmp(Section->Name,".bss" )) {
|
||
|
Mod->BssSize = Size;
|
||
|
}
|
||
|
else if (!_stricmp(Section->Name,".edata" )) {
|
||
|
Mod->ExportDataSize = Size;
|
||
|
}
|
||
|
else if (!_stricmp(Section->Name,".idata" )) {
|
||
|
Mod->ImportDataSize = Size;
|
||
|
}
|
||
|
else if (!_stricmp(Section->Name,".rsrc" )) {
|
||
|
Mod->ResourceDataSize = Size;
|
||
|
}
|
||
|
else if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
|
||
|
Mod->CodeSize += Size;
|
||
|
}
|
||
|
else if (Section->Characteristics & IMAGE_SCN_MEM_WRITE) {
|
||
|
Mod->DataSize += Size;
|
||
|
}
|
||
|
else if (Section->Characteristics & IMAGE_SCN_MEM_READ) {
|
||
|
Mod->RoDataSize += Size;
|
||
|
}
|
||
|
else {
|
||
|
Mod->DataSize += Size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Mod->CheckSum = LoadedImage.FileHeader->OptionalHeader.CheckSum;
|
||
|
Mod->TimeDateStamp = LoadedImage.FileHeader->FileHeader.TimeDateStamp;
|
||
|
|
||
|
UnmapViewOfFile(LoadedImage.MappedAddress);
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PrintLoadedDrivers(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
|
||
|
ULONG i;
|
||
|
PCHAR s;
|
||
|
HANDLE FileHandle;
|
||
|
CHAR KernelPath[MAX_PATH];
|
||
|
CHAR DriversPath[MAX_PATH];
|
||
|
PCHAR ModuleInfo;
|
||
|
ULONG ModuleInfoLength;
|
||
|
ULONG ReturnedLength;
|
||
|
PRTL_PROCESS_MODULES Modules;
|
||
|
PRTL_PROCESS_MODULE_INFORMATION Module;
|
||
|
NTSTATUS Status;
|
||
|
MODULE_DATA Sum;
|
||
|
MODULE_DATA Current;
|
||
|
|
||
|
printf("\n");
|
||
|
//
|
||
|
// Locate system drivers.
|
||
|
//
|
||
|
|
||
|
ModuleInfoLength = 64000;
|
||
|
while (1) {
|
||
|
ModuleInfo = malloc (ModuleInfoLength);
|
||
|
if (ModuleInfo == NULL) {
|
||
|
printf ("Failed to allocate memory for module information buffer of size %d\n",
|
||
|
ModuleInfoLength);
|
||
|
return;
|
||
|
}
|
||
|
Status = NtQuerySystemInformation (
|
||
|
SystemModuleInformation,
|
||
|
ModuleInfo,
|
||
|
ModuleInfoLength,
|
||
|
&ReturnedLength);
|
||
|
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
free (ModuleInfo);
|
||
|
if (Status == STATUS_INFO_LENGTH_MISMATCH &&
|
||
|
ReturnedLength > ModuleInfoLength) {
|
||
|
ModuleInfoLength = ReturnedLength;
|
||
|
continue;
|
||
|
}
|
||
|
printf("query system info failed status - %lx\n",Status);
|
||
|
return;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
GetSystemDirectory(KernelPath,sizeof(KernelPath));
|
||
|
strcpy(DriversPath,KernelPath);
|
||
|
strcat(DriversPath,"\\Drivers");
|
||
|
ZeroMemory(&Sum,sizeof(Sum));
|
||
|
PrintModuleHeader();
|
||
|
|
||
|
Modules = (PRTL_PROCESS_MODULES)ModuleInfo;
|
||
|
Module = &Modules->Modules[ 0 ];
|
||
|
for (i=0; i<Modules->NumberOfModules; i++) {
|
||
|
|
||
|
ZeroMemory(&Current,sizeof(Current));
|
||
|
s = &Module->FullPathName[ Module->OffsetToFileName ];
|
||
|
|
||
|
//
|
||
|
// try to open the file
|
||
|
//
|
||
|
|
||
|
SetCurrentDirectory(KernelPath);
|
||
|
|
||
|
FileHandle = CreateFile(
|
||
|
s,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if ( FileHandle == INVALID_HANDLE_VALUE ) {
|
||
|
SetCurrentDirectory(DriversPath);
|
||
|
|
||
|
FileHandle = CreateFile(
|
||
|
s,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( FileHandle != INVALID_HANDLE_VALUE ) {
|
||
|
GetModuleData(FileHandle,&Current);
|
||
|
CloseHandle(FileHandle);
|
||
|
}
|
||
|
|
||
|
SumModuleData(&Sum,&Current);
|
||
|
PrintModuleLine(s,&Current,Module);
|
||
|
Module++;
|
||
|
}
|
||
|
PrintModuleSeperator();
|
||
|
PrintModuleLine("Total",&Sum,NULL);
|
||
|
free (ModuleInfo);
|
||
|
}
|