/*++ 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 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 } ; // // 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, "%230s %lx", driverExpr, &Flags)) { driverExpr[0] = 0; } // // The debugger will treat C0000000 as a symbol first, then a number if // no match comes up. // if (driverExpr[0] == '\\') { driverToDump = FindObjectByName( driverExpr, 0); } else { driverToDump = FindObjectByName((PUCHAR) driverExprBuf, 0); if (driverToDump == 0) { driverToDump = GetExpression(driverExpr); } } 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); if (!Flags) { dprintf("\n"); } 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); if (Name_MaxLen > 1024) // sanity sheck { Name_MaxLen = 1024; } 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 // if (*dispatchTableText) { dprintf("[%02x] %s", i, *dispatchTableText) ; j=strlen(*dispatchTableText) ; } else { dprintf("[%02x] ???", i) ; 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. --*/ { while (*args && *args != '-' && *args != '/') ++args; ++args; if (*args == 'h' || *args == '?') { dprintf("!drivers is now replaced by \".reload -l\"\n" "Also lmv will give verbose info about loaded drivers\n"); return S_OK; } 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; }