Hi,
I am building an EDR project, and right now I'm focusing on the communication part between the user mode and the kernel driver. I'm using the inverted call model with the Cancel-safe Queue.
In the DeviceDispatchRoutine, I check the type of IOCTL, and when I find the correct one, I push the IRP into the queue (using IoCsqInsertIrpEx()), then flag the IRP as pending. Here comes the question:
I was flagging it as pending by setting Irp->IoStatus.Status = STATUS_PENDING, and then returning STATUS_PENDING as well. However, I recently saw that I am supposed to call IoMarkIrpPending(). Although I haven't been calling it before, the behavior always seemed fine — the user-mode application was notified normally without any problems.
Is it really necessary to call IoMarkIrpPending()?
the answer is yes
IoMarkIrpPending() informs the io manager that this IRP will completed in the future and its memory should not be recyled, and the completion callbacks asscociated with it will be called after you just complete it.
so the right thing is you must call IoMarkIrpPending() and set Irp->IoStatus.Status = STATUS_PENDING, insert the IRP into some queue, and finally complete it in somewhere while check the cancel status carefully
However, I encountered another problem. I followed your instructions, but I noticed that the cancel dispatch routine was never called. I'm pretty sure I added it correctly (although I didn’t add any spin locks for access protection). Only the cleanup dispatch routine was triggered.
The user-mode application appears to freeze when calling CancelIo(), and also when closing the handle to the driver.
Shouldn’t closing the handle notify the I/O manager to cancel all pending IRPs, thus calling the cancel dispatch routine?
Instead, the application just hangs.
Do you have a file system filter as part of this project? If yes just use a Filter Manager Communication Port. It’s just IRPs and inverted call underneath but it’s wrapped in a more convenient API.
Oh my god, I forgot that I already implemented this routine and forgot about it, that was the one what causes problems for my code because I was cancelling the IRPs twice :). thanks very much
for sorry the project doesn't need a minifilter driver (until now), but I know about the file manager communication port it's really perfect and easy to use, I just can't figure out why there isn't a library that wraps this communication functionality for non-filter drivers.
Mr mark another question if you have time, do I have also to take care of the pending IRPs in the Cleanup dispatch routine ? Like to test if there are any pending IRPs then fetch it from the queue and cancel it?
Or this task should be done only in the cancel callback routine of the cancel safe framework?
I saw the code in the documentation you sent and he put a code to remove any pending IRPs also in the cleanup dispatch routine, but I can't figure why it's important although the cancel routine will be called anyway and will cancel it?