WdfIoQueueFindRequest returns STATUS_NO_MORE_ENTRIES

I have two IOCTL which are handled by same kernel mode driver.
In 1st IOCTL, I forward the request to manual queue using WdfRequestForwardToIoQueue(). The return status of this function is a success.
in 2nd IOCTL, I am trying to find the request in the manual queue using WdfIoQueueFindRequest(). However, its returning the status as STATUS_NO_MORE_ENTRIES.
I am not quite sure what causes the STATUS_NO_MORE_ENTRIES error since the request looks to be forwarded successfully to manual queue by 1st IOCTL

Perhaps you should show us some code. This s a very common pattern.

Basically, in my first try I tried to forward the request to a manual queue and find the request in the manual queue as part of same IOCTL(This was just for testing):

// Queue creation in EvtDeviceAdd:

 WDF_OBJECT_ATTRIBUTES_INIT(&attr);
    attr.ExecutionLevel = WdfExecutionLevelPassive;
    WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);
    config.PowerManaged = WdfFalse;
    status = WdfIoQueueCreate(device,
                              &config,
                              &attr,
                              &context->manualQueue);

// IOCTL handler in which forwarding and searching is happening(1st try):

VOID
ProcessIoctl(
    _In_ WDFQUEUE   Queue,
    _In_ WDFREQUEST Request,
    _In_ size_t     outputlengthBuffer,
    _In_ size_t     inputlengthBuffer,
    _In_ ULONG      IoControlCode
    )
{
  switch(IoControlCode){
 NTSTATUS status = 0;
   case IOCTL1:
   {
       PCONTEXT context = GetContext(WdfIoQueueGetDevice(Queue));
       status = WdfRequestForwardToIoQueue(Request, context->manualQueue);
     if (NT_SUCCESS(status))
     {
        // Mark request pending
        status = STATUS_PENDING;
     }
    
  //Now start finding the request in manual queue appended above
   do {
        WDF_REQUEST_PARAMETERS_INIT(&params);
        status = WdfIoQueueFindRequest(
                                       context->manualQueue,
                                       prevTagRequest,
                                       NULL,
                                       &params,
                                       &tagRequest
                                       );
        if (prevTagRequest) {
            WdfObjectDereference(prevTagRequest);
        }
        if (status == STATUS_NO_MORE_ENTRIES) {  // This condition is getting triggered somehow
            break;
        }
        if (status == STATUS_NOT_FOUND) {
            //
            // The prevTagRequest request has disappeared from the
            // queue. There might be other requests that match
            // the criteria, so restart the search. 
            //
            prevTagRequest = tagRequest = NULL;
            continue;
        }
        if (!NT_SUCCESS(status)) { 
            status = STATUS_UNSUCCESSFUL;
            break;
        }
        if (IOCTL1 == params.Parameters.DeviceIoControl.IoControlCode){
            //
            // Found a match. Retrieve the request from the queue.
            //
            status = WdfIoQueueRetrieveFoundRequest(
                                                    context->manualQueue,
                                                    tagRequest,
                                                    Request1
                                                    );
            WdfObjectDereference(tagRequest);
            if (status == STATUS_NOT_FOUND) {
                //
                // The tagRequest request has disappeared from the
                // queue. There might be other requests that match 
                // the criteria, so restart the search. 
                //
                prevTagRequest = tagRequest = NULL;
                continue;
            }
            if (!NT_SUCCESS(status)) {
                status = STATUS_UNSUCCESSFUL;
                break;
            }
            //
            //  Found a request.
            //
            ASSERT(*Request1 == tagRequest);
            status =  STATUS_SUCCESS;
            break;
        } else {
            //
            // This request is not the correct one. Drop the reference 
            // on the tagRequest after the driver obtains the next request.
            //
            prevTagRequest = tagRequest;
            continue;
        }
    } while (TRUE);

   }

}
  

}

I am trying to forward request to queue and find the request in queue as part of same IOCTL:

//EvtDeviceAdd
    WDF_OBJECT_ATTRIBUTES_INIT(&attr);
    attr.ExecutionLevel = WdfExecutionLevelPassive;
    WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);
    config.PowerManaged = WdfFalse;
    status = WdfIoQueueCreate(device,
                              &config,
                              &attr,
                              &context->manualQueue);

