WdfRequestMarkCancelable-Funktion (wdfrequest.h)

[Gilt für KMDF und UMDF]

Die WdfRequestMarkCancelable-Methode ermöglicht das Abbrechen einer angegebenen E/A-Anforderung.

Syntax

void WdfRequestMarkCancelable(
  [in] WDFREQUEST             Request,
  [in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);

Parameter

[in] Request

Ein Handle für ein Frameworkanforderungsobjekt.

[in] EvtRequestCancel

Ein Zeiger auf eine vom Treiber definierte EvtRequestCancel-Rückruffunktion , die das Framework aufruft, wenn es die E/A-Anforderung abbricht.

Rückgabewert

Keine

Bemerkungen

Eine Fehlerüberprüfung tritt auf, wenn der Treiber ein ungültiges Objekthandle bereitstellt.

Nachdem Ihr Treiber eine E/A-Anforderung vom Framework erhalten hat, kann der Treiber WdfRequestMarkCancelable oder ab KMDF-Version 1.9 WdfRequestMarkCancelableEx aufrufen, um die Anforderung abzubrechen.

Beim Aufrufen von WdfRequestMarkCancelable muss Ihr Treiber eine EvtRequestCancel-Rückruffunktion angeben. Das Framework ruft die Rückruffunktion auf, wenn der E/A-Manager oder ein anderer Treiber versucht, die E/A-Anforderung abzubrechen.

Auswahl zwischen WdfRequestMarkCancelable und WdfRequestMarkCancelableEx

Wenn Ihr Treiber die automatische Synchronisierung des Frameworks verwendet, kann der Treiber entweder WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx aufrufen.

Wenn der Treiber keine automatische Synchronisierung verwendet, muss er aus den folgenden Gründen WdfRequestMarkCancelableEx anstelle von WdfRequestMarkCancelable aufrufen:

  • Wenn die angegebene Anforderung bereits abgebrochen wurde, ruft WdfRequestMarkCancelable vor der Rückgabe die Rückruffunktion EvtRequestCancel des Treibers auf. Wenn der Treiber vor dem Aufrufen von WdfRequestMarkCancelable einen Spinlock erwirbt und versucht, denselben Spinlock in EvtRequestCancel zu erhalten, versucht derselbe Thread zweimal, denselben Spinlock zu erhalten, was zu einem Deadlock führt.
  • Da WdfRequestMarkCancelableEx jedoch nie EvtRequestCancel aufruft, tritt dieses Szenario nicht auf. Wenn die Anforderung bereits abgebrochen wurde, gibt WdfRequestMarkCancelableExSTATUS_CANCELLED zurück. Wenn Ihr Treiber vor dem Aufruf von WdfRequestMarkCancelableEx einen Spinlock erhält (wodurch der IRQL auf DISPATCH_LEVEL festgelegt wird), PASSIVE_LEVEL wird die Rückruffunktion EvtRequestCancelableEx nach der Rückgabe von WdfRequestMarkCancelableEx nicht aufgerufen, bevor der Spinlock freigegeben wird. Daher tritt kein Deadlock auf, auch wenn die Rückruffunktion EvtRequestCancel denselben Spinlock verwendet.

Verarbeiten einer Anforderung nach dem Aktivieren des Abbruchs

Nachdem ein Treiber WdfRequestMarkCancelable aufgerufen hat, um das Abbrechen zu aktivieren, bleibt die Anforderung abbruchfähig, solange der Treiber das Anforderungsobjekt besitzt , es sei denn, der Treiber ruft WdfRequestUnmarkCancelable auf.

Wenn ein Treiber WdfRequestMarkCancelable aufgerufen hat und die EvtRequestCancel-Rückruffunktion des Treibers nicht ausgeführt und WdfRequestComplete aufgerufen wurde, muss der Treiber WdfRequestUnmarkCancelable aufrufen, bevor er WdfRequestComplete außerhalb der EvtRequestCancel-Rückruffunktion aufruft .

Wenn der Treiber WdfRequestForwardToIoQueue aufruft, um die Anforderung an eine andere Warteschlange weiterzuleiten, gelten die folgenden Regeln:

  • E/A-Anforderungen können nicht abgebrochen werden, wenn Ihr Treiber sie an eine andere Warteschlange weiterleitet.

    Im Allgemeinen sollte Ihr Treiber WdfRequestMarkCancelable nicht aufrufen, um das Abbrechen der Anforderung vor dem Aufrufen von WdfRequestForwardToIoQueue zu aktivieren. Wenn der Treiber die Anforderung abbruchfähig macht, muss er WdfRequestUnmarkCancelable aufrufen, um den Abbruch zu deaktivieren, bevor WdfRequestForwardToIoQueue aufgerufen wird.

  • Während sich die Anforderung in der zweiten Warteschlange befindet, besitzt das Framework sie und kann sie abbrechen, ohne den Treiber zu benachrichtigen.

    Wenn der Treiber eine Abbruchbenachrichtigung erfordert (damit er alle Ressourcen, die er möglicherweise vor dem Aufruf von WdfRequestForwardToIoQueue zugeordnet hat), zugeordnet werden kann, sollte der Treiber eine EvtIoCanceledOnQueue-Rückruffunktion registrieren und den anforderungsspezifischen Kontextspeicher verwenden, um Informationen zu den Ressourcen der Anforderung zu speichern.

  • Nachdem das Framework die Anforderung aus der zweiten Warteschlange entfernt und an den Treiber übermittelt hat, kann der Treiber WdfRequestMarkCancelable aufrufen, um das Abbrechen zu aktivieren.
Weitere Informationen zu WdfRequestMarkCancelable finden Sie unter Abbrechen von E/A-Anforderungen.

Beispiele

Das folgende Codebeispiel zeigt Teile von zwei Rückruffunktionen:

  • Eine EvtIoRead-Rückruffunktion , die anforderungsspezifische Aufgaben ausführt (z. B. das Erstellen von Unteranforderungen, die an ein E/A-Ziel gesendet werden sollen), ermöglicht dann den Abbruch der empfangenen E/A-Anforderung.
  • Eine EvtRequestCancel-Rückruffunktion , die eine E/A-Anforderung abbricht.
Der Treiber muss die automatische Synchronisierung des Frameworks verwenden.
VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    WdfRequestMarkCancelable(
                             Request,
                             MyEvtRequestCancel
                             );
    }
...
}
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
                       );
}

Anforderungen

Anforderung Wert
Zielplattform Universell
KMDF-Mindestversion 1.0
UMDF-Mindestversion 2.0
Kopfzeile wdfrequest.h (einschließen von Wdf.h)
Bibliothek Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
DDI-Complianceregeln DeferredRequestCompleted(kmdf), DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MarkCancOnCancReqLocal(kmdf), ReqIsCancOnCancReq(kmdf), ReqMarkCancelableSend(kmdf), ReqNotCanceledLocal(kmdf), RequestCompletedCompleted(kmdf), RequestCompletedLocal( kmdf)

Weitere Informationen

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelableEx

WdfRequestUnmarkCancelable