NT device drivers’ DispatchReadWrite routines queue transfer IRPs with valid parameters on to other driver routines for further processing on the device and return STATUS_PENDING.
Except for NT file systems, a higher-level driver layered above such a device driver usually does not have any internal driver queues for IRPs. Such a driver’s DispatchReadWrite routine can pass transfer IRPs with valid parameters on to lower drivers possibly after setting up its IoCompletion routine, as already described in Section 6.2.4.
However, an NT SCSI class driver’s DispatchReadWrite routine is responsible for splitting up large transfer requests, if necessary, before it sends an IRP with the major function code IRP_MJ_READ or IRP_MJ_WRITE to the SCSI port/miniport driver pair. For more information about requirements for SCSI class drivers and about how to split up a large transfer request, see Appendix A, and see also the section on adapter objects in Chapter 3.
If a higher-level driver allocates one or more IRPs, which it sets up for the next-lower driver(s) in its DispatchReadWrite routine, to request some number of partial transfers, the DispatchReadWrite routine must call IoSetCompletionRoutine with each driver-allocated IRP. Such a driver must register its IoCompletion routine to track how much data is transferred in each partial-transfer operation so that the IoCompletion routine can release all driver-allocated IRPs and, eventually, complete the original request.
If the underlying driver controls a removable-media device, any IRPs allocated by the higher-level driver must have a thread context. To set up such a thread context, the allocating driver must set the Irp->Tail.Overlay.Thread in each newly allocated IRP from the same value in the incoming transfer IRP.
If the underlying device driver returns an IRP for a partial transfer with an error, the IoCompletion routine can either retry the partial-transfer request or complete the original IRP with its I/O status block set with the returned error, after freeing any IRPs and memory the higher-level driver has allocated.
If a higher-level NT driver’s DispatchReadWrite routine allocates memory for partial-transfer operations and its allocation will be accessed by the driver’s IoCompletion routine (or by the underlying device driver), the DispatchReadWrite routine must allocate that memory from nonpaged pool.