Question On WDF Queue Creation

Hi Guys,
I am creating a Main Parallel Dispatch queue. This is the main queue which accepts only the IOCTL request. I do not support any other request. To create this queue, I am doing this (From a initialization worker thread):

    ======== CODE =======
 
  WDF_IO_QUEUE_CONFIG     wdfIoQueueConfig;
   ULONG                   CmdCnt = 0;

  CmdCnt = XYZ;

WDF_IO_QUEUE_CONFIG_INIT(
    &wdfIoQueueConfig,
    WdfIoQueueDispatchParallel
);

wdfIoQueueConfig.EvtIoDeviceControl = McrDrvIFaceEvtIoDeviceControl;
wdfIoQueueConfig.AllowZeroLengthRequests = FALSE;
wdfIoQueueConfig.Settings.Parallel.NumberOfPresentedRequests = CmdCnt;

status = WdfIoQueueCreate(
                DevExt->Device,
                &wdfIoQueueConfig,
                WDF_NO_OBJECT_ATTRIBUTES,
                &DevExt->MainIoctlQue);

if (!NT_SUCCESS(status)) {

    TraceEvents(
        TRACE_LEVEL_ERROR, 
        DBG_INIT, 
        "Error Creating Main Ioctl Queue 0x%x\n", 
        status);

    DRV_MARK_DEV_FAILED(DevExt);
    return status;
}

      ================================= 

The above code succeeds.

After this I am calling

       status = WdfDeviceConfigureRequestDispatching(
                                    DevExt->McDevice,
                                   DevExt->MainIoctlQue,
                                   WdfRequestTypeDeviceControl);

            if (!NT_SUCCESS(status)) {

                           TraceEvents(
                                            TRACE_LEVEL_ERROR, 
                                            DBG_INIT, 
                                            "Error in config'ing ioctl Queue 0x%x\n", 
                                            status); 

                              DRV_MARK_DEV_FAILED(DevExt);
                              return status;
                  }

WdfDeviceConfigureRequestDispatching fails with a error status of -1073741436

I am not sure if I really need to call WdfDeviceConfigureRequestDispatching since I have registered only EvtIoDeviceControl when I was creating the queue.

What am I missing here??

Please let me know.
Thanks
Aj-

Error values in hex are for more useful compared to decimal. What does !wdfkd.wdflogump say when the error code is returned ?

C0000184 is STATUS_INVALID_DEVICE_STATE. You do not need to call WdfDeviceConfigureRequestDispatching on your default queue.

Hi @Tim_Roberts and @Doron_Holan
Thanks for the replies. I really appreciate it.

I removed the WdfDeviceConfigureRequestDispatching and I was able to proceed. So here is what I have:

  1. In PrepareHardware I claim the PCIe resources and fire a command to hardware. I return from PrepareHardware.

  2. After I return, My ISR gets called for the completion of the command that I fired. My completion handler for the fired command, requests a passive level callback.

  3. In this callback I do all other initialization and at the end I create Three Queues. One is a parallel WDF queue and two manual queues. I create the parallel queue like this:-

              CmdCnt = XYZ;
    
         WDF_IO_QUEUE_CONFIG_INIT(                          
                   &wdfIoQueueConfig,
                  WdfIoQueueDispatchParallel
            );
    
        wdfIoQueueConfig.EvtIoDeviceControl = McrDrvIFaceEvtIoDeviceControl;
        wdfIoQueueConfig.AllowZeroLengthRequests = FALSE;
        wdfIoQueueConfig.Settings.Parallel.NumberOfPresentedRequests = CmdCnt;
    
       status = WdfIoQueueCreate(
             DevExt->Device,
             &wdfIoQueueConfig,
             WDF_NO_OBJECT_ATTRIBUTES,
             &DevExt->MainIoctlQue);
    
      if (!NT_SUCCESS(status)) {
    
            TraceEvents(
                    TRACE_LEVEL_ERROR, 
                    DBG_INIT, 
                    "Error Creating Main Ioctl Queue 0x%x\n", 
                   status);
    
            DRV_MARK_DEV_FAILED(DevExt);
            return status;
     }
    
  4. The model that I have is that the WDF should use the parallel queue to dispatch the request to my driver. Once the driver gets the request I forward to one of the manual queues.

  5. While testing the driver I found that my “EvtInContextCallback” get called. I probe and lock the pages, allocate a common buffer and put all that information in my “RequestContext” (which comes with WdfRequest).

  6. At the End of the InContextCallback, I call

          sts = WdfDeviceEnqueueRequest(
                               Device,
                               Request);
    
                if (!NT_SUCCESS(sts)) {
    
                         TraceEvents(
                                   TRACE_LEVEL_ERROR,
                                   DBG_PNP,
                                   "McrDrvIFaceEvtIoInCallerContext: Failed %!STATUS!\n",
                                   sts);
    
                        WdfRequestComplete(
                         Request,
                         sts);
            }
    
             return;
    
  7. WdfDeviceEnqueueRequest is returning me a status of C0000006 and I complete the command right there with failure.

