Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wywołania procedury odroczonej (DPC) stanowią wyzwanie dla Statycznego Weryfikatora Sterowników (SDV), ponieważ trudno jest śledzić obiekt żądania platformy. Jedną z trudności jest to, że żądanie musi zostać pobrane z wskaźnika globalnego, zwykle z kontekstu kolejki lub z elementu roboczego. Aby rozwiązać ten problem, weryfikator sterowników statycznych udostępnia dwie funkcje: __sdv_save_request i __sdv_retrieve_request. Te funkcje mapują odroczone żądanie na żądanie, które SDV może śledzić.
Funkcje __sdv_save_request i __sdv_retrieve_request mają następującą składnię:
__sdv_save_request( request )
__sdv_retrieve_request( request )
Gdzie żądanie może być dojściem do dowolnego obiektu żądania platformy.
Te funkcje są używane tylko przez narzędzia do analizy statycznej. Funkcje są ignorowane przez kompilator.
Poniższy przykład kodu pokazuje, w jaki sposób funkcje __sdv_save_request i __sdv_retrieve_request są używane do obsługi sdV, dzięki czemu sdV może mapować odroczone żądanie. SDV może użyć tego mapowania, aby zweryfikować regułę DeferredRequestCompleted. Reguła DeferredRequestCompleted wymaga, aby __sdv_save_request i __sdv_retrieve_request pojawiały się w kodzie. Istnieją dwie reguły właściwości sterownika (AliasWithinDispatch, AliasWithinTimerDpc), które szukają istnienia funkcji __sdv_save_request i __sdv_retrieve_request .
W poniższym przykładzie kodu funkcja EchoEvtIoRead jest funkcją wywołania zdarzenia EvtIoRead, która zapisuje uchwyt do obiektu żądania frameworku w obszarze kontekstu kolejki. Funkcja EchoEvtTimerFunc jest funkcją wywołania zwrotnego EvtTimerFunc, która pobiera tę wartość.
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;
}
W poniższym przykładzie kodu pokazano, jak funkcja __sdv_retrieve_request mapuje istniejące żądanie, dzięki czemu sdV może śledzić je do ukończenia.
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;
}