Sincronizando o código de cancelamento e conclusão
Se o driver chamar WdfRequestMarkCancelable ou WdfRequestMarkCancelableEx para tornar uma solicitação de E/S cancelável, há potencial para um problema de sincronização. Por exemplo, o driver e o dispositivo podem executar operações de E/S do dispositivo de forma assíncrona por meio das funções de retorno de chamada EvtInterruptIsr e EvtInterruptDpc , e as funções de retorno de chamada EvtInterruptDpc e EvtRequestCancel podem conter chamadas para WdfRequestComplete.
O driver deve chamar WdfRequestComplete apenas uma vez para concluir ou cancelar a solicitação. Mas se as funções de retorno de chamada EvtInterruptDpc e EvtRequestCancel não forem sincronizadas entre si, a estrutura poderá chamar uma enquanto a outra estiver em execução.
Evitar esse problema será fácil se o driver usar a sincronização automática da estrutura, pois a sincronização automática garante que as funções de retorno de chamada sejam chamadas uma de cada vez.
Se o driver não usar a sincronização automática da estrutura, ele poderá usar bloqueios de estrutura para sincronizar o código de cancelamento e de conclusão.
Se o driver usa a sincronização automática da estrutura ou fornece sua própria sincronização, a função de retorno de chamada EvtRequestCancel do driver deve chamar WdfRequestComplete para cancelar uma solicitação. A função de retorno de chamada EvtInterruptDpc do driver deve chamar WdfRequestUnmarkCancelable da seguinte maneira:
Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
WdfRequestComplete(Request, RequestStatus);
}
Esse código garante que o driver não chame WdfRequestComplete para concluir a solicitação se o driver já a tiver chamado para cancelar a solicitação.
Para obter mais informações sobre as regras que seu driver deve seguir ao chamar WdfRequestUnmarkCancelable, consulte WdfRequestUnmarkCancelable.