22
The !devstack extension displays a formatted view of the device stack associated with a device object.
The !devnode extension displays information about a node in the device tree.
1. WDM driver archecture is the layer structure.
2. Each device function has a device node.
3. Device node is made by device objects.
Â
1: kd> !devstack fffffa800201e830 (One of the device objects in the device node) !DevObj !DrvObj !DevExt ObjectName
fffffa800201e4d0 \Driver\kbdclass fffffa800201e620 KeyboardClass0
> fffffa800201e830 \Driver\i8042prt fffffa800201e980 fffffa8001a8f060 \Driver\ACPI fffffa8000c7b970 0000005e
!DevNode fffffa8001a90610 :
DeviceInst is “ACPI\PNP0303\4&27dc0b59&0”
ServiceName is “i8042prt”
1: kd> !DevNode fffffa8001a90610 1 (!devnode command can show us the device node information)DevNode 0xfffffa8001a90610 for PDO 0xfffffa8001a8f060
InstancePath is “ACPI\PNP0303\4&27dc0b59&0”
ServiceName is “i8042prt”
TargetDeviceNotify List – f 0xfffff8a000c5cb70 b 0xfffff8a000c5cb70
State = DeviceNodeStarted (0x308)
Previous State = DeviceNodeEnumerateCompletion (0x30d)
1: kd> !devobj fffffa8001a8f060 Device object (fffffa8001a8f060) is for:
0000005e \Driver\ACPI DriverObject fffffa8000c394e0
Current Irp 00000000 RefCount 1 Type 00000032 Flags 00003040
Dacl fffff9a100094441 DevExt fffffa8000c7b970 DevObjExt fffffa8001a8f1b0 DevNode fffffa8001a90610
ExtensionFlags (0x00000800)
Unknown flags 0x00000800
AttachedDevice (Upper) fffffa800201e830 \Driver\i8042prtDevice queue is not busy.
1: kd> dt nt!_device_object fffffa8001a8f060
+0x000 Type : 3
+0x002 Size : 0x150
+0x004 ReferenceCount : 1
+0x008 DriverObject : 0xfffffa80`00c394e0 _DRIVER_OBJECT
+0x010 NextDevice : 0xfffffa80`01a52720 _DEVICE_OBJECT
+0x018 AttachedDevice : 0xfffffa80`0201e830 _DEVICE_OBJECT
+0x020 CurrentIrp : (null)
+0x028 Timer : (null)
+0x030 Flags : 0x3040
+0x034 Characteristics : 0x80
+0x038 Vpb : (null)
+0x040 DeviceExtension : 0xfffffa80`00c7b970 (The device extension is not the fixed structure) +0x048 DeviceType : 0x32
+0x04c StackSize : 5 ”
+0x050 Queue :
+0x098 AlignmentRequirement : 0
+0x0a0 DeviceQueue : _KDEVICE_QUEUE
+0x0c8 Dpc : _KDPC
+0x108 ActiveThreadCount : 0
+0x110 SecurityDescriptor : 0xfffff8a0`00094440
+0x118 DeviceLock : _KEVENT
+0x130 SectorSize : 0
+0x132 Spare1 : 1
+0x138 DeviceObjectExtension : 0xfffffa80`01a8f1b0 _DEVOBJ_EXTENSION
+0x140 Reserved : (null)
1: kd> dt _DEVOBJ_EXTENSION 0xfffffa80`01a8f1b0 (Show the device object extension)nt!_DEVOBJ_EXTENSION
+0x000 Type : 13
+0x002 Size : 0
+0x008 DeviceObject : 0xfffffa80`01a8f060 _DEVICE_OBJECT
+0x010 PowerFlags : 0x10 (device/system power state information) +0x018 Dope : (null)
+0x020 ExtensionFlags : 0x800
+0x028 DeviceNode : 0xfffffa80`01a90610 +0x030 AttachedTo : (null) +0x038 StartIoCount : 0
+0x03c StartIoKey : 0
+0x040 StartIoFlags : 0
+0x048 Vpb : (null)
+0x050 DependentList : _LIST_ENTRY [ 0xfffffa80`01a8f200 – 0xfffffa80`01a8f200 ] +0x060 ProviderList : _LIST_ENTRY [ 0xfffffa80`01a8f210 – 0xfffffa80`01a8f210 ] In the WIndbg !devnode xxxxxxxx 1 command, it will show show the InstancePath, ServiceName, State, PreviousState.
2: kd> dt _device_node
nt!_DEVICE_NODE
+0x000 Sibling : Ptr64 _DEVICE_NODE
+0x008 Child : Ptr64 _DEVICE_NODE
+0x010 Parent : Ptr64 _DEVICE_NODE
+0x018 LastChild : Ptr64 _DEVICE_NODE
+0x020 PhysicalDeviceObject : Ptr64 _DEVICE_OBJECT
+0x028 InstancePath : _UNICODE_STRING
+0x038 ServiceName : _UNICODE_STRING
+0x048 PendingIrp : Ptr64 _IRP
+0x050 Level : Uint4B
+0x058 Notify : _PO_DEVICE_NOTIFY
+0x0c0 PoIrpManager : _PO_IRP_MANAGER
+0x0e0 State : _PNP_DEVNODE_STATE
+0x0e4 PreviousState : _PNP_DEVNODE_STATE
+0x0e8 StateHistory : [20] _PNP_DEVNODE_STATE
+0x138 StateHistoryEntry : Uint4B
+0x13c CompletionStatus : Int4B
+0x140 Flags : Uint4B
+0x144 UserFlags : Uint4B
+0x148 Problem : Uint4B
+0x150 ResourceList : Ptr64 _CM_RESOURCE_LIST
+0x158 ResourceListTranslated : Ptr64 _CM_RESOURCE_LIST
+0x160 DuplicatePDO : Ptr64 _DEVICE_OBJECT
+0x168 ResourceRequirements : Ptr64 _IO_RESOURCE_REQUIREMENTS_LIST
+0x170 InterfaceType : _INTERFACE_TYPE
+0x174 BusNumber : Uint4B
+0x178 ChildInterfaceType : _INTERFACE_TYPE
+0x17c ChildBusNumber : Uint4B
+0x180 ChildBusTypeIndex : Uint2B
+0x182 RemovalPolicy : UChar
+0x183 HardwareRemovalPolicy : UChar
+0x188 TargetDeviceNotify : _LIST_ENTRY
+0x198 DeviceArbiterList : _LIST_ENTRY
+0x1a8 DeviceTranslatorList : _LIST_ENTRY
+0x1b8 NoTranslatorMask : Uint2B
+0x1ba QueryTranslatorMask : Uint2B
+0x1bc NoArbiterMask : Uint2B
+0x1be QueryArbiterMask : Uint2B
+0x1c0 OverUsed1 :
+0x1c8 OverUsed2 :
+0x1d0 BootResources : Ptr64 _CM_RESOURCE_LIST
+0x1d8 BootResourcesTranslated : Ptr64 _CM_RESOURCE_LIST
+0x1e0 CapabilityFlags : Uint4B
+0x1e8 DockInfo :
+0x208 DisableableDepends : Uint4B
+0x210 PendedSetInterfaceState : _LIST_ENTRY
+0x220 LegacyBusListEntry : _LIST_ENTRY
+0x230 DriverUnloadRetryCount : Uint4B
+0x238 PreviousParent : Ptr64 _DEVICE_NODE
+0x240 DeletedChildren : Uint4B
+0x244 NumaNodeIndex : Uint4B
+0x248 ContainerID : _GUID
+0x258 OverrideFlags : UChar
+0x259 RequiresUnloadedDriver : UChar
+0x260 PendingEjectRelations : Ptr64 _PENDING_RELATIONS_LIST_ENTRY
“!drvobj Driver Name | PDRIVER_OBJECT pointer” will list all of the devices that a driver has created. I typically invoke this call with “!drvobj Driver Name.” For instance,
0: kd> !drvobj \Driver\i8042prt
Driver object (82158040) is for:
\Driver\i8042prt
Driver Extension List: (id , addr)
Device Object list:
8213c3d0 82153738
Once you have a list of devices, you can pass a device pointer to either !devobj or !devstack to get more information. !devobj will work for any type of device object and will give the device name, device extenion, current irp (for StartIo) and lot more information.
0: kd> !devobj 8213c3d0
Device object (8213c3d0) is for:
\Driver\i8042prt DriverObject 82158040
Current Irp 00000000 RefCount 0 Type 00000027 Flags 00002004
DevExt 8213c488 DevObjExt 8213c768
ExtensionFlags (0xe0000000) DOE_RAW_FDO, DOE_BOTTOM_OF_FDO_STACK,
DOE_DESIGNATED_FDO
AttachedDevice (Upper) 8213c250 \DRIVER\VERIFIER
AttachedTo (Lower) 8213c820 \DRIVER\VERIFIER
Device queue is not busy.
If the device is a pnp device object (FDO, PDO, filter, doesn’t matter), !devstack will show you the entire stack of devices. This can give you a better picture of the environment that your device is executing in. In the following example, I am dumping the device which controsl the PS2 mouse. Furthermore, the device stack is being verifier by driver verifier which is why you see the 2 device objects created by \Driver\VERIFIER.
0: kd> !devstack 8213c3d0
!DevObj !DrvObj !DevExt ObjectName
8213b030 \Driver\Mouclass 8213b0e8 PointerClass0
8213c250 \DRIVER\VERIFIER 8213c308
> 8213c3d0 \Driver\i8042prt 8213c488
8213c820 \DRIVER\VERIFIER 8213c8d8
822923e8 \Driver\ACPI 822b2270 00000050
!DevNode 8228f4c8 :
DeviceInst is “ACPI\PNP0F13\4&1506bb2e&0”
ServiceName is “i8042prt”
Using either !devobj or !devstack, you can get your device extension and then dump it. This is useful if you have a BSOD where you know your driver is at fault, but the callstack itself does not have any backpointers to your device or the needed context.
0: kd> dt 8213c488 i8042prt!_PORT_MOUSE_EXTENSION
+0x000 Self : 0x8213c3d0 _DEVICE_OBJECT
+0x004 InterruptObject : 0x81f44bb0 _KINTERRUPT
+0x008 InterruptSpinLock : 0
+0x00c TopOfStack : 0x8213c820 _DEVICE_OBJECT
+0x010 PDO : 0x822923e8 _DEVICE_OBJECT
[…]
Finally, if you have a pnp device object, you can see the information that power maintains on your device object by running !podev. In the following example, I ran !podev when an Sx irp was being sent to the mouse stack (by setting a bp on i8042prt!I8xPower)
1: kd> !podev 0x8213c3d0
Device object is for:
DriverObject 82158040
Current Irp 00000000 RefCount 0 Type 00000000 AttachedDev 8213c250 DevFlags 00002004 DO_POWER_PAGABLE
Device queue is not busy.
Device Object Extension: 8213c768:
PowerFlags: 00000110 =>SystemState=0 DeviceState=1 syact
Dope: 00000000:
For instance, if your driver calls PoSetPowerState() properly for each S and D irp, the PowerFlags will indicate the current S and D state of the device (i8042prt only calls it for D irps). PowerFlags also can tell you if there is an S or D irp active on your device (unfortunately, not the PIRP value itself which would be useful); in this case, there is an S irp active as indicated by the “sysact” output. By continuing on and keeping the same breakpoint, I can see when a device power irp is active
1: kd> !podev 0x8213c3d0
[…] PowerFlags: 00000410 =>SystemState=0 DeviceState=1 dvact