Every device driver that transfers data from its device to the system must handle read requests in a DispatchRead or DispatchReadWrite routine, as must any higher-level driver layered over such a device driver.
Any time following the successful completion of a create request.
Possibly, a user-mode application or Win32® component with a handle for the file object representing the target device object has requested a data transfer from the device. Possibly, a higher-level driver has created and set up the read IRP.
The driver’s I/O stack location in the IRP indicates how many bytes to transfer at Parameters.Read.Length.
Some drivers use the value at Parameters.Read.Key to sort incoming read requests into a driver-determined order in the device queue or in a driver-managed internal queue of IRPs. Certain types of drivers also use the value at Parameters.Read.ByteOffset, which indicates the starting offset for the transfer operation.
Depending on whether the underlying device driver sets up the target device object’s Flags with DO_BUFFERED_IO or with DO_DIRECT_IO, data is transferred into one of the following:
On receipt of a read request, a higher-level driver sets up the I/O stack location in the IRP for the next-lower driver, or it creates and sets up additional IRPs for one or more lower drivers. It can set up its IoCompletion routine, which is optional for the input IRP but required for driver-created IRPs, by calling IoSetCompletionRoutine. Then, the driver passes the request on to the next-lower driver with IoCallDriver.
On receipt of a read request, a device driver transfers data from its device to system memory. The device driver sets the Information field of the I/O status block to the number of bytes transferred when it completes the IRP.