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 |
---|---|
|
A solicitação de E/S foi cancelada. Consulte Comentários para obter mais informações. |
|
|
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:
- Conclua ou pare de processar a solicitação, juntamente com as sub-solicitações que ela pode ter criado.
- Chame WdfRequestComplete, especificando um valor status de STATUS_CANCELLED.
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.
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.
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) |