Dela via


Ordning för enhetsfilterdrivrutiner

Microsoft har utvecklat en metod för att deklarativt lägga till filter genom att uttrycka avsikten med filtret i stället för stackpositionen, så kallad enhetsfilterdrivrutinsordning.

Behovet av sekvensering av enhetsfilterdrivrutiner

Före Windows 10 version 1903 var det enda sättet att registrera en drivrutin för enhetsfilter att lägga till en registerpost (med hjälp av AddReg-direktivet). Den här metoden för registermanipulering ger dock inte flexibiliteten att ange exakt vilken position som ska registreras för ett visst filter.

Filterregistrering med hjälp av AddReg-direktivet lägger helt enkelt till filtret i slutet av filterlistan. Den här metoden använder en lista med värden där ordningen är viktig och avgör var i stacken filtret läses in.

Att använda en enda lista med ordnade värden är mindre än idealiskt, särskilt när AddRegbaraläggertill i slutet, eftersom det finns negativa konsekvenser när mer än en drivrutin lägger till filter på samma enhet.

I scenariot där det finns minst en tilläggs-INF , om INF:erna felaktigt använder AddReg (med andra ord inte använder tilläggsflaggan), kan de rensa ett filter som lagts till av en annan INF.

Dessutom kan flera tilläggs-INF:er lägga till filter, och den relativa ordningen för dessa filter kan vara viktig. PnP-plattformen (Plug and Play) garanterar dock inte någon installationsorder för tilläggen. Resultatet är att ordningen på "tilläggen" inte garanteras.

Implementera ordningen för enhetsfilterdrivrutin

För att tillhandahålla en flexibel deklarativ metod för att registrera enhetsfilter har Microsoft utvecklat en metod för att deklarativt lägga till filter genom att uttrycka avsikten med filtret i stället för stackpositionen. Lösningen ger funktionsdrivrutinens författare möjlighet att i sin INF uttrycka en ordnad uppsättning positioner (kallas nivåer) som ett filter kan registrera sig mot.

Förutom en specifik nivå kan ett filter deklarativt registrera sig som ett filter på övre eller lägre nivå.

Infrastrukturen baseras på en ny filterregistreringsmetod för att avgöra vilka orderdrivrutiner som ska ingå i enhetsstacken. Den nya metoden bryter inte kompatibiliteten för det gamla sättet att lägga till filter. Det gör dock att nya filter kan övergå till en mer robust och flexibel registreringsmekanism.

Metoden aktiveras genom att bas-INF definierar en ordnad lista med en eller flera "nivåer". Både bas-INF och eventuella tilläggs-INF:er kan registrera ett deklarativt filter via ett nytt INF-direktiv som anger tjänstnamnet och nivån som filtret tillhör. De övre och nedre filtren representeras av respektive ordnad lista över nivåer.

Dessa övre och nedre filterlistor skapas genom att alla filterdrivrutiner sorteras efter deras nivå. Ordningen på filtren på varje nivå bör betraktas som godtycklig, där man inte kan förlita sig på filterordningen inom en viss nivå. I scenarier där den relativa ordningen på två filter måste garanteras bör de registreras på olika nivåer.

Tänk på följande exempel på enhetsdrivrutiner:

Installation av enhetsdrivrutiner som visas som en enhetsstackordning som sammanfogar listorna med filterdrivrutiner samtidigt som önskad positionering och ordning respekteras.

Enhetsdrivrutinens bas-INF deklarerar två övre filternivåer, A och B (i den ordningen). I bas-INF:ets associerade tilläggs-INF läggs två filter till i var och en av de två nivåerna.

Resultatet av installationen av drivrutinen är en enhetsstackordning som sammanfogar listorna med filterdrivrutiner samtidigt som önskad positionering och ordning respekteras. Den resulterande enhetsstackens ordning säkerställer att alla filter som placeras på A-nivån kommer före alla filter på B-nivån. Inom varje nivå är dock ordningen godtycklig.

Som du ser i exemplet kan Filter3 komma före Filter5 eller så kan det komma efter Filter5. I vilket fall som helst kommer Filter3 och Filter5 före filtren på nästa nivå, "B".

När du utformar serien med nivåer som filter kan registreras mot, i stället för att skapa en serie nivåer för ordningens skull, bör nivåerna namnges och ordnas så att de mappas till filtrets avsikt. Till exempel kan en I/O-enhet definiera nivån Kryptering, till vilken alla krypteringsfilter ska registreras. Detta gör avsikten med filtret lätt att förstå och hantera, och det gör stacken mer robust mot brytande ändringar i funktionsdrivrutinen.

Anmärkning

Även utan nivåer som definieras av bas-INF kan ett deklarativt filter registreras som helt enkelt övre eller lägre. När nivåerna inte har definierats är detta logiskt detsamma som att lägga till filtret i slutet av registervärdet UpperFilters/LowerFilters. När nivåerna definieras måste en av nivåerna markeras som standardnivån i basdrivrutinen, och i det här fallet registreras filtret på den nivån.

Scenarier

Överväg en I/O-enhetsdrivrutin som krypterar de data som kommer genom stacken. En typisk implementering kan använda en lägre filterdrivrutin direkt under funktionsdrivrutinen för att åstadkomma detta. För att säkerställa att krypteringsfiltret placeras på exakt den position som drivrutinsförfattaren önskar kan de använda deklarativa filter enligt nedan:

Diagram som visar att genom att uttryckligen placera filterdrivrutinen

Bas-INF upprättar två nivåer av lägre filter, "Kryptering" och "Övervakning" (standard). "Övervakning" (Standard) i det här exemplet är de övriga lägre filter som kan finnas för den här enheten. Genom att uttryckligen placera filterdrivrutinen "Kryptera" på nivån "Kryptering" ser drivrutinen till att den resulterande enhetsstackens ordning placerar filterdrivrutinen "Kryptera" före andra lägre filter och omedelbart följer funktionsdrivrutinen.

Vi tar exemplet ett steg längre. Anta att en nyare version av drivrutinen kommer ut och att författaren har byggt in kryptering till funktionsdrivrutinen. Detta tar bort behovet av en separat "Kryptera"-filterdrivrutin. Författaren behöver helt enkelt ta bort nivån som innehöll "Encrypt"-filtret från Base INF och när drivrutinen uppdateras skapas stacken dynamiskt igen.

Om ett filter deklarerar sig vara på en explicit nivå som inte finns hamnar filtret inte i enhetsstacken. I exemplet har Bas-INF uppdaterats och även om inf-tillägget förblir detsamma undantar den resulterande enhetsstacken filtret "Encrypt" eftersom det inte ingick i Base INF:s deklaration av nivåer.

Diagram som tar bort nivån som innehöll

Standardfilternivå

För att generera den slutliga filterstacken sammanfogas alla källor med filterinformation till en enda lista. Observera att kopplingslogik utförs när du skapar enhetsstacken. Om ett nytt filter läggs till genom att installera en ny/uppdaterad bas- eller tilläggsdrivrutin startas enheterna om under installationen och en ny filterlista hämtas.

Vissa filterkällor saknar någon positionsinformation, nämligen filter som läggs till via äldre Registervärden för UpperFilters/LowerFilters eller genom deklarativ syntax endast för position (beskrivs nedan).

För att stödja en effektiv sammanslagning när det saknas positionsinformation måste ytterligare information definieras av bas-INF: en standardfilternivå. Standardfilternivån är en position där filter, som saknar nivå- eller positionsinformation, infogas.

Till exempel kan filternivåer definieras i bas-INF som:

Level Order: A, B, C
DefaultFilterLevel: C

Om du anger standardnivån som den sista nivån anger du att alla filter som saknar positionsinformation läggs till i filterlistan. Alternativt kanske drivrutinsförfattaren vill att stacken alltid ska sluta med filter som uttryckligen är registrerade på nivå C:

Level Order: A, B, C
DefaultFilterLevel: B

På grund av den standardfilternivå som anges till B infogas ytterligare filter utan positionsinformation mellan A:s filter och C:s filter.

Syntax

Registrera filter

Mer information finns i avsnittet INF DDInstall.Filters och dokumentationen för AddFilter-direktivet .

[DDInstall.Filters]
AddFilter = <FilterName>, [Flags], FilterSection

FilterLevel OR FilterPosition kan anges på något av två sätt:

Alternativ 1:

[FilterSection]
FilterLevel=<LevelName>

Alternativ 2:

[FilterSection]
FilterPosition=Upper/Lower

Detta kan göras i både bas- och tilläggs-INF:er.

[DDInstall.Filters]

FilterName är namnet på tjänsten i systemet.

Flaggor är för närvarande oanvända och bör lämnas tomma eller inställda på 0.

FilterSection är ett avsnitt som beskriver filtret.

Filter-avsnitt

Ett filteravsnitt måste innehålla exakt ett av följande två direktiv: FilterLevel eller FilterPosition.

En FilterLevel är en specifik plats för att infoga enhetsfiltret i stacken, som definieras av Bas-INF.  Inom varje nivå är filterordningen godtycklig.

En FilterPosition används i det fall där klassen har en specifik plats för filter från tredje part som ska infogas.

Definiera filternivåer

[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"

Detta kan bara göras av en basdrivrutin .

Den fullständiga deklarativa listan med filter för en specifik enhet kan hämtas genom att köra frågor mot följande egenskaper:

DEVPKEY_Device_CompoundUpperFilters
DEVPKEY_Device_CompoundLowerFilters

Äldre ekvivalent filterregistrering

Nu ska vi undersöka hur du utför den äldre metoden för att försöka lägga till ett övre filter via INF:

[DDInstall.HW]
AddReg = Filters

[Filters]
HKR,,"UpperFilters", 0x00010008, "MyFilter"

Den här syntaxen lägger till "MyFilter" i slutet av listan med övre filter.

Med den nya syntax som har introducerats liknar ovanstående avsnitt logiskt:

[DDInstall.Filters]
AddFilter = MyFilter,,MyUpperFilterInstall

[MyUpperFilterInstall]
FilterPosition = Upper

Detta anger att filtret "MyFilter" ska läggas till i listan över övre filter. Om bas-INF har angett filternivåer registreras filtret på standardnivån för den positionen med FilterPosition .

Om filternivåerna inte anges registreras det här filtret som ett övre filter i godtycklig ordning.

Se även

Avsnittet INF DDInstall.Filters

AddFilter-direktiv