裝置篩選驅動程式排序
Microsoft已開發宣告式新增篩選的方法,方法是表示篩選的意圖,而不是堆棧位置,稱為裝置篩選驅動程式排序。
裝置篩選驅動程式排序的需求
在 Windows 10 版本 1903 之前,註冊裝置篩選驅動程式的唯一支援方式是新增登錄專案(使用 AddReg 指示詞)。 不過,這個登錄操作方法並不提供彈性來確切地指定 要註冊特定篩選的位置 。
使用 AddReg 指示詞篩選註冊只會將篩選附加至篩選清單的結尾。 此方法會使用值清單,其中順序很重要,並決定載入篩選條件在堆疊中的位置。
使用單一排序值清單並不理想,特別是當 AddReg 只附加至結尾時,因為當多個驅動程式將篩選新增至相同裝置時,會產生負面影響。
在涉及至少一個 擴充功能 INF 的案例中,如果 INF 不正確地使用 AddReg (換句話說不要使用附加旗標),他們可以抹除由不同 INF 新增的篩選。
此外,多個擴充功能 INF 可以新增篩選,而且這些篩選的相對順序可能很重要;不過,隨插即用 (PnP) 平臺並不保證延伸模組的安裝順序。 結果是「附加」的順序不保證。
實作裝置篩選驅動程式排序
為了提供彈性的宣告式方法來註冊裝置篩選,Microsoft已藉由表達篩選的意圖,而不是堆棧位置,來開發以宣告方式新增篩選的方法。 此解決方案可讓函式驅動程式作者在其 INF 中表達篩選條件可能自行註冊的已排序位置集(稱為層級)。
除了特定層級之外,篩選條件也可以以宣告方式註冊為 上 層或 較低 層級篩選條件。
基礎結構是以新的篩選註冊方法為基礎,以判斷要包含在裝置堆疊中的驅動程序順序。 新方法不會中斷舊版新增篩選的相容性。 不過,它可讓新的篩選器移至更健全且更有彈性的註冊機制。
方法的啟用方式是讓基底 INF 定義一或多個「層級」的已排序列表。 基底 INF 和任何擴充 INF 都可能透過新的 INF 指示詞註冊宣告式篩選,以指定篩選所屬的服務名稱和層級。 每個上層和下層篩選都會以各自的已排序層級清單來表示。
這些上層和下層篩選清單會依層級排序所有篩選驅動程式來建立。 每個層級內的篩選順序都應該視為 任意,而特定層級內的篩選順序不可以採用任何相依性。 在必須 保證兩個篩選條件的相對順序的情況下,應該註冊到不同的層級。
請考慮下列裝置驅動器範例:
裝置驅動程式的基底 INF 會宣告兩個上層篩選層級 A 和 B(依該順序)。 在基底 INF 的關聯擴充功能 INF 中,會將兩個篩選新增至兩個層級。
裝置驅動程式安裝的結果是一種裝置堆疊順序,可合併篩選驅動程式的清單,同時遵守所需的定位和排序。 產生的裝置堆疊順序可確保放置在 「A」 層級中的任何篩選都位於 「B」 層級中的任何篩選之前。 不過,在每個層級內,順序都是任意的。
如範例所示,Filter3 可能位於 Filter5 之前,或可能位於 Filter5 之後。 在任何情況下,Filter3 和 Filter5 都會出現在下一個層級 “B” 的篩選條件之前。
設計可針對篩選條件註冊的一系列層級時,而不是為了排序而建立一系列層級時,層級應該命名並排序,使其對應至篩選的意圖。 例如,I/O 裝置可以定義應該註冊任何加密篩選的層級 加密。 這可讓篩選的意圖更容易理解及管理,並讓堆疊更強固,以防止對函式驅動程序進行重大變更。
注意
即使沒有基底 INF 所定義的層級,宣告式篩選也可以登錄為上下層。 未定義層級時,這在邏輯上相當於將篩選附加至 UpperFilters/LowerFilters 登錄值的結尾。 定義層級時,其中一個層級必須標示為基底驅動程式中的預設層級,在此情況下,篩選會註冊到該層級。
案例
請考慮 I/O 裝置驅動器,以加密通過堆疊的數據。 一般實作可能會使用函式驅動程式下方的較低篩選驅動程式來完成這項作業。 為了確保加密篩選器放置在驅動程式作者想要的確切位置,他們可以使用宣告式篩選,如下所示:
Base INF 會建立兩個較低層級的篩選,「加密」和「監視」(預設值)。 此範例中的「監視」(預設值)是此特定裝置可能存在的其餘較低篩選器。 藉由明確地將 「Encrypt」 篩選驅動程式放在 「加密」層級,驅動程式可確保產生的裝置堆疊順序會將 「Encrypt」 篩選驅動程式放在任何其他較低的篩選之前,並緊接在函式驅動程序之後。
讓我們進一步採取範例。 假設有較新版本的驅動程序出來,且作者已內建函式驅動程序的加密。 這可移除個別「加密」篩選驅動程式的需求。 作者只需要從基底 INF 移除包含 「Encrypt」 篩選的層級,以及驅動程式更新時,堆疊會再次動態建置。
如果篩選條件將本身宣告為不存在的明確層級,篩選條件最終不會出現在裝置堆疊中。 在此範例中,基底 INF 已更新,即使擴充功能 INF 保持不變,產生的裝置堆疊會排除 “Encrypt” 篩選器,因為它未包含在Base INF的層級宣告中。
默認篩選層級
若要產生最終篩選堆疊,篩選資訊的所有來源都會合併成單一清單。 請務必注意,在建立裝置堆疊時會執行 合併邏輯。 如果藉由安裝新的/更新基底或擴充功能驅動程式來新增篩選,裝置將會在安裝期間重新啟動,並挑選新的篩選清單。
某些篩選來源缺少任何位置資訊,也就是透過舊版 UpperFilters/LowerFilters 登錄值新增的篩選,或透過僅限位置的宣告式語法(如下所述)。
若要在缺少位置資訊時支援有效的合併,基底 INF 必須定義額外的資訊片段:預設篩選層級。 默認篩選層級是會插入篩選條件、缺少層級或位置資訊的位置。
例如,篩選層級可能會在基底 INF 中定義為:
Level Order: A, B, C
DefaultFilterLevel: C
將預設層級指定為最終層級,表示任何缺少位置資訊的篩選都會 附加 至篩選清單。 或者,驅動程式作者可能希望堆疊一律以明確註冊至層級 C 的篩選條件結尾:
Level Order: A, B, C
DefaultFilterLevel: B
由於預設篩選層級設定為 B,任何沒有位置資訊的額外篩選都會插入 A 篩選條件與 C 篩選之間。
語法
註冊篩選
如需詳細資訊,請參閱 INF DDInstall.Filters 一節和 AddFilter 指示詞檔。
[DDInstall.Filters]
AddFilter = <FilterName>, [Flags], FilterSection
FilterLevel OR FilterPosition 可透過下列兩種方式之一指定:
選項 1:
[FilterSection]
FilterLevel=<LevelName>
選項 2:
[FilterSection]
FilterPosition=Upper/Lower
這可以在Base和ExtensionINF的中完成。
[DDInstall.Filters]
FilterName 是系統上的服務名稱。
旗標 目前未使用,且應該保留空白或設定為 0。
FilterSection 是描述篩選的區 段。
[Filter 區段]
篩選區段必須只包含下列兩個指示詞之一: FilterLevel 或 FilterPosition。
FilterLevel 是一個在基底 INF 所定義的堆疊上插入裝置篩選的特定位置。 在每個層級內,篩選的順序是任意的。
在類別有一個要插入第三方篩選的特定位置的情況下,會使用 FilterPosition。
定義篩選層級
[DDInstall.HW]
AddReg = FilterLevel_Definition
[FilterLevel_Definition]
HKR,,UpperFilterLevels,%REG_MULTI_SZ%,"LevelA","LevelB","LevelC"
HKR,,UpperFilterDefaultLevel,,"LevelC"
HKR,,LowerFilterLevels,%REG_MULTI_SZ%,"LevelD","LevelE","LevelF"
HKR,,LowerFilterDefaultLevel,,"LevelE"
這隻能由 基底 驅動程式完成。
您可以藉由查詢下列屬性來擷取特定裝置的完整宣告式篩選清單:
DEVPKEY_Device_CompoundUpperFilters
DEVPKEY_Device_CompoundLowerFilters
舊版對等篩選註冊
讓我們來看看如何完成嘗試透過 INF 新增上層篩選的舊版方法:
[DDInstall.HW]
AddReg = Filters
[Filters]
HKR,,"UpperFilters", 0x00010008, "MyFilter"
此語法會將 「MyFilter」 新增至上方篩選清單的結尾。
透過引進的新語法,上述區段在邏輯上類似:
[DDInstall.Filters]
AddFilter = MyFilter,,MyUpperFilterInstall
[MyUpperFilterInstall]
FilterPosition = Upper
這會指定應該將篩選 「MyFilter」 新增至上層篩選清單。 如果基底 INF 已指定篩選層級,則使用 FilterPosition 會在該位置的預設層級中註冊篩選。
如果未指定篩選層級,此篩選會以任意順序註冊為上層篩選。