3.2.2 Creating a Device Object and Device Extension

Each NT driver determines the size (StackSize in Figure 3.2) of the device extension when it calls IoCreateDevice to set up a device object.

For most NT drivers, this call is made only from the DriverEntry routine. For some NT drivers, such as disk drivers that must re-create logical device objects dynamically if the user repartitions a disk while the system is running, this call also can be made from a Dispatch routine.

However, every NT driver must call IoCreateDevice one or more times when it initializes to create a named device object to represent each physical, logical, or virtual device for which it handles I/O requests. Otherwise, the driver either will not be loaded if it creates no device object or it will not get IRPs for any target device for which it did not create a device object in its DriverEntry routine.

As shown in Figure 3.2, the caller also passes arguments that determine the following when IoCreateDevice sets up a device object:

For every NT driver except FSDs, the I/O Manager also sets up an associated device queue object for every successful call to IoCreateDevice. The device queue object associated with a device object represents a queue of IRPs bound for a driver’s StartIo routine after the driver is loaded. NT drivers that manage their own internal IRP queues, such as the system floppy controller driver described in Chapter 2, do not use the device queues associated with their device objects.

NT drivers can create additional device queue objects like the NT SCSI port driver, as already mentioned in Section 3.1. For more information about Kernel-defined device queue objects, see Section 3.8 later in this chapter.

If the call to IoCreateDevice succeeds, the I/O Manager provides storage for the device object itself and for all other data structures associated with the device object, including the driver’s device extension, which it initializes with zeros.