VOID
ProcessIoctl(
    _In_ WDFQUEUE   Queue,
    _In_ WDFREQUEST Request,
    _In_ size_t     lengthOutputBuffer,
    _In_ size_t     lengthInputBuffer,
    _In_ ULONG      IoControlCode
    )
{
switch(IoControlCode)
{
  case IOCTL1:
{

      PCONTEXT context = GetContext(WdfIoQueueGetDevice(Queue));;

      status = WdfRequestForwardToIoQueue(Request, context->manualQueue);
     if (NT_SUCCESS(status))
    {
        status = STATUS_PENDING;
    }
    

  //Now find the request in the queue previously forwarded
WDF_REQUEST_PARAMETERS  params;
    WDFREQUEST  tagRequest;
    WDFREQUEST  prevTagRequest;

    WDF_REQUEST_PARAMETERS_INIT(&params);
 
    *Request = NULL;
    prevTagRequest = tagRequest = NULL;

    do {
        WDF_REQUEST_PARAMETERS_INIT(&params);
        status = WdfIoQueueFindRequest(
                                       context->manualQueue,
                                       prevTagRequest,
                                       NULL,
                                       &params,
                                       &tagRequest
                                       );
        if (prevTagRequest) {
            WdfObjectDereference(prevTagRequest);
        }
        if (status == STATUS_NO_MORE_ENTRIES) {
            status = STATUS_UNSUCCESSFUL;
            break;
        }
        if (status == STATUS_NOT_FOUND) {
            //
            // The prevTagRequest request has disappeared from the
            // queue. There might be other requests that match
            // the criteria, so restart the search. 
            //
            prevTagRequest = tagRequest = NULL;
            continue;
        }
        if (!NT_SUCCESS(status)) { 
            status = STATUS_UNSUCCESSFUL;
            break;
        }
        if (FunctionCode == params.Parameters.DeviceIoControl.IoControlCode){
            //
            // Found a match. Retrieve the request from the queue.
            //
            status = WdfIoQueueRetrieveFoundRequest(
                                                    context->manualQueue,
                                                    tagRequest,
                                                    Request1,
                                                    );
            WdfObjectDereference(tagRequest);
            if (status == STATUS_NOT_FOUND) {
                //
                // The tagRequest request has disappeared from the
                // queue. There might be other requests that match 
                // the criteria, so restart the search. 
                //
                prevTagRequest = tagRequest = NULL;
                continue;
            }
            if (!NT_SUCCESS(status)) {
                status = STATUS_UNSUCCESSFUL;
                break;
            }
            //
            //  Found a request.
            //
            ASSERT(*Request1 == tagRequest);
            status =  STATUS_SUCCESS;
            break;
        } else {
            //
            // This request is not the correct one. Drop the reference 
            // on the tagRequest after the driver obtains the next request.
            //
            prevTagRequest = tagRequest;
            continue;
        }
    } while (TRUE);

}

}
}

Your “ASSERT” is incorrect. The request that you get from WdfIoQueueFindRequest is a “fake” shadow request that refers to the real request. You will not get the same request handle when you do WdfdIoQueueRetrieveFoundRequest. If you call WdfIoQueueGetState, does it show there are requests in the queue?

1 Like

I used the following piece of code to achieve what you are trying to say(right after forwarding request to the Queue):

ULONG num_request = 0;

    WDF_IO_QUEUE_STATE state = WdfIoQueueGetState(context->manualQueue,&num_request,NULL);

It does say that the num_request = 1 after function execution, state variable is set to 0x0B.

Also, looks like when I use WdfIoQueueRetrieveNextRequest() instead of WdfIoQueueFindRequest(), I see that the code returns success code.
Is there any limitation for use of WdfIoQueueFindRequest() that causes it to return error status?

Theoretically, your code should work. After all, you copied it word-for-word from the WdfIoQueueFindRequest documentation page, after all. However, I have had better luck with WdfIoQueueRetrieveNextRequest.

1 Like