Função WdfRequestMarkCancelableEx (wdfrequest.h)

[Aplica-se a KMDF e UMDF]

O método WdfRequestMarkCancelableEx permite o cancelamento de uma solicitação de E/S especificada.

Sintaxe

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

Parâmetros

[in] Request

Um identificador para um objeto de solicitação de estrutura.

[in] EvtRequestCancel

Um ponteiro para uma função de retorno de chamada EvtRequestCancel definida pelo driver, que a estrutura chama se cancela a solicitação de E/S.

Retornar valor

WdfRequestMarkCancelableEx retornará STATUS_SUCCESS se habilitar com êxito o cancelamento da solicitação de E/S especificada. Caso contrário, esse método pode retornar um dos seguintes valores:

Código de retorno Descrição
STATUS_CANCELLED
A solicitação de E/S foi cancelada. Consulte Comentários para obter mais informações.
STATUS_INVALID_DEVICE_REQUEST
  • O driver não possui a solicitação de E/S.
  • A solicitação de E/S já pode ser cancelada.
 

Esse método também pode retornar outros valores NTSTATUS.

Um bug marcar ocorrerá se o driver fornecer um identificador de objeto inválido.

Comentários

Depois que o driver receber uma solicitação de E/S da estrutura, o driver poderá chamar WdfRequestMarkCancelable ou, começando com KMDF versão 1.9, WdfRequestMarkCancelableEx para tornar a solicitação cancelável. Para obter informações sobre como escolher entre os dois métodos, consulte WdfRequestMarkCancelable.

Ao chamar WdfRequestMarkCancelableEx, seu driver deve especificar uma função de retorno de chamada EvtRequestCancel . A estrutura chamará a função de retorno de chamada se o gerenciador de E/S ou outro driver estiver tentando cancelar a solicitação de E/S.

Se WdfRequestMarkCancelableEx retornar falha, o driver deverá executar as mesmas atividades de cancelamento executadas pela função de retorno de chamada EvtRequestCancel . Por exemplo:

  1. Conclua ou pare de processar a solicitação, juntamente com as sub-solicitações que ela pode ter criado.
  2. Chame WdfRequestComplete, especificando um valor status de STATUS_CANCELLED.
Consulte os exemplos de código abaixo para implementação.

Como WdfRequestMarkCancelableEx nunca chama EvtRequestCancel, esse método está seguro contra o risco de deadlock descrito nos Comentários de WdfRequestMarkCancelable.

Processando uma solicitação após habilitar o cancelamento

Depois que um driver chama WdfRequestMarkCancelableEx para habilitar o cancelamento, a solicitação permanece cancelável enquanto o driver possui o objeto de solicitação, a menos que o driver chame WdfRequestUnmarkCancelable.

Se um driver tiver chamado WdfRequestMarkCancelableEx e se a função de retorno de chamada EvtRequestCancel do driver não tiver sido executada e chamada WdfRequestComplete, o driver deverá chamar WdfRequestUnmarkCancelable antes de chamar WdfRequestComplete fora da função de retorno de chamada EvtRequestCancel .

Se o driver chamar WdfRequestForwardToIoQueue para encaminhar a solicitação para uma fila diferente, as seguintes regras se aplicarão:

  • As solicitações de E/S não podem ser canceladas quando o driver as encaminha para uma fila diferente.

    Em geral, o driver não deve chamar WdfRequestMarkCancelableEx para habilitar o cancelamento da solicitação antes de chamar WdfRequestForwardToIoQueue. Se o driver tornar a solicitação cancelável, ele deverá chamar WdfRequestUnmarkCancelable para desabilitar o cancelamento antes de chamar WdfRequestForwardToIoQueue.

  • Embora a solicitação esteja na segunda fila, a estrutura a possui e pode cancelá-la sem notificar o driver.

    Se o driver exigir notificação de cancelamento (para que ele possa desalocar todos os recursos que ele possa ter alocado antes de chamar WdfRequestForwardToIoQueue), o driver deverá registrar uma função de retorno de chamada EvtIoCanceledOnQueue e deve usar a memória de contexto específica da solicitação para armazenar informações sobre os recursos da solicitação.

  • Depois que a estrutura tiver desativado a solicitação da segunda fila e entregue-a ao driver, o driver poderá chamar WdfRequestMarkCancelableEx para habilitar o cancelamento.
Para obter mais informações sobre WdfRequestMarkCancelableEx, consulte Cancelando solicitações de E/S.

Exemplos

Os exemplos de código a seguir mostram partes de duas funções de retorno de chamada:

  • Uma função de retorno de chamada EvtIoRead que executa um trabalho específico da solicitação (como a criação de sub-solicitações para enviar para um destino de E/S) e, em seguida, permite o cancelamento da solicitação de E/S recebida.
  • Uma função de retorno de chamada EvtRequestCancel que cancela uma solicitação de E/S.
No primeiro exemplo, o driver está usando a sincronização automática da estrutura. No segundo exemplo, o driver está fornecendo sua própria sincronização usando spinlocks.

Exemplo 1: um driver que usa a sincronização automática.

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

Exemplo 2: um driver que usa sua própria sincronização.

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

Requisitos

Requisito Valor
Plataforma de Destino Universal
Versão mínima do KMDF 1,9
Versão mínima do UMDF 2,0
Cabeçalho wdfrequest.h (inclua Wdf.h)
Biblioteca Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
Regras de conformidade da 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)

Confira também

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable