Exécution des demandes d’E/S dans UMDF
Avertissement
UMDF 2 est la dernière version d’UMDF et remplace UMDF 1. Tous les nouveaux pilotes UMDF doivent être écrits à l’aide d’UMDF 2. Aucune nouvelle fonctionnalité n’est ajoutée à UMDF 1 et la prise en charge d’UMDF 1 est limitée sur les versions plus récentes de Windows 10. Les pilotes Windows universels doivent utiliser UMDF 2.
Les exemples UMDF 1 archivés sont disponibles dans la mise à jour des exemples de pilotes Windows 11, version 22H2 - Mai 2022.
Pour plus d’informations, consultez Prise en main avec UMDF.
Chaque demande d’E/S doit être effectuée par un pilote UMDF. Pour terminer une requête, le pilote doit appeler la méthode IWDFIoRequest::Complete ou IWDFIoRequest::CompleteWithInformation . Lorsque le pilote termine la demande, il indique l’un des scénarios suivants :
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’est pas valide au moment de sa réception et ne peut donc pas communiquer avec l’appareil.
L’opération d’E/S demandée a été annulée.
Le pilote appelle la méthode IWDFIoRequest::CompleteWithInformation pour transmettre des informations supplémentaires sur l’opération de requête. Par exemple, pour une opération de lecture, le pilote doit fournir le nombre d’octets lus.
Pour terminer une demande d’E/S, le pilote doit passer la status d’achèvement appropriée au paramètre CompletionStatus dans l’appel à IWDFIoRequest::Complete ou IWDFIoRequest::CompleteWithInformation. Le pilote utilise un code HRESULT pour communiquer les status de la demande terminée.
Le processus hôte du pilote UMDF convertit le code HRESULT en code NTSTATUS avant de transmettre la requête terminée au réflecteur (Wudfrd.sys). Le réflecteur transmet le code NTSTATUS au système d’exploitation. Le système d’exploitation convertit le code NTSTATUS en code d’erreur Microsoft Win32 avant de présenter le résultat à l’application appelante.
Pour vous assurer que les codes d’erreur de votre pilote peuvent être convertis correctement, vous devez créer des codes d’erreur à l’aide de l’une des techniques suivantes :
Utilisez un code d’erreur de Winerror.h et appliquez la macro HRESULT_FROM_WIN32.
Utilisez un code d’erreur de Ntstatus.h et appliquez la macro HRESULT_FROM_NT.
Pour plus d’informations sur ces macros, consultez la documentation Microsoft Windows SDK.
L’exemple de code suivant montre comment effectuer une demande avec un code d’erreur approprié :
VOID
STDMETHODCALLTYPE
CMyQueue::OnWrite(
__in IWDFIoQueue *pWdfQueue,
__in IWDFIoRequest *pWdfRequest,
__in SIZE_T BytesToWrite
)
{
--------------------
if( BytesToWrite > MAX_WRITE_LENGTH ) {
pWdfRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_MORE_DATA), 0);
return;
}
---------------------
}
Lorsqu’un pilote termine correctement une requête, il retourne S_OK, qui est une valeur HRESULT. Étant donné que S_OK équivaut à NO_ERROR dans Winerror.h et STATUS_SUCCESS dans Ntstatus.h, les macros de conversion ne sont pas nécessaires.
Si le vérificateur de pilote est activé pour le réflecteur, il identifie un code de status non valide et provoque une vérification d’erreur système.
Note Le vérificateur de pilote pour Windows XP provoque de manière incorrecte une vérification d’erreur système pour les codes d’erreur Win32 dont les valeurs dépassent 1024 décimales (1024L). Si votre pilote s’exécute sur Windows XP, tenez compte de ce problème si vous activez le vérificateur de pilotes pour le réflecteur.
Si le pilote a précédemment envoyé une requête à un pilote de niveau inférieur, il doit être notifié lorsque le pilote de niveau inférieur termine la demande. Pour s’inscrire à la notification, le pilote appelle la méthode IWDFIoRequest::SetCompletionCallback pour inscrire l’interface de la méthode que l’infrastructure appelle lorsque le pilote de niveau inférieur termine la demande. Le pilote implémente la fonction de rappel IRequestCallbackRequestCompletion::OnCompletion pour effectuer les opérations requises pour terminer la requête.
Un pilote ne termine pas une demande d’E/S qu’il a créée en appelant IWDFDevice::CreateRequest. Au lieu de cela, le pilote doit appeler IWDFObject::D eleteWdfObject 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 IWDFDevice::CreateRequest 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 IRequestCallbackRequestCompletion::OnCompletion de la requête plus petite peut appeler IWDFIoRequest2::Reuse 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 OnCompletion peut appeler IWDFObject::D eleteWdfObject pour supprimer l’objet de requête créé par le pilote et le pilote peut appeler IWDFIoRequest::Complete pour terminer la requête d’origine.
Appel de IWDFDevice::CreateRequest 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 OnCompletion pour chacune des demandes plus petites. Chaque fois que la fonction de rappel OnCompletion est appelée, elle peut appeler IWDFObject::D eleteWdfObject 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 IWDFIoRequest::Complete pour terminer la requête d’origine.
Obtention des informations d’achèvement
Pour obtenir des informations sur une demande d’E/S effectuée par un autre pilote, un pilote UMDF peut :
Utilisez l’interface IWDFRequestCompletionParams pour obtenir l’achèvement d’une demande d’E/S status et d’autres informations.
Utilisez l’interface IWDFIoRequestCompletionParams pour obtenir les mémoires tampons de la demande d’E/S.
Utilisez l’interface IWDFUsbRequestCompletionParams pour obtenir des mémoires tampons et d’autres informations relatives à une requête envoyée à un objet de canal cible USB.
En outre, un pilote basé sur UMDF peut utiliser la méthode IWDFIoRequest2::GetStatus pour obtenir la status actuelle d’une requête d’E/S, avant ou après l’achèvement de la demande.