[oR] Both the I/O Manager and a driver need to know what's going on with an I/O device at all times. Device objects make this possible by keeping information about the device's characteristics and state. There is one device object for each virtual, logical, and physical device on the system. The life cycle of a device object is shown below. -
The DriverEntry routine creates a device object for each of its devices. For WDM drivers, the Device object is created by the AddDevice Plug and Play routine. -
The I/O Manager uses a back-pointer in the device object to locate the corresponding driver object. There it can find driver routines to operate on I/O requests. It also maintains a queue of current and pending IRPs attached to the device object. -
Various driver routines use the device object to locate the corresponding device extension. As an I/O request is processed, the driver uses the extension to store any device-specific state information. -
The driver's Unload routine deletes the device object when the driver is unloaded. The act of deleting the device object also deletes the associated device extension. For WDM drivers, RemoveDevice performs the task of deleting the Device object. Physical device drivers are not alone in their use of device objects. Chapter 15 describes the way higher-level drivers use device objects. Layout of the Device Object Figure 4.3 illustrates the structure of the device object and its relationship to other structures. Although the device object contains a lot of data, much of it is the exclusive property of the I/O Manager. A driver should limit its access to only those fields listed in Table 4.6. Figure 4.3. The device object. Manipulating Device Objects Table 4.7 lists many of the I/O Manager functions that operate on device objects. The I/O Manager also passes a device object pointer as an argument to most of the routines in a driver. Table 4.6. Externally Visible Fields of a Device Object Device Object Fields | Field | Description | PVOID DeviceExtension | Points to device extension structure | PDRIVER_OBJECT DriverObject | Points to driver object for this device | ULONG Flags | Specifies buffering strategy for device | | DO_BUFFERED_IO | | DO_DIRECT_IO | PDEVICE_OBJECT NextDevice | Points to next device belonging to this driver | CCHAR StackSize | Minimum number of I/O stack locations needed by IRPs sent to this device | ULONG AlignmentRequirement | Memory alignment required for buffers | Table 4.7. Access Functions for a Device Object Device Object Access Functions | Function | Description | Called by... | IoCreateDevice | Creates a device object | DriverEntry or AddDevice | IoCreateSymbolicLink | Makes device object visible to Win32 | DriverEntry or AddDevice | IoAttachDevice | Attaches a filter to a device object | DriverEntry or AddDevice | IoAttachDeviceByPointer | Attaches a filter to a device object | DriverEntry or AddDevice | IoGetDeviceObjectPointer | Layers one driver on top of another | DriverEntry or AddDevice | IoCallDriver | Sends request to another driver | Dispatch | IoDetachDevice | Disconnects from a lower driver | Unload or RemoveDevice | IoDeleteSymbolicLink | Removes device object from the Win32 namespace | Unload or RemoveDevice | IoDeleteDevice | Removes device object from system | Unload or RemoveDevice | Device Extensions Connected to the device object is another important data structure, the device extension. The extension is simply a block of nonpaged pool that the I/O Manager automatically attaches to any device object created. The driver author specifies both the size and contents of the device extension. Typically, it is used to hold any information associated with a particular device. The use of global or static variables violates the requirement that a driver must be fully reentrant. By keeping device state in the device extension, a single copy of driver code can manage multiple devices. The device extension typically includes -
A back-pointer to the device object -
Any device state or driver context information -
A pointer to the interrupt object and an interrupt-expected flag -
A pointer to a controller object -
A pointer to an adapter object and a count of mapping registers Since the device extension is driver-specific, its structure must be defined in a driver header file. Although the extension's exact contents depend on what a driver does, its general layout looks something like the following: typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT DeviceObject; // back pointer : // other driver-specific declarations : } DEVICE_EXTENSION, *PDEVICE_EXTENSION; The code samples throughout this book will use the device extension in many ways. |