向驱动程序堆栈的下层传递 IRP
当驱动程序的调度例程收到 IRP 时,它必须调用 IoGetCurrentIrpStackLocation,以便它可以检查自己的 I/O 堆栈位置,并确定任何参数都有效。 如果驱动程序无法满足并完成请求本身,它可以执行以下操作之一:
传递 IRP,供较低级别的驱动程序进一步处理。
创建一个或多个新 IRP,并将其向下传递给较低级别的驱动程序。
较高级别的驱动程序应将 I/O 请求传递到下一个较低级别的驱动程序,如下所示:
如果驱动程序将输入 IRP 传递到下一个较低级别的驱动程序,则调度例程应调用 IoSkipCurrentIrpStackLocation 或 IoCopyCurrentIrpStackLocationToNext 来设置下一个较低级别的驱动程序的 I/O 堆栈位置。
如果驱动程序调用 IoAllocateIrp 为较低级别的驱动程序分配一个或多个额外的 IRP,则调度例程必须按照 在 Intermediate-Level 驱动程序中处理 IRP 中所述的步骤初始化下一个较低驱动程序的 I/O 堆栈位置。
调度例程可以针对某些请求修改下一个较低驱动程序的 I/O 堆栈位置中的一些参数。 例如,当基础设备具有已知的传输容量限制时,较高级别的驱动程序可能会修改大型传输请求的参数,并重复使用 IRP 将部分传输请求发送到基础设备驱动程序。
-
如果调度例程将收到的 IRP 传递给下一个较低级别的驱动程序,则设置 IoCompletion 例程是可选的,但很有用,因为该例程可以执行诸如确定较低驱动程序完成请求的方式、重用 IRP 进行部分传输、更新驱动程序在跟踪 IRP 时保持的任何状态,以及重试返回并出现错误的请求。
如果调度例程已分配了新的 IRP,则需要设置 IoCompletion 例程,因为该例程必须在较低的驱动程序完成该例程后释放每个 IRP。
有关 IoCompletion 例程的详细信息,请参阅 完成 IRP。
使用要由较低驱动程序处理的每个 IRP 调用 IoCallDriver 。
返回相应的 NTSTATUS 值,例如:
STATUS_PENDING
如果输入 IRP 是异步请求 (例如IRP_MJ_READ 或IRP_MJ_WRITE),驱动程序通常会返回 STATUS_PENDING。
调用 IoCallDriver 的结果
如果输入 IRP 是同步请求(例如IRP_MJ_CREATE),驱动程序通常会返回对 IoCallDriver 的调用结果。
最低级别的设备驱动程序将在其调度例程中无法完成的任何 IRP 传递给其他驱动程序例程,如下所示:
使用输入 IRP 调用 IoMarkIrpPending 。
调用 IoStartPacket 将 IRP 传递到驱动程序的 StartIo 例程或排队,除非驱动程序管理自己的内部 IRP 队列,如 驱动程序管理的 IRP 队列中所述。
如果驱动程序没有 StartIo 例程,但处理可取消的 IRP,则必须注册 取消 例程或实现 取消安全 IRP 队列。 有关 取消 例程的详细信息,请参阅 取消 IRP。
返回STATUS_PENDING。