Ordenação do driver de filtro de dispositivo
A Microsoft desenvolveu um método de adicionar filtros declarativamente expressando a intenção do filtro, em vez da posição da pilha, conhecido como ordenação do driver de filtro de dispositivo.
A necessidade de ordenação do driver de filtro de dispositivo
Antes do Windows 10 versão 1903, a única maneira com suporte de registrar um driver de filtro de dispositivo era pela adição de uma entrada do Registro (usando a diretiva AddReg). No entanto, esse método de manipulação do Registro não fornece a flexibilidade de especificar exatamente em qual posição registrar um filtro específico.
O registro de filtro usando a diretiva AddReg simplesmente acrescenta o filtro ao final da lista de filtros. Essa abordagem usa uma lista de valores em que a ordem é importante e determina onde na pilha o filtro é carregado.
Usar uma única lista de valores ordenados é menos do que o ideal, especialmente quando AddReg acrescenta apenas ao final, pois há consequências negativas quando mais de um driver está adicionando filtros ao mesmo dispositivo.
No cenário em que há pelo menos um INF de Extensão envolvido, se os INFs usarem AddReg incorretamente (em outras palavras, não usem o sinalizador de acréscimo), eles poderão eliminar um filtro adicionado por um INF diferente.
Além disso, vários INFs de extensão podem estar adicionando filtros, e a ordem relativa desses filtros pode ser importante; no entanto, a plataforma Plug and Play (PnP) não garante uma ordem de instalação para as extensões. O resultado é que a ordem dos "anexos" não é garantida.
Implementando a ordenação do driver de filtro de dispositivo
Para fornecer um método declarativo flexível para registrar filtros de dispositivo, a Microsoft desenvolveu um método de adicionar filtros declarativamente expressando a intenção do filtro, em vez da posição da pilha. A solução fornece aos autores do driver de função a capacidade de expressar em seu INF um conjunto ordenado de posições (chamados níveis) em relação ao qual um filtro pode se registrar.
Além de um nível específico, um filtro pode ser registrado declarativamente simplesmente como um filtro de nível superior ou inferior .
A infraestrutura é baseada em um novo método de registro de filtro para determinar qual ordem os drivers devem ser incluídos na pilha de dispositivos. O novo método não interrompe a compatibilidade com a maneira antiga de adicionar filtros. No entanto, permite que novos filtros passem para um mecanismo de registro mais robusto e flexível.
O método é habilitado fazendo com que o INF base defina uma lista ordenada de um ou mais "níveis". O INF base e quaisquer INFs de extensão podem registrar um filtro declarativo por meio de uma nova diretiva INF que especifica o nome do serviço e o nível ao qual o filtro pertence. Os filtros superior e inferior são representados por sua própria lista ordenada de níveis.
Essas listas de filtros superior e inferior são criadas classificando todos os drivers de filtro por seu nível. A ordem dos filtros dentro de cada nível deve ser considerada arbitrária, onde nenhuma dependência pode ser tomada na ordem dos filtros dentro de um determinado nível. Em cenários em que a ordem relativa de dois filtros deve ser garantida, eles devem ser registrados em níveis diferentes.
Considere o seguinte exemplo de driver de dispositivo:
O INF base do driver de dispositivo declara dois níveis de filtro superiores, A e B (nessa ordem). No INF de extensão associado ao INF base, dois filtros são adicionados a cada um dos dois níveis.
O resultado da instalação do driver de dispositivo é uma ordem de pilha de dispositivos que mescla as listas de drivers de filtro, respeitando o posicionamento e a ordenação desejados. A ordem de pilha de dispositivos resultante garante que qualquer filtro colocado no nível "A" venha antes de qualquer filtro no nível "B". No entanto, dentro de cada nível, a ordem é arbitrária.
Conforme mostrado no exemplo, o Filtro3 pode vir antes do Filtro5 ou pode vir depois do Filtro5. De qualquer forma, o Filtro3 e o Filtro5 virão antes dos filtros no próximo nível, "B".
Ao projetar a série de níveis em que os filtros podem ser registrados, em vez de criar uma série de níveis para fins de ordenação, os níveis devem ser nomeados e ordenados de forma que sejam mapeados para a intenção do filtro. Por exemplo, um dispositivo de E/S pode definir o nível de criptografia, no qual qualquer filtro de criptografia deve ser registrado. Isso permite que a intenção do filtro seja facilmente compreendida e gerenciada e torna a pilha mais robusta contra alterações significativas no driver de função.
Observação
Mesmo sem níveis definidos pelo INF base, um filtro declarativo pode ser registrado como simplesmente superior ou inferior. Quando os níveis não são definidos, isso é logicamente equivalente a acrescentar o filtro ao final do valor do Registro UpperFilters/LowerFilters. Quando os níveis são definidos, um dos níveis deve ser marcado como o nível padrão no driver base e, nesse caso, o filtro será registrado nesse nível.
Cenários
Considere um driver de dispositivo de E/S que criptografa os dados que estão passando pela pilha. Uma implementação típica pode usar um driver de filtro inferior imediatamente abaixo do driver de função para fazer isso. Para garantir que o filtro de criptografia seja colocado na posição exata que o autor do driver deseja, eles podem usar filtros declarativos, conforme mostrado abaixo:
O INF Base estabelece dois níveis de filtros inferiores, "Criptografia" e "Monitoramento" (Padrão). "Monitoramento" (padrão) neste exemplo são os demais filtros inferiores que podem existir para esse dispositivo específico. Ao colocar explicitamente o driver de filtro "Criptografar" no nível "Criptografia", o driver garante que a ordem de pilha de dispositivos resultante colocará o driver de filtro "Criptografar" antes de qualquer outro filtro inferior e imediatamente após o driver de função.
Vamos dar um passo adiante no exemplo. Imagine que uma versão mais recente do driver seja lançada e o autor tenha integrado criptografia ao driver de função. Isso elimina a necessidade de um driver de filtro "Criptografar" separado. O autor simplesmente precisa remover o nível que continha o filtro "Criptografar" do INF Base e, quando o driver for atualizado, a pilha será criada dinamicamente novamente.
Se um filtro se declarar em um nível explícito que não existe, o filtro não terminará na pilha de dispositivos. No exemplo, o INF Base foi atualizado e, embora o INF de Extensão permaneça o mesmo, a pilha de dispositivos resultante exclui o filtro "Criptografar", pois ele não foi incluído na declaração de níveis do INF Base.
Nível de filtro padrão
Para gerar a pilha de filtros final, todas as fontes de informações de filtro são mescladas em uma única lista. É importante observar que a lógica de mesclagem é executada ao criar a pilha de dispositivos. Se um novo filtro for adicionado instalando um driver base ou de extensão novo/atualizado, os dispositivos serão reiniciados durante a instalação e selecionarão uma nova lista de filtros.
Algumas fontes de filtros não têm nenhuma informação de posição, ou seja, filtros adicionados por meio dos valores herdados do Registro UpperFilters/LowerFilters ou por meio da sintaxe declarativa somente posição (discutida abaixo).
Para dar suporte a uma mesclagem eficaz quando faltam informações de posição, uma informação adicional deve ser definida pelo INF Base: um nível de filtro padrão. O nível de filtro padrão é uma posição em que filtros, sem informações de nível ou posição, serão inseridos.
Por exemplo, os níveis de filtro podem ser definidos no INF Base como:
Level Order: A, B, C
DefaultFilterLevel: C
Especificar o nível padrão como o nível final indica que qualquer filtro que não tenha informações de posição será anexado à lista de filtros. Como alternativa, o autor do driver pode querer que a pilha sempre termine com filtros explicitamente registrados no nível C:
Level Order: A, B, C
DefaultFilterLevel: B
Devido ao nível de filtro padrão ser definido como B, qualquer filtro adicional sem informações de posição será inserido entre os filtros de A e os filtros de C.
Sintaxe
Registrando filtros
Consulte a seção INF DDInstall.Filters e a documentação da diretiva AddFilter para obter mais informações.
[DDInstall.Filters]
AddFilter = <FilterName>, [Flags], FilterSection
FilterLevel OR FilterPosition pode ser especificado de duas maneiras:
Opção 1:
[FilterSection]
FilterLevel=<LevelName>
Opção 2:
[FilterSection]
FilterPosition=Upper/Lower
Isso pode ser feito em INFs de Base e de Extensão.
[DDInstall.Filters]
FilterName é o nome do serviço no sistema.
Flags não é usado no momento e deve ser deixado vazio ou definido como 0.
FilterSection é uma seção que descreve o filtro.
[Seção de filtro]
Uma seção de filtro deve conter exatamente uma das duas diretivas a seguir: FilterLevel ou FilterPosition.
Um FilterLevel é um local específico para inserir o filtro de dispositivo na pilha, definido pelo INF Base. Dentro de cada nível, a ordem dos filtros é arbitrária.
Um FilterPosition é usado no caso em que a classe tem um local específico para filtros de terceiros a serem inseridos.
Definindo níveis de filtro
[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"
Isso só pode ser feito por um driver básico .
A lista declarativa completa de filtros para um dispositivo específico pode ser recuperada consultando as seguintes propriedades:
DEVPKEY_Device_CompoundUpperFilters
DEVPKEY_Device_CompoundLowerFilters
Registro de filtro equivalente a legado
Vamos examinar como realizar a abordagem herdada de tentar adicionar um filtro superior via INF:
[DDInstall.HW]
AddReg = Filters
[Filters]
HKR,,"UpperFilters", 0x00010008, "MyFilter"
Essa sintaxe adicionará "MyFilter" ao final da lista de filtros superiores.
Com a nova sintaxe que foi introduzida, a seção acima é logicamente semelhante a:
[DDInstall.Filters]
AddFilter = MyFilter,,MyUpperFilterInstall
[MyUpperFilterInstall]
FilterPosition = Upper
Isso especifica que o filtro "MyFilter" deve ser adicionado à lista de filtros superiores. Se o INF base tiver especificado níveis de filtro, o uso de FilterPosition registrará o filtro no nível padrão para essa posição.
Se os níveis de filtro não forem especificados, esse filtro será registrado como um filtro superior em ordem arbitrária.