Partager via


IO_COMPLETION_ROUTINE fonction de rappel (wdm.h)

La routine IoCompletion termine le traitement des opérations d’E/S.

Syntaxe

IO_COMPLETION_ROUTINE IoCompletionRoutine;

NTSTATUS IoCompletionRoutine(
  [in]           PDEVICE_OBJECT DeviceObject,
  [in]           PIRP Irp,
  [in, optional] PVOID Context
)
{...}

Paramètres

[in] DeviceObject

Pointeur fourni par l’appelant vers une structure DEVICE_OBJECT . Il s’agit de l’objet d’appareil pour l’appareil cible, précédemment créé par la routine AddDevice du pilote.

[in] Irp

Pointeur fourni par l’appelant vers une structure IRP qui décrit l’opération d’E/S.

[in, optional] Context

Pointeur fourni par l’appelant vers des informations de contexte spécifiques au pilote, précédemment fournies lors de l’appel de IoSetCompletionRoutine ou IoSetCompletionRoutineEx. Les informations de contexte doivent être stockées dans la mémoire non paginée, car une routine IoCompletion peut être appelée à DISPATCH_LEVEL. Pour plus d'informations, consultez la section Notes qui suit.

Valeur retournée

Si la routine IoCompletion détermine qu’un traitement supplémentaire est nécessaire pour l’IRP, elle doit retourner STATUS_MORE_PROCESSING_REQUIRED. Pour plus d'informations, consultez la section Notes qui suit. Sinon, elle doit retourner STATUS_SUCCESS. (Le gestionnaire d’E/S vérifie uniquement la présence ou l’absence de STATUS_MORE_PROCESSING_REQUIRED.)

Remarques

La routine IoCompletion d’un pilote s’exécute dans un thread ou un contexte DPC arbitraire et à un IRQL inférieur ou égal à DISPATCH_LEVEL. Étant donné que le code écrit pour s’exécuter à DISPATCH_LEVEL s’exécute également à des niveaux inférieurs, les routines IoCompletion doivent être conçues pour être exécutées à DISPATCH_LEVEL. Toutefois, comme il n’est pas garanti que ces routines s’exécutent à DISPATCH_LEVEL, elles ne doivent pas appeler des routines système qui nécessitent une exécution à DISPATCH_LEVEL. (Pour plus d’informations sur les IRQL, consultez Gestion des priorités matérielles.)

Pour inscrire une routine IoCompletion pour une IRP spécifique, un pilote doit appeler IoSetCompletionRoutine ou IoSetCompletionRoutineEx, qui stocke l’adresse de la routine IoCompletion dans l’emplacement de pile d’E/S du pilote inférieur suivant. (Par conséquent, un pilote de niveau inférieur ne peut pas inscrire une routine IoCompletion .) Un pilote appelle généralement IoSetCompletionRoutine ou IoSetCompletionRoutineEx à partir de l’une de ses routines de distribution, chaque fois qu’un IRP est reçu. La plupart des pilotes, y compris tous les pilotes PnP, peuvent utiliser IoSetCompletionRoutine pour inscrire leur routine IoCompletion . Les pilotes non PnP qui peuvent être déchargés avant l’exécution de leur routine IoCompletion doivent utiliser IoSetCompletionRoutineEx à la place.

Lorsqu’un pilote termine une IRP, il appelle IoCompleteRequest, qui appelle à son tour la routine IoCompletion de chaque pilote de niveau supérieur, du plus élevé au plus élevé, jusqu’à ce que toutes les routines IoCompletion supérieures aient été appelées ou jusqu’à ce qu’une routine retourne STATUS_MORE_PROCESSING_REQUIRED.

Lorsque vous créez l’IRP, allouez un emplacement de pile pour le pilote actuel ainsi que pour les pilotes inférieurs. Si vous n’allouez pas suffisamment d’emplacements de pile, le pointeur DeviceObject peut être défini sur NULL lorsque la routine d’achèvement est appelée. Vous pouvez éviter d’allouer un emplacement de pile supplémentaire pour le pilote actuel si vous utilisez le champ Contexte pour transmettre des informations à IoCompletion au lieu de vous appuyer sur le paramètre DeviceObject .

Si une routine IoCompletion retourne STATUS_MORE_PROCESSING_REQUIRED, l’appel du pilote inférieur à IoCompleteRequest retourne immédiatement. Dans ce cas, un pilote de niveau supérieur devra appeler IoCompleteRequest pour terminer l’IRP.

Pour plus d’informations sur l’implémentation de routines IoCompletion , consultez Achèvement des irps.

Exemples

Pour définir une routine de rappel IoCompletion , vous devez d’abord fournir une déclaration de fonction qui identifie le type de routine de rappel que vous définissez. Windows fournit un ensemble de types de fonctions de rappel pour les pilotes. La déclaration d’une fonction à l’aide des types de fonction de rappel permet à l’analyse du code pour les pilotes, au vérificateur de pilotes statiques (SDV) et à d’autres outils de vérification de trouver des erreurs. Il s’agit d’une exigence pour l’écriture de pilotes pour le système d’exploitation Windows.

Par exemple, pour définir une routine de rappel IoCompletion nommée MyIoCompletion, utilisez le type IO_COMPLETION_ROUTINE comme indiqué dans cet exemple de code :

IO_COMPLETION_ROUTINE MyIoCompletion;

Ensuite, implémentez votre routine de rappel comme suit :

_Use_decl_annotations_
NTSTATUS
  MyIoCompletion(
    PDEVICE_OBJECT  DeviceObject,
    PIRP  Irp,
    PVOID  Context
    )
  {
      // Function body
  }

Le type de fonction IO_COMPLETION_ROUTINE est défini dans le fichier d’en-tête Wdm.h. Pour identifier plus précisément les erreurs lors de l’exécution des outils d’analyse du code, veillez à ajouter l’annotation _Use_decl_annotations_ à votre définition de fonction. L’annotation _Use_decl_annotations_ garantit que les annotations appliquées au type de fonction IO_COMPLETION_ROUTINE dans le fichier d’en-tête sont utilisées. Pour plus d’informations sur la configuration requise pour les déclarations de fonction, consultez Déclaration de fonctions à l’aide de types de rôles de fonction pour les pilotes WDM. Pour plus d’informations sur _Use_decl_annotations_, consultez Annotating Function Behavior.

Configuration requise

Condition requise Valeur
Plateforme cible Desktop (Expérience utilisateur)
En-tête wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
IRQL Appelé à l’adresse IRQL <= DISPATCH_LEVEL (voir la section Remarques).