December 1997

Microsoft Systems Journal Homepage

Processing I/O Requests

The I/O system creates an IRP to describe each unit of work to be performed by the stacked drivers for a device, and it creates an IO_STACK_LOCATION for the exclusive use of each driver in the stack. In the case of I/O requests that involve data transfer, the I/O system also creates auxiliary data structures describing the memory buffers to be used. It passes the initialized IRP to the dispatch routine for the major function type contained in the IRP. This sidebar presents an overview of how the dispatch routine handles the request from then on. Details of each of the alternatives appear in various parts of the article. A dispatch routine may complete the request without delay and without involving other drivers. If the IRP contains erroneous parameters, for example, the appropriate action for a dispatch routine that recognizes the error would be to complete the request with an error status. To complete a request, the dispatch routine sets the Status and Information fields of the IoStatus member of the IRP, calls IoCompleteRequest, and returns a status code equaling the value placed into IoStatus.Status. The CompleteRequest routine in the sample driver illustrates the necessary mechanics for performing these functions (see Figure 2). A dispatch routine may instead pend the request by placing it into a queue for later processing. A standard way of pending and queuing a request is to call IoMarkIrpPending to mark the IRP pending and IoStartPacket to queue the request for processing by the driver's StartIo routine. The dispatch routine then returns STATUS_PENDING to indicate that the request will complete asynchronously. Later on, some other routine within the driver will set the IoStatus fields and make the requisite call to IoCompleteRequest. A dispatch routine's third option is to pass the request down the driver stack. If the driver wants to inspect the results of the lower drivers' processing, it may establish an I/O completion routine and then call IoCallDriver to pass the request down. The completion routine eventually regains control of the IRP to perform the desired postprocessing. If the driver is indifferent to what happens to the request, it can simply call IoCallDriver to pass the request down. In either case, the dispatch routine must take some care to maintain the IRP stack pointer.