Partager via


WdfRequestMarkCancelableEx, fonction (wdfrequest.h)

[S’applique à KMDF et UMDF]

La méthode WdfRequestMarkCancelableEx permet l’annulation d’une demande d’E/S spécifiée.

Syntaxe

NTSTATUS WdfRequestMarkCancelableEx(
  [in] WDFREQUEST             Request,
  [in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);

Paramètres

[in] Request

Handle d’un objet de requête d’infrastructure.

[in] EvtRequestCancel

Pointeur vers une fonction de rappel EvtRequestCancel définie par le pilote, que l’infrastructure appelle s’il annule la demande d’E/S.

Valeur retournée

WdfRequestMarkCancelableEx retourne STATUS_SUCCESS s’il permet l’annulation de la demande d’E/S spécifiée. Sinon, cette méthode peut retourner l’une des valeurs suivantes :

Code de retour Description
STATUS_CANCELLED
La demande d’E/S a été annulée. Pour plus d’informations, consultez Remarques.
STATUS_INVALID_DEVICE_REQUEST
  • Le pilote n’est pas propriétaire de la demande d’E/S.
  • La demande d’E/S est déjà annulable.
 

Cette méthode peut également retourner d’autres valeurs NTSTATUS.

Un bogue case activée se produit si le pilote fournit un handle d’objet non valide.

Remarques

Une fois que votre pilote a reçu une demande d’E/ S de l’infrastructure, il peut appeler WdfRequestMarkCancelable ou, à compter de KMDF version 1.9, WdfRequestMarkCancelableEx pour rendre la demande annulable. Pour plus d’informations sur le choix entre les deux méthodes, consultez WdfRequestMarkCancelable.

Lors de l’appel de WdfRequestMarkCancelableEx, votre pilote doit spécifier une fonction de rappel EvtRequestCancel . L’infrastructure appelle la fonction de rappel si le gestionnaire d’E/S ou un autre pilote tente d’annuler la demande d’E/S.

Si WdfRequestMarkCancelableEx retourne un échec, le pilote doit effectuer les mêmes activités d’annulation que la fonction de rappel EvtRequestCancel . Par exemple :

  1. Terminez ou arrêtez le traitement de la demande, ainsi que les sous-requêtes qu’elle a pu créer.
  2. Appelez WdfRequestComplete en spécifiant une valeur status de STATUS_CANCELLED.
Consultez les exemples de code ci-dessous pour l’implémentation.

Étant donné que WdfRequestMarkCancelableEx n’appelle jamais EvtRequestCancel, cette méthode est à l’abri du risque d’interblocage décrit dans les remarques de WdfRequestMarkCancelable.

Traitement d’une demande après l’activation de l’annulation

Une fois qu’un pilote appelle WdfRequestMarkCancelableEx pour activer l’annulation, la demande reste annulable tant que le pilote est propriétaire de l’objet de requête, sauf si le pilote appelle WdfRequestUnmarkCancelable.

Si un pilote a appelé WdfRequestMarkCancelableEx et si la fonction de rappel EvtRequestCancel du pilote n’a pas été exécutée et a appelé WdfRequestComplete, le pilote doit appeler WdfRequestUnmarkCancelable avant d’appeler WdfRequestComplete en dehors de la fonction de rappel EvtRequestCancel .

Si le pilote appelle WdfRequestForwardToIoQueue pour transférer la demande vers une autre file d’attente, les règles suivantes s’appliquent :

  • Les demandes d’E/S ne peuvent pas être annulées lorsque votre pilote les transfère vers une autre file d’attente.

    En règle générale, votre pilote ne doit pas appeler WdfRequestMarkCancelableEx pour activer l’annulation de la demande avant d’appeler WdfRequestForwardToIoQueue. Si le pilote rend la demande annulable, il doit appeler WdfRequestUnmarkCancelable pour désactiver l’annulation avant d’appeler WdfRequestForwardToIoQueue.

  • Lorsque la requête se trouve dans la deuxième file d’attente, l’infrastructure la possède et peut l’annuler sans en avertir le pilote.

    Si le pilote a besoin d’une notification d’annulation (afin qu’il puisse libérer toutes les ressources qu’il aurait allouées avant d’appeler WdfRequestForwardToIoQueue), le pilote doit inscrire une fonction de rappel EvtIoCanceledOnQueue , et il doit utiliser la mémoire contextuelle spécifique à la demande pour stocker des informations sur les ressources de la requête.

  • Une fois que l’infrastructure a retiré la requête de la deuxième file d’attente et l’a remise au pilote, le pilote peut appeler WdfRequestMarkCancelableEx pour activer l’annulation.
Pour plus d’informations sur WdfRequestMarkCancelableEx, consultez Annulation des demandes d’E/S.

Exemples

Les exemples de code suivants montrent des parties de deux fonctions de rappel :

  • Une fonction de rappel EvtIoRead qui effectue un travail spécifique à la demande (par exemple, la création de sous-requêtes à envoyer à une cible d’E/S), permet ensuite l’annulation de la demande d’E/S reçue.
  • Fonction de rappel EvtRequestCancel qui annule une demande d’E/S.
Dans le premier exemple, le pilote utilise la synchronisation automatique de l’infrastructure. Dans le deuxième exemple, le pilote fournit sa propre synchronisation à l’aide de spinlocks.

Exemple 1 : pilote qui utilise la synchronisation automatique.

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
       // Remove request-specific work here, because
       // we don't want the work to be done if the
       // request was canceled or an error occurred.

        WdfRequestComplete (Request, status);
    }
...
}

VOID
MyEvtRequestCancel(
    IN WDFREQUEST  Request
 )
{
    // Remove request-specific work here, because
    // we don't want the work to be done if the
    // request was canceled.

    WdfRequestComplete(
                       Request,
                       STATUS_CANCELLED
                       );
}

Exemple 2 : pilote qui utilise sa propre synchronisation.

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
        // Remove request-specific work here, because
        // we don't want the work to be done if the
        // request was canceled or an error occurred.
     }
    WdfSpinlockRelease(MyCancelSpinLock);
    if (!NT_SUCCESS(status)) {
        WdfRequestComplete (
                            Request,
                            Status
                            );
    }
...
}
VOID
MyEvtRequestCancel(
    IN WDFREQUEST  Request
 )
{
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Remove request-specific work here, because
    // we don't want the work to be done if the
    // request was canceled.
    WdfSpinlockRelease(MyCancelSpinLock);
    WdfRequestComplete (Request, STATUS_CANCELLED);
}

Configuration requise

Condition requise Valeur
Plateforme cible Universal
Version KMDF minimale 1,9
Version UMDF minimale 2.0
En-tête wdfrequest.h (include Wdf.h)
Bibliothèque Wdf01000.sys (KMDF) ; WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
Règles de conformité DDI DeferredRequestCompleted(kmdf),DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf),KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MarkCancOnCancReqLocal(kmdf),ReqIsCancOnCancReq(kmdf), ReqMarkCancelableSend(kmdf), ReqNotCanceledLocal(kmdf), RequestCompleted(kmdf), RequestCompletedLocal( kmdf)

Voir aussi

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable