Depending on the position of a particular driver in a chain of layered NT drivers, on the nature of the underlying device, and on the design of the driver, its DriverEntry routine also can be responsible for doing following:
For example, a SCSI class driver calls IoGetDeviceObjectPointer repeatedly, passing an updated Unicode name string \Device\ScsiPortDigit where Digit is a count enumerating the SCSI HBAs in the machine. Then, the class driver uses the returned device object pointers to send get-configuration requests to the NT SCSI port driver, in order to determine which HBAs control a bus with attached devices of the class driver’s type. (For more information about initializing SCSI drivers, see also Appendix A.)
A successful call to IoGetDeviceObjectPointer returns pointers to both the lower driver’s device object and the file object associated with that device object. A higher-level driver must save the returned device object pointer so it can pass this device object pointer to IoCallDriver when it passes IRPs on for processing by lower drivers.
Few higher-level NT drivers except FSDs have any use for the returned pointer to the file object. However, a higher-level NT driver should save this returned pointer to the file object if it might break its connection to the lower driver later, for example when being unloaded. To break such a connection, higher-level drivers call ObDereferenceObject to release the file object pointer returned by IoGetDeviceObjectPointer.
For more information about driver Unload routines, see Chapter 15.
Calling IoAttachDevice successfully allows a higher-level NT driver to intercept requests bound for the lower driver’s device by aliasing the target device object to its own device object. Note that the device object created by the higher-level driver is not required to have a name, because the lower driver’s device object is still the named target for I/O requests.
If a highest-level NT driver uses executive worker threads, as many NT file system drivers do, it must have a callback routine of type WORKER_THREAD_ROUTINE, which takes a single input PVOID Parameter.
An NT driver must provide storage, usually in the device extension of a device object, for any Kernel-defined objects and executive spin locks it uses. NT drivers also must provide storage for pointers to certain objects obtained from the HAL or I/O Manager, as explained in Chapter 3.
Most device and intermediate drivers provide storage in their device or controller extensions for every NT object and system resource they use to process I/O requests. Their DriverEntry routines initialize certain resources, such as any Kernel-defined object stored in the device (or controller) extension, that the driver uses thereafter.
However, an NT driver designer might decide to allocate additional system-space memory for the driver’s needs, such as for long-term I/O buffers or a zone buffer. If so, the DriverEntry routine can call one (or more) of the following routines:
For more information about using memory, see Chapter 16. For more information about using common buffers for DMA, see the section on adapter objects in Chapter 3.