在处理 IRP 的驱动程序例程中同步取消

取消排队或使用处于可取消状态的 IRP 调用的任何驱动程序例程(包括驱动程序的 StartIo 例程)都必须执行以下操作:

  1. 调用 IoAcquireCancelSpinLock

  2. 检查以确保 Irp 等于 DeviceObject-CurrentIrp>。 如果没有,请调用 IoReleaseCancelSpinLock 并返回控制权。

    如果两者不相同,则从 IoStartPacket 释放取消旋转锁到此例程获取该锁之间,CurrentIrp 可能已取消。

  3. 使用 NULLCancelRoutine 指针调用 IoSetCancelRoutine,以将 IRP 从可取消状态中删除。

  4. 检查 Irp-Cancel> 字段以确定是取消 IRP 还是开始处理 I/O 请求。

    如果 Irp-Cancel> 设置为 TRUE,请执行以下操作:

    • 调用 IoReleaseCancelSpinLock

    • Irp-IoStatus.Status> 设置为 STATUS_CANCELLED。

    • Irp-IoStatus.Information> 设置为 0。

    • StartIo 例程) 调用 IoStartNextPacket (以启动下一个数据包。

    • 调用 IoCompleteRequest ,优先级提升为 IO_NO_INCREMENT 以完成 IRP。

    如果 Irp-Cancel> 设置为 FALSE,请调用 IoReleaseCancelSpinLock 并启动请求处理 I/O 请求,或根据需要将 IRP 传递给下一个较低的驱动程序。

管理自己的 IRP 队列(而不是使用 I/O 管理器提供的设备队列)的驱动程序在调用 IoSetCancelRoutine 时不需要获取取消旋转锁。 但是,这些驱动程序应检查 IoSetCancelRoutine 返回的 Cancel 例程指针,以确定取消例程是否已启动。

在任何处理可取消 IRP 的驱动程序中,在针对请求的 I/O 操作对基础设备进行编程之前处理 IRP 的每个驱动程序例程都应检查所有传入 IRP 的可取消状态。 具体而言,具有 StartIoControllerControl 例程的最高级别设备驱动程序应处理这两个驱动程序例程中的传入 IRP,如前所述。