Exécution des demandes d’E/S

Chaque pilote basé sur l’infrastructure doit finalement terminer chaque demande d’E/S qu’il reçoit de l’infrastructure. Les pilotes terminent les requêtes en appelant la méthode WdfRequestComplete, WdfRequestCompleteWithInformation ou WdfRequestCompleteWithPriorityBoost de l’objet de requête .

Quand effectuer une demande

Un pilote doit effectuer une requête lorsqu’il détermine que l’un des cas suivants est vrai :

  • L’opération d’E/S demandée s’est terminée avec succès.

  • L’opération d’E/S demandée a démarré mais a échoué avant sa fin.

  • L’opération d’E/S demandée n’est pas prise en charge ou n’était pas valide au moment de sa réception et n’a pas pu être démarrée.

  • L’opération d’E/S demandée a été annulée.

Si le pilote traite la demande d’E/S en créant une activité d’E/S sur l’appareil, le pilote appelle généralement WdfRequestComplete à partir de sa fonction de rappel EvtInterruptDpc ou EvtDpcFunc .

Si le pilote reçoit une requête non prise en charge ou non valide, il appelle généralement WdfRequestComplete à partir du gestionnaire de requêtes qui a reçu la demande.

Si l’opération d’E/S a été annulée, le pilote appelle généralement WdfRequestComplete à partir de sa fonction de rappel EvtRequestCancel .

Si le pilote transfère la demande d’E/S à une cible d’E /S, le pilote termine la demande une fois que la cible d’E/S a terminé la demande, comme suit :

  • Si votre pilote transfère la requête d’E/S de manière synchrone à la cible d’E/S, l’appel du pilote à la cible d’E/S ne retourne qu’une fois qu’un pilote de niveau inférieur a terminé la demande (sauf si une erreur se produit). Une fois la cible d’E/S retournée, votre pilote doit appeler WdfRequestComplete.

  • Si votre pilote transfère la demande d’E/S de façon asynchrone, vous souhaiterez que votre pilote soit averti lorsqu’un pilote de niveau inférieur termine la demande. Si votre pilote inscrit une fonction de rappel CompletionRoutine , l’infrastructure appelle cette fonction de rappel une fois que la cible d’E/S a terminé la demande. La fonction de rappel CompletionRoutine appelle généralement WdfRequestComplete.

Pour inscrire une fonction de rappel CompletionRoutine , le pilote doit appeler WdfRequestSetCompletionRoutine avant de transférer la demande d’E/S à une cible d’E/S.

Si votre pilote n’a pas besoin d’être averti lorsqu’une cible d’E/S termine une demande d’E/S transférée de manière asynchrone, il n’a pas besoin d’inscrire une fonction de rappel CompletionRoutine . Au lieu de cela, le pilote peut définir l’indicateur WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET lors de l’appel de WdfRequestSend. Dans ce cas, le pilote n’appelle pas WdfRequestComplete.

Un pilote ne termine pas une demande d’E/S qu’il a créée en appelant WdfRequestCreate ou WdfRequestCreateFromIrp. Au lieu de cela, le pilote doit appeler WdfObjectDelete pour supprimer l’objet de requête, généralement une fois qu’une cible d’E/S a terminé la demande.

Par exemple, un pilote peut recevoir une demande de lecture ou d’écriture pour une quantité de données supérieure à ce que les cibles d’E/S du pilote peuvent gérer en même temps. Le pilote doit diviser les données en plusieurs requêtes plus petites et envoyer ces demandes plus petites à une ou plusieurs cibles d’E/S. Les techniques de gestion de cette situation sont les suivantes :

  • Appel de WdfRequestCreate pour créer un seul objet de requête supplémentaire qui représente une requête plus petite.

    Le pilote peut envoyer cette requête de manière synchrone à une cible d’E/S. La fonction de rappel CompletionRoutine de la plus petite requête peut appeler WdfRequestReuse afin que le pilote puisse réutiliser la requête et l’envoyer à nouveau à la cible d’E/S. Une fois que la cible d’E/S a terminé la dernière des demandes plus petites, la fonction de rappel CompletionRoutine peut appeler WdfObjectDelete pour supprimer l’objet de requête créé par le pilote et le pilote peut appeler WdfRequestComplete pour terminer la requête d’origine.

  • Appel de WdfRequestCreate pour créer plusieurs objets de requête supplémentaires qui représentent les demandes plus petites.

    Les cibles d’E/S du pilote peuvent traiter ces multiples demandes plus petites de manière asynchrone. Le pilote peut inscrire une fonction de rappel CompletionRoutine pour chacune des demandes plus petites. Chaque fois que la fonction de rappel CompletionRoutine est appelée, elle peut appeler WdfObjectDelete pour supprimer un objet de requête créé par le pilote. Une fois que la cible d’E/S a terminé toutes les demandes plus petites, le pilote peut appeler WdfRequestComplete pour terminer la requête d’origine.

Fournir des informations d’achèvement

Lorsqu’un pilote termine une demande, il peut éventuellement fournir des informations supplémentaires auxquelles d’autres pilotes peuvent accéder. Par exemple, un pilote peut fournir le nombre d’octets qui ont été transférés pour une demande de lecture ou d’écriture. Pour fournir ces informations, le pilote peut effectuer l’une des opérations suivantes :

Obtention des informations d’achèvement

Pour obtenir des informations sur une demande d’E/S effectuée par un autre pilote, un pilote peut :

Si un pilote envoie une requête d’E/S de manière synchrone, il appelle généralement WdfRequestGetStatus, WdfRequestGetCompletionParams et WdfRequestGetInformation après le retour de l’appel synchrone. Si un pilote envoie une requête d’E/S de façon asynchrone, il appelle généralement ces méthodes à partir d’une fonction de rappel CompletionRoutine .

Pour plus d’informations sur l’exécution des demandes d’E/S, consultez Synchronisation du code d’annulation et d’achèvement.