You must unlearn what you have learned before you can complete your request.
Or here, you must unmark what you mark before you can complete. In this case I'm playing around with marking and unmarking requests as cancelable. The driver is pending a request, marking it cancelable, completing another request, then calling the Complete() on the pended request and was then calling the UnmarkCancelable(); method for the pended request.
Well that doesn't quite work, you can actually end up with a race condition in that case. To be more specific, a double completion is potential as that completed request winds back up the stack, the cancel routine could be invoked and trigger double completion.
The UMDF documentation does cover that the order of those calls must be UnmarkCancelable(); followed by Complete(); (or CompleteWithInformation();), but I'd like to just stress it a little more here as I didn't read the documentation too thoroughly before I hit the problem, and again, we learn better by laughing at other's mistakes.
One of the other little bugaboos I ran into was in synchronization again. Unlike previous problems, this one didn't cause a blue screen. So it was actually harder to debug. *g*
UMDF supplies a method to customize the locking mode for the user callbacks (Device I/O, Read, Write) by using the the IWDFDeviceInitialize::SetLockingConstraint method during driver initialzation with either a None or a WdfDeviceLevel value. If you don't define that locking constraint, by default UMDF uses the WdfDeviceLevel (again, this is in the documentation), but some of you may want to exploit the None value if you're in to optimizing and want unserialized I/O. In my particular case, the driver I was working on was playing around with stalling requests. Not pending them, but actually stalling them by creating an event, sitting on WaitForSingleObject with that event and then using a later request to signal those events.
Sounded great in theory, but in practice, w/ the WdfDeviceLevel set, those queues become backed up and nothing else will get through, including any requests you have which may want to signal those stalling events.