Função WdfRequestMarkCancelable (wdfrequest.h)
[Aplica-se a KMDF e UMDF]
O método WdfRequestMarkCancelable permite o cancelamento de uma solicitação de E/S especificada.
Sintaxe
void WdfRequestMarkCancelable(
[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
Nenhum
Comentários
Um bug marcar ocorrerá se o driver fornecer um identificador de objeto inválido.
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.
Ao chamar WdfRequestMarkCancelable, o 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.
Escolhendo entre WdfRequestMarkCancelable e WdfRequestMarkCancelableEx
Se o driver usar a sincronização automática da estrutura, o driver poderá chamar WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx.Se o driver não usar a sincronização automática, ele deverá chamar WdfRequestMarkCancelableEx em vez de WdfRequestMarkCancelable pelos seguintes motivos:
- Se a solicitação especificada já tiver sido cancelada, WdfRequestMarkCancelable chamará a função de retorno de chamada EvtRequestCancel do driver antes de retornar. Se o driver adquirir um spinlock antes de chamar WdfRequestMarkCancelable e tentar adquirir o mesmo spinlock dentro de EvtRequestCancel, o mesmo thread tentará adquirir o mesmo spinlock duas vezes, causando um deadlock.
- No entanto, como WdfRequestMarkCancelableEx nunca chama EvtRequestCancel, esse cenário não ocorre. Se a solicitação já tiver sido cancelada, WdfRequestMarkCancelableEx retornará STATUS_CANCELLED. Se o driver adquirir um spinlock (que define o IRQL como DISPATCH_LEVEL) antes de chamar WdfRequestMarkCancelableEx e liberar o spinlock (que define o IRQL como PASSIVE_LEVEL) depois que WdfRequestMarkCancelableEx retornar, a função de retorno de chamada EvtRequestCancel não será chamada antes do spinlock ser lançado. Portanto, um deadlock não ocorre mesmo que a função de retorno de chamada EvtRequestCancel use o mesmo spinlock.
Processando uma solicitação após habilitar o cancelamento
Depois que um driver chama WdfRequestMarkCancelable 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 WdfRequestMarkCancelable 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 WdfRequestMarkCancelable 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 WdfRequestMarkCancelable para habilitar o cancelamento.
Exemplos
O exemplo de código a seguir mostra 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.
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
);
}
Requisitos
Requisito | Valor |
---|---|
Plataforma de Destino | Universal |
Versão mínima do KMDF | 1.0 |
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) |