ユーザーがデバイスを取り外す
システムの実行中、ユーザーは 2 つの方法のいずれかでデバイスを削除できます。順序正しい取り外しとは、デバイスがこれから取り外されることをユーザーがシステムに通知するものです (たとえば、Unplug or Eject Hardwareプログラムを使用)。突然の取り外しでは、ユーザーはシステムに通知せずにデバイスを取り外します。 バスが突然の取り外しをサポートしている場合 (USB など)、デバイスのドライバーは、デバイスが突然消失することに対応できる必要があります。
順序正しい取り外し
ユーザーは、システムの Unplug or Eject Hardware プログラムを使用するか、デバイス マネージャーを使用してデバイスを無効にするか、取り出し可能なデバイスの取り出しボタンを押すことによって、取り外しを要求します。 フレームワークを使用すると、ドライバーが次の場合でない限り、デバイスを削除または無効にすることができます。
WdfDeviceSetSpecialFileSupport を呼び出し、特殊ファイルがデバイスで開かれている。
WdfDeviceSetStaticStopRemove を呼び出した。
EvtDeviceQueryRemove コールバック関数を指定し、コールバック関数が取り外しを拒否した。
デバイスをサポートする関数とフィルター ドライバーごとに、フレームワークは、ドライバー スタックで最も高いドライバーから始めて、ドライバーを 1 つずつ順番に、次の処理を行います。
ドライバーが自己管理 I/O を使用している場合、フレームワークはドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。
フレームワークは、ドライバーの電源管理 I/O キューをすべて停止します。
ハードウェアとドライバーが DMA をサポートしている場合、フレームワークは、作成された各 DMA チャネルのドライバーの EvtDmaEnablerSelfManagedIoStop、EvtDmaEnablerFlush、EvtDmaEnablerDisable コールバック関数 (存在する場合) を呼び出します。
フレームワークは、ドライバーの EvtDeviceD0ExitPreInterruptsDisabled コールバック関数 (存在する場合) を呼び出し、ドライバーがデバイスの割り込みを無効にできるように、割り込みごとにドライバーの EvtInterruptDisable コールバック関数 (存在する場合) を呼び出します。
フレームワークは、ドライバーの EvtDeviceD0Exit コールバック関数を呼び出します (存在する場合)。
フレームワークは、ドライバーの EvtDeviceReleaseHardware コールバック関数 (存在する場合) を呼び出し、PnP マネージャーがデバイスに割り当てたハードウェア リソースの一覧を渡します。
ドライバーが自己管理 I/O を使用している場合、フレームワークはドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。
ドライバーが自己管理 I/O を使用している場合、フレームワークはドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。
バス ドライバーは、スタック内の最後に呼び出されるドライバーです。 フレームワークがバス ドライバーの EvtDeviceD0Exit コールバック関数を呼び出すと、コールバック関数はデバイス (バスの子デバイス) の電源状態を D3 に設定します。 バス ドライバーは、フレームワークが WdfDeviceInitSetReleaseHardwareOrderOnFailure を呼び出すことによって、その EvtDeviceReleaseHardware コールバック関数を呼び出すタイミングを制御できます。
突然の取り外し
ユーザーが予期せずデバイスを取り外しました。 デバイスのバスのバス ドライバーは、デバイスが見つからないことを検出し、WdfChildListUpdateChildDescriptionAsMissing を呼び出します。
デバイスをサポートする関数とフィルター ドライバーごとに、フレームワークは、ドライバー スタックで最も高いドライバーから始めて、ドライバーを 1 つずつ順番に、次の処理を行います。
- フレームワークは、ドライバーの EvtDeviceSurpriseRemoval コールバック関数 (存在する場合) を呼び出します。
- デバイスの取り外し時にデバイスが動作 (D0) 状態であった場合:
- フレームワークは、ドライバーの電源管理 I/O キューをすべて停止します。
- ドライバーが自己管理 I/O を使用している場合、フレームワークはドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。
- ハードウェアとドライバーが DMA をサポートしている場合、フレームワークは、作成された各 DMA チャネルのドライバーの EvtDmaEnablerSelfManagedIoStop、EvtDmaEnablerFlush、EvtDmaEnablerDisable コールバック関数 (存在する場合) を呼び出します。
- フレームワークは、ドライバーの EvtDeviceD0ExitPreInterruptsDisabled コールバック関数と EvtInterruptDisable コールバック関数 (存在する場合) を呼び出して、ドライバーがデバイスの割り込みを無効にできるようにします。
- フレームワークは、ドライバーの EvtDeviceD0Exit コールバック関数を呼び出します (存在する場合)。
- フレームワークは、ドライバーの EvtDeviceReleaseHardware コールバック関数 (存在する場合) を呼び出し、PnP マネージャーがデバイスに割り当てたハードウェア リソースの一覧を渡します。
- ドライバーが自己管理 I/O を使用している場合、フレームワークはドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。
- ドライバーが自己管理 I/O を使用している場合、フレームワークはドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。
デバイスはいつでも予期せず削除される可能性があることに注意してください。 そのため、フレームワークは、前の手順で示した以外のタイミングでドライバーの EvtDeviceSurpriseRemoval コールバック関数を呼び出す可能性があります。 たとえば、低電力状態に入っている間にユーザーが予期せずデバイスを取り外した場合、フレームワークは EvtDeviceReleaseHardware コールバック関数を呼び出した後に EvtDeviceSurpriseRemoval コールバック関数を呼び出す可能性があります。 EvtDeviceSurpriseRemoval コールバック関数は、そのコールバック関数とその他のコールバック関数が特定のシーケンスで呼び出されることを前提にコーディングしないでください。
さらに、フレームワークは、デバイスの EvtDeviceSurpriseRemoval コールバック関数を、前の手順で示したそのデバイスのコールバック関数と同期しません。 したがって、 EvtDeviceSurpriseRemoval コールバック関数は、前に示したコールバック関数の別の関数も実行されている間に実行される可能性があります。