支援 UMDF 1.x 驅動程式中的Kernel-Mode用戶端

警告

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 1.9 版和更新版本允許 UMDF 驅動程式支援 核心模式用戶端。 核心模式用戶端可以是下列其中一項:

  • 存在於裝置驅動程式堆疊中 UMDF 驅動程式上方的核心模式驅動程式。

  • 一個裝置堆疊的核心模式驅動程式,可支援一個裝置、開啟另一個裝置的控制碼,而後者裝置的驅動程式堆疊包含 UMDF 驅動程式。

換句話說,支援核心模式用戶端的 UMDF 驅動程式可以從核心模式驅動程式接收 I/O 要求。 核心模式驅動程式可以轉送它從使用者模式應用程式收到的 I/O 要求,也可以建立新的 I/O 要求,並將其傳送至使用者模式驅動程式。

若要判斷 UMDF 驅動程式是否必須支援核心模式用戶端,您必須瞭解驅動程式將新增至哪個驅動程式堆疊,以及驅動程式所在的位置。 您也必須判斷來自另一個堆疊的驅動程式是否可能會將 I/O 要求傳送至驅動程式的裝置。

如果您的驅動程式必須支援核心模式用戶端,如果:

  • 核心模式驅動程式可以直接位於驅動程式堆疊中的 UMDF 驅動程式上方。 例如,核心模式篩選驅動程式可能直接位於 UMDF 型函式驅動程式上方。

  • 來自另一個堆疊的核心模式驅動程式可以將 I/O 要求傳送至驅動程式的裝置。 例如,您的驅動程式可能會建立符號連結,讓另一個堆疊中的核心模式驅動程式可用來開啟驅動程式裝置的控制碼。 然後核心模式驅動程式可以將 I/O 要求傳送至裝置。

如何在 UMDF 驅動程式中支援核心模式用戶端

只有在 UMDF 驅動程式已啟用核心模式用戶端支援時,UMDF 驅動程式才能從核心模式驅動程式接收 I/O 要求。 此外,如果裝置安裝嘗試在裝置驅動程式堆疊的 UMDF 驅動程式上方載入核心模式驅動程式,則架構只有在 UMDF 驅動程式已啟用核心模式用戶端支援時,才會允許驅動程式載入。

若要啟用 UMDF 驅動程式對核心模式用戶端的支援,UMDF 驅動程式的 INF 檔案必須在其 INF DDInstall中包含UmdfKernelModeClientPolicy指示詞。WDF區段。 如果 UMDF 驅動程式的 INF 檔案不包含此指示詞,UMDF 不允許在 UMDF 驅動程式上方安裝的核心模式驅動程式執行。

架構提供兩種方法,對支援核心模式用戶端的驅動程式很有用。 驅動程式可以呼叫 IWDFIoRequest2::GetRequestorMode 方法來判斷 I/O 要求是否來自核心模式或使用者模式。 如果 I/O 要求來自使用者模式,驅動程式可以呼叫 IWDFIoRequest2::IsFromUserModeDriver 來判斷要求是否來自應用程式或其他使用者模式驅動程式。

核心模式驅動程式的限制

