向设备堆栈的下层传递 PnP IRP
PnP 管理器使用 IRP 来指示驱动程序启动、停止和删除设备,以及查询驱动程序的设备。 所有 PnP IRP 都有 IRP_MJ_PNP的主要函数代码,并且所有 PnP 驱动程序都必须提供 DispatchPnP 例程来为此函数代码提供服务。 PnP 管理器在发送 IRP 时将 Irp-IoStatus.Status> 初始化为STATUS_NOT_SUPPORTED。 有关详细信息,请参阅 DispatchPnP 例程。
有关 PnP 次要 IRP 的列表,请参阅即插即用次要 IRP。
设备的所有驱动程序都必须有机会响应 PnP IRP,除非堆栈中的驱动程序无法通过 IRP。 (请参阅下图。)
设备没有单个驱动程序可以假定它是唯一将响应 PnP IRP 的驱动程序。 例如,考虑一个函数驱动程序,它响应 IRP_MN_QUERY_CAPABILITIES 请求并完成 IRP 而不将其传递给下一个较低的驱动程序。 未报告较低驱动程序支持的任何功能,例如父总线驱动程序支持的唯一实例 ID 或电源管理功能。
当父总线驱动程序调用 IoCompleteRequest 且 I/O 管理器调用由函数驱动程序或筛选器驱动程序注册的任何 IoCompletion 例程时,PnP IRP 将备份设备堆栈。
函数或筛选器驱动程序在收到 PnP IRP 时必须执行以下操作:
- 如果驱动程序执行操作以响应 IRP:
- 执行相应的操作。
- 将 Irp-IoStatus.Status> 设置为适当的状态,例如STATUS_SUCCESS。 设置 Irp-IoStatus.Information>(如果适用于 IRP)。
- 使用 IoSkipCurrentIrpStackLocation 或 IoCopyCurrentIrpStackLocationToNext 设置下一个堆栈位置。 如果设置 IoCompletion 例程,请调用后一个例程。
- 如有必要,请设置 IoCompletion 例程。
- 不要完成 IRP。 (不要调用 IoCompleteRequest.) 父总线驱动程序将完成 IRP。
- 如果驱动程序不对此 IRP 执行操作,则只需准备将 IRP 传递给下一个驱动程序:
- 调用 IoSkipCurrentIrpStackLocation 以从 IRP 中删除其堆栈位置。
- 请勿在 Irp-IoStatus> 中设置任何字段。
- 不要设置 IoCompletion 例程。
- 不要完成 IRP。 (不要调用 IoCompleteRequest.) 父总线驱动程序将完成 IRP。
如果函数或筛选器驱动程序未使 IRP 失败,它将 IRP 传递给具有 IoCallDriver 的下一个较低驱动程序。 驱动程序具有指向下一个较低驱动程序的指针;该指针是从更高驱动程序的 AddDevice 例程中的 IoAttachDeviceToDeviceStack 调用返回的。
父总线驱动程序在执行任何任务以响应 IRP 后完成 IRP。 在总线驱动程序调用 IoCompleteRequest 后,I/O 管理器调用由设备函数或筛选器驱动程序注册的任何 IoCompletion 例程。