DispatchPnP 例程

驱动程序的DispatchPnP例程通过处理IRP_MJ_PNPI/O 功能代码的 IRP,来支持即插即用功能。 与 IRP_MJ_PNP 函数代码关联的是几个次要 I/O 函数代码(请参阅 即插即用次要 IRP),其中一些驱动程序必须处理,其中一些驱动程序可以选择性地处理。 PnP 管理器使用这些次要函数代码来指示驱动程序启动、停止和删除设备以及查询驱动程序的相关信息。

设备的所有驱动程序都必须有机会处理该设备的 PnP IRP,但在少数情况下,允许功能驱动程序或筛选驱动程序拒绝该 IRP。

每个驱动程序的 DispatchPnP 例程必须遵循以下规则:

  • 函数或筛选器驱动程序必须将 PnP IRP 向下传递到设备堆栈中的下一个驱动程序,除非函数或筛选器驱动程序处理 IRP 并遇到故障(例如,由于资源不足)。

    设备的所有驱动程序都必须有机会处理设备的 PnP IRP,除非其中一个驱动程序遇到错误。 PnP 管理器将 IRP 发送到设备堆栈中的顶部驱动程序。 函数和筛选器驱动程序将 IRP 向下传递到下一个驱动程序,父总线驱动程序完成 IRP。 有关详细信息,请参阅“在设备堆栈中传递 PnP IRP”。

    如果驱动程序尝试处理 IRP 并遇到错误(例如资源不足),驱动程序可能无法完成 IRP。 如果驱动程序收到一个它无法处理的代码的 IRP,则驱动程序不应导致 IRP 失败。 它必须将此类 IRP 向下传递到下一个驱动程序,而无需修改 IRP 的状态。

  • 驱动程序必须处理某些即插即用(PnP)IRP,并且可以选择是否处理其他 IRP。

    每个 PnP 驱动程序都需要处理某些 IRP,例如 IRP_MN_REMOVE_DEVICE,并且可以选择性地处理其他 IRP。 有关每种驱动程序(函数驱动程序、筛选器驱动程序和总线驱动程序)的必需 IRP 和可选 IRP 的信息,请参阅 即插即用次要 IRP

    驱动程序可能导致所需的 PnP IRP 失败,并返回适当的错误状态,但驱动程序不得对该 IRP 返回 STATUS_NOT_SUPPORTED。

  • 如果驱动程序成功处理 PnP IRP,驱动程序会将 IRP 状态设置为成功。 它不依赖于堆栈中的另一个驱动程序来设置状态。

    驱动程序将 Irp-IoStatus.Status> 设置为STATUS_SUCCESS,以通知 PnP 管理器驱动程序已成功处理 IRP。 对于某些 IRP,非总线驱动程序可能能够依赖其父总线驱动程序将状态设置为成功。 但是,这是一种有风险的做法。 为了保持一致性和稳定性,驱动程序必须在成功处理每个 PnP IRP 时,将其 IRP 状态设置为成功。

  • 如果驱动程序未能通过一个IRP,驱动程序将完成该IRP并标记错误状态,而不会将IRP传递给下一个驱动程序。

    若要使 IRP(如 IRP_MN_QUERY_STOP_DEVICE)失败,驱动程序会将 Irp-IoStatus.Status> 设置为STATUS_UNSUCCESSFUL。 其他 IRP 的其他错误状态值包括STATUS_INSUFFICIENT_RESOURCES和STATUS_INVALID_DEVICE_STATE。

    驱动程序在处理 IRP 时不会将其设置为 STATUS_NOT_SUPPORTED。 这是 PnP 管理器设置的初始状态。 如果 IRP 已完成此状态,则表示堆栈中没有驱动程序处理 IRP;所有驱动程序都刚刚将 IRP 传递给下一个驱动程序。

  • 驱动程序必须在其调度例程中处理 PnP IRP(IRP 向下经过设备堆栈时)、IoCompletion 例程中处理(IRP 返回向上经过设备堆栈时),或者两者同时处理,具体情况取决于 IRP 的参考页中的规定。

    某些 PnP IRP(如 IRP_MN_REMOVE_DEVICE)必须先由设备堆栈顶部的驱动程序处理,然后由每个下一个较低的驱动程序进行处理。 其他(如 IRP_MN_START_DEVICE)必须首先由父总线驱动程序处理。 其他请求(如 IRP_MN_QUERY_CAPABILITIES)可以在设备栈下降和上升过程中处理。 请参阅 即插即用次要 IRP ,了解适用于每个 PnP IRP 的规则。 请参阅 推迟 PnP IRP 处理,直到较低驱动程序完成,以了解如何处理需由父总线驱动程序优先处理的 PnP IRP。

  • 驱动程序必须在 IRP 下行设备堆栈时添加信息,并在 IRP 上行时修改或删除信息。

    返回响应 PnP 查询 IRP 的信息时,驱动程序必须遵循此约定,以便通过分层驱动程序有序地传递设备信息。

  • 除非明确记录,否则驱动程序不得依赖于以任何特定顺序发送的 PnP IRP。

  • 当驱动程序发送 PnP IRP 时,它必须将 IRP 发送到设备堆栈中的顶部驱动程序。

    大多数 PnP IRP 是由 PnP 管理器发送的,但某些 IRP 可由驱动程序发送(例如 IRP_MN_QUERY_INTERFACE)。 驱动程序必须将 PnP IRP 传递给设备堆栈顶部的驱动程序。 调用 IoGetAttachedDeviceReference 以获取指向设备堆栈顶部驱动程序的设备对象的指针。