The Windows 2000 and later PnP manager sends this IRP to notify drivers that a device is no longer available for I/O operations and has probably been unexpectedly removed from the machine ("surprise removal").
The PnP manager sends an IRP_MN_SURPRISE_REMOVAL request for the following reasons:
If the bus has hot-plug notification, it notifies the device's parent bus driver that the device has disappeared. The bus driver calls IoInvalidateDeviceRelations. In response, the PnP manager queries the bus driver for its children (IRP_MN_QUERY_DEVICE_RELATIONS for BusRelations). The PnP manager determines that the device is not in the new list of children and initiates its surprise-removal operations for the device.
The bus is enumerated for another reason and the surprise-removed device is not included in the list of children. The PnP manager initiates its surprise removal operations.
The function driver for the device determines that the device is no longer present (because, for example, its requests repeatedly time out). The bus might be enumerable but it does not have hot-plug notification. In this case, the function driver calls IoInvalidateDeviceState. In response, the PnP manager sends an IRP_MN_QUERY_PNP_DEVICE_STATE request to the device stack. The function driver sets the PNP_DEVICE_FAILED flag in the PNP_DEVICE_STATE bitmask indicating that the device has failed.
All PnP drivers must handle this IRP and must set Irp->IoStatus.Status to STATUS_SUCCESS. A driver for a PnP device must be prepared to handle IRP_MN_SURPRISE_REMOVAL at any time after the driver's AddDevice routine is called. Proper handling of the IRP enables the drivers and the PnP manager to:
Disable the device, in case it is still connected.
Release hardware resources assigned to the device and make them available to another device.
As soon as a device is no longer available, its hardware resources should be freed. The PnP manager can then reassign the resources to another device, including the same device, which a user might hot-plug back into the machine.
Minimize the risk of data loss and system disruption.
Devices that support hot-plugging and their drivers should be designed to handle surprise removal. Users expect to be able to remove devices that support hot-plugging at any time.
The PnP manager sends an IRP_MN_SURPRISE_REMOVAL at IRQL = PASSIVE_LEVEL in the context of a system thread.
The PnP manager sends this IRP to drivers before notifying user-mode applications and other kernel-mode components. After the IRP completes, the PnP manager sends an EventCategoryTargetDeviceChange notification with GUID_TARGET_DEVICE_REMOVE_COMPLETE to kernel-mode components that registered for such notification on the device.
The IRP_MN_SURPRISE_REMOVAL IRP is handled first by the top driver in the device stack and then by each next lower driver.
In response to IRP_MN_SURPRISE_REMOVAL, a driver must do the following, in the listed order:
Determine if the device has been removed.
The driver must always attempt to determine if the device is still connected. If it is, the driver must attempt to stop the device and disable it.
Release the device's hardware resources (interrupts, I/O ports, memory registers, and DMA channels).
Prevent any new I/O operations on the device.
A driver should process subsequent IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_POWER, and IRP_MJ_PNP requests, but the driver must prevent any new I/O operations. A driver must fail any subsequent IRPs that the driver would have handled if the device were present, besides close, clean-up, and PnP IRPs.
A driver can set a bit in the device extension to indicate that the device has been surprise-removed. The driver's dispatch routines should check this bit.
Fail outstanding I/O requests on the device.
Continue to pass down any IRPs that the driver does not handle for the device.
Disable device interfaces with IoSetDeviceInterfaceState.
Clean up any device-specific allocations, memory, events, or other system resources.
A driver could postpone such clean-up until it receives the subsequent IRP_MN_REMOVE_DEVICE request, but if a legacy component has an open handle that cannot be closed, the remove IRP will never be sent.
Leave the device object attached to the device stack.
Do not detach and delete the device object until the subsequent IRP_MN_REMOVE_DEVICE request.
Finish the IRP.
In a function or filter driver:
Set Irp->IoStatus.Status to STATUS_SUCCESS.
Propagate the status from IoCallDriver as the return status from the DispatchPnP routine.
Do not complete the IRP.
In a bus driver (that is handling this IRP for a child PDO):
Set Irp->IoStatus.Status to STATUS_SUCCESS.
Complete the IRP (IoCompleteRequest) with IO_NO_INCREMENT.
Return from the DispatchPnP routine.
After this IRP succeeds and all open handles to the device are closed, the PnP manager sends an IRP_MN_REMOVE_DEVICE request to the device stack. In response to the remove IRP, drivers detach their device objects from the stack and delete them. If a legacy component has a handle open to the device and it leaves the handle open despite I/O failures, the PnP manager never sends the remove IRP.
All drivers should handle this IRP and should note that the device has been physically removed from the machine. Some drivers, however, will not cause adverse results if they do not handle the IRP. For example, a device that consumes no system hardware resources and resides on a protocol-based bus, such as USB or 1394, cannot tie up hardware resources because it does not consume any. There is no risk of drivers attempting to access the device after it has been removed because the function and filter drivers access the device only through the parent bus driver. Because the bus supports removal notification, the parent bus driver is notified when the device disappears and the bus driver fails all subsequent attempts to access the device.
On Windows 98/Me, the PnP manager does not send this IRP. If a user removes a device without first using the appropriate user interface, the PnP manager sends only an IRP_MN_REMOVE_DEVICE request to the drivers for the device. All WDM drivers must handle both IRP_MN_SURPRISE_REMOVAL and IRP_MN_REMOVE_DEVICE. The code for IRP_MN_REMOVE_DEVICE should check whether the driver received a prior surprise-remove IRP and should handle both cases.