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. |
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. |