Usando __sdv_save_request e __sdv_retrieve_request para chamadas de procedimento adiado
As DPCs (chamadas de procedimento adiado) apresentam desafios para o SDV (Verificador de Driver Estático) porque é difícil rastrear o objeto de solicitação de estrutura. Uma dificuldade é que a solicitação deve ser recuperada de um ponteiro global, geralmente do contexto da fila ou de um item de trabalho. Para superar essa dificuldade, o Verificador de Driver Estático fornece duas funções: __sdv_save_request e __sdv_retrieve_request. Essas funções mapeiam a solicitação adiada para uma solicitação que o SDV pode acompanhar.
As funções __sdv_save_request e __sdv_retrieve_request têm a seguinte sintaxe:
__sdv_save_request( request )
__sdv_retrieve_request( request )
Onde a solicitação pode ser um identificador para qualquer objeto de solicitação de estrutura.
Essas funções são usadas apenas pelas ferramentas de análise estática. As funções são ignoradas pelo compilador.
O exemplo de código a seguir mostra como as funções __sdv_save_request e __sdv_retrieve_request são usadas para orientar o SDV, para que o SDV possa mapear a solicitação adiada. O SDV pode usar esse mapeamento para verificar a regra DeferredRequestCompleted . A regra DeferredRequestCompleted requer que __sdv_save_request e __sdv_retrieve_request apareçam em seu código. Há duas regras de propriedade de driver (AliasWithinDispatch, AliasWithinTimerDpc) que procuram a existência das funções __sdv_save_request e __sdv_retrieve_request .
No exemplo de código a seguir, a função EchoEvtIoRead é uma função de retorno de chamada de evento EvtIoRead que salva o identificador no objeto de solicitação de estrutura na área de contexto da fila. A função EchoEvtTimerFunc é uma função de retorno de chamada de evento EvtTimerFunc que a recupera.
VOID
EchoEvtIoRead(
)in WDFQUEUE Queue,
__in WDFREQUEST Request,
__in size_t Length
)
{
/* ..................... */
// Mark the request as cancelable
WdfRequestMarkCancelable(Request, EchoEvtRequestCancel);
// Defer the completion to another thread from the timer DPC and save the handle to the framework request object by using the __sdv_save_request function.
queueContext->CurrentRequest = Request;
__sdv_save_request(Request);
queueContext->CurrentStatus = Status;
return;
}
O exemplo de código a seguir demonstra como a função __sdv_retrieve_request mapeia uma solicitação existente para que o SDV possa rastreá-la para conclusão.
VOID
EchoEvtTimerFunc(
IN WDFTIMER Timer
)
{...................................................
queue = WdfTimerGetParentObject(Timer);
queueContext = QueueGetContext(queue);
//
// The DPC is automatically synchronized to the queue lock,
// so this prevents race conditions from occurring without explicit driver-managed locking. The __sdv_retrieve_request function is used so that SDV can restore the deferred request in the timer DPC. Because we know that this deferred request is valid (because it has been previously saved), the __analysis_assume function is used to suppress false defects that might otherwise result in this code path.
//
__sdv_retrieve_request(queueContext->CurrentRequest);
Request = queueContext->CurrentRequest;
__analysis_assume(Request != NULL);
if( Request != NULL ) {
//
// Try to remove cancel status from the request.
//
// The request is not completed if it is already canceled
// because the EchoEvtIoCancel function has run, or is about to run,
// and we are racing with it.
Status = WdfRequestUnmarkCancelable(Request);
// Because we know that the request is not NULL in this code path and that the request is no longer marked cancelable, we can use the __analysis_assume function to suppress the reporting of a false defect.
__analysis_assume(Status != STATUS_CANCELLED);
if( Status != STATUS_CANCELLED ) {
queueContext->CurrentRequest = NULL;
Status = queueContext->CurrentStatus;
KdPrint(("CustomTimerDPC Completing request 0x%p, Status 0x%x \n", Request,Status));
WdfRequestComplete(Request, Status);
}
else {
KdPrint(("CustomTimerDPC Request 0x%p is STATUS_CANCELLED, not completing\n",
Request));
}
}
return;
}