Just a quick update to close-off this thread; I was successful in replacing the use of collections with a queue.
- No real change in logic, other than removing the EvtCancel function; Although I could have kept it, but I had no need to clean-up before completing the request.
- I eliminated all the “(Un)MarkCancelable” calls:
- cancellable requests cannot be forwarded to a queue.
- While the request is in the queue, the framework handles cancellation.
- In my case, once the driver starts to process the request, i.e. request removed from queue, it cannot be canceled.
Thanks again Tim, Doron and Peter.
Queue creation
WDF_IO_QUEUE_CONFIG queueConfig;
WDF_IO_QUEUE_CONFIG_INIT( &queueConfig, WdfIoQueueDispatchManual );
queueConfig.PowerManaged = WdfFalse;
queueConfig.AllowZeroLengthRequests = FALSE;
queueConfig.DefaultQueue = FALSE;
WDF_OBJECT_ATTRIBUTES queueAttributes;
WDF_OBJECT_ATTRIBUTES_INIT( &queueAttributes );
queueAttributes.SynchronizationScope = WdfSynchronizationScopeQueue;
NTSTATUS status{ WdfIoQueueCreate( wdfDevice, &queueConfig, &queueAttributes, &myWdfPendedRequests ) };
if( !NT_SUCCESS( status ) )
{
TraceEvents( TRACE_LEVEL_ERROR, DBG_REQUESTHANDLER, "Queue creation failed. status=[%!STATUS!]", status);
}
return status;
enqueueReadRequest
NTSTATUS status{ validateRequestParameters( request ) };
if( NT_SUCCESS( status ) )
{
status = WdfRequestForwardToIoQueue( request, myWdfPendedRequests );
if( NT_SUCCESS( status ) )
{
KeSetEvent( &( EvtNewReadRequest ), priority, FALSE );
}
else
{
TraceEvents( TRACE_LEVEL_ERROR, DBG_REQUESTHANDLER,
"Failed to add request to queue. status=[%!STATUS!]", status);
}
}
return status;
getRequest
WDFREQUEST request{ NULL };
NTSTATUS status { WdfIoQueueRetrieveNextRequest( myWdfPendedRequests, &request ) };
if( STATUS_NO_MORE_ENTRIES == status )
{
TraceEvents( TRACE_LEVEL_INFORMATION, DBG_REQUESTHANDLER, "Queue is empty." );
request = NULL;
}
else if( !NT_SUCCESS( status ) )
{
TraceEvents( TRACE_LEVEL_ERROR, DBG_REQUESTHANDLER,
"Failed to retrieve next request from queue. status=[%STATUS!].", status );
request = NULL;
}
return request;
processRequest
WDFREQUEST request { getRequest() };
if( NULL != request )
{
WDFMEMORY readFileMemory;
NTSTATUS status { WdfRequestRetrieveOutputMemory( request, &readFileMemory ) };
if( NT_SUCCESS( status ) )
{
status = WdfMemoryCopyFromBuffer( readFileMemory, 0, &data, numBytes );
if( !NT_SUCCESS( status ) )
{
TraceEvents( TRACE_LEVEL_ERROR, DBG_REQUESTHANDLER,
"WdfMemoryCopyFromBuffer() failed, status=[%!STATUS!]", status );
status = STATUS_UNSUCCESSFUL;
numBytes = 0;
}
}
else
{
TraceEvents( TRACE_LEVEL_ERROR, DBG_REQUESTHANDLER,
"Call to WdfRequestRetrieveOutputMemory() failed, status=[%!STATUS!]", status );
status = STATUS_UNSUCCESSFUL;
numBytes = 0;
}
completeRequest( request, status, numBytes );
} // if not null