在处理 IRP 的驱动程序例程中同步取消
取消排队或调用处于可取消状态(包括驱动程序的 StartIo 例程)的任何驱动程序例程都必须执行以下操作:
检查以确保 Irp 等于 DeviceObject-CurrentIrp>。 如果没有,请调用 IoReleaseCancelSpinLock 并返回控件。
如果两者不同,则当 IoStartPacket 释放取消旋转锁并且此例程获取时,CurrentIrp 可能已被取消。
使用 NULL CancelRoutine 指针调用 IoSetCancelRoutine 以从可取消状态中删除 IRP。
检查 Irp-Cancel> 字段以确定是取消 IRP 还是开始处理 I/O 请求。
如果 Irp-Cancel> 设置为 TRUE,请执行以下操作:
调用 IoReleaseCancelSpinLock。
将 Irp-IoStatus.Status> 设置为STATUS_CANCELLED。
将 Irp-IoStatus.Information> 设置为 0。
调用 IoStartNextPacket(在 StartIo 例程中)启动下一个数据包。
调用 具有优先级提升IO_NO_INCREMENT的 IoCompleteRequest 以完成 IRP。
如果 Irp-Cancel> 设置为 FALSE,请调用 IoReleaseCancelSpinLock 并启动请求处理 I/O 请求,或根据需要将 IRP 传递到下一个下一个驱动程序。
在调用 IoSetCancelRoutine 时,管理其自己的 IRP 队列的驱动程序(而不是使用 I/O 管理器提供的设备队列)不需要获取取消旋转锁。 但是,这些驱动程序应检查 IoSetCancelRoutine 返回的 Cancel 例程指针,以确定取消例程是否已启动。
在任何处理可取消 IRP 的驱动程序中,在为请求的 I/O 操作编程基础设备之前处理 IRP 的每个驱动程序例程都应检查所有传入 IRP 的可取消状态。 具体而言,具有 StartIo 和 ControllerControl 例程的最高级别设备驱动程序应在这两个驱动程序例程中处理传入的 IRP,如前所述。