在总线驱动程序中删除设备

删除子设备 (子 PDO) 时,父总线驱动程序必须撤消为添加和启动设备而执行的任何操作。

总线驱动程序在其 DispatchPnP 例程中使用如下过程删除子设备:

  1. 驱动程序以前处理过此 PDO 的IRP_MN_SURPRISE_REMOVAL 请求吗?

    如果是,请执行任何剩余的清理并跳到步骤 4。

    驱动程序通常在设备扩展中维护一个标志,指示驱动程序是否已处理设备的 IRP_MN_SURPRISE_REMOVAL 请求。

  2. 完成驱动程序中排队的任何请求。

  3. 如果总线驱动程序能够这样做,请从设备中删除电源,并通过调用 PoSetPowerState 通知电源管理器。

    如果可能,总线驱动程序关闭子设备,并通知电源管理器设备的电源状态更改。 总线驱动程序执行此操作以响应 IRP_MN_REMOVE_DEVICE 请求;删除设备时,设备的电源策略所有者不会发送 IRP_MN_SET_POWER 请求。 有关其他信息,请参阅 电源管理

  4. 如果总线驱动程序在最近对 BusRelationsIRP_MN_QUERY_DEVICE_RELATIONS请求的响应中报告了此设备,则设备仍实际存在于计算机上。 在这种情况下,总线驱动程序:

    • 保留设备的 PDO,直到设备被物理删除。

    • Irp-IoStatus.Status> 设置为 STATUS_SUCCESS。

    • 使用 IoCompleteRequest 完成 IRP。

    • DispatchPnP 例程返回 。

    总线驱动程序必须继续在后续枚举中报告此设备, (BusRelations) IRP_MN_QUERY_DEVICE_RELATIONS,直到设备被物理移除。 PnP 管理器跟踪枚举设备是否已添加和启动。

  5. 如果总线驱动程序对 BusRelations的IRP_MN_QUERY_DEVICE_RELATIONS请求的最新响应中未包含该设备,则总线驱动程序会将该设备视为从计算机中物理删除。 在这种情况下,总线驱动程序执行以下操作:

    • 清理特定于设备的分配、内存、事件等。

    • Irp-IoStatus.Status> 设置为 STATUS_SUCCESS。

    • 使用 IoCompleteRequest 完成 IRP。

    • 使用 IoDeleteDevice 释放 PDO。

      如果驱动程序从最新的 BusRelations 列表中省略了设备,则总线驱动程序必须删除 PDO。 如果用户再次将设备插入计算机,总线驱动程序必须创建新的 PDO 以响应下一个 BusRelations 查询。 如果总线驱动程序对设备的新实例重复使用同一 PDO,则计算机将无法正常运行。

    • DispatchPnP 例程返回 。

如果在 PnP 管理器发送 IRP_MN_REMOVE_DEVICE 请求时设备仍然存在,则总线驱动程序会保留 PDO。 如果稍后某个时间将设备从总线上物理移除,则 PnP 管理器会发送另一 个IRP_MN_REMOVE_DEVICE。 收到后续删除 IRP 后,总线驱动程序将删除设备的 PDO。

总线驱动程序必须能够处理已移除且其 PDO 标记为要删除的设备 IRP_MN_REMOVE_DEVICE 。 为了响应此类 IRP,总线驱动程序可以成功执行 IRP 或返回STATUS_NO_SUCH_DEVICE。 尽管总线驱动程序以前调用 了 IoDeleteDevice,但在这种情况下尚未删除设备的 PDO,因为某些组件仍具有对 对象的引用。 因此,总线驱动程序可以在处理第二个删除 IRP 时访问 PDO。 总线驱动程序不得为 PDO 再次调用 IoDeleteDevice ;当 PDO 的引用计数达到零时,I/O 系统将删除 PDO。

在收到对设备的 IRP_MN_REMOVE_DEVICE 请求之前,总线驱动程序不会删除子设备的数据结构。 总线驱动程序可能会检测到设备已被移除并调用 IoInvalidateDeviceRelations,但在 PnP 管理器发送 IRP_MN_REMOVE_DEVICE 请求之前,它不得删除设备的 PDO。