示例:简单Pass-Through调度和完成
注意
为了获得最佳可靠性和性能,请使用支持筛选器管理器的 文件系统微筛选器驱动程序 ,而不是旧版文件系统筛选器驱动程序。 若要将旧驱动程序移植到微筛选器驱动程序,请参阅 移植旧筛选器驱动程序的指南。
若要为 IRP 设置完成例程并向下传递 IRP,旧文件系统筛选器驱动程序的调度例程必须执行以下操作:
调用 IoCopyCurrentIrpStackLocationToNext ,将参数从当前堆栈位置复制到下一个较低级别的驱动程序的位置。
调用 IoSetCompletionRoutine 以指定 IRP 的完成例程。
调用 IoCallDriver 将 IRP 向下传递到下一个较低级别的驱动程序。
以下代码示例演示了此方法:
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp, // Irp
MyLegacyFilterPassThroughCompletion, // CompletionRoutine
(PVOID)recordList, // Context
TRUE, // InvokeOnSuccess
TRUE, // InvokeOnError
TRUE); // InvokeOnCancel
return IoCallDriver ( NextLowerDriverDeviceObject, Irp );
在此示例中,对 IoSetCompletionRoutine 的调用为 IRP 设置完成例程。
调用 IoSetCompletionRoutine 中的前两个参数是指向 IRP 的指针和完成例程的名称。 第三个参数是指向要传递到完成例程的驱动程序定义结构的指针。 此结构包含完成例程在 IRP 上执行完成处理时所需的上下文信息。 必须从非分页池中分配上下文结构,因为可以在 IRQL DISPATCH_LEVEL调用完成例程。
传递给 IoSetCompletionRoutine 的最后三个参数是指定在 I/O 请求成功、失败还是取消时调用完成例程的标志。
如果调度例程设置完成例程并在调用 IoCallDriver (后立即返回,如上一个调度例程) 所示,则相应的完成例程必须检查 IRP 的 PendingReturned 标志,如果已设置,则调用 IoMarkIrpPending。 然后,它应返回STATUS_SUCCESS,如以下示例所示:
if (Irp->PendingReturned) {
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
此方法的优点
设置完成例程允许驱动程序在较低级别的驱动程序处理 IRP 后进一步处理 IRP。 完成例程可以根据请求的 I/O 操作的结果来决定如何处理 IRP。
此方法的缺点
由于它在 IRQL <= DISPATCH_LEVEL 的任意线程上下文中运行,因此完成例程只能对 IRP 执行有限的处理。