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

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