I had time to look at the code you posted…
LxEvtFileCleanup
KMDF will automatically cancel all i/o with the file object being cleaned up for you. The purge might be more of the semantic you want, but i wanted to let you know that KMDF does work for you here.
fileContext->pDataQueue
Why are you storying the pointer to the queue handle? it is just a handle, you can store the value itself. That way you don’t have to dereference it and you don’t have to compare addresses (pDataQueue == &pDeviceContext->BeadDataQueue), rather you can compare ordinal values (dataQueue == pDeviceContext->BeadDataQueue)
WdfRequestGetFileObject returning a NULL handle in LxEvtIoRead (and any other callback for that matter)
you should never have to check for NULL, the file object will always be there if you are receiving handle based i/o (e.g. from an application). The only time you may have to check for NULL is if another driver is sending you I/O (that is the only way it could possibly not be in the PIRP), but even then, the sending driver has a bug in it if it doesn’t properly format the IRP before sending it to your driver.
Same goes for GetFileObjectContext, it will never return NULL if you setup the file object config properly during device init
LxEvtIoRead
You will double complete the request in the path where WdfRequestForwardToIoQueue fails since status will != STATUS_PENDING, so you complete the request the first time immediately after the !NT_SUCCESS check and then again at the bottom of the function at the status != STATUS_PENDING check.
additionally, you could easily fold the pDataQueue check into
if (pDataQueue == NULL) { complete with error }
else { forwardtoqueue(request, *pDataQueue); }
without checking which queue you are forwarding to.
Overall, i see nothing wrong with the initialization of your device or how you are setting up your queues (WdfDeviceConfigureRequestDispatching is not a problem here). Again, I think you need to look at your application since the framework does not represent I/O on cancellation…I do wonder how the application will know which instance of the GUID_CLASS_LX_DETECTOR device interface will be associated with status data or bead data since the device interface string is supposed to be opaque. I would have thought that you would have used 2 different GUIDs, this way the app enumerates both interfaces and definitively knows which interface instance has what i/o contract.
d