完成 I/O 请求
每个基于框架的驱动程序最终都必须完成它从框架收到的每个 I/O 请求。 驱动程序通过调用请求对象的 WdfRequestComplete、 WdfRequestCompleteWithInformation 或 WdfRequestCompleteWithPriorityBoost 方法完成请求。
何时完成请求
驱动程序在确定以下情况之一为 true 时,必须完成请求:
请求的 I/O 操作已成功完成。
请求的 I/O 操作已启动,但在完成之前失败。
请求的 I/O 操作不受支持,或在收到操作时无效,无法启动。
请求的 I/O 操作已取消。
如果驱动程序通过在设备上创建 I/O 活动来为 I/O 请求提供服务,驱动程序通常会从其 EvtInterruptDpc 或 EvtDpcFunc 回调函数调用 WdfRequestComplete。
如果驱动程序收到不受支持的请求或无效请求,它通常从接收请求的请求处理程序调用 WdfRequestComplete。
如果 I/O 操作被取消,驱动程序通常会从其 EvtRequestCancel 回调函数调用 WdfRequestComplete。
如果驱动程序将 I/O 请求 转发 到 I/O 目标,驱动程序在 I/O 目标完成请求后完成请求,如下所示:
如果驱动程序将 I/O 请求 同步 转发到 I/O 目标,则驱动程序对 I/O 目标的调用仅在较低级别的驱动程序完成请求 (后返回,除非) 发生错误。 I/O 目标返回后,驱动程序必须调用 WdfRequestComplete。
如果驱动程序 以异步方式转发 I/O 请求,你将希望在较低级别的驱动程序完成请求时收到通知。 如果驱动程序注册 CompletionRoutine 回调函数,框架会在 I/O 目标完成请求后调用此回调函数。 CompletionRoutine 回调函数通常调用 WdfRequestComplete。
若要注册 CompletionRoutine 回调函数,驱动程序必须先调用 WdfRequestSetCompletionRoutine ,然后才能将 I/O 请求转发到 I/O 目标。
如果在 I/O 目标完成异步转发的 I/O 请求时不需要通知驱动程序,则驱动程序不必注册 CompletionRoutine 回调函数。 相反,驱动程序可以在调用 WdfRequestSend 时设置WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET标志。 在这种情况下,驱动程序不调用 WdfRequestComplete。
驱动程序无法完成它通过调用 WdfRequestCreate 或 WdfRequestCreateFromIrp 创建的 I/O 请求。 相反,驱动程序必须调用 WdfObjectDelete 来删除请求对象,通常是在 I/O 目标完成请求之后。
例如,驱动程序可能会收到读取或写入请求,该请求的数据量大于驱动程序的 I/O 目标一次可以处理的数据量。 驱动程序必须将数据划分为多个较小的请求,并将这些较小的请求发送到一个或多个 I/O 目标。 处理这种情况的方法包括:
调用 WdfRequestCreate 以创建表示较小请求的单个附加请求对象。
驱动程序可以同步将此请求发送到 I/O 目标。 较小请求的 CompletionRoutine 回调函数可以调用 WdfRequestReuse ,以便驱动程序可以重用请求并再次将其发送到 I/O 目标。 在 I/O 目标完成最后一个较小的请求后, CompletionRoutine 回调函数可以调用 WdfObjectDelete 以删除驱动程序创建的请求对象,驱动程序可以调用 WdfRequestComplete 来完成原始请求。
调用 WdfRequestCreate 以创建表示较小请求的其他几个请求对象。
驱动程序的 I/O 目标可以异步处理这些多个较小的请求。 驱动程序可以为每个较小的请求注册 CompletionRoutine 回调函数。 每次调用 CompletionRoutine 回调函数时,它都可以调用 WdfObjectDelete 来删除驱动程序创建的请求对象。 I/O 目标完成所有较小的请求后,驱动程序可以调用 WdfRequestComplete 来完成原始请求。
提供完成信息
驱动程序完成请求后,可以选择提供其他驱动程序可以访问的一些附加信息。 例如,驱动程序可以提供为读取或写入请求传输的字节数。 若要提供此信息,驱动程序可以执行以下任一操作:
获取完成信息
若要获取有关另一个驱动程序已完成的 I/O 请求的信息,驱动程序可以:
调用 WdfRequestGetStatus 以获取较低级别驱动程序在调用 WdfRequestComplete 时指定的完成状态值。
调用 WdfRequestGetCompletionParams 以获取包含有关已完成请求的其他信息的 WDF_REQUEST_COMPLETION_PARAMS 结构,例如表示请求缓冲区的内存对象的句柄或特定于总线的信息。
驱动程序只能在调用 WdfRequestSend 以同步或异步方式将 I/O 请求发送到 I/O 目标之后调用 WdfRequestGetCompletionParams。 驱动程序调用将 I/O 请求仅 (同步发送到 I/O 目标的方法之一(例如 WdfIoTargetSendReadSynchronously) )后,不得调用 WdfRequestGetCompletionParams。
调用 WdfRequestGetInformation 以获取较低级别驱动程序在调用 WdfRequestSetInformation 或 WdfRequestCompleteWithInformation 时指定的附加 I/O 完成信息(如果驱动程序堆栈中的驱动程序提供此类信息)。
如果驱动程序以同步方式发送 I/O 请求,则它通常在同步调用返回后调用 WdfRequestGetStatus、 WdfRequestGetCompletionParams 和 WdfRequestGetInformation 。 如果驱动程序异步发送 I/O 请求,它通常从 CompletionRoutine 回调函数中调用这些方法。
有关完成 I/O 请求的详细信息,请参阅 同步取消和完成代码。