Partilhar via


Gravando rotinas de retorno de chamada pré-operação

Um driver de minifiltro usa uma ou mais rotinas de retorno de chamada pré-operação para filtrar operações de E/S. As rotinas de retorno de chamada de pré-operação são semelhantes às rotinas de expedição usadas no modelo de filtro herdado.

Um minifiltro registra uma rotina de retorno de chamada pré-operação para um tipo específico de operação de E/S armazenando o ponto de entrada da rotina de retorno de chamada no membro OperationRegistration da estrutura FLT_REGISTRATION . O minifiltro passa esse membro para FltMgr como um parâmetro para FltRegisterFilter em sua rotina DriverEntry .

Os minifiltros recebem apenas esses tipos de operações de E/S para as quais registraram uma rotina de retorno de chamada pré-operação ou pós-operação. Um minifiltro pode registrar uma rotina de retorno de chamada pré-operação para um determinado tipo de operação de E/S sem registrar uma rotina de retorno de chamada pós-operação e vice-versa.

Cada rotina de retorno de chamada pré-operação é definida da seguinte maneira:

typedef FLT_PREOP_CALLBACK_STATUS 
(*PFLT_PRE_OPERATION_CALLBACK) ( 
    IN OUT PFLT_CALLBACK_DATA Data, 
    IN PCFLT_RELATED_OBJECTS FltObjects, 
    OUT PVOID *CompletionContext 
    ); 

Quando o FltMgr chama a rotina de retorno de chamada pré-operação de um minifiltro para uma determinada operação de E/S, o minifiltro controla temporariamente a operação de E/S. O minifiltro mantém esse controle até que ele:

  • Retorna um valor de status diferente de FLT_PREOP_PENDING de sua rotina de retorno de chamada pré-operação.

  • Chama FltCompletePendedPreOperation de uma rotina de trabalho que processou uma operação que estava anteriormente pendente em sua rotina de retorno de chamada pré-operação.

A tabela a seguir lista alguns cenários de uso possíveis da rotina de retorno de chamada pré-operação de um minifiltro e fornece detalhes de implementação e o valor retornado para cada cenário.

Cenário de uso Implementação Valor Retornado
A rotina não é relevante para a operação e não requer a status final da operação ou não tem retorno de chamada pós-operação. Passe a operação de E/S e diga ao FltMgr para não chamar o retorno de chamada pós-operação do minifiltro após a conclusão. FLT_PREOP_SUCCESS_NO_CALLBACK
A rotina requer a status final da operação. Passe a operação e diga ao FltMgr para chamar a rotina de retorno de chamada pós-operação do minifiltro. FLT_PREOP_SUCCESS_WITH_CALLBACK
O minifiltro deve concluir ou continuar processando essa operação no futuro. Coloque a operação em um estado pendente. Use FltCompletePendedPreOperation para concluir a operação posteriormente. Pode haver uma corrida aceitável entre a rotina de pré-operação que retorna FLT_PREOP_PENDING e FltCompletePendingOperation sendo chamado. O FltMgr manipula esse cenário sem a entrada do driver. FLT_PREOP_PENDING
O processamento pós-operação deve ocorrer no contexto do mesmo thread que a rotina de expedição foi chamada. Essa condição garante IRQL consistente e mantém seu estado de variável local. Sincronize a operação com a pós-operação. FLT_PREOP_SYNCHRONIZE
A rotina de retorno de chamada pré-operação precisa concluir a operação. Pare o processamento da operação e atribua o valor final de NTSTATUS. FLT_PREOP_COMPLETE

Rotinas de retorno de chamada de IRQL e pré-operação

O FltMgr não tem como saber o que um minifiltro pode fazer em seu retorno de chamada pré-operação (ou qualquer retorno de chamada). Portanto, o FltMgr não tem como saber se uma chamada para o retorno de chamada pré-operatório do miniport pode causar um problema. (Há coisas que você pode fazer com segurança em IRQL elevado e coisas que você não pode). Portanto, cabe ao minifiltro estar ciente do IRQL e tratá-lo adequadamente. Um minifiltro pode chamar KeGetCurrentIRQL com segurança e barato para situações em que ele precisa saber o IRQL em que foi chamado.

As seguintes informações sobre o IRQL de rotina de retorno de chamada pré-operação de um minifiltro são úteis para saber:

  • Um retorno de chamada de pré-operação pode ser chamado em IRQL = PASSIVE_LEVEL ou IRQL = APC_LEVEL. A maioria dos retornos de chamada de pré-operação são chamados em IRQL = PASSIVE_LEVEL, no contexto do thread que originou a solicitação de E/S. Apenas um punhado de retornos de chamada pré-operação podem ser chamados em IRQL = APC_LEVEL.

  • Para operações baseadas em IRP, o retorno de chamada pré-operação de um minifiltro pode ser chamado no contexto de um thread de trabalho do sistema se um filtro mais alto ou um driver de minifiltro aguardar a operação para processamento pelo thread de trabalho. Um retorno de chamada pré-operação é o equivalente à rotina de expedição de um filtro herdado, portanto, conhecer o IRQL e o contexto de thread da rotina de expedição de um filtro herdado pode ser útil.

  • Objetos de contexto não podem ser recuperados em rotinas pós-operação no IRQL > APC_LEVEL. Em vez disso, obtenha o objeto de contexto durante uma rotina de pré-operação e passe-o para a rotina pós-operação ou execute o processamento pós-operação em IRQL <= APC_LEVEL. Para obter mais informações sobre contextos, consulte Gerenciando contextos.

Passando uma operação de E/S para baixo na pilha de instâncias de minifiltro

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

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

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