WdfRequestUnmarkCancelable, fonction (wdfrequest.h)
[S’applique à KMDF et UMDF]
La méthode WdfRequestUnmarkCancelable désactive l’annulation d’une demande d’E/S spécifiée.
Syntaxe
NTSTATUS WdfRequestUnmarkCancelable(
[in] WDFREQUEST Request
);
Paramètres
[in] Request
Handle pour un objet de requête d’infrastructure.
Valeur retournée
WdfRequestUnmarkCancelable retourne STATUS_SUCCESS si l’opération réussit. Sinon, cette méthode peut retourner l’une des valeurs suivantes :
Code de retour | Description |
---|---|
|
Un paramètre d’entrée n’est pas valide ou la demande n’est pas déjà annulable. |
|
Le pilote n’est pas propriétaire de la demande. |
|
La demande a été annulée. |
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
Un pilote peut appeler WdfRequestUnmarkCancelable pour désactiver l’annulation d’une demande d’E/S, si le pilote a précédemment appelé WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx pour activer l’annulation de la demande.
Si WdfRequestUnmarkCancelable retourne une valeur autre que STATUS_CANCELLED, la fonction de rappel EvtRequestCancel du pilote n’est pas appelée pour la demande.
Si le pilote a précédemment appelé WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx, la fonction de rappel EvtRequestCancel du pilote peut appeler WdfRequestComplete avec un paramètre Status de STATUS_CANCELLED. La fonction de rappel EvtRequestCancel n’a pas besoin d’appeler WdfRequestUnmarkCancelable. Si le pilote appelle WdfRequestComplete en dehors de sa fonction de rappel EvtRequestCancel , le pilote doit d’abord appeler WdfRequestUnmarkCancelable.
Toutefois, le pilote ne doit pas appeler WdfRequestUnmarkCancelable après qu’EvtRequestCancel a appelé WdfRequestComplete. Dans la section Exemple suivant, l’exemple stocke une copie locale du handle de requête, puis l’efface lorsque la fonction de rappel EvtRequestCancel appelle WdfRequestComplete. Le pilote n’appelle pas WdfRequestUnmarkCancelable si la copie locale du handle de demande a été effacée. Cet exemple utilise la synchronisation automatique de l’infrastructure pour synchroniser les fonctions de rappel.
Notez que l’appel de WdfObjectReference pour ajouter une référence supplémentaire à l’objet de requête ne permet pas à votre pilote d’appeler WdfRequestUnmarkCancel après que la fonction de rappel EvtRequestCancel du pilote appelle WdfRequestComplete.
Si WdfRequestUnmarkCancelable retourne STATUS_CANCELLED, puis Qu’EvtRequestCancel termine la requête, le pilote ne doit pas utiliser l’objet request par la suite.
Si WdfRequestUnmarkCancelable retourne STATUS_CANCELLED, le pilote ne doit pas terminer la demande avant que le framework appelle EvtRequestCancel. Sinon, l’infrastructure peut appeler evtRequestCancel du pilote avec une requête non valide. Pour obtenir des exemples de code connexes, consultez IWDFIoRequest ::UnmarkCancelable.
Pour plus d’informations sur WdfRequestUnmarkCancelable, consultez Annulation des demandes d’E/S.
Exemples
L’exemple de code suivant fournit des versions simplifiées des fonctions de rappel EvtIoRead, EvtRequestCancel et EvtTimerFunc que contient l’exemple de pilote ECHO . Cet exemple montre comment appeler WdfRequestMarkCancelable, WdfRequestUnmarkCancelable et WdfRequestComplete dans un pilote qui utilise la synchronisation automatique de l’infrastructure. (L’exemple ECHO utilise la synchronisation au niveau de l’appareil.)
Si votre pilote n’utilise pas la synchronisation automatique de l’infrastructure, consultez les deux exemples sur IWDFIoRequest ::UnmarkCancelable. Lorsqu’ils sont écrits pour un pilote UMDF, ces exemples illustrent les techniques que vous pouvez utiliser pour gérer la synchronisation entre le rappel d’annulation et un autre thread qui appelle la routine Unmark .
VOID
EchoEvtIoRead(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
PQUEUE_CONTEXT queueContext = QueueGetContext(Queue);
// Prepare for read operation here.
// (See the Echo sample driver for details.)
...
// Enable cancellation.
WdfRequestMarkCancelable(
Request,
EchoEvtRequestCancel
);
// Save the request handle. We'll clear it after
// we call WdfRequestComplete.
queueContext->CurrentRequest = Request;
return
}
VOID
EchoEvtRequestCancel(
IN WDFREQUEST Request
)
{
PQUEUE_CONTEXT queueContext =
QueueGetContext(WdfRequestGetIoQueue(Request));
WdfRequestComplete(
Request,
STATUS_CANCELLED,
);
// Clear the request handle so EchEvtTimerFunc will
// know that we called WdfRequestComplete.
queueContext->CurrentRequest = NULL;
return;
}
VOID
EchoEvtTimerFunc(
IN WDFTIMER Timer
)
{
NTSTATUS Status;
WDFREQUEST Request;
WDFQUEUE queue;
PQUEUE_CONTEXT queueContext;
// Retrieve our saved copy of the request handle.
queue = WdfTimerGetParentObject(Timer);
queueContext = QueueGetContext(queue);
Request = queueContext->CurrentRequest;
// We cannot call WdfRequestUnmarkCancelable
// after a request completes, so check here to see
// if EchoEvtRequestCancel cleared our saved
// request handle.
if( Request != NULL ) {
Status = WdfRequestUnmarkCancelable(Request);
if(Status != STATUS_CANCELLED) {
queueContext->CurrentRequest = NULL;
Status = queueContext->CurrentStatus;
WdfRequestComplete(
Request,
Status
);
}
}
return;
}
Configuration requise
Condition requise | Valeur |
---|---|
Plateforme cible | Universal |
Version KMDF minimale | 1.0 |
Version UMDF minimale | 2.0 |
En-tête | wdfrequest.h (inclure Wdf.h) |
Bibliothèque | Wdf01000.sys (KMDF) ; WUDFx02000.dll (UMDF) |
IRQL | <=DISPATCH_LEVEL |
Règles de conformité DDI | CompleteCanceledReq(kmdf), DeferredRequestCompleted(kmdf), DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MarkCancOnCancReqLocal(kmdf), ReqIsCancOnCancReq(kmdf), ReqMarkCancelableSend(kmdf), ReqNotCanceledLocal(kmdf) |