如何执行完成处理
注意
为了获得最佳可靠性和性能,请使用支持筛选器管理器的 文件系统微筛选器驱动程序 ,而不是旧的文件系统筛选器驱动程序。 若要将旧驱动程序移植到微筛选器驱动程序,请参阅 移植旧版筛选器驱动程序指南。
完成处理分两个阶段执行。 第一个阶段在任意线程上下文中执行,在 IRQL <= DISPATCH_LEVEL。 在此阶段中,将执行以下任务:
依次调用为 IRP 注册的每个完成例程,从最低 IRP 堆栈位置开始。 如果完成例程返回STATUS_MORE_PROCESSING_REQUIRED,则完成处理将停止。
如果 IRP 包含内存描述符列表 (MDL) ,则 MDL 映射的任何物理页都将解锁。
I/O 完成的第二阶段将排到目标 (请求) 线程作为特殊内核 APC。
第二个阶段在发起 I/O 请求的线程的上下文中执行。 它作为特殊内核 APC 执行,因此在 IRQL APC_LEVEL运行。 在此阶段中,将执行以下任务:
如果 IRP 表示缓冲的操作,则 Irp-AssociatedIrp.SystemBuffer> 的内容将复制到 Irp-UserBuffer>。
如果 IRP 包含 MDL,则释放 MDL。
Irp-IoStatus> 的内容将复制到 Irp-UserIosb>,以便 I/O 请求的发起方可以查看操作的最终状态。
如果在 Irp-UserEvent> 中提供了事件,则会发出信号。 否则,如果此 IRP 有一个文件对象,则会向其事件发出信号。
如果 IRP 是通过调用 IoBuildDeviceIoControlRequest 或 IoBuildSynchronousFsdRequest 创建的,则会将其从线程的挂起 I/O 请求列表中取消排队。
如果用户 APC 已排队(如果调用方请求)。
IRP 已释放。
如果由于STATUS_MORE_PROCESSING_REQUIRED返回的完成例程而停止了 IRP 的完成处理,可以通过在同一 IRP 上调用 IoCompleteRequest 来恢复该处理。 发生这种情况时,第一阶段处理会恢复,从驱动程序的完成例程开始,紧靠其完成例程返回STATUS_MORE_PROCESSING_REQUIRED。