次の方法で共有


ファンクション ドライバーでのデバイスの削除

デバイスを削除するとき、フィルター ドライバーは、デバイスを追加して起動するために実行したすべての操作を元に戻す必要があります。 この説明では、周辺機器の関数ドライバーとバス デバイスの関数ドライバーが含まれます。

関数ドライバーは、DispatchPnP ルーチンで、次のようなプロシージャを使用してデバイスを削除します。

  1. これはバス デバイスの関数ドライバーですか?

    その場合は、バス上のデバイスの未処理の子 PDO が削除される可能性があります。

    バス ドライバーが子デバイスの以前の IRP_MN_SURPRI Standard Edition_REMOVAL要求を処理し、ドライバーがまだ後続の IRP_MN_REMOVE_DEVICE 要求を受け取っていなければ、バス ドライバーは子 PDO をそのまま残します。 後で、子デバイスへのすべてのハンドルが閉じられると、PnP マネージャーは子デバイスの削除 IRP を送信し、バス ドライバーはその時点で子 PDO を削除します。

    バス ドライバーがデバイスの以前の IRP_MN_REMOVE_DEVICE 要求を処理し、後続の IRP_MN_SURPRI Standard Edition_REMOVAL 要求がなければ、バス ドライバーは子 PDO を削除します。 この場合、PnP マネージャーは、親バス デバイスに削除 IRP を送信する前に、すべての関数ドライバーとフィルター ドライバーが子デバイスから削除されていること (FDO とフィルターの DO が削除されていること) を確認します。 子 PDO がまだ存在する可能性があるため、バス ドライバーは、バス デバイスを削除する前に子 PDO を削除する必要があります。

  2. ドライバーは、現在の FDO に対する以前の IRP_MN_SURPRI Standard Edition_REMOVAL 要求を処理済みでますか?

    その場合は、残りのクリーンアップを実行し、手順 8 の IoCallDriver に進みます。

    通常、ドライバーは、デバイスの IRP_MN_SURPRI Standard Edition_REMOVAL 要求を処理したかどうかを示すフラグをデバイス拡張機能で管理します。

  3. ドライバーが以前にデバイスのウェイクアップを有効にした場合は、IRP_MN_WAIT_WAKE 要求を取り消します。

  4. デバイスが非アクティブになっていることを確認します。

    デバイスが以前の IRP_MN_QUERY_REMOVE_DEVICEに対応してまだ非アクティブになっていない場合、ドライバーは、新しい要求を受け入れないことをデバイスにマークし、現在のドライバーでキューに登録されている要求を完了する必要があります。 このデバイスへのアクセスを必要とする未処理の要求に、ドライバーは必ず失敗します。

    ドライバーは、 IoXxxRemoveLockXxx ルーチンで未処理の I/O をカウントし、削除処理を続行できることを示すイベントを設定することができます。

  5. 電源を切る操作を実行します。

    デバイスの各ドライバーは、IRP_MN_REMOVE_DEVICE 要求を受け取ったときに、その電源ダウン操作 (ある場合) を実行します。 デバイスの電源ポリシー所有者 (通常はファンクション ドライバー) は、デバイスの電源状態を D3 に設定するために、個別の IRP_MN_Standard Edition T_POWER 要求を送信しません。 通常、親バス ドライバーはスロットの電源を切り、バス ドライバーが IRP の削除を取得したときに PoSetPowerState で電源マネージャーに通知します。 詳細については、「電源管理」を参照してください

  6. IoSetDeviceInterfaceState を呼び出して、デバイス インターフェイスを無効にします。

  7. ドライバーで使用中のデバイスのハードウェア リソースを解放します。

    個々の操作はデバイスとドライバーによって異なりますが、IoDisconnectInterrupt による割り込みの切断、MmUnmapIoSpace による物理アドレス範囲の解放、I/O ポートの解放などがあります。

  8. IRP_MN_REMOVE_DEVICE 要求を次のドライバーに渡します。

    IoSkipCurrentIrpStackLocation で次の下位ドライバーの IRP スタックの場所をセット アップし、IoCallDriver で次のドライバーに IRP を渡します。

    ドライバーは、その削除アクティビティを続行する前に、下位ドライバーによる削除操作を完了するまで待つ必要はありません。

  9. IoDetachDevice でデバイス スタックからデバイス オブジェクトを削除します

    TargetDevice パラメーターとして、次の下位デバイス オブジェクトへのポインターを指定します。 ドライバーは、IoAttachDeviceToDeviceStack への呼び出しからこのようなポインターをドライバーの AddDevice ルーチンで受け取ります。

  10. デバイス固有の割り当て、メモリ、イベントなどをクリーン アップします。

  11. IoDeleteDeviceでFDO を解放します。

  12. DispatchPnP ルーチンから戻り、IoCallDriver からの戻りステータスを伝達します。

関数ドライバーは、削除 IRP の IoCompletion ルーチンを指定せず、IRP を完了しません。 削除 IRP は、親バス ドライバーが完了します。