在 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 消費者入門。
UMDF 驅動程式最終必須完成每個 I/O 要求。 若要完成要求,驅動程式必須呼叫 IWDFIoRequest::Complete 或 IWDFIoRequest::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,因此不需要轉換宏。
如果已啟用反映 器的驅動程式驗證程式 ,它會識別不正確狀態碼,並導致系統錯誤檢查。
注意 Windows XP 的驅動程式驗證器不正確地針對其值超過十進位 1024 (1024L) 的 Win32 錯誤碼,造成系統錯誤檢查。 如果您的驅動程式在 Windows XP 上執行,如果您為反映器啟用驅動程式驗證器,請注意此問題。
如果驅動程式先前已將要求傳送至較低層級的驅動程式,則當較低層級驅動程式完成要求時,驅動程式需要通知。 若要註冊通知,驅動程式會呼叫 IWDFIoRequest::SetCompletionCallback 方法,以註冊架構在較低層級驅動程式完成要求時所呼叫之方法的介面。 驅動程式會實作 IRequestCallbackRequestCompletion::OnCompletion 回呼函式,以執行完成要求所需的作業。
驅動程式未完成它透過呼叫 IWDFDevice::CreateRequest所建立的 I/O 要求。 相反地,驅動程式必須呼叫 IWDFObject::D eleteWdfObject 來刪除要求物件,通常是在 I/O 目標完成要求之後。
例如,驅動程式可能會收到大於驅動程式 I/O 目標的資料量讀取或寫入要求,一次可以處理。 驅動程式必須將資料分割成數個較小的要求,並將這些較小的要求傳送至一或多個 I/O 目標。 處理這種情況的技術包括:
呼叫 IWDFDevice::CreateRequest 來建立代表較小要求的單一額外要求物件。
驅動程式可以將此要求同步傳送至 I/O 目標。 較小的要求的 IRequestCallbackRequestCompletion::OnCompletion 回呼函式可以呼叫 IWDFIoRequest2::Reuse ,讓驅動程式可以重複使用要求並將它再次傳送至 I/O 目標。 I/O 目標完成最後一個較小的要求之後, OnCompletion 回呼函式可以呼叫 IWDFObject::D eleteWdfObject 來刪除驅動程式建立的要求物件,而驅動程式可以呼叫 IWDFIoRequest::Complete 來完成原始要求。
呼叫 IWDFDevice::CreateRequest 來建立數個代表較小要求的額外要求物件。
驅動程式的 I/O 目標可以非同步處理這些多個較小的要求。 驅動程式可以為每個較小的要求註冊 OnCompletion 回呼函式。 每次呼叫 OnCompletion 回呼函式時,都可以呼叫 IWDFObject::D eleteWdfObject 來刪除驅動程式建立的要求物件。 I/O 目標完成所有較小的要求之後,驅動程式可以呼叫 IWDFIoRequest::Complete 來完成原始要求。
取得完成資訊
若要取得另一個驅動程式已完成之 I/O 要求的相關資訊,UMDF 型驅動程式可以:
使用 IWDFRequestCompletionParams 介面來取得 I/O 要求的完成狀態和其他資訊。
使用 IWDFIoRequestCompletionParams 介面來取得 I/O 要求的記憶體緩衝區。
使用 IWDFUsbRequestCompletionParams 介面來取得記憶體緩衝區和其他與傳送至 USB 目標管道物件之要求相關的資訊。
此外,UMDF 型驅動程式可以使用 IWDFIoRequest2::GetStatus 方法來取得 I/O 要求的目前狀態,不論是在要求完成之前或之後。