Methods for Accessing Data Buffers

One of the primary responsibilities of driver stacks is transferring data between user-mode applications and a system's devices. The operating system provides the following three methods for accessing data buffers:

Buffered I/O
The operating system creates a nonpaged system buffer, equal in size to the application's buffer. For write operations, the I/O manager copies user data into the system buffer before calling the driver stack. For read operations, the I/O manager copies data from the system buffer into the application's buffer after the driver stack completes the requested operation.

For more information, see Using Buffered I/O.

Direct I/O
The operating system locks the application's buffer in memory. It then creates a memory descriptor list (MDL) that identifies the locked memory pages, and passes the MDL to the driver stack. Drivers access the locked pages through the MDL.

For more information, see Using Direct I/O.

Neither Buffered Nor Direct I/O
The operating system passes the application buffer's virtual starting address and size to the driver stack. The buffer is only accessible from drivers that execute in the application's thread context.

For more information, see Using Neither Buffered Nor Direct I/O.

For IRP_MJ_READ and IRP_MJ_WRITE requests, drivers specify the I/O method by using flags in each DEVICE_OBJECT structure. For more information, see Initializing a Device Object.

For IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL requests, the I/O method is determined by the TransferType value that is contained in each IOCTL value. For more information, see Defining I/O Control Codes.

All drivers in a driver stack must use the same buffer access method for each request, except possibly for the highest-level driver (which can use the "neither" method, regardless of the method used by lower drivers).