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

调用方提供的指向特定于驱动程序的上下文信息的指针,以前在调用 IoSetCompletionRoutineIoSetCompletionRoutineEx 时提供。 上下文信息必须存储在非分页内存中,因为可以在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 例程,驱动程序必须调用 IoSetCompletionRoutineIoSetCompletionRoutineEx,后者将 IoCompletion 例程的地址存储在下一个较低驱动程序的 I/O 堆栈位置中。 (因此,最低级别的驱动程序无法注册 IoCompletion 例程。) 驱动程序通常在每次收到 IRP 时从其某个调度例程调用 IoSetCompletionRoutineIoSetCompletionRoutineEx 。 大多数驱动程序(包括所有 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 操作系统编写驱动程序的要求。

例如,若要定义名为 MyIoCompletionIoCompletion 回调例程,请使用 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 (请参阅备注部分) 。