Criando um driver WDF para várias versões do Windows

O WDF sempre permitiu que você criasse um driver uma vez e usizasse o binário resultante em várias versões do Windows, mas antes de Windows 10 versão 1803 (Redstone 4), isso era limitado a "criar em versões mais antigas e executadas em versão mais recente". A partir Windows 10 versão 1803, o WDF adiciona "build on newer, run on older", com o benefício adicional da execução condicional. Para resumir:

  • Existente: binários criados com versões mais antigas da estrutura são executados em versões do Windows que incluem versões mais recentes da estrutura, fornecidas com as versões principais correspondentes. Por exemplo, um driver criado com KMDF 1.9 (Windows 7) é executado em um sistema de Windows 8 (KMDF 1.11). No exemplo, o driver está limitado à funcionalidade do KMDF 1.9.
  • Adicionado: a partir do KMDF versão 1.25 e UMDF versão 2.25 no Windows 10 versão 1803, você pode criar um driver com uma versão mais recente da estrutura e o binário de driver resultante é executado em versões anteriores do Windows (no mínimo Windows 10 versão 1803). Além disso, o driver pode usar condicionalmente a funcionalidade que só está disponível em versões de estrutura mais recentes.

Isso significa que seu driver não só é executado em versões futuras do Windows, como sempre fez, mas também é executado em versões anteriores, de volta para Windows 10 versão 1803.

Há duas etapas para fazer isso: especificar as configurações de build no Visual Studio e executar um runtime marcar antes de invocar uma API ou acessar uma estrutura ou campo que possa ou não estar presente.

Observação: esse recurso é opcional e um driver só deve habilitá-lo para criar um driver que usa a funcionalidade mais recente do WDF enquanto permanece carregando em versões anteriores do Windows que não têm a funcionalidade mais recente do WDF.

Se você não definir Versão Secundária (Versão de Destino) ou Versão Secundária (Mínimo Necessário), o controle de versão permanecerá o mesmo que antes.

Especificando o mínimo necessário

As novas configurações no Visual Studio são:

  • Versão secundária do KMDF (mínimo necessário)
  • Versão secundária do UMDF (mínimo necessário)

De acordo com essa alteração, os nomes de duas configurações existentes foram atualizados:

  • Versão secundária do KMDF –>KMDF versão secundária (versão de destino)
  • Versão secundária do UMDF ->UMDF versão secundária (versão de destino)

Se você não definir Mínimo Obrigatório, o Visual Studio criará para a Versão de Destino e para cima e não fornecerá suporte para baixo nível. Isso corresponde ao comportamento das propriedades secundárias da versão antiga.

Se você definir Mínimo Obrigatório, os seguintes requisitos se aplicarão:

  • 25 <= Mínimo Necessário <= Versão de Destino
  • Em Propriedades de Configuração-Configurações> do Driver-Geral>, defina _NT_TARGET_VERSION como 0x0A000005 (RS4) ou posterior.

Verificando se a funcionalidade está presente

Antes de cada uso de uma API, estrutura ou membro que possa ou não estar presente, você deve chamar uma das seguintes macros, que são definidas em WdfFuncEnum.h:

BOOLEAN
WDF_IS_FUNCTION_AVAILABLE (
    FunctionName
    );

BOOLEAN
WDF_IS_STRUCTURE_AVAILABLE (
    StructName
    );

BOOLEAN
WDF_IS_FIELD_AVAILABLE (
    StructName,
    FieldName
    );

Considere o exemplo a seguir. Quando o WDF v29 é lançado, ele adiciona uma nova API: WdfSomeNewFeature. Se você definir a Versão de Destino como 29 e Mínimo Obrigatório como 25, o driver resultante será carregado em qualquer versão da estrutura de 25 a 29 (e além, desde que a versão principal não seja alterada), chamará APIs da versão 25 como antes e fará o seguinte marcar antes de cada chamada de qualquer API v29:

if (WDF_IS_FUNCTION_AVAILABLE(WdfSomeNewFeature)) {
    WdfSomeNewFeature();
}

Se você não fizer o marcar condicional, poderá ver o seguinte:

  • Se a API retornar NTSTATUS, a chamada retornará um código de falha.
  • Se a API retornar algo diferente de NTSTATUS:
    • KMDF: verificações de bug do computador.
    • UMDF: o processo WudfHost falha com um erro driverStop.
  • Se o Verificador de Driver estiver habilitado, o driver também falhará. Isso ajuda a identificar o problema em um ambiente de teste.
  • Corrupção de memória silenciosa (ao acessar uma estrutura ou campo).

Uma falha de driver contém o nome do driver com falha, o nome da estrutura e o índice de API com falha. Você pode recuperar o nome da API pesquisando o valor de WDFFUNCENUM em WdfFuncEnum.h.

Para obter mais informações sobre as propriedades do Visual Studio para WDF, consulte Propriedades de configurações do modelo de driver para projetos de driver.