A User Unplugs a Device
While a system is running, a user can remove a device in one of two ways: by orderly removal, which means that the user informs the system that the device is about to be removed (for example, by using the Unplug or Eject Hardware program); or by surprise removal, which means that the user unplugs the device without informing the system. If the bus supports surprise removal (for example, USB), the device's drivers must be able to handle the device's sudden disappearance.
Orderly Removal
The user requests removal by using the system's Unplug or Eject Hardware program, by disabling the device by using Device Manager, or by pushing an ejectable device's eject button. The framework allows the device to be removed or disabled, unless the driver has:
Called WdfDeviceSetSpecialFileSupport and a special file is open on the device.
Called WdfDeviceSetStaticStopRemove.
Supplied an EvtDeviceQueryRemove callback function, and the callback function has vetoed the removal.
For each function and filter driver that supports the device, the framework does the following, in sequence, one driver at a time, starting with the driver that is highest in the driver stack:
If the driver is using self-managed I/O, the framework calls the driver's EvtDeviceSelfManagedIoSuspend callback function.
The framework stops all of the driver's power-managed I/O queues.
If the hardware and driver support DMA, the framework calls the driver's EvtDmaEnablerSelfManagedIoStop, EvtDmaEnablerFlush, and EvtDmaEnablerDisable callback functions (if they exist) for each DMA channel that was created.
The framework calls the driver's EvtDeviceD0ExitPreInterruptsDisabled callback function (if it exists), and then calls the driver's EvtInterruptDisable callback function (if it exists) for each interrupt so that the driver can disable device interrupts.
The framework calls the driver's EvtDeviceD0Exit callback function (if it exists).
The framework calls the driver's EvtDeviceReleaseHardware callback function (if it exists), passing it the list of hardware resources that the PnP manager has assigned to the device.
If the driver is using self-managed I/O, the framework calls the driver's EvtDeviceSelfManagedIoFlush callback function.
If the driver is using self-managed I/O, the framework calls the driver's EvtDeviceSelfManagedIoCleanup callback function.
The bus driver is the driver in the stack that is called last. When the framework calls the bus driver's EvtDeviceD0Exit callback function, the callback function sets the power state of the device (a child device of the bus) to D3. The bus driver can control when the framework calls its EvtDeviceReleaseHardware callback function by calling WdfDeviceInitSetReleaseHardwareOrderOnFailure.
Surprise Removal
A user unplugs a device unexpectedly. The bus driver for the device's bus discovers that the device is missing and calls WdfChildListUpdateChildDescriptionAsMissing.
For each function and filter driver that supports the device, the framework does the following, in sequence, one driver at a time, starting with the driver that is highest in the driver stack:
- The framework calls the driver's EvtDeviceSurpriseRemoval callback function (if it exists).
- If the device was in its working (D0) state when it was unplugged:
- The framework stops all of the driver's power-managed I/O queues.
- If the driver is using self-managed I/O, the framework calls the driver's EvtDeviceSelfManagedIoSuspend callback function.
- If the hardware and driver support DMA, the framework calls the driver's EvtDmaEnablerSelfManagedIoStop, EvtDmaEnablerFlush, and EvtDmaEnablerDisable callback functions (if they exist) for each DMA channel that was created.
- The framework calls the driver's EvtDeviceD0ExitPreInterruptsDisabled and EvtInterruptDisable callback functions (if they exist) so that the driver can disable device interrupts.
- The framework calls the driver's EvtDeviceD0Exit callback function (if it exists).
- The framework calls the driver's EvtDeviceReleaseHardware callback function (if it exists), passing the list of hardware resources that the PnP manager has assigned to the device.
- If the driver is using self-managed I/O, the framework calls the driver's EvtDeviceSelfManagedIoFlush callback function.
- If the driver is using self-managed I/O, the framework calls the driver's EvtDeviceSelfManagedIoCleanup callback function.
Note that a device can be unexpectedly removed at any time. Therefore, the framework might call the driver's EvtDeviceSurpriseRemoval callback function at a time other than that shown in the previous steps. For example, if a user unexpectedly unplugs the device while it is entering a low-power state, the framework might call the EvtDeviceSurpriseRemoval callback function after it calls the EvtDeviceReleaseHardware callback function. You must not code an EvtDeviceSurpriseRemoval callback function in a manner that assumes that it and other callback functions are called in a particular sequence.
In addition, the framework does not synchronize a device's EvtDeviceSurpriseRemoval callback function with any of the callback functions listed in the previous steps for that device. Therefore, the EvtDeviceSurpriseRemoval callback function might run while another of the previously listed callback functions is also running.