IO_COMPLETION_ROUTINE回调函数 (wdm.h)
IoCompletion 例程完成 I/O 操作的处理。
语法
IO_COMPLETION_ROUTINE IoCompletionRoutine;
NTSTATUS IoCompletionRoutine(
[in] PDEVICE_OBJECT DeviceObject,
[in] PIRP Irp,
[in, optional] PVOID Context
)
{...}
参数
[in] DeviceObject
调用方提供的指向 DEVICE_OBJECT 结构的指针。 这是目标设备的设备对象,以前由驱动程序的 AddDevice 例程创建。
[in] Irp
调用方提供的指向描述 I/O 操作的 IRP 结构的指针。
[in, optional] Context
调用方提供的指向特定于驱动程序的上下文信息的指针,以前在调用 IoSetCompletionRoutine 或 IoSetCompletionRoutineEx 时提供。 上下文信息必须存储在非分页内存中,因为可以在DISPATCH_LEVEL调用 IoCompletion 例程。 有关更多信息,请参见下面的“备注”部分。
返回值
如果 IoCompletion 例程确定 IRP 需要进行其他处理,则必须返回STATUS_MORE_PROCESSING_REQUIRED。 有关更多信息,请参见下面的“备注”部分。 否则,它应返回STATUS_SUCCESS。 (I/O 管理器仅检查是否存在 STATUS_MORE_PROCESSING_REQUIRED.)
注解
驱动程序的 IoCompletion 例程在任意线程或 DPC 上下文中以及小于或等于 DISPATCH_LEVEL的 IRQL 中执行。 由于编写为在 DISPATCH_LEVEL 执行的代码也会在较低级别执行, 因此 IoCompletion 例程应设计为在DISPATCH_LEVEL执行。 但是,由于不保证这些例程在DISPATCH_LEVEL运行,因此它们不得调用实际需要在DISPATCH_LEVEL执行的系统例程。 (有关 IRQL 的详细信息,请参阅 管理硬件优先级。)
若要为特定 IRP 注册 IoCompletion 例程,驱动程序必须调用 IoSetCompletionRoutine 或 IoSetCompletionRoutineEx,后者将 IoCompletion 例程的地址存储在下一个较低驱动程序的 I/O 堆栈位置中。 (因此,最低级别的驱动程序无法注册 IoCompletion 例程。) 驱动程序通常在每次收到 IRP 时从其某个调度例程调用 IoSetCompletionRoutine 或 IoSetCompletionRoutineEx 。 大多数驱动程序(包括所有 PnP 驱动程序)都可以使用 IoSetCompletionRoutine 注册其 IoCompletion 例程。 在执行 IoCompletion 例程之前可能卸载的非 PnP 驱动程序应改用 IoSetCompletionRoutineEx 。
当任何驱动程序完成 IRP 时,它会调用 IoCompleteRequest,后者又调用每个更高级别驱动程序的 IoCompletion 例程(从下一个最高到最高),直到调用所有更高的 IoCompletion 例程或直到一个例程返回STATUS_MORE_PROCESSING_REQUIRED。
创建 IRP 时,请为当前驱动程序以及任何较低的驱动程序分配堆栈位置。 如果未分配足够的堆栈位置,则调用完成例程时 ,DeviceObject 指针可能会设置为 NULL 。 如果使用 “上下文” 字段将信息传递给 IoCompletion ,而不是依赖于 DeviceObject 参数,则可以避免为当前驱动程序分配额外的堆栈位置。
如果 IoCompletion 例程返回STATUS_MORE_PROCESSING_REQUIRED,则下级驱动程序对 IoCompleteRequest 的调用会立即返回。 在这种情况下,更高级别的驱动程序必须调用 IoCompleteRequest 才能完成 IRP。
有关实现 IoCompletion 例程的详细信息,请参阅 完成 IRP。
示例
若要定义 IoCompletion 回调例程,必须先提供一个函数声明,用于标识要定义的回调例程的类型。 Windows 为驱动程序提供了一组回调函数类型。 使用回调函数类型声明函数可帮助 驱动程序的代码分析、 静态驱动程序验证程序 (SDV) 和其他验证工具查找错误,这是为 Windows 操作系统编写驱动程序的要求。
例如,若要定义名为 MyIoCompletion
的 IoCompletion 回调例程,请使用 IO_COMPLETION_ROUTINE 类型,如以下代码示例所示:
IO_COMPLETION_ROUTINE MyIoCompletion;
然后,按如下所示实现回调例程:
_Use_decl_annotations_
NTSTATUS
MyIoCompletion(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
// Function body
}
IO_COMPLETION_ROUTINE函数类型在 Wdm.h 头文件中定义。 若要在运行代码分析工具时更准确地识别错误,请务必将 _Use_decl_annotations_
注释添加到函数定义。 注释 _Use_decl_annotations_
可确保使用应用于头文件中IO_COMPLETION_ROUTINE函数类型的注释。 有关函数声明要求的详细信息,请参阅 使用 WDM 驱动程序的函数角色类型声明函数。 有关 的信息 _Use_decl_annotations_
,请参阅 批注函数行为。
要求
要求 | 值 |
---|---|
目标平台 | 桌面 |
标头 | wdm.h(包括 Wdm.h、Ntddk.h、Ntifs.h) |
IRQL | 在 IRQL <= DISPATCH_LEVEL (请参阅备注部分) 。 |