驅動程式套件隔離
驅動程式套件隔離是 Windows 驅動程式的需求,可讓驅動程式套件對外部變更更有彈性、更容易更新,以及更容易安裝。
注意
雖然 Windows 驅動程式需要驅動程式套件隔離,但 Windows 桌面驅動程式仍可透過改善的復原能力和可服務性來受益於此驅動程式。
下表顯示一些舊版驅動程式套件實務範例,這些做法已不再允許左欄中的 Windows 驅動程式,以及右側數據行中 Windows 驅動程式的必要行為。
非隔離驅動程式 | 隔離驅動程式 |
---|---|
INF 會將檔案複製到 %windir%\System32 或 %windir%\System32\drivers | 驅動程式檔案是從 驅動程式存放區執行 |
使用硬式編碼路徑與裝置堆疊/驅動程序互動 | 使用系統提供的函式或裝置介面與裝置堆疊/驅動程序互動 |
全域登錄位置的硬式編碼路徑 | 針對登錄和檔案狀態的相對位置使用 HKR 和系統提供的函式 |
運行時間檔案寫入任何位置 | 檔案會相對於作業系統提供的位置寫入 |
如需判斷驅動程式套件是否符合驅動程式套件隔離需求的說明,請參閱 驗證 Windows 驅動程式。 如需如何更新 INF 以符合驅動程式套件隔離需求的範例,請參閱 移植 INF 以遵循驅動程式套件隔離。
從驅動程式存放區執行
所有隔離的驅動程式套件都會將其驅動程式套件檔案保留在驅動程式存放區中。 這表示他們在 INF 中指定 DIRID 13 ,以指定安裝時驅動程式套件檔案的位置。 如需如何在驅動程式套件中使用此功能的詳細資訊,請參閱 從驅動程式存放區執行。
讀取和寫入狀態
注意
如果您的元件使用裝置或裝置介面 屬性 來儲存狀態,請繼續使用該方法和適當的OS API來儲存和存取狀態。 下列登錄和檔案狀態指引適用於 元件需要儲存的其他 狀態。
若要存取各種登錄和檔案狀態,應該藉由呼叫函式來提供狀態位置的呼叫端來完成,然後狀態會相對於該位置讀取/寫入。 請勿使用硬式編碼的絕對登錄路徑和檔案路徑。
本節包含下列子區段:
登錄狀態
本節包含下列子區段:
PnP 裝置登錄狀態
隔離的驅動程式套件和使用者模式元件通常會使用兩個位置的其中一個,將裝置狀態儲存在登錄中。 這些是 裝置的硬體金鑰(裝置金鑰 )和 裝置的軟體金鑰 (驅動程式金鑰)。 硬體 密鑰 通常適用於與個別裝置實例如何與硬體互動的相關設定。 例如,若要啟用硬體功能,或將硬體放入特定模式。 軟體 金鑰 通常適用於與個別裝置實例如何與系統和其他軟體互動的相關設定。 例如,若要設定資料檔的位置、與架構互動,或存取裝置的應用程式設定。 若要擷取這些登錄位置的句柄,請使用下列其中一個選項:
IoOpenDeviceRegistryKey (WDM)
INF AddReg 指示詞在 INF DDInstall 區段或 DDInstall.HW 區段中參考的 add-registry-section 中使用 HKR reg-root 專案,如下所示:
[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg
[Example_DDInstall.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll
裝置介面登錄狀態
若要讀取和寫入裝置介面登錄狀態,請使用下列其中一個選項:
在 add-interface-section 參考的 add-registry-section 中,使用 HKR reg-root 專案 INF AddReg 指示詞
服務登錄狀態
服務狀態應分類為3個類別之一
不可變的服務登錄狀態
固定服務狀態是安裝服務的驅動程式套件所提供的狀態。 這些由 INF 為驅動程式和 Win32 服務設定的登錄值,必須儲存在服務的 「參數」子機碼下,方法是在 AddReg 區段中提供 HKR 行,然後在 INF 的服務安裝區段中參考該區段。 例如:
[ExampleDDInstall.Services]
Addservice = ExampleService, 0x2, Example_Service_Inst
[Example_Service_Inst]
DisplayName = %ExampleService.SvcDesc%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %13%\ExampleService.sys
AddReg=Example_Service_Inst.AddReg
[Example_Service_Inst.AddReg]
HKR, Parameters, ExampleValue, 0x00010001, 1
若要在執行時間從服務存取此狀態的位置,請使用下列其中一個函式:
具有 DriverRegKeyParameters DRIVER_REGKEY_TYPE的 IoOpenDriverRegistryKey (WDM)
GetServiceRegistryStateKey (Win32 Services) 與 ServiceRegistryStateParameters SERVICE_REGISTRY_STATE_TYPE
INF 在服務的 「Parameters」 子機碼中提供的這些登錄值,應該只在運行時間讀取,而不會修改。 應該將它們視為唯讀。
如果 INF 所提供的登錄值是可在運行時間覆寫的預設設定,則覆寫值應該寫入 服務的內部服務登錄狀態 或 共用服務登錄狀態 。 擷取設定時,可以先在可變動狀態中尋找設定。 如果不存在,則可以在不可變的狀態中尋找設定。 RtlQueryRegistryValueWithFallback 可用來協助查詢設定,例如具有覆寫和預設值的查詢設定。
內部服務登錄狀態
內部服務狀態是在運行時間寫入且只由服務本身所擁有和管理的狀態,而且只能供該服務存取。 若要存取內部服務狀態的位置,請使用服務的其中一個函式:
具有 DriverRegKeyPersistentState DRIVER_REGKEY_TYPE的 IoOpenDriverRegistryKey (WDM)
GetServiceRegistryStateKey (Win32 Services) 與 ServiceRegistryStatePersistent SERVICE_REGISTRY_STATE_TYPE
如果服務想要允許其他元件修改這些設定,服務必須公開另一個元件可以呼叫的介面,告知服務如何改變這些設定。 例如,Win32 服務可能會公開 COM 或 RPC 介面,而驅動程式服務可以透過裝置介面公開 IOCTL 介面。
共用服務登錄狀態
共用服務狀態是在運行時間寫入的狀態,如果元件具有足夠的許可權,則可以與其他使用者模式元件共用。 若要存取此共享服務狀態的位置,請使用下列其中一個函式:
具有 DriverRegKeySharedPersistentState DRIVER_REGKEY_TYPE的 IoOpenDriverRegistryKey (WDM)
GetSharedServiceRegistryStateKey (Win32 Services) 與 ServiceSharedRegistryPersistentState SERVICE_SHARED_REGISTRY_STATE_TYPE
檔案狀態
本節包含下列子區段:
裝置檔案狀態
如果與裝置相關的檔案必須在運行時間寫入,這些檔案應該與透過OS API提供的句柄或檔案路徑相對儲存。 該裝置特有的組態檔是此處要儲存的檔類型的其中一個範例。 若要存取此狀態的位置,請使用服務中的其中一個函式:
服務檔案狀態
服務檔案狀態可分類為3個類別之一
不可變的服務檔案狀態
不可變的服務檔案狀態是屬於驅動程式套件的檔案。 如需存取這些檔案的詳細資訊,請參閱 從驅動程式存放區執行。
內部服務檔案狀態
內部服務檔案狀態是在運行時間寫入,且只由服務本身擁有和管理的狀態,而且只能供該服務存取。 若要存取內部服務狀態的位置,請使用服務的其中一個函式:
IoGetDriverDirectory (WDM, KMDF) ,並將 DirectoryType 參數設定為 DriverDirectoryData
GetServiceDirectory (Win32 Services) ,並將 eDirectoryType 參數設定為 ServiceDirectoryPersistentState
如果服務想要允許其他元件修改這些設定,服務必須公開另一個元件可以呼叫的介面,告知服務如何改變這些設定。 例如,Win32 服務可能會公開 COM 或 RPC 介面,而驅動程式服務可以透過裝置介面公開 IOCTL 介面。
共用服務檔案狀態
共用服務檔案狀態是在運行時間寫入的狀態,如果元件具有足夠的許可權,則可以與其他使用者模式元件共用。 若要存取此共享服務狀態的位置,請使用下列其中一個函式:
IoGetDriverDirectory (WDM, KMDF) ,並將 DirectoryType 參數設定為 DriverDirectorySharedData
GetSharedServiceDirectory (Win32 Services) ,並將 DirectoryType 參數設定為 ServiceSharedDirectoryPersistentState
DriverData 和 ProgramData
可以與其他元件共用但不符合 共用服務檔案狀態 類別的檔案,可以寫入 DriverData
或 ProgramData
位置。
這些位置提供元件位置,以寫入要由其他元件取用的暫存狀態或狀態,並可能從系統收集並複製,以便由另一個系統處理。 例如,自定義記錄檔或損毀傾印符合此描述。
避免在 或 ProgramData
目錄的DriverData
根目錄中寫入檔案。 相反地,請使用您的公司名稱建立子目錄,然後在該目錄中寫入檔案和進一步子目錄。
例如,針對 Contoso 的公司名稱,內核模式驅動程式可以將自定義記錄寫入 , \DriverData\Contoso\Logs
而使用者模式應用程式可以從 收集或分析記錄檔 %DriverData%\Contoso\Logs
。
DriverData
此 DriverData
目錄可在 Windows 10 版本 1803 和更新版本中使用,而且可供系統管理員和 UMDF 驅動程式存取。
內核模式驅動程式會使用稱為\DriverData
的系統提供的符號連結來存取DriverData
目錄。
使用者模式程式會使用環境變數 %DriverData%
來存取DriverData
目錄。
ProgramData
使用者 %ProgramData%
模式環境變數可用於儲存數據時要使用的使用者模式元件。
暫存檔案
臨時檔通常用於中繼作業。 這些可以寫入 或 %TMP%
環境變數下的%TEMP%
子路徑。 由於這些位置是透過環境變數存取,因此這項功能僅限於使用者模式元件。 在關閉這些暫存盤的句柄之後,這些暫存盤的存留期或持續性沒有任何保證。 操作系統或使用者可以隨時移除它們,而且可能無法在重新啟動期間保存。
避免在 或 %TMP%
目錄的%TEMP%
根目錄中寫入檔案。 相反地,請使用您的公司名稱建立子目錄,然後在該目錄中寫入檔案和進一步子目錄。
屬性狀態
裝置和裝置介面都支援透過 PnP 屬性模型儲存狀態。 屬性模型允許針對裝置或裝置介面儲存結構化屬性數據。 這適用於較小的數據,可合理地納入屬性模型所支援的屬性類型。
若要存取裝置屬性,可以使用這些 API:
WDM 驅動程式
WDF 驅動程式
使用者模式程序代碼
若要存取裝置介面屬性,可以使用這些 API:
WDM 驅動程式
WDF 驅動程式
使用者模式程序代碼
使用裝置介面
如果驅動程式想要允許其他元件讀取或修改驅動程式的內部狀態,驅動程式應該公開另一個元件可以呼叫的介面,告知驅動程式要傳回哪些設定,或如何修改特定設定。 例如,驅動程式服務可以透過裝置介面公開IOCTL介面。
一般而言,擁有狀態的驅動程式會在自定義裝置介面類別中公開裝置介面。 當驅動程式準備好讓其他元件能夠存取狀態時,它會啟用 介面。 若要在啟用裝置介面時收到通知,使用者模式元件可以註冊 裝置介面抵達通知 ,而核心模式元件可以使用 IoRegisterPlugPlayNotification。 若要讓這些元件存取狀態,啟用介面的驅動程序必須為其自定義裝置介面類別定義合約。 此合約通常是兩種類型之一:
I/O 合約可以與該裝置介面類別相關聯,該類別提供存取狀態的機制。 其他元件會使用已啟用的裝置介面來傳送符合合約的 I/O 要求。
透過 查詢介面傳回的直接呼叫介面 。 其他驅動程式可能會傳送 IRP_MN_QUERY_INTERFACE ,以從驅動程式擷取要呼叫的函式指標。
或者,如果擁有狀態的驅動程式允許直接存取狀態,其他驅動程式可以使用系統提供的函式來存取狀態,以程序設計方式存取裝置介面狀態。 如需詳細資訊,請參閱 裝置介面登錄狀態 。
這些介面或狀態(視所使用的共用方法而定)必須正確設定版本,以便擁有狀態的驅動程式可以獨立於存取該狀態的其他元件進行服務。 驅動程式廠商無法依賴與驅動程式同時服務的其他元件,並保持相同的版本。
因為控制介面的裝置和驅動程式會來回走,驅動程式和應用程式應該避免在元件啟動時呼叫 IoGetDeviceInterfaces ,以取得已啟用介面的清單。 相反地,最佳做法是註冊裝置介面抵達或移除的通知,然後呼叫適當的函式以取得計算機上現有已啟用介面的清單。
如需裝置介面的詳細資訊,請參閱:
狀態管理 API 作業系統支援的快速參考
大部分的驅動程式套件都需要支援一系列操作系統版本。 如需如何在驅動程式套件中達成此目的的詳細資訊,請參閱 支援多個操作系統版本 。 下表提供針對各種狀態管理 API 新增作業系統支援時的快速參考。
WDM 驅動程式
KMDF 驅動程式
UMDF 驅動程式
使用者模式程序代碼
作業系統 | 已新增支援 |
---|---|
Windows 2000 | CM_Open_DevNode_Key |
Windows Vista | CM_Open_Device_Interface_Key CM_Get_DevNode_Property CM_Set_DevNode_Property CM_Get_Device_Interface_Property CM_Set_Device_Interface_Property |
Windows 10 2004 | GetServiceRegistryStateKey GetServiceDirectory |
Windows 11 21H2 | GetSharedServiceRegistryStateKey GetSharedServiceDirectory |