6.3.3.1 DispatchReadWrite Using Buffered I/O

Any NT device driver that sets up its device objects for buffered I/O satisfies a read request by returning data transferred from its device into a locked down system-space buffer at Irp->AssociatedIrp.SystemBuffer. It satisfies a write request by transferring data from the same buffer out to its device.

Consequently, the DispatchReadWrite routine of such a device driver usually does the following on receipt of a transfer request:

  1. Calls IoGetCurrentIrpStackLocation and determines the direction of the transfer request if necessary.

  2. Checks the the validity of the parameters for the request.

    • For a read request, such a driver usually checks the driver’s IoStackLocation->Parameters.Read.Length value to determine whether the buffer is large enough to contain some discrete amount of data transferred from its device.

      For example, the system keyboard class driver processes read requests that come only from the Win32® user input thread. This driver defines a structure, KEYBOARD_INPUT_DATA, in which to store keystrokes from the device and, at any given moment, holds some number of these structures in an internal ring buffer in order to satisfy read requests as they come in.

    • For a write request, such a driver usually checks the value at Parameters.Write.Length, and checks the data at Irp->AssociatedIrp.SystemBuffer for validity if necessary: that is, if its device accepts only structured data packets containing members with defined value ranges.

  3. If any parameters are invalid, the DispatchReadWrite routine completes the IRP immediately, as already described in Section 6.2.2. Otherwise, the DispatchReadWrite passes the IRP on for further processing by other driver routines, as described in Section 6.2.4.

NT device drivers that use buffered I/O usually must satisfy a transfer request with some discrete amount of data that the originator of the request can use or set up. Such a driver is likely to define a structure for data coming in from or being sent to its device and is likely to buffer structured data internally as the system keyboard class driver does.

Drivers that buffer data internally should support IRP_MJ_FLUSH_BUFFERS requests, and can also support IRP_MJ_SHUTDOWN requests (see Section 6.1.2).

It is usually the responsibility of the highest-level driver in a chain to check the input IRP’s parameters before passing a read/write request on to lower drivers. Consequently, many lower-level NT drivers can assume that their I/O stack locations in a read/write IRP have valid parameters. The lowest-level driver in a chain is required to check the validity of the parameters in its I/O stack location if its device places constraints on data transfers known only to that device driver.