2.2. Code to Create Queues for Read Requests
The driver creates a manual queue for read requests
in the same way that it did for write requests. The only difference is
that it configures the queue for request dispatching, so that KMDF
places read requests directly into the queue. The driver creates the
queue as follows:
WDF_IO_QUEUE_CONFIG_INIT (
&ioQueueConfig,
WdfIoQueueDispatchManual
);
status = WdfIoQueueCreate (
FdoData->WdfDevice,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&FdoData->PendingReadQueue
);
if (!NT_SUCCESS (status))
{
return status;
}
Status = WdfDeviceConfigureRequestDispatching (
FdoData->WdfDevice,
FdoData->PendingReadQueue,
WdfRequesttypeRead
);
if (!NT_SUCCESS (status))
{
ASSERT (NT_SUCCESS (status));
return status;
}
2.3. Code to Create Queues for Device I/O Control Requests
The driver creates a second pair of parallel and internal manual queues for IRP_MJ_DEVICE_IO_CONTROL requests, just as it did for write requests, as follows:
WDF_IO_QUEUE_CONFIG_INIT (
&ioQueueConfig,
WdfIoQueueDispatchParallel
);
ioQueueConfig.EvtIoDeviceControl =
PciDrvEvtIoDeviceControl;
status = WdfIoQueueCreate (
FdoData->WdfDevice,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&FdoData->IoctlQueue
);
if (!NT_SUCCESS (status))
{
return status;
}
status = WdfDeviceConfigureRequestDispatching (
FdoData->WdfDevice,
FdoData->IoctlQueue,
WdfRequestTypeDeviceControl
);
if (!NT_SUCCESS (status))
{
ASSERT (NT_SUCCESS (status));
return status;
}
// Create internal queue for pending IOCTL requests.
WDF_IO_QUEUE_CONFIG_INIT (
&ioQueueConfig,
WdfIoQueueDispatchManual
);
status = WdfIoQueueCreate (
FdoData->WdfDevice,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&FdoData-PendingIoctlQueue
);
if (!NT_SUCCESS (status))
{
return status;
}
The
driver configures these two queues exactly as it did the parallel and
manual queues for write requests. The only difference is that it set a
callback for EvtDeviceIoControl instead of EvtIoWrite and configures request dispatching for WdfRequestTypeDeviceControl instead of WdfRequestTypeWrite.