Share via


Contraintes sur les routines de répartition

Notes

Pour une fiabilité et des performances optimales, utilisez des pilotes de minifiltre de système de fichiers avec prise en charge de Filter Manager au lieu des pilotes de filtre de système de fichiers hérités. Pour porter votre pilote hérité vers un pilote de minifiltre, consultez Recommandations pour le portage des pilotes de filtre hérités.

Les instructions suivantes expliquent brièvement comment les pilotes de filtre de système de fichiers hérités peuvent éviter les erreurs de programmation courantes dans les routines de répartition.

Pour plus d’informations sur les types d’IRP utilisés dans la pagination des E/S, consultez Dispatch Routine IRQL et Thread Context.

  • Les routines de répartition dans le chemin d’E/S de pagination ne doivent jamais appeler IoCallDriver à une valeur IRQL supérieure à APC_LEVEL. Vous ne pouvez pas effectuer de pagination d’E/S (ou d’E/S) au DISPATCH_LEVEL, car le système utilise des API pour traiter l’achèvement des E/S, de sorte que vous ne verrez jamais l’opération terminée. Si une routine de répartition déclenche IRQL, elle doit la réduire avant d’appeler IoCallDriver.

  • Il n’est pas nécessairement sûr pour une routine de répartition d’appeler IoCallDriver à APC_LEVEL dans toutes les situations. Consultez Dispatch Routine IRQL et Thread Context pour déterminer si vous pouvez être à APC_LEVEL ou à PASSIVE_LEVEL.

  • Les routines de répartition dans le chemin d’E/S de pagination, telles que la lecture et l’écriture, ne peuvent pas appeler en toute sécurité les routines en mode noyau qui nécessitent que les appelants s’exécutent au PASSIVE_LEVEL IRQL.

  • Les routines de répartition qui se trouvent dans le chemin d’E/S du fichier de pagination ne peuvent pas appeler en toute sécurité les routines en mode noyau qui nécessitent qu’un appelant s’exécute au DISPATCH_LEVEL IRQL < .

  • Les routines de répartition qui ne se trouve pas dans le chemin d’E/S de pagination ne doivent jamais appeler IoCallDriver à une valeur IRQL supérieure à PASSIVE_LEVEL. Si une routine de répartition déclenche IRQL, elle doit la réduire avant d’appeler IoCallDriver.

Contraintes sur le traitement des IRPs

  • Si les paramètres IRP incluent des adresses d’espace utilisateur, ces adresses doivent être validées avant d’être utilisées. Pour plus d’informations, consultez Erreurs dans les E/S mises en mémoire tampon.

  • En outre, si l’IRP contient une mémoire tampon IOCTL ou FSCTL qui a été envoyée d’une plateforme 32 bits à une plateforme 64 bits, le contenu de la mémoire tampon peut avoir besoin d’être fragmenté. Pour plus d’informations, consultez Prise en charge des E/S 32 bits dans votre pilote 64 bits.

  • Contrairement aux systèmes de fichiers, les pilotes de filtre de système de fichiers ne doivent jamais appeler FsRtlEnterFileSystem ou FsRtlExitFileSystem , sauf avant d’appeler ExAcquireFastMutexUnsafe ou ExAcquireResourceExclusiveLite. FsRtlEnterFileSystem et FsRtlExitFileSystem désactivent les API de noyau normales, qui sont nécessaires à la plupart des systèmes de fichiers.

  • Vous ne pouvez pas émettre d’autres IRPs à partir d’un chemin d’E/S de pagination. Vous pouvez mettre en file d’attente un thread de travail qui émet des E/S, mais vous ne devez pas attendre de façon synchrone que ce thread de travail se termine, car l’attente provoque des blocages.

Contraintes sur l’exécution des IIP

  • Les pilotes de filtre de système de fichiers doivent utiliser uniquement les valeurs de réussite et d’état d’erreur lors de l’exécution des IRPs.

  • Bien que STATUS_PENDING soit une valeur NTSTATUS réussie, il s’agit d’une erreur de programmation pour effectuer un IRP avec STATUS_PENDING.

  • Une fois qu’une routine de répartition a appelé IoCompleteRequest, le pointeur IRP n’est plus valide et ne peut pas être déréférencé en toute sécurité.

Contraintes sur la définition d’une routine d’achèvement

Pour plus d’informations sur la définition des routines d’achèvement, consultez Utilisation de routines d’achèvement.

  • Lorsqu’une routine de répartition appelle IoSetCompletionRoutine, elle peut éventuellement passer un pointeur de contexte à une structure pour la routine d’achèvement à utiliser lors du traitement de l’IRP donné. Cette structure doit être allouée à partir d’un pool non paginé, car la routine d’achèvement peut être appelée IRQL DISPATCH_LEVEL.

  • Si une routine de répartition définit une routine d’achèvement qui peut retourner STATUS_MORE_PROCESSING_REQUIRED, elle doit effectuer l’une des opérations suivantes pour empêcher le Gestionnaire d’E/S de terminer l’IRP prématurément :

Contraintes sur la transmission des IRPs vers le bas

  • Une fois qu’une routine de répartition a appelé IoCallDriver, le pointeur IRP n’est plus valide et ne peut pas être déréférencé en toute sécurité, sauf si la routine de répartition attend que la routine d’achèvement signale qu’elle a été appelée.

  • Il s’agit d’une erreur de programmation d’appeler PoCallDriver à partir d’un pilote de filtre de système de fichiers. (PoCallDriver est utilisé pour transmettre IRP_MJ_POWER requêtes aux pilotes de niveau inférieur. Les pilotes de filtre de système de fichiers ne reçoivent jamais IRP_MJ_POWER demandes.)

Contraintes sur l’état de retour

  • Sauf lors de l’exécution d’une IRP, une routine de répartition qui ne définit pas de routine d’achèvement doit toujours retourner la valeur NTSTATUS retournée par IoCallDriver. À moins que cette valeur ne soit STATUS_PENDING, elle doit correspondre à la valeur de Irp-IoStatus.Status> définie par le pilote qui a terminé l’IRP.

  • Quand IoCallDriver retourne STATUS_PENDING, la routine de répartition doit également retourner STATUS_PENDING, sauf si elle attend que la routine d’achèvement signale un événement.

  • Lorsque la routine de répartition publie l’IRP dans une file d’attente de worker pour un traitement ultérieur, elle doit marquer l’IRP en attente et retourner STATUS_PENDING.

  • Lorsque la routine de répartition définit une routine d’achèvement qui peut publier l’IRP dans une file d’attente worker pour un traitement ultérieur, elle doit marquer l’IRP en attente et retourner STATUS_PENDING.

  • Une routine de distribution qui marque un IRP en attente doit retourner STATUS_PENDING.

  • Les opérations Oplock ne peuvent pas être suspendus (publiées dans une file d’attente worker) et les routines de répartition ne peuvent pas retourner STATUS_PENDING pour elles.

Contraintes relatives à la publication des IRPs dans une file d’attente de travail

  • Si une routine de répartition publie des IRP dans une file d’attente de travail, elle doit appeler IoMarkIrpPending avant de publier chaque IRP dans la file d’attente worker. Sinon, l’IRP pourrait être mis en file d’attente, terminé par une autre routine de pilote et libéré par le système avant que l’appel à IoMarkIrpPending se produise, provoquant ainsi un incident.