/*++ Copyright (c) 1992 Microsoft Corporation Module Name: device.c Abstract: WinDbg Extension Api Author: Wesley Witt (wesw) 15-Aug-1993 Environment: User Mode. Revision History: --*/ #include "precomp.h" #pragma hdrstop #define FLAG_NAME(flag) {flag, #flag} FLAG_NAME DeviceObjectExtensionFlags[] = { FLAG_NAME(DOE_UNLOAD_PENDING), // 00000001 FLAG_NAME(DOE_DELETE_PENDING), // 00000002 FLAG_NAME(DOE_REMOVE_PENDING), // 00000004 FLAG_NAME(DOE_REMOVE_PROCESSED), // 00000008 FLAG_NAME(DOE_START_PENDING), // 00000010 FLAG_NAME(DOE_RAW_FDO), // 20000000 FLAG_NAME(DOE_BOTTOM_OF_FDO_STACK), // 40000000 FLAG_NAME(DOE_DESIGNATED_FDO), // 80000000 { 0, 0 } }; DECLARE_API( devobj ) /*++ Routine Description: Dump a device object. Arguments: args - the location of the device object to dump. Return Value: None --*/ { ULONG64 deviceToDump ; char deviceExprBuf[256] ; char *deviceExpr ; // // !devobj DeviceAddress DumpLevel // where DeviceAddress can be an expression or device name // and DumpLevel is a hex mask // strcpy(deviceExprBuf, "\\Device\\") ; deviceExpr = deviceExprBuf+strlen(deviceExprBuf) ; deviceToDump = 0 ; if (StringCchCopy(deviceExpr, sizeof(deviceExprBuf) - strlen(deviceExprBuf), args) != S_OK) { deviceExpr[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 (IsHexNumber(deviceExpr)) { deviceToDump = GetExpression(deviceExpr) ; } else if (deviceExpr[0] == '\\') { deviceToDump = FindObjectByName( deviceExpr, 0); } else if (isalpha(deviceExpr[0])) { // // Perhaps it's an object. Try with \\Device\\ prepended... // deviceToDump = FindObjectByName((PUCHAR) deviceExprBuf, 0); } if (deviceToDump == 0) { // // Last try, is it an expression to evaluate? // deviceToDump = GetExpression( deviceExpr ) ; } if(deviceToDump == 0) { dprintf("Device object %s not found\n", args); return E_INVALIDARG; } DumpDevice( deviceToDump, 0, TRUE); return S_OK; } VOID DumpDevice( ULONG64 DeviceAddress, ULONG FieldLength, BOOLEAN FullDetail ) /*++ Routine Description: Displays the driver name for the device object if FullDetail == FALSE. Otherwise displays more information about the device and the device queue. Arguments: DeviceAddress - address of device object to dump. FieldLength - Width of printf field for driver name (eg %11s). FullDetail - TRUE means the device object name, driver name, and information about Irps queued to the device. Return Value: None --*/ { ULONG result; ULONG i; ULONG64 nextEntry; ULONG64 queueAddress; ULONG64 irp; BOOLEAN devObjExtRead; ULONG Type=0, ReferenceCount=0, DeviceType=0, Flags=0, DeviceObjEx_ExtensionFlags=0, DeviceQueue_Busy=0; ULONG64 DriverObject=0, CurrentIrp=0, Vpb=0, DeviceObjectExtension=0, DeviceExtension=0, DeviceObjEx_Dope=0, DeviceObjEx_DeviceNode=0, DeviceObjEx_AttachedTo=0, AttachedDevice=0, DeviceQueue_Dev_Flink=0, DeviceQueue_Dev_Blink=0, SecurityDescriptor = 0; #define RECUR DBG_DUMP_FIELD_RECUR_ON_THIS #define F_ADDR DBG_DUMP_FIELD_RETURN_ADDRESS #define COPY DBG_DUMP_FIELD_COPY_FIELD_DATA FIELD_INFO deviceFields[] = { {"DriverObject", NULL, 0, COPY, 0, (PVOID) &DriverObject}, {"Type", NULL, 0, COPY, 0, (PVOID) &Type}, {"CurrentIrp", NULL, 0, COPY, 0, (PVOID) &CurrentIrp}, {"ReferenceCount", NULL, 0, COPY, 0, (PVOID) &ReferenceCount}, {"DeviceType", NULL, 0, COPY, 0, (PVOID) &DeviceType}, {"Flags", NULL, 0, COPY, 0, (PVOID) &Flags}, {"Vpb", NULL, 0, COPY, 0, (PVOID) &Vpb}, {"SecurityDescriptor", NULL, 0, COPY, 0, (PVOID) &SecurityDescriptor}, {"DeviceObjectExtension", NULL, 0, COPY | RECUR, 0, (PVOID) &DeviceObjectExtension}, {"DeviceObjectExtension->Dope", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_Dope}, {"DeviceObjectExtension->DeviceNode", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_DeviceNode}, {"DeviceObjectExtension->ExtensionFlags", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_ExtensionFlags}, {"DeviceObjectExtension->AttachedTo", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_AttachedTo}, {"DeviceExtension",NULL, 0, COPY, 0, (PVOID) &DeviceExtension}, {"AttachedDevice", NULL, 0, COPY, 0, (PVOID) &AttachedDevice}, {"DeviceQueue", NULL, 0, RECUR,0, NULL}, {"DeviceQueue.Busy", NULL, 0, COPY, 0, (PVOID) &DeviceQueue_Busy}, {"DeviceQueue.DeviceListHead", NULL, 0, RECUR | F_ADDR, 0, NULL}, {"DeviceQueue.DeviceListHead.Flink", NULL, 0, COPY | F_ADDR, 0, (PVOID) &DeviceQueue_Dev_Flink}, {"DeviceQueue.DeviceListHead.Blink", NULL, 0, COPY | F_ADDR, 0, (PVOID) &DeviceQueue_Dev_Blink}, }; SYM_DUMP_PARAM DevSym = { sizeof (SYM_DUMP_PARAM), "nt!_DEVICE_OBJECT", DBG_DUMP_NO_PRINT, DeviceAddress, NULL, NULL, NULL, sizeof (deviceFields) / sizeof (FIELD_INFO), &deviceFields[0] }; if ((Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size))) { dprintf("%08p: Could not read device object or _DEVICE_OBJECT not found\n", DeviceAddress); return; } if (Type != IO_TYPE_DEVICE) { dprintf("%08p: is not a device object\n", DeviceAddress); return; } if (FullDetail == TRUE) { // // Dump the device name if present. // dprintf("Device object (%08p) is for:\n ", DeviceAddress); DumpObjectName(DeviceAddress) ; } DumpDriver( DriverObject, FieldLength, 0); if (FullDetail == TRUE) { // // Dump Irps related to driver. // dprintf(" DriverObject %08p\n", DriverObject); dprintf("Current Irp %08p RefCount %d Type %08lx Flags %08lx\n", CurrentIrp, ReferenceCount, DeviceType, Flags); if (Vpb) { dprintf("Vpb %08p ", Vpb); } if (SecurityDescriptor) { // Ceck if this has a DACL associated with it ULONG sdControl; ULONG64 Dacl; if ((GetFieldValue(SecurityDescriptor, "nt!_SECURITY_DESCRIPTOR", "Control", sdControl) == NO_ERROR) && (GetFieldValue(SecurityDescriptor, "nt!_SECURITY_DESCRIPTOR", "Dacl", Dacl) == NO_ERROR)) { if ((sdControl & SE_DACL_PRESENT) && Dacl) { // Dacl present if (sdControl & SE_SELF_RELATIVE) { Dacl += SecurityDescriptor; } dprintf("Dacl %p ", Dacl); } } } dprintf("DevExt %08p DevObjExt %08p ", DeviceExtension, DeviceObjectExtension); devObjExtRead = FALSE ; if (DeviceObjectExtension) { devObjExtRead = TRUE ; if (DeviceObjEx_Dope) { dprintf("Dope %08p ", DeviceObjEx_Dope); } if(DeviceObjEx_DeviceNode) { dprintf("DevNode %08p ", DeviceObjEx_DeviceNode); } dprintf("\n"); DumpFlags(0, "ExtensionFlags", DeviceObjEx_ExtensionFlags, DeviceObjectExtensionFlags); } else { dprintf("\n"); } if (AttachedDevice) { dprintf("AttachedDevice (Upper) %08p", AttachedDevice); DumpDevice(AttachedDevice, 0, FALSE) ; dprintf("\n") ; } if (devObjExtRead && DeviceObjEx_AttachedTo) { dprintf("AttachedTo (Lower) %08p", DeviceObjEx_AttachedTo); DumpDevice(DeviceObjEx_AttachedTo, 0, FALSE) ; dprintf("\n") ; } if (DeviceQueue_Busy) { ULONG64 listHead = DeviceAddress, DevFlinkAddress; for (i=0; iSizeOfStruct = sizeof(DEBUG_DEVICE_OBJECT_INFO); pDevObjInfo->DevObjAddress = DeviceObject; if (InitTypeRead(DeviceObject, nt!_DEVICE_OBJECT)) { return E_INVALIDARG; } pDevObjInfo->CurrentIrp = ReadField(CurrentIrp); pDevObjInfo->DevExtension = ReadField(DevExtension); pDevObjInfo->DevObjExtension = ReadField(DevObjExtension); pDevObjInfo->DriverObject = ReadField(DriverObject); pDevObjInfo->QBusy = (BOOL) ReadField(DeviceQueue.Busy); pDevObjInfo->ReferenceCount = (ULONG) ReadField(ReferenceCount); return S_OK; } EXTENSION_API( GetDevObjInfo )( IN PDEBUG_CLIENT Client, IN ULONG64 DeviceObject, OUT PDEBUG_DEVICE_OBJECT_INFO pDevObjInfo) { HRESULT Hr = E_FAIL; INIT_API(); if (pDevObjInfo && (pDevObjInfo->SizeOfStruct == sizeof(DEBUG_DEVICE_OBJECT_INFO))) { Hr = GetDevObjInfo(DeviceObject, pDevObjInfo); } EXIT_API(); return Hr; }