Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

875 lines
28 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
DumpImage(
ULONG Base,
BOOL DoHeaders,
BOOL DoSections
);
PUCHAR DispatchRoutineTable[]=
{
"IRP_MJ_CREATE",
"IRP_MJ_CREATE_NAMED_PIPE",
"IRP_MJ_CLOSE",
"IRP_MJ_READ",
"IRP_MJ_WRITE",
"IRP_MJ_QUERY_INFORMATION",
"IRP_MJ_SET_INFORMATION",
"IRP_MJ_QUERY_EA",
"IRP_MJ_SET_EA",
"IRP_MJ_FLUSH_BUFFERS",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION",
"IRP_MJ_DIRECTORY_CONTROL",
"IRP_MJ_FILE_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CONTROL",
"IRP_MJ_INTERNAL_DEVICE_CONTROL",
"IRP_MJ_SHUTDOWN",
"IRP_MJ_LOCK_CONTROL",
"IRP_MJ_CLEANUP",
"IRP_MJ_CREATE_MAILSLOT",
"IRP_MJ_QUERY_SECURITY",
"IRP_MJ_SET_SECURITY",
"IRP_MJ_POWER",
"IRP_MJ_SYSTEM_CONTROL",
"IRP_MJ_DEVICE_CHANGE",
"IRP_MJ_QUERY_QUOTA",
"IRP_MJ_SET_QUOTA",
"IRP_MJ_PNP",
NULL
} ;
PUCHAR FastIoDispatchTable[]=
{
"FastIoCheckIfPossible",
"FastIoRead",
"FastIoWrite",
"FastIoQueryBasicInfo",
"FastIoQueryStandardInfo",
"FastIoLock",
"FastIoUnlockSingle",
"FastIoUnlockAll",
"FastIoUnlockAllByKey",
"FastIoDeviceControl",
"AcquireFileForNtCreateSection",
"ReleaseFileForNtCreateSection",
"FastIoDetachDevice",
"FastIoQueryNetworkOpenInfo",
"AcquireForModWrite",
"MdlRead",
"MdlReadComplete",
"PrepareMdlWrite",
"MdlWriteComplete",
"FastIoReadCompressed",
"FastIoWriteCompressed",
"MdlReadCompleteCompressed",
"MdlWriteCompleteCompressed",
"FastIoQueryOpen",
"ReleaseForModWrite",
"AcquireForCcFlush",
"ReleaseForCcFlush",
NULL
} ;
BOOL
IsName(PSTR str)
{
if (!((tolower(*str) >= 'a' && tolower(*str) <= 'z') || *str == '_')) {
return FALSE;
}
++str;
while (*str) {
if (!((*str >= '0' && *str <= '9' ) ||
(tolower(*str) >= 'a' && tolower(*str) <= 'z') ||
*str == '_')) {
return FALSE;
}
++str;
}
return TRUE;
}
//
// Change this value and update the above table if IRP_MJ_MAXIMUM_FUNCTION
// is increased.
//
#define IRP_MJ_MAXIMUM_FUNCTION_HANDLED 0x1b
DECLARE_API( drvobj )
/*++
Routine Description:
Dump a driver object.
Arguments:
args - the location of the driver object to dump.
Return Value:
None
--*/
{
ULONG64 driverToDump;
ULONG Flags;
char driverExprBuf[256] ;
char *driverExpr ;
//
// !drvobj DriverAddress DumpLevel
// where DriverAddress can be an expression or driver name
// and DumpLevel is a hex mask
//
strcpy(driverExprBuf, "\\Driver\\") ;
driverExpr = driverExprBuf+strlen(driverExprBuf) ;
Flags = 1;
driverToDump = 0 ;
if (!sscanf(args, "%s %lx", driverExpr, &Flags)) {
driverExpr[0] = 0;
}
//
// The debugger will treat C0000000 as a symbol first, then a number if
// no match comes up. We sanely reverse this ordering.
//
if (driverExpr[0] == '\\') {
driverToDump = FindObjectByName( driverExpr, 0);
} else {
if (IsName(driverExpr)) {
driverToDump = FindObjectByName((PUCHAR) driverExprBuf, 0);
} else {
driverToDump = GetExpression( driverExpr ) ;
if (driverToDump == 0) {
driverToDump = FindObjectByName((PUCHAR) driverExprBuf, 0);
}
}
}
if(driverToDump == 0) {
dprintf("Driver object %s not found\n", args);
return E_INVALIDARG;
}
dprintf("Driver object (%08p) is for:\n", driverToDump);
DumpDriver( driverToDump, 0, Flags);
return S_OK;
}
VOID
DumpDriver(
ULONG64 DriverAddress,
ULONG FieldWidth,
ULONG Flags
)
/*++
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.
FieldWidth - Width of printf field (eg %11s) for driver name.
Use 0 for full display.
Flags - Bit 0, Dump out device objects owned by driver
Bit 1, Dump out dispatch routines for driver
Return Value:
None
--*/
{
// DRIVER_OBJECT driverObject;
ULONG result;
ULONG i,j;
PUCHAR buffer;
ULONG64 deviceAddress;
// DEVICE_OBJECT deviceObject;
UNICODE_STRING unicodeString;
ULONG64 displacement;
UCHAR component[512];
PUCHAR *dispatchTableText ;
// FAST_IO_DISPATCH FastIoDispatch;
ULONG64 *p;
ULONG Type=0, Name_MaxLen=0, Name_Len=0, LongAddr, IoD_SizeOfFastIoDispatch=0;
ULONG64 MajorFunction[IRP_MJ_MAXIMUM_FUNCTION_HANDLED+1]= {0}, IoD[27] = {0};
ULONG64 Name_Buf=0, DriverExtension=0, Ext_ClientDriverExtension=0, DeviceObject=0,
FastIoDispatch=0, IoD_FastIoCheckIfPossible=0;
ULONG64 DriverEntry=0, DriverUnload=0, DriverStartIo=0;
FIELD_INFO DriverFields[] = {
{"DriverExtension", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA |
((Flags & 1) ? DBG_DUMP_FIELD_RECUR_ON_THIS : 0), 0, (PVOID) &DriverExtension},
{"DriverName", "", 0, DBG_DUMP_FIELD_RECUR_ON_THIS, 0, NULL},
{"DriverName.MaximumLength", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &Name_MaxLen},
{"DriverName.Length", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &Name_Len},
{"DriverName.Buffer", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &Name_Buf},
{"DriverExtension.ClientDriverExtension", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &Ext_ClientDriverExtension},
{"DeviceObject", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &DeviceObject},
{"DriverInit", "DriverEntry", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &DriverEntry},
{"DriverStartIo", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &DriverStartIo},
{"DriverUnload", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &DriverUnload},
{"MajorFunction", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &MajorFunction[0]},
{"FastIoDispatch","", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA |
DBG_DUMP_FIELD_RECUR_ON_THIS, 0, (PVOID) &FastIoDispatch},
{"FastIoDispatch.SizeOfFastIoDispatch", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD_SizeOfFastIoDispatch},
{"FastIoDispatch.FastIoCheckIfPossible", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[0]},
{"FastIoDispatch.FastIoRead", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[1]},
{"FastIoDispatch.FastIoWrite", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[2]},
{"FastIoDispatch.FastIoQueryBasicInfo", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[3]},
{"FastIoDispatch.FastIoQueryStandardInfo", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[4]},
{"FastIoDispatch.FastIoLock", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[5]},
{"FastIoDispatch.FastIoUnlockSingle", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[6]},
{"FastIoDispatch.FastIoUnlockAll", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[7]},
{"FastIoDispatch.FastIoUnlockAllByKey", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[8]},
{"FastIoDispatch.FastIoDeviceControl", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[9]},
{"FastIoDispatch.AcquireFileForNtCreateSection", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[10]},
{"FastIoDispatch.ReleaseFileForNtCreateSection", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[11]},
{"FastIoDispatch.FastIoDetachDevice", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[12]},
{"FastIoDispatch.FastIoQueryNetworkOpenInfo", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[13]},
{"FastIoDispatch.AcquireForModWrite", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[14]},
{"FastIoDispatch.MdlRead", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[15]},
{"FastIoDispatch.MdlReadComplete", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[16]},
{"FastIoDispatch.PrepareMdlWrite", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[17]},
{"FastIoDispatch.MdlWriteComplete", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[18]},
{"FastIoDispatch.FastIoReadCompressed", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[19]},
{"FastIoDispatch.FastIoWriteCompressed", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[20]},
{"FastIoDispatch.MdlReadCompleteCompressed", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[21]},
{"FastIoDispatch.MdlWriteCompleteCompressed", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[22]},
{"FastIoDispatch.FastIoQueryOpen", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[23]},
{"FastIoDispatch.ReleaseForModWrite", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[24]},
{"FastIoDispatch.AcquireForCcFlush", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[25]},
{"FastIoDispatch.ReleaseForCcFlush", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &IoD[26]},
};
SYM_DUMP_PARAM DriverSym = {
sizeof (SYM_DUMP_PARAM), "nt!_DRIVER_OBJECT", DBG_DUMP_NO_PRINT, (ULONG64) DriverAddress,
NULL, NULL, NULL, sizeof (DriverFields) / sizeof(FIELD_INFO), &DriverFields[0]
};
if (GetFieldValue(DriverAddress, "nt!_DRIVER_OBJECT",
"Type", Type)) {
dprintf("Cannot read _DRIVER_OBJECT at %p\n", DriverAddress);
return;
}
LongAddr = IsPtr64();
if (Type != IO_TYPE_DRIVER) {
dprintf("%08p: is not a driver object\n", DriverAddress);
return;
}
Ioctl(IG_DUMP_SYMBOL_INFO, &DriverSym, DriverSym.size);
buffer = LocalAlloc(LPTR, Name_MaxLen);
if (buffer == NULL) {
dprintf("Could not allocate %d bytes\n",
Name_MaxLen);
return;
}
//
// This memory may be paged out.
//
unicodeString.Buffer = (PWSTR)buffer;
unicodeString.Length = (USHORT) Name_Len;
unicodeString.MaximumLength = (USHORT) Name_MaxLen;
if (!ReadMemory( Name_Buf,
buffer,
Name_MaxLen,
&result)) {
dprintf(" Name paged out");
} else {
sprintf(component, " %wZ", &unicodeString);
dprintf("%s", component) ;
for(i = strlen(component); i<FieldWidth; i++) {
dprintf(" ") ;
}
}
LocalFree(buffer);
if (Flags&1) {
dprintf("\n");
//
// Dump the list of client extensions
//
if(DriverExtension) {
ULONG sz = GetTypeSize("nt!_IO_CLIENT_EXTENSION");
ULONG64 clientExtension = Ext_ClientDriverExtension;
dprintf("Driver Extension List: (id , addr)\n");
//
// Check to see if there are any extensions.
//
while(clientExtension != 0) {
ULONG64 ClientIdentificationAddress=0, NextExtension=0;
FIELD_INFO IoCltFields[] = {
{"ClientIdentificationAddress", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA,
0, (PVOID) &ClientIdentificationAddress},
{"NextExtension", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA,
0, (PVOID) &NextExtension},
};
// IO_CLIENT_EXTENSION buffer;
DriverSym.sName = "_IO_CLIENT_EXTENSION"; DriverSym.addr = clientExtension;
DriverSym.nFields = 2; DriverSym.Fields = &IoCltFields[0];
if (!Ioctl(IG_DUMP_SYMBOL_INFO, &DriverSym, DriverSym.size)) {
/* ReadMemory((DWORD) clientExtension,
&buffer,
sizeof(buffer),
&result)) {*/
dprintf("(%08p %08p) ",
ClientIdentificationAddress,
clientExtension + sz);
clientExtension = NextExtension;
} else {
dprintf("\nCouldn't read extension at %#08p\n", clientExtension);
clientExtension = 0;
}
}
dprintf("\n");
}
dprintf("Device Object list:\n");
deviceAddress = DeviceObject;
for (i= 0; deviceAddress != 0; i++) {
ULONG64 NextDevice=0;
FIELD_INFO DevFields = {"NextDevice", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &NextDevice};
DriverSym.sName = "_DEVICE_OBJECT"; DriverSym.addr = deviceAddress;
DriverSym.nFields = 1; DriverSym.Fields = &DevFields;
if (Ioctl(IG_DUMP_SYMBOL_INFO, &DriverSym, DriverSym.size)) {
dprintf("%08p: Could not read device object\n", deviceAddress);
break;
}
dprintf("%08p%s", deviceAddress, ((i & 0x03) == 0x03) ? "\n" : " ");
deviceAddress = NextDevice;
}
dprintf("\n");
}
if (Flags&0x2) {
GetSymbol(DriverEntry, component, &displacement);
dprintf("\nDriverEntry: %8.8p\t%s\n", DriverEntry, component);
GetSymbol(DriverStartIo, component, &displacement);
dprintf("DriverStartIo: %8.8p\t%s\n", DriverStartIo, component);
GetSymbol(DriverUnload, component, &displacement);
dprintf("DriverUnload: %8.8p\t%s\n", DriverUnload, component);
dprintf ("\nDispatch routines:\n");
dispatchTableText = DispatchRoutineTable ;
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION_HANDLED; i++) {
//
// Get the read pointer values depending on 32 or 64 bit addresses
//
if (LongAddr) {
GetSymbol(MajorFunction[i], component, &displacement);
} else {
GetSymbol((ULONG64) (LONG64) (LONG) (((PULONG) &MajorFunction[0])[i]), component, &displacement);
}
//
// Forms are:
// [1b] IRP_MJ_PNP C0000000 DispatchHandler+30
// [1b] IRP_MJ_PNP C0000000 DispatchHandler
// [1b] ??? C0000000 <either of above>
//
if (*dispatchTableText) {
dprintf("[%02x] %s", i, *dispatchTableText) ;
j=strlen(*dispatchTableText) ;
} else {
dprintf("[%02x] ???") ;
j=3 ;
}
while(j++<35) dprintf(" ") ;
if (LongAddr) {
dprintf("%8.8p\t%s", MajorFunction[i], component);
} else {
dprintf("%8.8x\t%s", (((PULONG) &MajorFunction[0])[i]), component);
}
// dprintf("%8.8x\t%s", driverObject.MajorFunction[i], component) ;
if (displacement) {
dprintf("+0x%1p\n", displacement) ;
} else {
dprintf("\n") ;
}
if (*dispatchTableText) {
dispatchTableText++ ;
}
}
if (FastIoDispatch) {
dprintf("\nFast I/O routines:\n");
dispatchTableText = FastIoDispatchTable ;
for (i=0;i < ((IoD_SizeOfFastIoDispatch - 4)/ (LongAddr ? 8 : 4)); i++) {
if (IoD[i]) {
GetSymbol(IoD[i], component, &displacement);
if (*dispatchTableText) {
dprintf("%s", *dispatchTableText) ;
j=strlen(*dispatchTableText) ;
} else {
dprintf("???") ;
j=3 ;
}
while(j++<40) dprintf(" ") ;
dprintf("%8.8p\t%s", IoD[i], component) ;
if (displacement) {
dprintf("+0x%1p", displacement) ;
}
dprintf("\n") ;
}
if (*dispatchTableText) {
dispatchTableText++ ;
}
}
}
dprintf("\n");
}
}
UCHAR *PagedOut = {"Header Paged Out"};
DECLARE_API( drivers )
/*++
Routine Description:
Displays physical memory usage by driver.
Arguments:
None.
Return Value:
None.
--*/
{
return ExecuteCommand(Client, ".reload -l");
#if 0
LIST_ENTRY64 List;
ULONG64 Next;
ULONG64 ListHead;
NTSTATUS Status = 0;
ULONG Result;
ULONG64 DataTable;
LDR_DATA_TABLE_ENTRY DataTableBuffer;
WCHAR UnicodeBuffer[128];
UNICODE_STRING BaseName;
ULONG64 NtHeader;
ULONG64 DosHeader;
ULONG SizeOfData;
ULONG SizeOfCode;
ULONG SizeOfLocked;
ULONG TotalCode = 0;
ULONG TotalData = 0;
ULONG TotalValid = 0;
ULONG TotalTransition = 0;
ULONG DosHeaderSize;
ULONG TimeDateStamp;
LONG_PTR TDStamp;
ULONG InLoadOrderLinksOff;
PUCHAR time;
ULONG64 Flags;
UCHAR LdrName[] = "_LDR_DATA_TABLE_ENTRY";
Flags = GetExpression(args);
ListHead = GetNtDebuggerData( PsLoadedModuleList );
if (!ListHead) {
dprintf("Unable to get value of PsLoadedModuleListHead\n");
return E_INVALIDARG;
}
if (GetFieldValue(ListHead, "_LIST_ENTRY", "Flink", List.Flink)) {
dprintf("Couldn't read _LIST_ENTRY @ %p\n", ListHead);
return E_INVALIDARG;
}
Next = List.Flink;
if (Next == 0) {
dprintf("PsLoadedModuleList is NULL, trying loader block instead\n");
ListHead = GetUlongValue ("KeLoaderBlock");
if (ListHead == 0) {
dprintf ("KeLoaderBlock is NULL\n");
return E_INVALIDARG;
}
if (GetFieldValue(ListHead, "_LIST_ENTRY", "Flink", List.Flink)) {
dprintf("Couldn't read _LIST_ENTRY1 @ %p\n", ListHead);
return E_INVALIDARG;
}
if (GetFieldValue(List.Flink, "_LIST_ENTRY", "Flink", List.Flink)) {
dprintf("Couldn't read _LIST_ENTRY2 @ %p\n", ListHead);
return E_INVALIDARG;
}
if (!IsPtr64()) {
ListHead = (ULONG64)(LONG64)(LONG)ListHead;
}
Next = List.Flink;
}
dprintf("Loaded System Driver Summary\n\n");
if (Flags & 1) {
dprintf("Base Code Size Data Size Resident Standby Driver Name\n");
} else if (Flags & 2) {
dprintf("Base Code Data Locked Resident Standby Loader Entry Driver Name\n");
} else {
dprintf("Base Code Size Data Size Driver Name Creation Time\n");
}
// Get The offset of InLoadOrderLinks
if (GetFieldOffset("_LDR_DATA_TABLE_ENTRY", "InLoadOrderLinks", &InLoadOrderLinksOff)){
dprintf("Cannot find _LDR_DATA_TABLE_ENTRY type\n");
return E_INVALIDARG;
}
while (Next != ListHead) {
ULONG64 BaseDllBuffer=0, DllBase=0;
ULONG BaseDllNameLen=0, SizeOfImage=0;
if (CheckControlC()) {
return E_INVALIDARG;
}
DataTable = Next - InLoadOrderLinksOff;
if (GetFieldValue(DataTable, LdrName, "BaseDllName.Buffer", BaseDllBuffer)) {
dprintf("Unable to read LDR_DATA_TABLE_ENTRY at %08lx - status %08p\n",
DataTable,
Status);
return E_INVALIDARG;
}
GetFieldValue(DataTable, LdrName, "BaseDllName.Length", BaseDllNameLen);
if (BaseDllNameLen > sizeof(UnicodeBuffer)) {
BaseDllNameLen = sizeof(UnicodeBuffer);
}
//
// Get the base DLL name.
//
if ((!ReadMemory(BaseDllBuffer,
UnicodeBuffer,
BaseDllNameLen,
&Result)) || (Result < BaseDllNameLen)) {
dprintf("Unable to read name string at %08p - status %08lx\n",
DataTable,
Status);
return E_INVALIDARG;
}
BaseName.Buffer = UnicodeBuffer;
BaseName.Length = BaseName.MaximumLength = (USHORT)Result;
GetFieldValue(DataTable, LdrName, "DllBase", DllBase);
DosHeader = DllBase;
DosHeaderSize=0;
if (GetFieldValue(DosHeader, "_IMAGE_DOS_HEADER", "e_lfanew", DosHeaderSize)) {
//dprintf("Unable to read DosHeader at %08lx - status %08lx\n",
// &DosHeader->e_lfanew,
// Status);
SizeOfCode = 0;
SizeOfData = 0;
SizeOfLocked = -1;
time = PagedOut;
} else {
NtHeader = DosHeader + DosHeaderSize;
if (GetFieldValue(NtHeader, "_IMAGE_NT_HEADERS", "OptionalHeader.SizeOfCode", SizeOfCode)) {
dprintf("Unable to read DosHeader at %08p - status %08lx\n",
NtHeader,
Status);
goto getnext;
}
GetFieldValue(NtHeader, "_IMAGE_NT_HEADERS", "OptionalHeader.SizeOfInitializedData", SizeOfData);
GetFieldValue(NtHeader, "_IMAGE_NT_HEADERS", "FileHeader.TimeDateStamp", TimeDateStamp);
// TimeDateStamp is always a 32 bit quantity on the target, and we
// need to sign extend for 64 bit host
TDStamp = (LONG_PTR)(LONG)TimeDateStamp;
time = ctime((time_t *)&TDStamp);
if (time) {
time[strlen(time)-1] = 0; // ctime always returns 26 char ending win \n\0
}
}
GetFieldValue(DataTable, LdrName, "SizeOfImage", SizeOfImage);
if (Flags & 1) {
ULONG64 Va;
ULONG64 EndVa;
ULONG States[3] = {0,0,0};
Va = DllBase;
EndVa = Va + SizeOfImage;
// PLATFORM SPECIFIC
while (Va < EndVa) {
States[GetAddressState(Va)] += _KB;
Va += PageSize;
}
dprintf("%08p %6lx (%4ld kb) %6lx (%4ld kb) (%5ld kb %5ld kb) %12wZ\n",
DllBase,
SizeOfCode,
SizeOfCode / 1024,
SizeOfData,
SizeOfData / 1024,
States[ADDRESS_VALID],
States[ADDRESS_TRANSITION],
&BaseName);
TotalValid += States[ADDRESS_VALID];
TotalTransition += States[ADDRESS_TRANSITION];
} else if (Flags & 2) {
ULONG i;
ULONG SizeToLock;
ULONG64 PointerPte;
ULONG64 LastPte;
ULONG64 BaseAddress;
ULONG64 Va;
ULONG64 EndVa;
ULONG States[3] = {0,0,0};
ULONG64 NtSection;
ULONG SizeOfOptionalHeader=0, NumberOfSections=0;
Va = DllBase;
EndVa = Va + SizeOfImage;
while (Va < EndVa) {
States[GetAddressState(Va)] += _KB;
Va += PageSize;
}
SizeOfLocked = 0;
//
// Read the sections in the executable header to see which are
// locked. Don't bother looking for refcounted PFNs.
//
NtHeader = DosHeader + DosHeaderSize;
if (GetFieldValue(NtHeader, "_IMAGE_NT_HEADERS", "FileHeader.SizeOfOptionalHeader", SizeOfOptionalHeader)) {
dprintf("Unable to read FileHeader at %08lx - status %08lx\n",
NtHeader,
Status);
goto getnext;
}
GetFieldValue(NtHeader, "_IMAGE_NT_HEADERS", "FileHeader.NumberOfSections", NumberOfSections);
NtSection = NtHeader +
GetTypeSize("ULONG") +
GetTypeSize("_IMAGE_FILE_HEADER") +
SizeOfOptionalHeader;
for (i = 0; i < NumberOfSections; i += 1) {
ULONG NumberOfLinenumbers=0, PointerToRelocations=0, SizeOfRawData=0;
if (GetFieldValue(NtSection, "_IMAGE_SECTION_HEADER", "NumberOfLinenumbers", NumberOfLinenumbers)) {
dprintf("Unable to read NtSectionData at %08lx - status %08p\n",
NtSection,
Status);
goto getnext;
}
GetFieldValue(NtSection, "_IMAGE_SECTION_HEADER", "SizeOfRawData", SizeOfRawData);
GetFieldValue(NtSection, "_IMAGE_SECTION_HEADER", "PointerToRelocations", PointerToRelocations);
if ((NumberOfLinenumbers == 1) ||
(NumberOfLinenumbers == 2)) {
BaseAddress = PointerToRelocations;
SizeToLock = SizeOfRawData;
PointerPte = DbgGetPteAddress( BaseAddress);
LastPte = DbgGetPteAddress(BaseAddress + SizeToLock - 1);
SizeOfLocked += (ULONG) (LastPte - PointerPte + 1);
}
NtSection += 1;
}
#if 0
dprintf("Base Code Data Locked Resident Standby Loader Entry Driver Name\n");
#endif
dprintf("%08p %6lx %6lx %6lx %6lx %6lx %8lp %12wZ\n",
DllBase,
SizeOfCode,
SizeOfData,
SizeOfLocked,
States[ADDRESS_VALID],
States[ADDRESS_TRANSITION],
DataTable,
&BaseName);
TotalValid += States[ADDRESS_VALID];
TotalTransition += States[ADDRESS_TRANSITION];
} else {
dprintf("%08p %6lx (%4ld kb) %5lx (%3ld kb) %12wZ %s\n",
DllBase,
SizeOfCode,
SizeOfCode / 1024,
SizeOfData,
SizeOfData / 1024,
&BaseName,
time);
}
if (Flags & 4) {
dprintf("Cannot dump Image.\n");
/*DumpImage(DllBase,
(Flags & 2) == 2,
(Flags & 4) == 4
);*/
}
TotalCode += SizeOfCode;
TotalData += SizeOfData;
getnext:
GetFieldValue(DataTable, LdrName, "InLoadOrderLinks.Flink", Next);
}
dprintf("TOTAL: %6lx (%4ld kb) %6lx (%4ld kb) (%5ld kb %5ld kb)\n",
TotalCode,
TotalCode / 1024,
TotalData,
TotalData / 1024,
TotalValid,
TotalTransition);
return S_OK;
#endif
}
HRESULT
GetDrvObjInfo(
IN ULONG64 DriverObject,
OUT PDEBUG_DRIVER_OBJECT_INFO pDrvObjInfo)
{
ZeroMemory(pDrvObjInfo, sizeof(DEBUG_DRIVER_OBJECT_INFO));
pDrvObjInfo->SizeOfStruct = sizeof(DEBUG_DRIVER_OBJECT_INFO);
pDrvObjInfo->DriverObjAddress = DriverObject;
if (InitTypeRead(DriverObject, nt!_DRIVER_OBJECT)) {
return E_INVALIDARG;
}
pDrvObjInfo->DeviceObject = ReadField(DeviceObject);
pDrvObjInfo->DriverExtension = ReadField(DriverExtension);
pDrvObjInfo->DriverSize = (ULONG) ReadField(DriverSize);
pDrvObjInfo->DriverStart = ReadField(DriverStart);
pDrvObjInfo->DriverName.MaximumLength = (USHORT) ReadField(DriverName.MaximumLength);
pDrvObjInfo->DriverName.Length = (USHORT) ReadField(DriverName.Length);
pDrvObjInfo->DriverName.Buffer = ReadField(DriverName.Buffer);
return S_OK;
}
EXTENSION_API( GetDrvObjInfo )(
IN PDEBUG_CLIENT Client,
IN ULONG64 DriverObject,
OUT PDEBUG_DRIVER_OBJECT_INFO pDrvObjInfo)
{
HRESULT Hr = E_FAIL;
INIT_API();
if (pDrvObjInfo && (pDrvObjInfo->SizeOfStruct == sizeof(DEBUG_DRIVER_OBJECT_INFO))) {
Hr = GetDrvObjInfo(DriverObject, pDrvObjInfo);
}
EXIT_API();
return Hr;
}