Most NT device and all intermediate drivers set a bit in the DeviceObject->Flags, shown in Figure 3.2, by ORing the Flags either with DO_BUFFERED_IO or with DO_DIRECT_IO in each device object they create. NT drivers must use one of the following three ways to access user buffers for data transfers:
Generally, NT video, keyboard, mouse, serial, and parallel drivers request buffered I/O.
Any NT intermediate driver layered above such a device driver must set up its DeviceObject->Flags to match that of the next-lower-level driver.
Generally, NT mass-storage device drivers request direct I/O for transfer requests, including lowest-level drivers that use DMA or PIO, as well as any intermediate drivers chained above them.
Even drivers that request direct I/O use buffered I/O to satisfy certain IRPs. In particular, the system-defined, device-type-specific I/O control codes for IRP_MJ_DEVICE_CONTROL requests that require data transfers are buffered, whether a driver has ORed its device objects’ Flags with DO_DIRECT_IO or not.
Any NT intermediate driver layered above such a device driver must set up its DeviceObject->Flags to match that of the next-lower driver.
The following subsections describe how ORing device objects’ Flags with DO_BUFFERED_IO, DO_DIRECT_IO, or neither affects data transfer requests sent to NT drivers, including how the data can be stored in physical memory and how a driver can access that memory.