在系统 Set-Power IRP 响应中发送设备 Set-Power IRP

设备电源策略所有者应执行以下步骤来响应系统设置电源 IRP:

  1. 调用 IoAcquireRemoveLock,将当前 IRP 作为 Tag 参数传递,以确保驱动程序在处理电源 IRP 时不会收到即插即用IRP_MN_REMOVE_DEVICE请求。

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

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

  3. 在系统设置电源 IRP 中设置 IoCompletion 例程。

  4. 调用 IoMarkIrpPending 将系统设置电源 IRP 标记为挂起。

  5. 从 Windows Server 2003、Windows XP 和 Windows 2000 中的 Windows Vista) 或 PoCallDriver (开始调用 IoCallDriver (,) 将系统设置电源 IRP 传递给下一个较低的驱动程序。

  6. 从其 DispatchPower 例程返回STATUS_PENDING。

IoCompletion 例程 (请参阅前面列表中的步骤 3) ,设备电源策略所有者发送设备集电源 IRP,如下所示:

  1. 检查系统设置电源 IRP 以获取请求的系统电源状态。 为该系统电源状态选择适当的设备电源状态。 有关详细信息,请参阅 确定正确的设备电源状态

  2. 调用 PoRequestPowerIrp 为步骤 1 中确定的设备电源状态发送 IRP_MN_SET_POWER 。 即使设备已处于该状态,电源策略所有者也必须发送设备 set-power 请求。

  3. 在调用 PoRequestPowerIrp 时 (CompletionFunction) 指定电源完成回调例程,并在上下文缓冲区中传递系统 set-power IRP。

  4. IoCompletion 例程返回STATUS_MORE_PROCESSING_REQUIRED,以便驱动程序可以在电源完成回调例程中完成系统设置电源 IRP 的处理。

请记住,设备电源策略所有者不仅发送设备设置电源 IRP,而且还必须在它通过设备堆栈时处理此 IRP。 因此,设备电源策略所有者可能不仅具有与设备设置电源 IRP 关联的电源完成回调例程和系统设置电源 IRP 的 IoCompletion 例程,还可以具有设备集电源 IRP 的 IoCompletion 例程。 有关详细信息,请参阅 处理设备电源状态IRP_MN_SET_POWER

在 I/O 管理器调用所有设置为设备设置电源 IRP 的 IoCompletion 例程后,I/O 管理器调用电源完成回调例程。 此时,堆栈中的所有驱动程序都已完成设备设置电源 IRP,并且设备电源转换已完成。

电源完成回调例程必须执行以下操作:

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

  2. 完成系统设置电源 IRP (IoCompleteRequest) ,并返回设备设置电源 IRP 的状态。

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

  4. 返回设置电源 IRP 完成的状态。