Instructions pour le portage des pilotes de filtre hérités
Les développeurs sont encouragés à porter les pilotes de filtre hérités vers le modèle de gestionnaire de filtres afin d’obtenir de meilleures fonctionnalités pour leurs pilotes de filtre et d’améliorer la fiabilité du système. Les développeurs expérimentés doivent trouver relativement facile de porter un pilote de filtre hérité vers un pilote minifilter. Les développeurs de pilotes de filtre chez Microsoft recommandent l’approche suivante :
Commencez avec une suite de tests de régression fiable pour vérifier le comportement entre le pilote de filtre hérité et le pilote minifilter porté.
Créez un interpréteur de commandes de pilote minifilter et déplacez systématiquement la fonctionnalité du pilote de filtre hérité vers le pilote minifilter. Par exemple, faites fonctionner la pièce jointe, puis portez une opération à la fois, en testant après chaque opération.
Modifiez la communication en mode utilisateur/noyau en dernier, afin de pouvoir utiliser les outils existants pour tester le pilote minifilter.
Compilez avec PREfast et testez avec l’option de vérification des E/S du vérificateur de filtre activée dans Driver Verifier.
Pendant le processus de portage, vous devez passer en revue tout le code du pilote de filtre hérité pour tirer pleinement parti des fonctionnalités du gestionnaire de filtres. En particulier, gardez à l’esprit les points suivants :
Les E/S basées sur IRP et les opérations d’E/S rapides peuvent passer par la même opération le cas échéant, ce qui permet de réduire la duplication du code.
Lors de l’inscription aux opérations, un pilote minifilter peut choisir explicitement d’ignorer toutes les E/S de pagination et les E/S mises en cache, ce qui évite que du code case activée celles-ci.
Les notifications d’instance simplifient considérablement la logique d’attachement/détachement.
Inscrivez-vous uniquement pour les opérations que votre pilote minifilter doit gérer ; vous pouvez ignorer tout le reste.
Tirez parti du contexte du gestionnaire de filtres et de la prise en charge de la gestion des noms.
Tirez parti de la prise en charge du gestionnaire de filtres pour l’émission d’E/S non récursives.
Contrairement aux pilotes de filtre hérités, les pilotes de minifiltre ne peuvent pas s’appuyer sur des variables locales pour conserver le contexte, du traitement préopération au traitement post-opération. Envisagez d’allouer une liste de lookaside pour stocker l’état de l’opération.
Veillez à publier les références lorsque vous avez terminé avec un nom ou un contexte.
Les ports d’achèvement en mode utilisateur ajoutent une technique puissante pour créer des files d’attente. Vous n’aurez probablement besoin que d’une seule connexion à un seul port nommé.
Le tableau suivant répertorie les opérations courantes dans un pilote de filtre hérité et la façon dont elles sont mappées au modèle de gestionnaire de filtres.
Modèle de pilote de filtre hérité | Modèle de gestionnaire de filtres |
---|---|
Opération directe sans routine d’achèvement |
Si votre pilote minifilter ne fonctionne jamais pour ce type d’opération d’E/S, n’inscrivez pas de routine de rappel de préopération ou de post-opération pour cette opération. Sinon, retournez FLT_PREOP_SUCCESS_NO_CALLBACK à partir de la routine de rappel de préopération inscrite pour cette opération. |
Opération directe avec une routine d’achèvement |
Retourne FLT_PREOP_SUCCESS_WITH_CALLBACK de la routine de rappel de préopération. Consultez Retour FLT_PREOP_SUCCESS_WITH_CALLBACK. |
Opération Pend dans la routine de rappel de préopération |
Appelez FltLockUserBuffer si nécessaire pour vous assurer que toutes les mémoires tampons utilisateur sont correctement verrouillées afin qu’elles soient accessibles dans un thread de travail. Mettez le travail en file d’attente vers un thread de travail en appelant des routines de support telles que FltAllocateDeferredIoWorkItem et FltQueueDeferredIoWorkItem. Retourne FLT_PREOP_PENDING à partir de la routine de rappel de préopération. Lorsque vous êtes prêt à retourner l’opération d’E/S dans le gestionnaire de filtres, appelez FltCompletePendedPreOperation. Consultez En attente d’une opération d’E/S dans une routine de rappel de préopération. |
Opération Pend dans la routine de rappel postopération |
Dans la routine de rappel de préopération, appelez FltLockUserBuffer pour vous assurer que les mémoires tampons utilisateur sont correctement verrouillées afin qu’elles soient accessibles dans un thread de travail. Mettez le travail en file d’attente vers un thread de travail en appelant des routines de support telles que FltAllocateGenericWorkItem et FltQueueGenericWorkItem. Retournez FLT_POSTOP_MORE_PROCESSING_REQUIRED à partir de la routine de rappel post-opération. Lorsque vous êtes prêt à retourner l’opération d’E/S au gestionnaire de filtres, appelez FltCompletePendedPostOperation. Consultez En attente d’une opération d’E/S dans une routine de rappel de post-opération. |
Synchroniser l’opération |
Retourne FLT_PREOP_SYNCHRONIZE à partir de la routine de rappel de préopération. Consultez Retour FLT_PREOP_SYNCHRONIZE. |
Terminer l’opération dans la routine de rappel de préopération |
Définissez l’opération finale status et les informations dans le membre IoStatus de la structure FLT_CALLBACK_DATA de l’opération. Retourne FLT_PREOP_COMPLETE à partir de la routine de rappel de préopération. Consultez Achèvement d’une opération d’E/S dans une routine de rappel de préopération. |
Terminez l’opération une fois qu’elle a été suspendu dans la routine de rappel de préopération |
Définissez l’opération finale status et les informations dans le membre IoStatus de la structure FLT_CALLBACK_DATA de l’opération. Appelez FltCompletePendedPreOperation à partir du thread de travail qui traite l’opération d’E/S, en passant FLT_PREOP_COMPLETE en tant que paramètre CallbackStatus . Consultez Achèvement d’une opération d’E/S dans une routine de rappel de préopération. |
Effectuer tout le travail d’achèvement dans la routine d’achèvement |
Retourne FLT_POSTOP_FINISHED_PROCESSING à partir de la routine de rappel post-opération. |
Effectuer un travail d’achèvement à l’IRQL sécurisé |
Appelez FltDoCompletionProcessingWhenSafe à partir de la routine de rappel postopération. Consultez Vérifier que le traitement d’achèvement est effectué dans l’IRQL sécurisé. |
Signaler un événement à partir de la routine d’achèvement |
Retourne FLT_PREOP_SYNCHRONIZE de la routine de rappel de préopération pour cette opération. Le gestionnaire de filtres appelle la routine de rappel après opération dans le même contexte de thread que la routine de rappel de préopération, à l’adresse IRQL <= APC_LEVEL. Consultez Retour FLT_PREOP_SYNCHRONIZE. |
Échec d’une opération de création réussie |
Appelez FltCancelFileOpen à partir de la routine de rappel postopération pour l’opération de création. Définissez une valeur NTSTATUS d’erreur appropriée dans le membre IoStatus de la structure FLT_CALLBACK_DATA pour l’opération. Retourne FLT_POSTOP_FINISHED_PROCESSING. Consultez Échec d’une opération d’E/S dans une routine de rappel postopératoire. |
Interdire les E/S via le chemin d’E/S rapide pour une opération d’E/S |
Retourne FLT_STATUS_DISALLOW_FAST_IO de la routine de rappel de préopération pour l’opération. Consultez Interdire une opération d’E/S rapide dans une routine de rappel de préopération. |
Modifier les paramètres d’une opération d’E/S |
Définissez les valeurs de paramètre modifiées dans le membre Iopb de la structure FLT_CALLBACK_DATA de l’opération. Marquez la structure FLT_CALLBACK_DATA comme sale en appelant FltSetCallbackDataDirty, sauf si vous avez modifié le contenu du membre IoStatus de la structure FLT_CALLBACK_DATA. Consultez Modification des paramètres d’une opération d’E/S. |
Verrouiller la mémoire tampon utilisateur pour l’opération |
Utilisez les techniques et les instructions décrites dans Accès aux mémoires tampons utilisateur pour une opération d’E/S. |