Completing a new IRP causes another pending IRP to be completed

Dear all,

My driver has a message tracing mechanism that works by IRP Pending, means that in the user-mode app I have a while(true) which sends DeviceIoControl and if there is any message then it completes the IRP, otherwise, it marks IRP as pending (IoMarkIrpPending) and returns a pending status until a message is available so that it can complete the request. It works fine.

But my problem is whenever the IRP is in the pending state if my user-mode app calls for another IOCTL (not related to message tracing, another IOCTL in another thread), if I complete this IRP, another IRP which was previously in pending state is also completed!

Why? I just need my current IRP to be completed and not the other IRP which is in the pending state.

not really answer to your question(sorry), but consider converting your driver to KMDF - it is much easier to manage requests and queues with this framework

1 Like

No, that doesn’t happen. You are misdiagnosing the situation. My guess is that you have a routine somewhere that is popping the “next IRP” off of the list without realizing that you need to handle out-of-band requests first.

1 Like

@Tim_Roberts said:
No, that doesn’t happen. You are misdiagnosing the situation. My guess is that you have a routine somewhere that is popping the “next IRP” off of the list without realizing that you need to handle out-of-band requests first.

Well, I have a DPC routine that completes the previously Pending IRP, I put a breakpoint on it and it never hit. Also, commented everything in the IOCTL handler, which means that the only routines and fields that I use during my Ioctl Handler are “IrpStack = IoGetCurrentIrpStackLocation(Irp)”, “Irp->IoStatus.Status”, “Irp->IoStatus.Information” and finally “IoCompleteRequest(Irp, IO_NO_INCREMENT)”.

And it happens only if I set “Irp->IoStatus.Status” to STATUS_SUCCESS, for example, if I return STATUS_SUCCESS and “Irp->IoStatus.Status = STATUS_UNSUCCESSFUL” then it works means that another IRP is not completed.

Is there anything unusual with these routines and fields?

are you using cancel-safe queues https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/cancel-safe-irp-queues ?

post your code if you can (ioctl handler and DPC)

@Sergey_Pisarev said:
are you using cancel-safe queues https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/cancel-safe-irp-queues ?

post your code if you can (ioctl handler and DPC)

The full source code is here.

An IRP is in pending state (using IOCTL_REGISTER_EVENT IOCTL) and whenever I send another IOCTL (IOCTL_DEBUGGER_READ_MEMORY) in a separate thread then the previous IRP is also completed and both of them return to user mode.

I also create another IOCTL for test,

    case IOCTL_DEBUGGER_READ_MEMORY2:
        DbgBreakPoint();
        Status = STATUS_SUCCESS;
        break;

    DeviceIoControl(DeviceHandle,               // Handle to device
                        IOCTL_DEBUGGER_READ_MEMORY2, // IO Control code
                       NULL, // Input Buffer to driver.
                       NULL, // Input buffer length
                       NULL, // Output Buffer from driver.
                       NULL, // Length of output buffer in bytes.
                       NULL, // Bytes placed in buffer.
                       NULL  // synchronous call
      );

When the above IOCTL is called from user mode using the above code, then the same thing happens, both of the previously pending IRP and the above IRP return to user mode.

I solved it by calling CreateFile one more time for that thread, it seems that the problem was because I use the same handle for both IoCreateDevice(s).