Dispatching IRPs to I/O Queues

[Applies to KMDF and UMDF]

A framework-based driver can dynamically specify a target queue for an incoming IRP. To dispatch an IRP to a specific queue, a driver must call the WdfDeviceWdmDispatchIrpToIoQueue method.

Typically, a driver calls WdfDeviceWdmDispatchIrpToIoQueue from either its EvtDeviceWdmIrpPreprocess or EvtDeviceWdmIrpDispatch callback function. For best performance, most drivers do not provide both callback functions.

Note  A UMDF driver can supply a EvtDeviceWdmIrpDispatch callback function, but only KMDF drivers can provide EvtDeviceWdmIrpPreprocess.

If your driver already provides EvtDeviceWdmIrpPreprocess, you can use it to dynamically select a queue. If not, provide EvtDeviceWdmIrpDispatch and call WdfDeviceWdmDispatchIrpToIoQueue from within that callback function.

In addition, you should be aware of the following:

Dispatching Non-Preprocessed IRPs

To dispatch IRPs from a driver's EvtDeviceWdmIrpDispatch callback function, use the following procedure:

  1. From its EvtDriverDeviceAdd callback function, the driver calls WdfDeviceConfigureWdmIrpDispatchCallback to register a EvtDeviceWdmIrpDispatch callback function.

    If the target is the parent device's I/O queue, a KMDF driver must call WdfPdoInitAllowForwardingRequestToParent before it calls WdfDeviceCreate. If a KMDF driver has also provided a EvtDeviceWdmIrpPreprocess callback function, the framework calls that function first when an IRP arrives. After the callback function preprocesses the request, it calls WdfDeviceWdmDispatchPreprocessedIrp to return the IRP to the framework.

  2. The framework calls the driver's EvtDeviceWdmIrpDispatch callback function.

  3. From within EvtDeviceWdmIrpDispatch, the driver can call either WdfDeviceWdmDispatchIrpToIoQueue or WdfDeviceWdmDispatchIrp, but not both. A KMDF driver has the additional option of calling neither of these methods, and instead completing the IRP or marking it pending.

  4. If a KMDF driver has set the WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK flag and has not enabled guaranteed forward progress for the target I/O queue, the framework then calls the driver's EvtIoInCallerContext, if provided. After preprocessing the request, the callback function must either queue it by calling WdfDeviceEnqueueRequest or complete it by calling WdfRequestComplete.

Dispatching Preprocessed IRPs

To dispatch IRPs from a driver's EvtDeviceWdmIrpPreprocess callback function to a specific I/O queue, use the following procedure:

  1. The driver registers a EvtDeviceWdmIrpPreprocess callback function by calling WdfDeviceInitAssignWdmIrpPreprocessCallback.
  2. The driver calls WdfPdoInitAllowForwardingRequestToParent if the target is the parent device's I/O queue.
  3. From EvtDeviceWdmIrpPreprocess, call WdfDeviceWdmDispatchIrpToIoQueue with Flags set to WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP.
  4. If the driver has set the WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK flag and has not enabled guaranteed forward progress for the target I/O queue, the framework then calls the driver's EvtIoInCallerContext, if provided. After the callback function has finished preprocessing the request, it must either queue it by calling WdfDeviceEnqueueRequest or complete it by calling WdfRequestComplete.