My expectation is that the Request should be forwarded to the configured parallel dispatch queue for the Ioctl and then my registered callback will be called [Also note that the driver does not have any Default Queues at all, which I think should be fine as per the docs]

Not sure what am I missing here.
!wdfkd.wdflogdump does not print anything in debugger.

Would really appreciate any help here.
Thanks
Aj-

Why do you delay creating the queues? Typically, you create the queues and your interrupts in EvtDriverDeviceAdd, before the hardware is formally “activated”.

I don’t believe your status is actually C0000006. That’s a paging I/O error. Can you check that again?

Hi Tim,

I just checked again. The status value returned is [0n-1073741808] I am pasting it directly from debugger.

I had the queues created delayed because I wanted to create the queues after the hardware initialization was complete, so that the driver is not in situation where it can get the request before it was ready to fire the command. Anyway, I moved the WDF queue creation to Add device and still see the same issue.

The error code is really bugging me. I just do IoAllocateMdl and MmProbeAndLockPages (with ReadAndWrite access) and then a common buffer allocation. I save all this in to RequestContext. Not sure what I am missing.

If you get any ideas, let me know.

Thanks,
Ajitabh

That’s C0000010, which is STATUS_INVALID_DEVICE_REQUEST… You MUST get in the habit of printing these in hex.

Your EvtInContextCallback is going to get called for EVERY IRP, including opens and closes. Are you verifying that it’s IRP_MJ_DEVICE_CONTROL before you do your processing?

Yes. I have this code right at the top.

  WDF_REQUEST_PARAMETERS_INIT(&reqParams);

  WdfRequestGetParameters(
    Request,
    &reqParams);

if (reqParams.Type != WdfRequestTypeDeviceControl) {

    /*
    * If there is any non IOCTL request that comes to the driver
    * We will not do anything with it [yet]. We will just let
    * the framework handle that request.
    */
    sts = WdfDeviceEnqueueRequest(
        Device,
        Request);

    if (!NT_SUCCESS(sts)) {

        TraceEvents(
            TRACE_LEVEL_ERROR,
            DBG_PNP,
            "McrDrvIFaceEvtIoInCallerContext: Failed %!STATUS!\n",
            sts);

        WdfRequestComplete(
            Request,
            sts);
    }

    return;

}

Hi Guys,
Just thought I would post how I resolved this issue just so that if someone is trying to do the same thing does not have to spend time debugging this.
There are two observations:

  1. I was not creating any Default queue. I was creating three queues (one parallel and two manual. None of which were default queues)
  2. I was creating queue from a initialization thread.

I did two changes:

  1. Moved the Queue creation to AddDevice. (for some reason, if you try and create the default queue from initialization thread, it fails. Non default queues are fine.)

  2. Made the parallel queue as the default queue.

With these two changes, everything looks good and my device Io control is getting called.

Thanks guys for all the help. If someone can render some explanations on this, that will be awesome. :slight_smile:

@Tim_Roberts @Doron_Holan : Thanks for your time.

Regards,
Aj-

> Moved the Queue creation to AddDevice. (for some reason, if you try and create the default queue from initialization thread, it fails. Non default queues are fine.) That reason is during add device you set up all the device state needed to start processing io. By restricting the init of the default queue to add device the framework doesn’t need to handle setting it later , and thus, add locking and complexity around default queue processing.

The comments in the code say:

    //
    // If the queue is a default queue, then we restrict the creation to happen
    // a) before the device is started for pnp devices (FDO or PDO)
    // b) before the call to WdfControlDeviceFinishInitializing for controldevices.
    // This is done to prevent some unknown race conditions and reduce
    // the test matrix.
    //