处理设备电源策略所有者中的系统 Query-Power IRP

当设备电源策略所有者收到系统电源状态 的IRP_MN_QUERY_POWER 时,它会通过传递查询进行响应,并在 IoCompletion 例程中发送设备电源状态 的IRP_MN_QUERY_POWER 。 当堆栈中的所有驱动程序都已完成设备查询后,设备电源策略所有者将完成系统查询。

设备电源策略所有者应在其 DispatchPower 例程 中执行以下步骤来响应系统查询:

  1. 调用 IoAcquireRemoveLock,传递当前 IRP,以确保驱动程序在处理电源 IRP 时不会收到 PnP IRP_MN_REMOVE_DEVICE 请求。

    如果 IoAcquireRemoveLock 返回失败状态,驱动程序不应继续处理 IRP。 相反,从 Windows Vista 开始,驱动程序应调用 IoCompleteRequest 来完成 IRP 并返回失败状态。 在 Windows Server 2003、Windows XP 和 Windows 2000 中,驱动程序应调用 PoStartNextPowerIrp,调用 IoCompleteRequest 以完成 IRP,并返回失败状态。

  2. 确保驱动程序可以支持查询的系统电源状态,如 在筛选器或函数驱动程序中使系统Query-Power IRP 失败中所述。 如果没有,请使用该部分中所述的失败状态完成 IRP。

    但是,如果驱动程序的设备启用了唤醒,但无法将系统从休眠状态唤醒,则驱动程序不能使 S4 (PowerSystemHibernate) 查询失败。 在这种情况下,发送IRP_MN_WAIT_WAKE) 的驱动程序 (的电源策略所有者必须取消等待/唤醒 IRP 并成功执行系统查询。 有关详细信息,请参阅 取消等待/唤醒 IRP

  3. 如果驱动程序可以支持查询的系统电源状态,请调用 IoMarkIrpPending

  4. 通过调用 IoCopyCurrentIrpStackLocationToNext 为下一个较低级别的驱动程序设置 IRP 堆栈位置。

  5. 在系统查询电源 IRP 中设置 IoCompletion 例程。

  6. Windows Server 2003、Windows XP 和 Windows 2000) 中调用 Windows 7 和 Windows Vista) 或 PoCallDriver (中的 IoCallDriver (,将 IRP 传递给下一个较低的驱动程序。

  7. 返回STATUS_PENDING。

IoCompletion 例程应执行以下操作:

  1. 检查 Irp-IoStatus.Status> 以确保较低级别的驱动程序已成功完成 IRP。 如果较低的驱动程序指定了不成功的 NTSTATUS 值, IoCompletion 例程应返回 NTSTATUS 值。

  2. 如果较低的驱动程序已成功完成 IRP,则调用 PoRequestPowerIrp 以发送设备查询电源 IRP,以获取对查询的系统电源状态有效的设备电源状态。 如有必要,请查阅DEVICE_CAPABILITIES结构中的 DEVICE_STATE 数组,以确定哪些设备电源状态对查询的系统电源状态有效。

  3. 在对 PoRequestPowerIrp 的调用中) 指定 (CompletionFunction 参数的回调例程,并在上下文区域中传递系统 IRP。

  4. 返回STATUS_MORE_PROCESSING_REQUIRED,以便驱动程序可以在回调例程中完成系统查询 IRP 的处理。

完成 IRP 并运行 IRP 处理期间设置的所有 IoCompletion 例程后,电源管理器通过 I/O 管理器调用电源策略管理器的回调例程 (CompletionFunction 参数到 PoRequestPowerIrp) 。 回调例程反过来必须执行以下操作:

  1. 调用 PoStartNextPowerIrp 以启动下一个电源 IRP。 仅 (Windows Server 2003、Windows XP 和 Windows 2000。)

  2. 完成系统查询电源 IRP (使用设备查询电源 IRP 返回的状态调用 IoCompleteRequest) 。

  3. 调用 IoReleaseRemoveLock 以释放以前获取的锁。

请记住,设备电源策略所有者不仅发送设备查询,而且还必须在设备堆栈中处理它。 有关详细信息,请参阅 处理设备电源状态的IRP_MN_QUERY_POWER