Declarando funções usando tipos de função para drivers WDM

Observação

Do Windows 10 Versão 2004 em diante, o Driver Verifier estático (SDV) não requer mais anotações para identificar tipos de função de rotinas de despacho para drivers WDM. Siga as orientações na seção Inicializações básicas e avançadas desta página.

Para informar o SDV sobre os pontos de entrada do driver ao analisar um driver WDM, você deve declarar funções usando declarações de tipo de função. Os tipos de função são definidos em Wdm.h. Cada ponto de entrada na rotina DriverEntry no driver WDM deve ser declarado especificando o tipo de função correspondente. Os tipos de função são typedefs predefinidos que correspondem aos pontos de entrada reconhecidos em um driver WDM.

Por exemplo, para criar uma declaração de tipo de função para a rotina Unload do driver chamada CsampUnload, use a declaração predefinida de tipo de função DRIVER_UNLOAD do typedef. A declaração de tipo de função deve aparecer antes da definição da função.

DRIVER_UNLOAD CsampUnload;

A definição da função CsampUnload permanece inalterada:

VOID
CsampUnload(
    IN PDRIVER_OBJECT DriverObject
    )
{
    ...
}

O SDV reconhece os tipos de ponto de entrada mostrados na tabela a seguir.

Tipo de função WDM Rotina WDM

DRIVER_INITIALIZE

DriverEntry

DRIVER_STARTIO

StartIO

DRIVER_UNLOAD

Descarregar

DRIVER_ADD_DEVICE

AddDevice

Dispatch_type (tipo) DRIVER_DISPATCH

A(s) rotina(s) de despacho utilizada(s) pelo driver. Consulte Criação de rotinas de despacho.

IO_COMPLETION_ROUTINE

IoCompletion

A rotina IoCompletion é definida ao chamar IoSetCompletionRoutine ou IoSetCompletionRoutineEx e transmitir o ponteiro de função para a rotinaIoCompletion como segundo parâmetro.

DRIVER_CANCEL

Cancelar

A rotina Cancel é definida ao chamar IoSetCancelRoutine e transmitindo o ponteiro de função para a rotina de cancelamento do IRP como o segundo parâmetro para a função.

IO_DPC_ROUTINE

DpcForIsr

A rotina DpcForIsr é registrada ao chamar IoInitializeDpcRequest e transmitir o ponteiro de função para a rotina DpcForIsr como o segundo parâmetro. Para adicionar DPC à fila, chame IoQueueDpc da rotina ISR usando o mesmo objeto DPC.

KDEFERRED_ROUTINE

CustomDpc

A rotina CustomDpc está definida para chamar KeInitializeDpc e transmitindo o ponteiro de função para CustomDpc como o segundo parâmetro. Para adicionar CustomDpc à fila do driver, chame KeInsertQueueDpc da rotina ISR usando o mesmo objeto DPC.

KSERVICE_ROUTINE

InterruptService

A rotina InterruptService (ISR) atende a uma interrupção de dispositivo e agenda o processamento pós-interrupção dos dados recebidos, se necessário.

REQUEST_POWER_COMPLETE

A rotina de retorno de chamada PowerCompletion conclui o processamento de um IRP de energia. Se o driver precisar de tarefas adicionais depois que todos os outros drivers tiverem concluído o IRP, o driver registrará uma rotina de retorno de chamada PowerCompletion durante a chamada para a rotina PoRequestPowerIrp que aloca o IRP.

WORKER_THREAD_ROUTINE

Rotina

Routine é a rotina de retorno de chamada especificada no segundo parâmetro para a função ExInitializeWorkItem.

A Routine deverá ser declarada dessa maneira somente se o driver chamar ExQueueWorkItem para adicionar o item de trabalho a uma fila do sistema.

Declaração de rotinas de despacho de driver

Do Windows 10 Versão 2004 em diante, as declarações de tipo de função para rotinas de despacho são refinadas com sua categoria IRP automaticamente com base na inicialização da tabela DriverObject->MajorFunction na rotina DriverEntry de um driver WDM.

Um driver Foo deve realizar declarações de função usando o estilo básico ou avançado de declaração para ser compatível com SDV.

Inicializações básicas e avançadas

O estilo básico pode ser visto no exemplo abaixo (note que os nomes de rotina de despacho FooCreate e FooCleanup são apenas exemplos, qualquer nome apropriado pode ser usado):

DriverObject->MajorFunction[IRP_MJ_CREATE] = FooCreate; //Basic style
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCleanup;

Uma abordagem mais avançada poderá ser adotada para encurtar a lista necessária. Embora a mesma rotina de despacho seja usada para mais de uma categoria de IRP, um driver poderá codificar duas inicializações desta maneira:

DriverObject->MajorFunction[IRP_MJ_CREATE] = 
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FooCreateCleanup; // Advanced style for a multi-role dispatch routine 

Para que um driver seja capaz de executar um SDV corretamente, o driver deverá usar somente o estilo básico ou avançado mostrado acima. A verificação SDV no driver não funcionará como esperado se um desses dois métodos não for usado.

Parâmetros de função e tipos de função

Conforme exigido na linguagem de programação C, os tipos de parâmetro que você usa na definição de função devem corresponder aos tipos de parâmetro do protótipo de função ou, nesse caso, ao tipo de função. O SDV depende das assinaturas de função para análise e ignora funções cujas assinaturas não coincidem.

Por exemplo, você deve declarar uma rotina IoCompletion usando o tipo de função IO_COMPLETION_ROUTINE:

IO_COMPLETION_ROUTINE myCompletionRoutine;

Ao implementar myCompletionRoutine, os tipos de parâmetro deverão corresponder àqueles usados por IO_COMPLETION_ROUTINE, ou seja, PDEVICE_OBJECT, PIRP e PVOID (consulte a rotina IoCompletion para obter a sintaxe).

NTSTATUS
myCompletionRoutine(
 PDEVICE_OBJECT  DeviceObject,
 PIRP  Irp,
 PVOID  Context
 )
{
}

Execução da análise de código para drivers para verificar as declarações de função

Para ajudar você a determinar se o código-fonte está preparado, execute Análise de código para drivers. A análise de código para drivers verifica se há declarações de tipo de função e pode ajudar a identificar declarações de função que podem ter sido perdidas, bem como avisar quando os parâmetros da definição de função não correspondem aos parâmetros do tipo de função.