Condividi tramite


Funzione WdfRequestMarkCancelableEx (wdfrequest.h)

[Si applica a KMDF e UMDF]

Il metodo WdfRequestMarkCancelableEx consente l'annullamento di una richiesta di I/O specificata.

Sintassi

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

Parametri

[in] Request

Handle per un oggetto richiesta del framework.

[in] EvtRequestCancel

Puntatore a una funzione di callback EvtRequestCancel definita dal driver, che il framework chiama se annulla la richiesta di I/O.

Valore restituito

WdfRequestMarkCancelableEx restituisce STATUS_SUCCESS se abilita correttamente l'annullamento della richiesta di I/O specificata. In caso contrario, questo metodo potrebbe restituire uno dei valori seguenti:

Codice restituito Descrizione
STATUS_CANCELLED
La richiesta di I/O è stata annullata. Per altre info, vedi La sezione Osservazioni.
STATUS_INVALID_DEVICE_REQUEST
  • Il driver non è proprietario della richiesta di I/O.
  • La richiesta di I/O è già annullabile.
 

Questo metodo potrebbe anche restituire altri valori NTSTATUS.

Se il driver fornisce un handle di oggetto non valido, si verifica un controllo di bug.

Commenti

Dopo che il driver ha ricevuto una richiesta di I/O dal framework, il driver può chiamare WdfRequestMarkCancelable o, a partire da KMDF versione 1.9, WdfRequestMarkCancelableEx per rendere la richiesta annullabile. Per informazioni sulla scelta tra i due metodi, vedi WdfRequestMarkCancelable.

Quando si chiama WdfRequestMarkCancelableEx, il driver deve specificare una funzione di callback EvtRequestCancel . Il framework chiama la funzione di callback se il gestore di I/O o un altro driver tenta di annullare la richiesta di I/O.

Se WdfRequestMarkCancelableEx restituisce un errore, il driver deve eseguire le stesse attività di annullamento eseguite dalla funzione di callback EvtRequestCancel . Ad esempio:

  1. Completare o interrompere l'elaborazione della richiesta, insieme alle sottoquery che potrebbero essere state create.
  2. Chiamare WdfRequestComplete, specificando un valore di stato di STATUS_CANCELLED.
Per l'implementazione, vedere gli esempi di codice seguenti.

Poiché WdfRequestMarkCancelableEx non chiama mai EvtRequestCancel, questo metodo è sicuro dal rischio di deadlock descritto nelle osservazioni di WdfRequestMarkCancelable.

Elaborazione di una richiesta dopo l'abilitazione dell'annullamento

Dopo che un driver chiama WdfRequestMarkCancelableEx per abilitare l'annullamento, la richiesta rimane annullabile mentre il driver è proprietario dell'oggetto richiesta, a meno che il driver non chiami WdfRequestUnmarkCancelable.

Se un driver ha chiamato WdfRequestMarkCancelableEx e se la funzione di callback EvtRequestCancel del driver non è stata eseguita e chiamata WdfRequestComplete, il driver deve chiamare WdfRequestUnmarkCancelable prima di chiamare WdfRequestComplete all'esterno della funzione di callback EvtRequestCancel .

Se il driver chiama WdfRequestForwardToIoQueue per inoltrare la richiesta a una coda diversa, si applicano le regole seguenti:

  • Le richieste di I/O non possono essere annullabili quando il driver le inoltra a una coda diversa.

    In genere, il driver non deve chiamare WdfRequestMarkCancelableEx per abilitare l'annullamento della richiesta prima di chiamare WdfRequestForwardToIoQueue. Se il driver rende annullabile la richiesta, deve chiamare WdfRequestUnmarkCancelable per disabilitare l'annullamento prima di chiamare WdfRequestForwardToIoQueue.

  • Mentre la richiesta si trova nella seconda coda, il framework lo possiede e può annullarlo senza notificare al driver.

    Se il driver richiede una notifica di annullamento (in modo che possa deallocare qualsiasi risorsa allocata prima di chiamare WdfRequestForwardToIoQueue), il driver deve registrare una funzione di callback EvtIoCanceledOnQueue e deve usare la memoria del contesto specifica della richiesta per archiviare informazioni sulle risorse della richiesta.

  • Dopo che il framework ha annullato la richiesta dalla seconda coda e l'ha recapitata al driver, il driver può chiamare WdfRequestMarkCancelableEx per abilitare l'annullamento.
Per altre informazioni su WdfRequestMarkCancelableEx, vedere Annullamento delle richieste di I/O.

Esempio

Gli esempi di codice seguenti illustrano le parti di due funzioni di callback:

  • Funzione di callback EvtIoRead che esegue operazioni specifiche della richiesta ,ad esempio la creazione di sottoquery da inviare a una destinazione di I/O, quindi abilita l'annullamento della richiesta di I/O ricevuta.
  • Funzione di callback EvtRequestCancel che annulla una richiesta di I/O.
Nel primo esempio il driver usa la sincronizzazione automatica del framework. Nel secondo esempio, il driver fornisce la propria sincronizzazione usando spinlock.

Esempio 1: driver che usa la sincronizzazione automatica.

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
                       );
}

Esempio 2: driver che usa la propria sincronizzazione.

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);
}

Requisiti

Requisito Valore
Piattaforma di destinazione Universale
Versione KMDF minima 1,9
Versione UMDF minima 2,0
Intestazione wdfrequest.h (include Wdf.h)
Libreria Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
Regole di 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)

Vedi anche

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable