Preprocessing and Postprocessing IRPs

[S’applique à KMDF uniquement]

Si votre pilote doit intercepter un paquet de demande d’E/S (IRP) avant ou après que l’infrastructure gère l’IRP, le pilote peut appeler WdfDeviceInitAssignWdmIrpPreprocessCallback pour inscrire une fonction de rappel d’événement EvtDeviceWdmIrpPreprocess pour un code de fonction d’E/S principal et, éventuellement, pour des codes de fonction d’E/S secondaires spécifiques qui sont associés au code principal. Par la suite, l’infrastructure appelle la fonction de rappel EvtDeviceWdmIrpPreprocess du pilote chaque fois que le pilote reçoit un IRP qui contient un code de fonction principal et secondaire spécifié.

La fonction de rappel EvtDeviceWdmIrpPreprocess peut faire tout ce qui est nécessaire pour prétraiter l’IRP, puis elle doit appeler WdfDeviceWdmDispatchPreprocessedIrp pour renvoyer l’IRP à l’infrastructure, sauf si le pilote gère un IRP que l’infrastructure ne prend pas en charge.

Une fois que le pilote a appelé WdfDeviceWdmDispatchPreprocessedIrp, l’infrastructure traite l’IRP de la même façon que si le pilote n’avait pas fourni de fonction de rappel EvtDeviceWdmIrpPreprocess . Si le code de la fonction d’E/S de l’IRP est un code que l’infrastructure transmet aux pilotes, le pilote recevra à nouveau l’IRP en tant qu’objet de requête.

Si le pilote doit posttraiter l’IRP après qu’un pilote de niveau inférieur a terminé l’IRP, la fonction de rappel EvtDeviceWdmIrpPreprocess du pilote peut appeler IoSetCompletionRoutine pour définir une routine IoCompletion avant d’appeler WdfDeviceWdmDispatchPreprocessedIrp.

Une fois que votre pilote a appelé WdfDeviceInitAssignWdmIrpPreprocessCallback, le framework oblige le gestionnaire d’E/S à ajouter un emplacement de pile d’E/S supplémentaire à tous les IRP afin que la fonction de rappel EvtDeviceWdmIrpPreprocess puisse définir une routine IoCompletion . La fonction de rappel doit mettre à jour le pointeur d’emplacement de la pile d’E/S de l’IRP avant d’appeler WdfDeviceWdmDispatchPreprocessedIrp.

Appel de WdfDeviceWdmDispatchPreprocessedIrp

Étant donné que le gestionnaire d’E/S ajoute un emplacement de pile d’E/S supplémentaire à l’IRP, la fonction de rappel EvtDeviceWdmIrpPreprocess doit appeler IoSkipCurrentIrpStackLocation ou IoCopyCurrentIrpStackLocationToNext (pour configurer l’emplacement de pile d’E/S suivant dans l’IRP) avant d’appeler WdfDeviceWdmDispatchPreprocessedIrp.

Si votre pilote prétrait une IRP, mais pas le post-traitement de l’IRP, il n’a pas besoin de définir une routine IoCompletion pour l’IRP et peut appeler IoSkipCurrentIrpStackLocation, comme le montre l’exemple de code suivant.

NTSTATUS
  EvtDeviceMyIrpPreprocess(
    IN WDFDEVICE Device,
    IN OUT PIRP Irp
    )
{
//
// Perform IRP preprocessing operations here.
//
...
//
// Deliver the IRP back to the framework. 
//
IoSkipCurrentIrpStackLocation(Irp);
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

Si votre pilote est en cours de post-traitement de l’IRP, il doit appeler IoCopyCurrentIrpStackLocationToNext, puis il doit appeler IoSetCompletionRoutine pour définir une routine IoCompletion pour l’IRP, comme le montre l’exemple de code suivant.

NTSTATUS
  EvtDeviceMyIrpPreprocess(
    IN WDFDEVICE Device,
    IN OUT PIRP Irp
    )
{
//
// Perform IRP preprocessing operations here, if needed.
//
...
//
// Set a completion routine and deliver the IRP back to
// the framework. 
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
                       Irp,
                       MyIrpCompletionRoutine,
                       NULL,
                       TRUE,
                       TRUE,
                       TRUE
                      );
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

Votre pilote ne doit pas appeler IoCopyCurrentIrpStackLocationToNext (et ne doit donc pas définir une routine IoCompletion ) si l’objet de périphérique gère que la fonction de rappel EvtDeviceWdmIrpPreprocess du pilote reçoit représente un objet d’appareil physique (PDO) et si le code de fonction principal de l’IRP est IRP_MJ_PNP ou IRP_MJ_POWER. Dans le cas contraire, le vérificateur de pilote signale une erreur.

Pour plus d’informations sur le moment d’appeler IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocation et IoSetCompletionRoutine, consultez Passage d’IRPs dans la pile des pilotes.