Monday, 11 November 2013

!devobj and _DEVICE_OBJECT

I've explained the use of the !devobj extension before, but in this blog post, I thought I would provide a more detailed explanation of device objects and their creation.

Device Objects are a structure called DEVICE_OBJECT, and are used to represent a physical or virtual device within the Device Tree, which in turn consist of Device Nodes.

Device Tree Concept
We can produce output in WinDbg with !devobj or by using the dt nt!_DEVICE_OBJECT command. Let's take a look at both of these methods.

You will need to use the address of the Device Object. This is always supplied as the second parameter for Stop 0x9F bugchecks.


Here is the data structure, which provides much more information than the extension:


Most data structures will be documented by Microsoft, simply check the WDK documentation or the MSDN website for more information. You don't have to be a driver developer to understand it, although, that would be extremely useful in debugging BSODs.

I'll give a description of all the fields in the data structure, which are written on the MSDN website.

Type: This a integer used to correspond to a certain type of object for the use of Windows. I wouldn't confuse it with the _KOBJECTS (used for Dispatcher Objects) enumeration, which lists 3 as a Process Object.

Size: The size of the device object (in bytes) and it's Device Extension size.

ReferenceCount: The number of open handles pointing to the device object, having a reference count field prevents the I/O Manager from unloading a driver for the device.

DriverObject: A pointer to the DRIVER_OBJECT data structure, which is used to represent a loaded driver for the current device object.

NextDevice: A pointer to the next device, if any are present, which were created by the same driver object for the current device object.

AttachedDevice: A pointer to a attached device object. This is usually a filter driver device object. It is NULL if there is no device object attached.

CurrentIrp: List of IRPs which are being currently processed by the driver object for the device, but also contains a pointer to any IRP which was defined within the StartIO routine (starts the I/O operation).

Timer: A pointer to a timer object, which is used to by the I/O Manager to call the IoInitializeTimer every second.

Flags: Used by device drivers to perform a bitwise OR (||) operation on the device object, to set a certain flag for that device. Read the Flags section for DEVICE_OBJECT.

Characteristics: System-defined constants which are used in a bitwise OR (||) operation to provide information about the device object. Read the Characteristics section for DEVICE_OBJECT.

Vpb: A pointer to the Volume Paramter Block, useful for file system drivers.

DeviceExtension: A pointer to the device extension.

DeviceType: Defines the type of hardware for the device object. In this case, we are looking at a FILE_DEVICE_VIDEO device (graphics card). More Information - Device Types

StackSize: The number of stack locations in IRPs to be sent to the driver which is using this device.

Queue: Reserved for the I/O Manager. Queues the device when necessary. 

AlignmentRequirement: Device address alignment for data transfers. Address alignment is needed to ensure that the alignment is correct for direct I/O and DMA buffers.

DeviceQueue: List of queued IRPs for the driver which is associated with the current device object.

Dpc: DPC for device object.

ActiveThreadCount: Reserved.

SecurityDescriptor: Security descriptor for the device object. If no value is specified, then the default security settings are given.

DeviceLock: Synchronization event object from I/O Manager.

SectorSize: Size of sector if the device object is a volume. 

Spare1: Reserved.

DeviceObjectExtension: Pointer to the device object extension (used by I/O Manager and PnP Manager) to gain information about the state of the device.

Reserved: Self-explanatory. 

I'm going to explain the FILE_DEVICE_SECURE_OPEN characteristic flag, which can be seen with the !devobj extension. This flag is used by the I/O Manager to perform security access checks on any open requests for the device object, these checks are then checked against the ACL (Access Control List) for the device object.

























1 comment: