在 UMDF 中完成 I/O 请求

警告

UMDF 2 是 UMDF 的最新版本,取代了 UMDF 1。 所有新的 UMDF 驱动程序都应使用 UMDF 2 编写。 不会向 UMDF 1 添加任何新功能,并且较新版本的 Windows 10 上对 UMDF 1 的支持有限。 通用 Windows 驱动程序必须使用 UMDF 2。

存档的 UMDF 1 示例可在 Windows 11 版本 22H2 - 2022 年 5 月驱动程序示例更新中找到。

有关详细信息,请参阅使用 UMDF 入门

每个 I/O 请求最终必须由 UMDF 驱动程序完成。 若要完成请求,驱动程序必须调用 IWDFIoRequest::CompleteIWDFIoRequest::CompleteWithInformation 方法。 当驱动程序完成请求时,它指示以下方案之一:

  • 请求的 I/O 操作已成功完成。

  • 请求的 I/O 操作已启动,但在完成之前失败。

  • 请求的 I/O 操作在收到时不受支持或无效,因此无法与设备通信。

  • 请求的 I/O 操作 已取消

驱动程序调用 IWDFIoRequest::CompleteWithInformation 方法以传递有关请求操作的其他信息。 例如,对于读取操作,驱动程序应提供读取的字节数。

若要完成 I/O 请求,驱动程序必须在调用 IWDFIoRequest::Complete 或 IWDFIoRequest::CompleteWithInformation 时将相应的完成状态传递给 CompletionStatus 参数。 驱动程序使用 HRESULT 代码来传达已完成请求的状态。

UMDF 驱动程序主机进程先将 HRESULT 代码转换为 NTSTATUS 代码,然后再将完成的请求传递给反射器 (Wudfrd.sys) 。 反射器将 NTSTATUS 代码传递给操作系统。 操作系统先将 NTSTATUS 代码转换为 Microsoft Win32 错误代码,然后再将结果呈现给调用应用程序。

若要确保驱动程序的错误代码可以正确转换,应使用以下任一方法创建错误代码:

  • 使用 Winerror.h 中的错误代码并应用 HRESULT_FROM_WIN32 宏。

  • 使用 Ntstatus.h 中的错误代码并应用 HRESULT_FROM_NT 宏。

有关这些宏的详细信息,请参阅Microsoft Windows SDK文档。

以下示例代码演示如何使用合适的错误代码完成请求:

VOID
STDMETHODCALLTYPE
CMyQueue::OnWrite(
    __in IWDFIoQueue *pWdfQueue,
    __in IWDFIoRequest *pWdfRequest,
    __in SIZE_T BytesToWrite
    )
{
            -------------------- 
    if( BytesToWrite > MAX_WRITE_LENGTH ) {
        pWdfRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_MORE_DATA), 0);
        return;
    }
            ---------------------
}

当驱动程序成功完成请求时,它将返回S_OK,即 HRESULT 值。 由于 S_OK 等效于 Winerror.h 中的NO_ERROR和 Ntstatus.h 中的STATUS_SUCCESS,因此不需要转换宏。

如果为反射器启用了 驱动程序验证程序 ,它将标识无效状态代码并导致系统 bug 检查。

注意 Windows XP 驱动程序验证程序错误地导致 Win32 错误代码的系统错误检查,其值超过十进制 1024 (1024L) 。 如果你的驱动程序在 Windows XP 上运行,如果为反射器启用驱动程序验证程序,请注意此问题。

如果驱动程序以前向较低级别的驱动程序发送了请求,则当较低级别的驱动程序完成请求时,驱动程序需要通知。 为了注册通知,驱动程序调用 IWDFIoRequest::SetCompletionCallback 方法,以在较低级别驱动程序完成请求时为框架调用的方法注册接口。 驱动程序实现 IRequestCallbackRequestCompletion::OnCompletion 回调函数,以执行完成请求所需的操作。

驱动程序无法完成它通过调用 IWDFDevice::CreateRequest 创建的 I/O 请求。 相反,驱动程序必须调用 IWDFObject::D eleteWdfObject 来删除请求对象,通常是在 I/O 目标完成请求之后。

例如,驱动程序可能会收到读取或写入请求,该请求的数据量大于驱动程序的 I/O 目标一次可以处理的数据量。 驱动程序必须将数据划分为多个较小的请求,并将这些较小的请求发送到一个或多个 I/O 目标。 处理这种情况的方法包括:

获取完成信息

若要获取有关其他驱动程序已完成的 I/O 请求的信息,基于 UMDF 的驱动程序可以:

此外,基于 UMDF 的驱动程序可以使用 IWDFIoRequest2::GetStatus 方法在请求完成之前或之后获取 I/O 请求的当前状态。