待機/ウェイク IRP のキャンセル

待機/ウェイク IRP を送信したドライバーのみが、その IRP を取り消すことができます。

ドライバーは、次の状況で保留中の待機/ウェイク IRP を取り消す必要があります。

  • ドライバーは、デバイスの PnP IRP_MN_STOP_DEVICEIRP_MN_QUERY_REMOVE_DEVICEIRP_MN_REMOVE_DEVICE、またはIRP_MN_SURPRISE_REMOVAL要求を受け取ります。 ドライバーは、デバイスの再起動後に待機/ウェイク IRP (PoRequestPowerIrp) を再発行する必要があります。

  • システムはスリープ状態になりますが、デバイスを有効にしてシステムをスリープ解除することはできません。

    たとえば、USB ハブ ドライバーは、後で入力デバイスの 1 つをスリープ状態にした場合に備えて、デバイスの起動時に IRP_MN_WAIT_WAKE 要求を送信する場合があります。 システムが動作状態にある間、デバイスからのウェイク 信号はデバイスを動作状態に戻します (ただし、システムの電源状態には影響しません)。 システムがシャットダウンを準備すると、USB ハブ ドライバーは、デバイスがシステムを目覚めさせることはできません場合、この IRP を取り消します。

  • システムがスリープ状態に入り、そこからデバイスがスリープ状態に入り、そこからデバイスを目覚めさせることはできません。 つまり、DEVICE_CAPABILITIES 構造体で指定された SystemWake 値よりもパワーが低い状態に入ります。

  • デバイスが電源状態に入り、そこからウェイクアップ信号に応答できません。 つまり、DEVICE_CAPABILITIES構造体で指定された DeviceWake 値よりもパワーが低い状態に入ります。

待機/ウェイク IRP を取り消すには、IRP を送信したドライバーは IoCancelIrp を呼び出し、ドライバーが PoRequestPowerIrp を呼び出したときに以前に返された IRP へのポインターを渡します。

ドライバーは、送信されなかった待機/ウェイク IRP を取り消してはなりません。

待機/スリープ解除 IRP のキャンセル ルーチン

多くの関数ドライバーとバス ドライバーは、保留中の待機/スリープ解除 IRP の Cancel ルーチンを設定する必要があります。次の種類のドライバーは、このようなルーチンを設定する必要があります。

  • ウェイクアップを有効または無効にするためにデバイス設定を変更するドライバー。

  • 親デバイスのドライバーに IRP_MN_WAIT_WAKE 要求を送信するドライバー。

Cancel ルーチンを使用すると、ドライバーは、そのデバイスのウェイク アップを無効にし、保留中の待機/ウェイク IRP に関連するすべてのデータをクリーンできます。 親デバイスの待機/スリープ解除 IRP を要求するドライバーは、これらの IRP も取り消すことができます。

待機/スリープ解除 Cancel ルーチンでは、ドライバーは次の手順を実行する必要があります。

  1. IoSetCancelRoutine を呼び出して、IRP の Cancel ルーチンを NULL にリセットします。

  2. IoReleaseCancelSpinLock を呼び出し、IRP で指定された CancelIRQL を渡して、IRP のキャンセル スピン ロックを解放します。

  3. デバイス拡張機能の関連フィールドをリセットします。 たとえば、待機/ウェイク IRP が保留中の場合、ほとんどのドライバーはフラグを設定し、デバイス拡張機能で IRP へのポインターを保持します。

    別のこのような IRP を取り消している間に、ドライバーが待機/ウェイク IRP を受け取る可能性があることに注意してください。 ドライバーは、スピン ロック保護 (またはそれに相当する) の下に IRP が既にあるかどうかを確認するチェック必要があります。 その場合、ドライバーは慎重に正しい IRP を取り消すために、その処理を同期する必要があります。 Cancel ルーチンでのスピン ロックの使用の詳細については、「IRP のキャンセル」を参照してください。

  4. 必要なデバイス設定を変更します。 たとえば、モデム ドライバーは、デバイスのウェイク設定を無効にします。

  5. Irp->IoStatus.Status を STATUS_CANCELLED に設定します。

  6. IoCompleteRequest を呼び出して待機/ウェイク IRP を完了し、IO_NO_INCREMENTを指定します。

  7. ドライバーが以前に親デバイスの関連する IRP_MN_WAIT_WAKE を要求した場合、ドライバーは Cancel ルーチン内 からその IRP を取り消す必要があります。 ドライバーは、親の IRP を取り消す前に、キャンセル スピン ロックを解放する必要があります。

    たとえば、デバイスのバス ドライバーとして機能し、その親の電源ポリシー ドライバーを所有するドライバーは、以前に親に送信された関連する待機/ウェイク IRP を取り消す必要があります。 IoCancelIrp を呼び出すと、親の Cancel ルーチンが呼び出され、デバイス スタックがダウンします。