デバイス電源ポリシー オーナーでのシステム電源クエリ 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. フィルターまたはファンクション ドライバーでのシステム クエリ Power IRP の失敗」の説明に従って、ドライバーがクエリ対象のシステム電源状態をサポートできることを確認します。 できない場合、そのセクションの説明に従って、エラー ステータスを使用して IRP を完了します。

    ただし、デバイスでウェイクアップが有効になっているが、システムを休止状態から復帰できない場合、ドライバーは S4 (PowerSystemHibernate) のクエリを失敗させることはできません。 この場合、(IRP_MN_WAIT_WAKE を送信した) ドライバーの電源ポリシー所有者は、待機/ウェイク IRP を取り消し、システム クエリに成功する必要があります。 詳細については、「待機/ウェイク IRP の取り消し」を参照してください。

  3. ドライバーがクエリ対象のシステム電源状態をサポートできる場合、IoMarkIrpPending を呼び出 します。

  4. IoCopyCurrentIrpStackLocationToNext を呼び出して、次の下位ドライバーの IRP スタック位置を設定します。

  5. システム クエリ電源 IRP で IoCompletion ルーチンを設定します。

  6. IoCallDriver (Windows 7 と Windows Vista の場合) を呼び出すか、PoCallDriver (Windows Server 2003、Windows XP、Windows 2000 の場合) を呼び出し、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. ドライバーがコールバック ルーチンでシステム クエリ IRP の処理を完了できるよう、STATUS_MORE_PROCESSING_REQUIRED を返します。

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 の処理」を参照してください。