只有在核心模式驅動程式符合下列需求時,UMDF 驅動程式才能處理來自核心模式驅動程式的 I/O 要求:

  • 當核心模式驅動程式傳送 I/O 要求時,必須在 IRQL = PASSIVE_LEVEL執行。

  • 除非驅動程式已將 UmdfFileObjectPolicy INF 指示詞設定為 AllowNullAndUnknownFileObjects,否則核心模式驅動程式傳送至使用者模式驅動程式的每個 I/O 要求都必須有相關聯的檔案物件。 架構先前必須收到 I/O 管理員已建立檔案物件的通知。 (這類通知會導致架構呼叫使用者模式驅動程式的 IQueueCallbackCreate::OnCreateFile 回呼函式,但該回呼函式是選擇性的。)

  • I/O 要求不能包含 IRP_MJ_INTERNAL_DEVICE_CONTROL 函式程式碼。

  • I/O 要求的緩衝區不得包含其他資訊的指標,因為使用者模式驅動程式無法取值指標。

  • 如果 I/O 要求包含指定「兩者」緩衝區存取方法的 I/O 控制項程式碼 ,則核心模式驅動程式必須在建立 I/O 要求之應用程式的處理常式內容中傳送 I/O 要求。 如需如何在 UMDF 基底驅動程式中支援「無」方法的詳細資訊,請參閱 在 UMDF 驅動程式中使用未緩衝 I/O 或直接 I/O

  • UMDF 驅動程式可能會在使用者模式中修改 I/O 要求的輸出資料。 因此,核心模式驅動程式必須驗證它從使用者模式驅動程式接收的任何輸出資料。

  • 核心模式用戶端通常會驗證 UMDF 驅動程式傳遞給IWDFIoRequest::CompleteWithInformation的資訊值。 如果用戶端是 KMDF 驅動程式,它可以呼叫 WdfRequestGetCompletionParams ,以在IO_STATUS_BLOCK結構中取得此資訊。

    一般而言,架構不會驗證 UMDF 驅動程式傳遞給 IWDFIoRequest::CompleteWithInformation的資訊值。 (此參數通常會指定已傳送的位元組數目。) 架構只會驗證輸出緩衝區的資訊值,而只會針對 緩衝的 I/O 資料存取方法驗證資訊值。 (例如,如果存取方法是緩衝處理 I/O.) ,架構會驗證已傳送的位元組數目未超過讀取作業的輸出緩衝區大小

處理 UMDF 1.x 驅動程式中的傳回狀態值

將傳回狀態值從使用者模式傳遞至核心模式需要特別注意,如下所示:

  • UMDF 第 1 版驅動程式通常會接收 HRESULT 類型的傳回值,而 KMDF 和 WDM 型核心模式驅動程式通常會接收 NTSTATUS 類型的值。 如果 UMDF 1。x 驅動程式會完成 I/O 要求,如果驅動程式有核心模式用戶端,驅動程式對 IWDFIoRequest::CompleteIWDFIoRequest::CompleteWithInformation 的呼叫應該指定驅動程式從 NTSTATUS 值產生的 HRESULT 值。 一般而言,UMDF 1。x 驅動程式應該使用 Winerror.h) 中定義的HRESULT_FROM_NT宏 (,將狀態傳回至核心模式用戶端。 下列範例示範如何在完成要求時使用此宏。

    hr = HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW)
    request->Complete(HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW);
    return hr;
    

    若要將特定 HRESULT 值傳回至核心模式用戶端,下列回呼必須使用HRESULT_FROM_NT宏:

    若要使用 ntstatus.h中定義的 NTSTATUS 值,則為 UMDF 1。x 驅動程式必須包含這兩行,才能包含任何其他標頭。

    #define UMDF_USING_NTSTATUS
    #include <ntstatus.h>
    

    請勿使用HRESULT_FROM_NT宏,將STATUS_SUCCESS從 NTSTATUS 值轉換成 HRESULT 值。 只要傳回S_OK,如下列範例所示。

    request->Complete(S_OK);
    
  • 架構代表 UMDF 驅動程式完成一些 I/O 要求。 有時候架構不會將 HRESULT 類型的傳回值轉換成對等的 NTSTATUS 值,因此架構可能會將 HRESULT 類型的完成狀態傳遞至核心模式用戶端。

    由於這種情況,核心模式用戶端在測試 I/O 要求的完成狀態時不應使用NT_ERROR宏,因為NT_ERROR宏不會針對 HRESULT 錯誤值傳回 TRUE 。 測試 I/O 要求的完成狀態時,核心模式驅動程式應該使用NT_SUCCESS宏。

舊版 UMDF 中的核心模式用戶端支援

對於 1.9 版之前的 UMDF 版本,驅動程式的 INF 檔案可以包含INF AddReg 指示詞,以在裝置硬體金鑰WUDF子機碼下建立REG_DWORD大小的UpperDriverOk登錄值。

如果 UpperDriverOk 登錄值設定為非零的數位,架構可讓核心模式驅動程式在使用者模式驅動程式上方載入。 核心模式驅動程式可以將 I/O 要求從使用者模式應用程式轉送至 UMDF 驅動程式,但核心模式驅動程式無法將核心模式中建立的 I/O 要求傳送至 UMDF 驅動程式。

針對 UMDF 1.9 版和更新版本, UpperDriverOk 登錄值已過時,且僅支援現有驅動程式。 新的驅動程式應該使用 UmdfKernelModeClientPolicy 指示詞。