Diretrizes para portabilidade de drivers de filtro herdados

Os desenvolvedores são incentivados a portar drivers de filtro herdados para o modelo do gerenciador de filtros para obter melhor funcionalidade para seus drivers de filtro e melhorar a confiabilidade do sistema. Os desenvolvedores experientes devem achar relativamente fácil portar um driver de filtro herdado para um driver de minifiltro. Os desenvolvedores de driver de filtro na Microsoft recomendam a seguinte abordagem:

  • Comece com um conjunto de testes de regressão confiável para verificar o comportamento entre o driver de filtro herdado e o driver de minifiltro portado.

  • Crie um shell de driver de minifiltro e mova sistematicamente a funcionalidade do driver de filtro herdado para o driver de minifiltro. Por exemplo, faça com que o anexo funcione e, em seguida, faça a portabilidade de uma operação por vez, testando após cada operação.

  • Altere a comunicação do modo de usuário/kernel por último, para que você possa usar as ferramentas existentes para testar o driver de minifiltro.

  • Compile com PREfast e teste com a opção de verificação de E/S do Verificador de Filtro no Verificador de Driver habilitada.

Durante o processo de portabilidade, você deve examinar todo o código do driver de filtro herdado para aproveitar ao máximo os recursos do gerenciador de filtros. Em particular, tenha o seguinte em mente:

  • As operações de E/S baseadas em IRP e E/S rápidas podem passar pela mesma operação quando apropriado, o que ajuda a reduzir a duplicação de código.

  • Ao registrar-se para operações, um driver de minifiltro pode optar explicitamente por ignorar todas as E/S de paginação e E/S armazenadas em cache, o que elimina a necessidade de código marcar-las.

  • As notificações de instância simplificam muito a lógica de anexação/desanexação.

  • Registre-se somente para operações que o driver de minifiltro deve manipular; você pode ignorar todo o resto.

  • Aproveite o contexto do gerenciador de filtros e o suporte ao gerenciamento de nomes.

  • Aproveite o suporte do gerenciador de filtros para emitir E/S não recursiva.

  • Ao contrário dos drivers de filtro herdados, os drivers de minifiltro não podem contar com variáveis locais para manter o contexto desde o processamento de pré-operação até o processamento de postoperation. Considere alocar uma lista lookaside para armazenar o estado da operação.

  • Certifique-se de liberar referências quando terminar com um nome ou contexto.

  • As portas de conclusão no modo de usuário adicionam uma técnica avançada para criar filas. Você provavelmente precisará de apenas uma única conexão com uma única porta nomeada.

A tabela a seguir lista as operações comuns em um driver de filtro herdado e como elas são mapeadas para o modelo do gerenciador de filtros.

Modelo de driver de filtro herdado Modelo do gerenciador de filtros

Operação de passagem sem rotina de conclusão

Se o driver de minifiltro nunca funcionar para esse tipo de operação de E/S, não registre uma rotina de retorno de chamada de pré-operação ou postoperation para esta operação.

Caso contrário, retorne FLT_PREOP_SUCCESS_NO_CALLBACK da rotina de retorno de chamada de pré-operação registrada para essa operação.

Consulte Retornando FLT_PREOP_SUCCESS_NO_CALLBACK.

Operação de passagem com uma rotina de conclusão

Retorne FLT_PREOP_SUCCESS_WITH_CALLBACK da rotina de retorno de chamada de pré-operação.

Consulte Retornando FLT_PREOP_SUCCESS_WITH_CALLBACK.

Operação pendente na rotina de retorno de chamada de pré-operação

Chame FltLockUserBuffer conforme necessário para garantir que todos os buffers de usuário estejam corretamente bloqueados para que possam ser acessados em um thread de trabalho.

Enfileirar o trabalho para um thread de trabalho chamando rotinas de suporte como FltAllocateDeferredIoWorkItem e FltQueueDeferredIoWorkItem.

Retorne FLT_PREOP_PENDING da rotina de retorno de chamada de pré-operação.

Quando estiver pronto para retornar a operação de E/S para o gerenciador de filtros, chame FltCompletePendedPreOperation.

