设备暂停时保持传入的 IRP

在重新平衡设备资源时,设备的驱动程序必须暂停设备。 在资源重新均衡期间,某些驱动程序会暂停设备以响应 IRP_MN_QUERY_STOP_DEVICE 请求,而其他驱动程序会延迟暂停设备,直到收到 IRP_MN_STOP_DEVICE 请求。 在任一情况下,当 IRP_MN_STOP_DEVICE 成功时,设备都必须暂停。

驱动程序必须完成设备上正在进行的任何 IRP,并避免启动任何需要访问设备的新 IRP。

若要在设备暂停时保留 IRP,驱动程序将实现如下过程:

  1. 在其 AddDevice 例程中,使用类似于 HOLD_NEW_REQUESTS 的名称在设备扩展中定义标志。 清除标志。

  2. 创建用于存放 IRP 的 FIFO 队列。

    如果驱动程序已对 IRP 进行排队,则可以重复使用同一队列,因为驱动程序需要在暂停设备之前完成任何未完成的请求。

    如果驱动程序还没有 IRP 队列,则必须在其 AddDevice 例程中创建一个。 它创建的队列类型取决于驱动程序刷新队列的方式。 驱动程序可能使用互锁、双链接列表和 ExInterlockedXxx列表 例程。

  3. 在其用于IRP_MN_QUERY_STOP_DEVICE (IRP_MN_STOP_DEVICE) 的 DispatchPnP 代码中,完成所有未完成的请求并设置HOLD_NEW_REQUESTS标志。

  4. 在访问设备的调度例程(如 DispatchWriteDispatchRead)中,检查是否设置了HOLD_NEW_REQUESTS标志。 如果是这样,驱动程序必须将 IRP 标记为挂起并将其排队。

    驱动程序的 DispatchPnP 例程必须继续处理 PnP IRP,而不是保留它们, DispatchPower 例程必须继续处理电源 IRP。

  5. DispatchPnP 中,为了响应启动或取消-停止 IRP,请清除HOLD_NEW_REQUESTS标志并启动 IRP 保留队列中的 IRP。

    这些操作可能是处理这些 PnP IRP 的最后步骤。 例如,为了响应启动 IRP,驱动程序必须先执行任何操作来启动设备,然后才能启动 IRP 持有队列中的 IRP。

    处理 IRP 持有队列中的 IRP 时出错不会影响为启动或取消-停止 IRP 返回的状态。