mirror of https://github.com/lianthony/NT4.0
378 lines
9.7 KiB
378 lines
9.7 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
driver.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 15-Aug-1993
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include <time.h>
|
|
|
|
VOID
|
|
DumpDriver(
|
|
PVOID DriverAddress,
|
|
BOOLEAN FullDetail
|
|
);
|
|
|
|
VOID
|
|
DumpImage(
|
|
ULONG Base,
|
|
BOOL DoHeaders,
|
|
BOOL DoSections
|
|
);
|
|
|
|
|
|
|
|
DECLARE_API( drvobj )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a driver object.
|
|
|
|
Arguments:
|
|
|
|
args - the location of the driver object to dump.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG deviceToDump;
|
|
|
|
sscanf(args, "%lx", &deviceToDump);
|
|
dprintf("Driver object is for:\n");
|
|
DumpDriver((PVOID) deviceToDump, TRUE);
|
|
}
|
|
|
|
VOID
|
|
DumpDriver(
|
|
PVOID DriverAddress,
|
|
BOOLEAN FullDetail
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays the driver name and the list of device objects created by
|
|
the driver.
|
|
|
|
Arguments:
|
|
|
|
DriverAddress - addres of the driver object to dump.
|
|
FullDetail - if TRUE give the list of device objects owned by the driver.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
DRIVER_OBJECT driverObject;
|
|
ULONG result;
|
|
ULONG i;
|
|
PUCHAR buffer;
|
|
PVOID deviceAddress;
|
|
DEVICE_OBJECT deviceObject;
|
|
UNICODE_STRING unicodeString;
|
|
|
|
if ((!ReadMemory( (DWORD) DriverAddress,
|
|
&driverObject,
|
|
sizeof(driverObject),
|
|
&result)) || result < sizeof(driverObject)) {
|
|
return;
|
|
}
|
|
|
|
if (driverObject.Type != IO_TYPE_DRIVER) {
|
|
dprintf("%08lx: is not a driver object\n", DriverAddress);
|
|
return;
|
|
}
|
|
|
|
buffer = LocalAlloc(LPTR, driverObject.DriverName.MaximumLength);
|
|
if (buffer == NULL) {
|
|
dprintf("Could not allocate %d bytes\n",
|
|
driverObject.DriverName.MaximumLength);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// This memory may be paged out.
|
|
//
|
|
|
|
unicodeString.Buffer = (PWSTR)buffer;
|
|
unicodeString.Length = driverObject.DriverName.Length;
|
|
unicodeString.MaximumLength = driverObject.DriverName.MaximumLength;
|
|
|
|
if (!ReadMemory( (DWORD) driverObject.DriverName.Buffer,
|
|
buffer,
|
|
driverObject.DriverName.MaximumLength,
|
|
&result )) {
|
|
dprintf(" Name paged out");
|
|
} else {
|
|
dprintf(" %wZ", &unicodeString);
|
|
}
|
|
LocalFree(buffer);
|
|
|
|
if (FullDetail == TRUE) {
|
|
dprintf("\n");
|
|
dprintf("Device Object list:\n");
|
|
|
|
deviceAddress = driverObject.DeviceObject;
|
|
|
|
for (i= 0; deviceAddress != NULL; i++) {
|
|
|
|
if ((!ReadMemory( (DWORD)deviceAddress,
|
|
&deviceObject,
|
|
sizeof(deviceObject),
|
|
&result) ) || result < sizeof(deviceObject)) {
|
|
dprintf("%08lx: Could not read device object\n", deviceAddress);
|
|
return;
|
|
}
|
|
|
|
dprintf("%08lx%s", deviceAddress, ((i & 0x03) == 0x03) ? "\n" : " ");
|
|
deviceAddress = deviceObject.NextDevice;
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
|
|
UCHAR *PagedOut = {"Header Paged Out"};
|
|
|
|
DECLARE_API( drivers )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays physical memory usage by driver.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
LIST_ENTRY List;
|
|
PLIST_ENTRY Next;
|
|
ULONG ListHead;
|
|
NTSTATUS Status = 0;
|
|
ULONG Result;
|
|
PLDR_DATA_TABLE_ENTRY DataTable;
|
|
LDR_DATA_TABLE_ENTRY DataTableBuffer;
|
|
WCHAR UnicodeBuffer[128];
|
|
UNICODE_STRING BaseName;
|
|
PIMAGE_NT_HEADERS NtHeader;
|
|
PIMAGE_DOS_HEADER DosHeader;
|
|
ULONG SizeOfData;
|
|
ULONG SizeOfCode;
|
|
ULONG TotalCode = 0;
|
|
ULONG TotalData = 0;
|
|
ULONG TotalValid = 0;
|
|
ULONG TotalTransition = 0;
|
|
ULONG DosHeaderSize;
|
|
ULONG TimeDateStamp;
|
|
PUCHAR time;
|
|
ULONG Flags;
|
|
|
|
Flags = 0;
|
|
sscanf(args,"%lx",&Flags);
|
|
|
|
ListHead = GetExpression( "PsLoadedModuleList" );
|
|
|
|
if (!ListHead) {
|
|
dprintf("Couldn't get offset of PsLoadedModuleListHead\n");
|
|
return;
|
|
} else {
|
|
if ((!ReadMemory((DWORD)ListHead,
|
|
&List,
|
|
sizeof(LIST_ENTRY),
|
|
&Result)) || (Result < sizeof(LIST_ENTRY))) {
|
|
dprintf("Unable to get value of PsLoadedModuleListHead\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
dprintf("Loaded System Driver Summary\n\n");
|
|
if (Flags & 1) {
|
|
dprintf("Base Code Size Data Size Resident Standby Driver Name\n");
|
|
} else {
|
|
dprintf("Base Code Size Data Size Driver Name Creation Time\n");
|
|
}
|
|
|
|
Next = List.Flink;
|
|
if (Next == NULL) {
|
|
dprintf("PsLoadedModuleList is NULL!\n");
|
|
return;
|
|
}
|
|
|
|
while ((ULONG)Next != ListHead) {
|
|
if (CheckControlC()) {
|
|
return;
|
|
}
|
|
DataTable = CONTAINING_RECORD(Next,
|
|
LDR_DATA_TABLE_ENTRY,
|
|
InLoadOrderLinks);
|
|
if ((!ReadMemory((DWORD)DataTable,
|
|
&DataTableBuffer,
|
|
sizeof(LDR_DATA_TABLE_ENTRY),
|
|
&Result)) || (Result < sizeof(LDR_DATA_TABLE_ENTRY))) {
|
|
dprintf("Unable to read LDR_DATA_TABLE_ENTRY at %08lx - status %08lx\n",
|
|
DataTable,
|
|
Status);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get the base DLL name.
|
|
//
|
|
if ((!ReadMemory((DWORD)DataTableBuffer.BaseDllName.Buffer,
|
|
UnicodeBuffer,
|
|
DataTableBuffer.BaseDllName.Length,
|
|
&Result)) || (Result < DataTableBuffer.BaseDllName.Length)) {
|
|
dprintf("Unable to read name string at %08lx - status %08lx\n",
|
|
DataTable,
|
|
Status);
|
|
return;
|
|
}
|
|
|
|
BaseName.Buffer = UnicodeBuffer;
|
|
BaseName.Length = BaseName.MaximumLength = (USHORT)Result;
|
|
|
|
DosHeader = (PIMAGE_DOS_HEADER)DataTableBuffer.DllBase;
|
|
|
|
if ((!ReadMemory((DWORD)&DosHeader->e_lfanew,
|
|
&DosHeaderSize,
|
|
sizeof(ULONG),
|
|
&Result)) || (Result < sizeof(ULONG))) {
|
|
//dprintf("Unable to read DosHeader at %08lx - status %08lx\n",
|
|
// &DosHeader->e_lfanew,
|
|
// Status);
|
|
|
|
SizeOfCode = 0;
|
|
SizeOfData = 0;
|
|
time = PagedOut;
|
|
} else {
|
|
|
|
NtHeader = (PIMAGE_NT_HEADERS)((ULONG)DosHeader + DosHeaderSize);
|
|
|
|
if ((!ReadMemory((DWORD)&(NtHeader->OptionalHeader.SizeOfCode),
|
|
&SizeOfCode,
|
|
sizeof(ULONG),
|
|
&Result)) || (Result < sizeof(ULONG))) {
|
|
dprintf("Unable to read DosHeader at %08lx - status %08lx\n",
|
|
&(NtHeader->OptionalHeader.SizeOfCode),
|
|
Status);
|
|
goto getnext;
|
|
}
|
|
|
|
if ((!ReadMemory((DWORD)&(NtHeader->OptionalHeader.SizeOfInitializedData),
|
|
&SizeOfData,
|
|
sizeof(ULONG),
|
|
&Result)) || (Result < sizeof(ULONG))) {
|
|
dprintf("Unable to read DosHeader at %08lx - status %08lx\n",
|
|
&(NtHeader->OptionalHeader.SizeOfCode),
|
|
Status);
|
|
goto getnext;
|
|
}
|
|
|
|
if ((!ReadMemory((DWORD)&(NtHeader->FileHeader.TimeDateStamp),
|
|
&TimeDateStamp,
|
|
sizeof(ULONG),
|
|
&Result)) || (Result < sizeof(ULONG))) {
|
|
dprintf("Unable to read DosHeader at %08lx - status %08lx\n",
|
|
&(NtHeader->FileHeader.TimeDateStamp),
|
|
Status);
|
|
goto getnext;
|
|
}
|
|
|
|
time = ctime((time_t *)&TimeDateStamp);
|
|
time[strlen(time)-1] = 0;
|
|
}
|
|
|
|
if (Flags & 1) {
|
|
PCHAR Va;
|
|
PCHAR EndVa;
|
|
ULONG States[3] = {0,0,0};
|
|
|
|
Va = DataTableBuffer.DllBase;
|
|
EndVa = Va + DataTableBuffer.SizeOfImage;
|
|
|
|
while (Va < EndVa) {
|
|
States[GetAddressState((PVOID)Va)] += PAGE_SIZE/1024;
|
|
Va += PAGE_SIZE;
|
|
}
|
|
dprintf("%08lx %6lx (%4ld kb) %6lx (%4ld kb) (%5ld kb %5ld kb) %12wZ\n",
|
|
DataTableBuffer.DllBase,
|
|
SizeOfCode,
|
|
SizeOfCode / 1024,
|
|
SizeOfData,
|
|
SizeOfData / 1024,
|
|
States[ADDRESS_VALID],
|
|
States[ADDRESS_TRANSITION],
|
|
&BaseName);
|
|
TotalValid += States[ADDRESS_VALID];
|
|
TotalTransition += States[ADDRESS_TRANSITION];
|
|
} else {
|
|
|
|
dprintf("%08lx %6lx (%4ld kb) %6lx (%4ld kb) %12wZ %s\n",
|
|
DataTableBuffer.DllBase,
|
|
SizeOfCode,
|
|
SizeOfCode / 1024,
|
|
SizeOfData,
|
|
SizeOfData / 1024,
|
|
&BaseName,
|
|
time);
|
|
}
|
|
|
|
if (Flags & 6) {
|
|
DumpImage((ULONG)DataTableBuffer.DllBase,
|
|
(Flags & 2) == 2,
|
|
(Flags & 4) == 4
|
|
);
|
|
}
|
|
|
|
TotalCode += SizeOfCode;
|
|
TotalData += SizeOfData;
|
|
getnext:
|
|
Next = DataTableBuffer.InLoadOrderLinks.Flink;
|
|
}
|
|
|
|
dprintf("TOTAL: %6lx (%4ld kb) %6lx (%4ld kb) (%5ld kb %5ld kb)\n",
|
|
TotalCode,
|
|
TotalCode / 1024,
|
|
TotalData,
|
|
TotalData / 1024,
|
|
TotalValid,
|
|
TotalTransition);
|
|
|
|
}
|