I think i have found a bug. While trying to get my drivers startio right, i cant fix 1 thing - irp is cancelable after dequeueing.
Ive read many disasembly listing from my kernel, some articles, and other stuff related. It is an obvious bug.
Msdn say to compare device_object->currentirp with irp, but in my opinion its useless because IoStartNextPacket and IoStartPacket are reentrant, so after my irp get dequeued but before it acquire cancel spinlock, another irp might get dequeued altering currentirp field. If i do this check, i will have no choice but to discard this irp and let the cancel routing handle it. This is unacceptable, because i might require constant (not nessecarly serialized) output from my device, and losing irps from time to time (leaking memory) id not an option. And using device_object->currentirp as a pointer to current irp is good if i want to complete irp twice and score bsod really fast...
My irp processing model looks like this:
StartIo:
- acquire cancel lock
- check irp agnist device_object->currentirp (useless!)
- check the cancel flag, if set, complete irp on my own. This can happen when somehow my queue got noncancelable irp.
- release cancel lock
Cancel:
- remove irp from queue, if returned false irp has already been dequeued (this short startio period), and startio hasnt yet removed cancel pointer.
- release cancel spinlock
- complete irp
from xp, i can set irp to be either noncancelable right after its dequeued, or startio to be serialized, both ways fixing 2 bugs. But its only from xp...
If i use my own irp queue, it will be almost identical to original one, with an excpetion of removing cnacel routine under cancel spinock after deququqing irp.
What do you think of it? Is it a bug? Or im just wrong, as always...?