读/写 Dispatch 例程摘要

实现 DispatchReadDispatchWriteDispatchReadWrite 例程时,请记住以下几点:

  • 在分层驱动程序链中,最高级别的驱动程序有责任在为 IRP 设置下一级驱动程序的 I/O 堆栈位置之前,检查传入读/写 IRP 的参数是否有效。

  • 中间和最低级别的驱动程序通常可以依赖于其链中的最高级别驱动程序来传递具有有效参数的传输请求。 但是,任何驱动程序都可以对其 IRP 的 I/O 堆栈位置中的参数执行理智检查,每个设备驱动程序都应检查可能违反其设备施加的任何限制的条件的参数。

  • 如果 DispatchReadWrite 例程在完成 IRP 时遇到错误,应该使用适当的 NTSTATUS 类型值设置 I/O 堆栈位置的 Status 成员,将 Information 成员设置为零,并使用 IRP 和 IO_NO_INCREMENT 的 PriorityBoost 调用 IoCompleteRequest

  • 如果驱动程序使用缓冲的 I/O,则可能需要定义一个结构以包含要传输的数据,并且可能需要在内部缓冲其中一些结构。

  • 如果驱动程序使用直接 I/O,则可能需要检查 Irp-MdlAddress> 上的 MDL 是否描述了一个缓冲区,该缓冲区包含过多的数据(或过多分页符),以便基础设备在单个传输作中处理。 如果是这样,驱动程序必须将原始传输请求拆分为较小的传输作序列。

    紧密耦合的类驱动程序可能会在其基础端口驱动程序的 DispatchReadWrite 例程中拆分此类请求。 需要 SCSI 类驱动程序(尤其是大容量存储设备)才能执行此作。 有关 SCSI 驱动程序要求的详细信息,请参阅 存储驱动程序

  • 较低级别设备驱动程序的 DispatchReadWrite 例程应推迟将大型传输请求拆分为部分传输,直至另一个驱动程序例程将IRP出队,以便为传输设置设备。

  • 如果较低级别的设备驱动程序将读/写 IRP 排队供其自己的例程进一步处理,则必须在将 IRP 排队之前调用 IoMarkIrpPending 。 在这些情况下,DispatchReadWrite 例程还必须以 STATUS_PENDING 状态返回控制。

  • 如果 DispatchReadWrite 例程将 IRP 传递到较低驱动程序,则必须为 IRP 中的下一个较低驱动程序设置 I/O 堆栈位置。 在与 IoCallDriver 一起传递 IoCompletion 之前,高级驱动程序是否还在 IRP 中设置 IoCompletion 例程取决于驱动程序的设计及其下分层的例程。

    但是,如果高级驱动程序分配任何资源(如 IRP 或内存),则必须先调用 IoSetCompletionRoutine ,然后才能调用 IoCallDriver 。 在较低驱动程序完成请求后,但在 IoCompletion 例程使用原始 IRP 调用 IoCompleteRequest 之前,其 IoCompletion 例程必须释放所有驱动程序分配的资源。

  • 如果较高级别的驱动程序为可能包含基础可移动媒体设备驱动程序的较低驱动程序分配 IRP,则分配驱动程序必须在分配的每个 IRP 中建立线程上下文。