Dear all,
I’ve been looking for information on the Internet on whether a driver that handles an Irp synchronously SHOULD or SHOULD NOT call IoCompleteRequest on it before returning (with a result OTHER THAN STATUS_PENDING).
I’ve found http://technologeeks.com/Courses/Windows%20Kernel%20-%20Excerpt.pdf which seems to indicate it SHOULD NOT call IoCompleteRequest, but then the post of Scott Noone in https://www.osronline.com/showthread.cfm?link=243753 seems to indicate it SHOULD.
My problem with the latter is that calling IoCompleteRequest causes an Apc to be queued (even if the call was handled synchronously as far as I can see). If the caller was holding a guarded mutex (thereby blocking Apc handling) when doing a call to IoCallDriver with an Ipc without completion-routine, but with a PKEVENT, then:
- The driver executes what it needs to do and then calls IoCompleteRequest (which queues an Apc that would call IopCompleteRequest) - but because of the mutex, the Apc is held back - and then returns a status OTHER THAN STATUS_PENDING.
- The IoCallDriver call returns and the caller then frees the event it created for waiting on in case of async handling (not needed here), its IO_STATUS_BLOCK and anything else it needed for the call, since it thinks the call was fully executed.
- At some point the caller releases the guarded mutex it was holding and then Windows triggers the Apc, but the resulting execution of IopCompleteRequest then tries to access stuff (event & IO_STATUS_BLOCK) which just isn’t there anymore, sometimes causing a pagefault.
The same also happens if the caller would be holding a spinlock i.s.o. a guarded mutex and although I cannot go into the details, we really need synchronization here. As far as I can tell from the IoCallDriver documentation of MS it should be OK to call it at IRQL <= DISPATCH_LEVEL, so …
If I don’t do the IoCompleteRequest call in the lower driver when completing the request synchronously (which is actually always the case), then the problem isn’t seen, but it bothers me that I cannot find conclusive documentation on whether that’s the correct approach or not. Can someone clear this up and indicate how to then address the problem above?
Thanks,
K