Holding Incoming IRPs When A Device Is Paused
The drivers for a device must pause the device when its resources are being rebalanced. During resource rebalancing, some drivers pause the device in response to an IRP_MN_QUERY_STOP_DEVICE request and other drivers delay pausing the device until they receive the IRP_MN_STOP_DEVICE request. In either case, the device must be paused when the IRP_MN_STOP_DEVICE succeeds.
The drivers must finish any IRPs in progress on the device and refrain from starting any new IRPs that require access to the device.
To hold IRPs while a device is paused, a driver implements a procedure such as the following:
In its AddDevice routine, define a flag in the device extension with a name like HOLD_NEW_REQUESTS. Clear the flag.
Create a FIFO queue for holding IRPs.
If the driver already queues IRPs, it can reuse the same queue because the driver is required to finish any outstanding requests before pausing the device.
If the driver does not already have an IRP queue, it must create one in its AddDevice routine. What kind of queue it creates depends on how the driver flushes the queue. A driver might use an interlocked, doubly linked list and the ExInterlockedXxxList routines.
In its DispatchPnP code for IRP_MN_QUERY_STOP_DEVICE (or IRP_MN_STOP_DEVICE), finish any outstanding requests and set the HOLD_NEW_REQUESTS flag.
The driver's DispatchPnP routine must continue to process PnP IRPs rather than hold them and the DispatchPower routine must continue to process power IRPs.
In DispatchPnP, in response to a start or cancel-stop IRP, clear the HOLD_NEW_REQUESTS flag and start the IRPs in the IRP-holding queue.
These actions are probably the last steps for processing these PnP IRPs. For example, in response to a start IRP, the driver must first perform any operations to start the device and then it can start the IRPs in the IRP-holding queue.
Errors in processing IRPs from the IRP-holding queue do not affect the status returned for the start or cancel-stop IRPs.