Écriture de routines de rappel de pré-opération
Un pilote minifilter utilise une ou plusieurs routines de rappel de pré-opération pour filtrer les opérations d’E/S. Les routines de rappel de pré-opération sont similaires aux routines de répartition utilisées dans le modèle de filtre hérité.
Un minifiltre inscrit une routine de rappel de pré-opération pour un type particulier d’opération d’E/S en stockant le point d’entrée de la routine de rappel dans le membre OperationRegistration de la structure FLT_REGISTRATION . Le minifilter transmet ce membre à FltMgr en tant que paramètre à FltRegisterFilter dans sa routine DriverEntry .
Les minifiltres reçoivent uniquement les types d’opérations d’E/S pour lesquelles ils ont inscrit une routine de rappel avant ou après opération. Un minifiltre peut inscrire une routine de rappel de pré-opération pour un type donné d’opération d’E/S sans inscrire une routine de rappel post-opération, et vice versa.
Chaque routine de rappel de pré-opération est définie comme suit :
typedef FLT_PREOP_CALLBACK_STATUS
(*PFLT_PRE_OPERATION_CALLBACK) (
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
);
Lorsque FltMgr appelle la routine de rappel de pré-opération d’un minifiltre pour une opération d’E/S donnée, le minifiltre contrôle temporairement l’opération d’E/S. Le minifilter conserve ce contrôle jusqu’à ce que :
Retourne une valeur status autre que FLT_PREOP_PENDING de sa routine de rappel avant opération.
Appelle FltCompletePendedPreOperation à partir d’une routine de travail qui a traité une opération précédemment pendée dans sa routine de rappel avant l’opération.
Le tableau suivant répertorie quelques scénarios d’utilisation possibles de la routine de rappel avant opération d’un minifiltre et fournit les détails de l’implémentation et la valeur de retour pour chaque scénario.
Scénario d'utilisation | Implémentation | Valeur de retour |
---|---|---|
La routine n’est pas pertinente pour l’opération et ne nécessite pas la status finale de l’opération ou elle n’a pas de rappel post-opération. | Transmettez l’opération d’E/S et demandez à FltMgr de ne pas appeler le rappel post-opération du minifiltre à l’achèvement. | FLT_PREOP_SUCCESS_NO_CALLBACK |
La routine nécessite la status finale de l’opération. | Transmettez l’opération et indiquez à FltMgr d’appeler la routine de rappel post-opération du minifilter. | FLT_PREOP_SUCCESS_WITH_CALLBACK |
Le minifiltre doit terminer ou poursuivre le traitement de cette opération à l’avenir. | Placez l’opération dans un état en attente. Utilisez FltCompletePendedPreOperation pour terminer l’opération ultérieurement. Il peut y avoir une concurrence acceptable entre la routine de préopération qui retourne FLT_PREOP_PENDING et l’appel de FltCompletePendingOperation . FltMgr gère ce scénario sans entrée du pilote. | FLT_PREOP_PENDING |
Le traitement post-opération doit se produire dans le contexte du même thread que celui que la routine de distribution a été appelée. Cette condition garantit un IRQL cohérent et maintient l’état de votre variable locale. | Synchronisez l’opération avec la post-opération. | FLT_PREOP_SYNCHRONIZE |
La routine de rappel de pré-opération doit terminer l’opération. | Arrêtez le traitement de l’opération et affectez la valeur NTSTATUS finale. | FLT_PREOP_COMPLETE |
Routines de rappel IRQL et de pré-opération
FltMgr n’a aucun moyen de savoir ce qu’un minifiltre peut faire dans son rappel de pré-opération (ou tout rappel). FltMgr n’a donc aucun moyen de savoir si un appel au rappel pré-op du miniport peut provoquer un problème. (Il y a des choses que vous pouvez faire en toute sécurité à l’IRQL élevé et des choses que vous ne pouvez pas). Par conséquent, il appartient au minifiltre d’être conscient de l’IRQL et de le gérer de manière appropriée. Un minifiltre peut appeler KeGetCurrentIRQL en toute sécurité et à moindre coût pour les situations dans lesquelles il doit connaître l’IRQL auquel il a été appelé.
Les informations suivantes sur la routine de rappel de pré-opération d’un minifiltre IRQL sont utiles à connaître :
Un rappel de pré-opération peut être appelé dans IRQL = PASSIVE_LEVEL ou IRQL = APC_LEVEL. La plupart des rappels de pré-opération sont appelés dans IRQL = PASSIVE_LEVEL, dans le contexte du thread à l’origine de la demande d’E/S. Seules quelques rappels de pré-opération peuvent être appelés dans IRQL = APC_LEVEL.
Pour les opérations basées sur IRP, le rappel de pré-opération d’un minifiltre peut être appelé dans le contexte d’un thread de travail système si un pilote de filtre ou de minifiltre supérieur arrête l’opération pour traitement par le thread de travail. Un rappel de pré-opération est l’équivalent de la routine de distribution d’un filtre hérité. Il peut donc être utile de connaître le contexte IRQL et le contexte de thread de la routine de répartition d’un filtre hérité .
Les objets de contexte ne peuvent pas être récupérés dans les routines post-opération au APC_LEVEL IRQL > . Au lieu de cela, récupérez l’objet de contexte pendant une routine de pré-opération et passez-le à la routine post-opération ou effectuez un traitement post-opération à IRQL <= APC_LEVEL. Pour plus d’informations sur les contextes, consultez Gestion des contextes.
Articles connexes
Passage d’une opération d’E/S vers le bas de la pile d’instances Minifilter
Exécution d’une opération d’E/S dans une routine de rappel de préopération
Interdiction d’une opération d’E/S rapide dans une routine de rappel de préopération
En attente d’une opération d’E/S dans une routine de rappel de préopération