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