Escribir rutinas de devolución de llamada de operación previa
Un controlador de minifiltro usa una o varias rutinas de devolución de llamada de operación previa para filtrar las operaciones de E/S. Las rutinas de devolución de llamada de operación previa son similares a las rutinas de envío usadas en el modelo de filtro heredado.
Un minifiltro registra una rutina de devolución de llamada previa a la operación para un tipo determinado de operación de E/S almacenando el punto de entrada de la rutina de devolución de llamada en el miembro OperationRegistration de la estructura FLT_REGISTRATION . El minifiltro pasa este miembro a FltMgr como parámetro a FltRegisterFilter en su rutina DriverEntry .
Los minifiltros reciben solo los tipos de operaciones de E/S para las que han registrado una rutina de devolución de llamada previa o posterior a la operación. Un minifiltro puede registrar una rutina de devolución de llamada de operación previa a la operación para un tipo determinado de operación de E/S sin registrar una rutina de devolución de llamada posterior a la operación y viceversa.
Cada rutina de devolución de llamada de operación previa se define de la siguiente manera:
typedef FLT_PREOP_CALLBACK_STATUS
(*PFLT_PRE_OPERATION_CALLBACK) (
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
);
Cuando FltMgr llama a la rutina de devolución de llamada de operación previa de un minifiltro para una operación de E/S determinada, el minifiltro controla temporalmente la operación de E/S. El minifiltro conserva este control hasta que:
Devuelve un valor de estado distinto de FLT_PREOP_PENDING de su rutina de devolución de llamada de operación previa.
Llama a FltCompletePendedPreOperation desde una rutina de trabajo que ha procesado una operación que se ha precedido previamente en su rutina de devolución de llamada de operación previa.
En la tabla siguiente se enumeran algunos escenarios de uso posibles de la rutina de devolución de llamada de un minifiltro previo a la operación y se proporcionan detalles de implementación y el valor devuelto para cada escenario.
Escenario de uso | Implementación | Valor devuelto |
---|---|---|
La rutina no es relevante para la operación y no requiere el estado final de la operación o no tiene ninguna devolución de llamada posterior a la operación. | Pase la operación de E/S a través e indique a FltMgr que no llame a la devolución de llamada posterior a la operación del minifiltro al finalizar. | FLT_PREOP_SUCCESS_NO_CALLBACK |
La rutina requiere el estado final de la operación. | Pase la operación y indique a FltMgr que llame a la rutina de devolución de llamada posterior a la operación del minifiltro. | FLT_PREOP_SUCCESS_WITH_CALLBACK |
El minifiltro debe completarse o continuar procesando esta operación en el futuro. | Coloque la operación en un estado pendiente. Use FltCompletePendedPreOperation para completar la operación más adelante. Puede haber una carrera aceptable entre la rutina de operación previa que devuelve FLT_PREOP_PENDING y se llama a FltCompletePendingOperation . FltMgr controla este escenario sin la entrada del controlador. | FLT_PREOP_PENDING |
El procesamiento posterior a la operación debe producirse en el contexto del mismo subproceso al que se llamó a la rutina de envío. Esta condición garantiza una IRQL coherente y mantiene el estado de la variable local. | Sincronice la operación con la operación posterior. | FLT_PREOP_SYNCHRONIZE |
La rutina de devolución de llamada de operación previa debe completar la operación. | Detenga el procesamiento de la operación y asigne el valor NTSTATUS final. | FLT_PREOP_COMPLETE |
Rutinas de devolución de llamada de IRQL y de operación previa
FltMgr no tiene forma de saber qué puede hacer un minifiltro en su devolución de llamada previa a la operación (o cualquier devolución de llamada). Por lo tanto, FltMgr no tiene ninguna manera de saber si una llamada a la devolución de llamada previa de la miniporte podría causar un problema. (Hay cosas que puede hacer de forma segura en IRQL con privilegios elevados y cosas que no puede). Por lo tanto, el minifiltro debe ser consciente de IRQL y controlarlo adecuadamente. Un minifiltro puede llamar de forma segura y barata a KeGetCurrentIRQL para situaciones en las que necesita saber el IRQL en el que se llamó.
La siguiente información sobre la rutina de devolución de llamada de operación previa del minifiltro IRQL es útil para saber:
Se puede llamar a una devolución de llamada previa a la operación en IRQL = PASSIVE_LEVEL o IRQL = APC_LEVEL. La mayoría de las devoluciones de llamada previas a la operación se llaman en IRQL = PASSIVE_LEVEL, en el contexto del subproceso que originó la solicitud de E/S. Solo se puede llamar a una serie de devoluciones de llamada previas a la operación en IRQL = APC_LEVEL.
En el caso de las operaciones basadas en IRP, se puede llamar a la devolución de llamada previa a la operación de un minifiltro en el contexto de un subproceso de trabajo del sistema si un filtro superior o un minifiltro del controlador lápiz la operación para su procesamiento por parte del subproceso de trabajo. Una devolución de llamada previa a la operación es el equivalente a la rutina de distribución de un filtro heredado, por lo que conocer el irQL y el contexto de subproceso de la rutina de distribución de un filtro heredado puede resultar útil.
Los objetos de contexto no se pueden recuperar en rutinas posteriores a la operación en IRQL > APC_LEVEL. En su lugar, obtenga el objeto de contexto durante una rutina de operación previa y páselo a la rutina posterior a la operación o realice el procesamiento posterior a la operación en IRQL <= APC_LEVEL. Para obtener más información sobre los contextos, vea Managing Contexts.
Artículos relacionados
Pasar una operación de E/S hacia abajo en la pila de instancias de minifiltro
Completar una operación de E/S en una rutina de devolución de llamada de preoperación
No permitir una operación de E/S rápida en una rutina de devolución de llamada de preoperación
Pendiente de una operación de E/S en una rutina de devolución de llamada de preoperación