Синхронизация кода отмены и завершения

Если драйвер вызывает WdfRequestMarkCancelable или WdfRequestMarkCancelableEx , чтобы отменить запрос ввода-вывода, может возникнуть проблема синхронизации. Например, драйвер и устройство могут выполнять операции ввода-вывода устройства асинхронно с помощью функций обратного вызова EvtInterruptIsr и EvtInterruptDpc , а функции обратного вызова EvtInterruptDpc и EvtRequestCancel могут содержать вызовы WdfRequestComplete.

Драйвер должен вызывать WdfRequestComplete только один раз, чтобы завершить или отменить запрос. Но если функции обратного вызова EvtInterruptDpc и EvtRequestCancel не синхронизированы друг с другом, платформа может вызывать одну из них во время выполнения другой.

Избежать этой проблемы легко, если драйвер использует автоматическую синхронизацию платформы, так как автоматическая синхронизация гарантирует, что функции обратного вызова будут вызываться по одному за раз.

Если драйвер не использует автоматическую синхронизацию платформы, он может использовать блокировки платформы для синхронизации кода отмены и завершения.

Независимо от того, использует ли драйвер автоматическую синхронизацию платформы или обеспечивает собственную синхронизацию, функция обратного вызова EvtRequestCancel драйвера должна вызвать WdfRequestComplete , чтобы отменить запрос. Функция обратного вызова EvtInterruptDpc драйвера должна вызывать WdfRequestUnmarkCancelable следующим образом:

Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
    WdfRequestComplete(Request, RequestStatus);
    }

Этот код гарантирует, что драйвер не вызывает WdfRequestComplete для выполнения запроса, если драйвер уже вызвал его для отмены запроса.

Дополнительные сведения о правилах, которым должен следовать драйвер при вызове WdfRequestUnmarkCancelable, см. в разделе WdfRequestUnmarkCancelable.