Consulte Pendente uma operação de E/S em uma rotina de retorno de chamada de pré-operação.

Operação pendente na rotina de retorno de chamada de postoperation

Na rotina de retorno de chamada de pré-operação, chame FltLockUserBuffer para garantir que os buffers de usuário estejam corretamente bloqueados para que possam ser acessados em um thread de trabalho.

Enfileirar o trabalho para um thread de trabalho chamando rotinas de suporte como FltAllocateGenericWorkItem e FltQueueGenericWorkItem.

Retorne FLT_POSTOP_MORE_PROCESSING_REQUIRED da rotina de retorno de chamada de postoperation.

Quando estiver pronto para retornar a operação de E/S para o gerenciador de filtros, chame FltCompletePendedPostOperation.

Consulte Pendente uma operação de E/S em uma rotina de retorno de chamada do Postoperation.

Sincronizar a operação

Retorne FLT_PREOP_SYNCHRONIZE da rotina de retorno de chamada de pré-operação.

Consulte Retornando FLT_PREOP_SYNCHRONIZE.

Concluir a operação na rotina de retorno de chamada de pré-operação

Defina a operação final status e informações no membro IoStatus da estrutura FLT_CALLBACK_DATA para a operação.

Retorne FLT_PREOP_COMPLETE da rotina de retorno de chamada de pré-operação.

Confira Como concluir uma operação de E/S em uma rotina de retorno de chamada de pré-operação.

Concluir a operação depois que ela tiver sido pendente na rotina de retorno de chamada de pré-operação

Defina a operação final status e informações no membro IoStatus da estrutura FLT_CALLBACK_DATA para a operação.

Chame FltCompletePendedPreOperation do thread de trabalho que processa a operação de E/S, passando FLT_PREOP_COMPLETE como o parâmetro CallbackStatus .

Confira Como concluir uma operação de E/S em uma rotina de retorno de chamada de pré-operação.

Fazer todo o trabalho de conclusão na rotina de conclusão

Retornar FLT_POSTOP_FINISHED_PROCESSING da rotina de retorno de chamada de postoperation.

Consulte Escrevendo rotinas de retorno de chamada de postoperação.

Fazer o trabalho de conclusão em IRQL seguro

Chame FltDoCompletionProcessingWhenSafe da rotina de retorno de chamada de postoperation.

Consulte Garantindo que o processamento de conclusão seja executado em IRQL seguro.

Sinalizar um evento da rotina de conclusão

Retorne FLT_PREOP_SYNCHRONIZE da rotina de retorno de chamada de pré-operação para essa operação.

O gerenciador de filtros chama a rotina de retorno de chamada de postoperation no mesmo contexto de thread que a rotina de retorno de chamada de pré-operação, em IRQL <= APC_LEVEL.

Consulte Retornando FLT_PREOP_SYNCHRONIZE.

Falha em uma operação de criação bem-sucedida

Chame FltCancelFileOpen da rotina de retorno de chamada de postoperation para a operação de criação.

Defina um valor NTSTATUS de erro apropriado no membro IoStatus da estrutura FLT_CALLBACK_DATA para a operação.

Retornar FLT_POSTOP_FINISHED_PROCESSING.

Confira Falha em uma operação de E/S em uma rotina de retorno de chamada de postoperation.

Não permitir E/S por meio do caminho de E/S rápido para uma operação de E/S

Retorne FLT_STATUS_DISALLOW_FAST_IO da rotina de retorno de chamada de pré-operação para a operação.

Confira Não permitir uma operação de E/S rápida em uma rotina de retorno de chamada de pré-operação.

Modificar os parâmetros de uma operação de E/S

Defina os valores de parâmetro modificados no membro Iopb da estrutura FLT_CALLBACK_DATA para a operação.

Marque a estrutura FLT_CALLBACK_DATA como sujo chamando FltSetCallbackDataDirty, exceto quando você tiver modificado o conteúdo do membro IoStatus da estrutura FLT_CALLBACK_DATA.

Consulte Modificando os parâmetros para uma operação de E/S.

Bloquear o buffer de usuário para a operação

Use as técnicas e diretrizes descritas em Acessar os buffers de usuário para uma operação de E/S.