KeGerCurrentIRQL Vs VERIFY_IS_IRQL_PASSIVE_LEVEL();

Hi Guys,
I am seeing something very strange (at least to me). I have a code something like this:-

    ``VERIFY_IS_IRQL_PASSIVE_LEVEL();
    if (KeGetCurrentIrql() != PASSIVE_LEVEL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "%s [ERROR]: Wait Specified At Non Passive Level\n", __FUNCTION__);

        return STATUS_INVALID_PARAMETER;
    }``

This code is at a start of a function. The function fires a command to the controller and then waits on a event passed to it.
I am sure that I am calling this function at IRQL passive level. The VERIFY_IS_IRQL_PASSIVE_LEVEL() does not complain and passes without issues.
But right after that KeGetCurrentIrql() returns a NON passive level IRQL and the driver returns STATUS_INVALID_PARAMETER.

There is only one command in the driver and I am testing the Abort of that command. I am in debugger doing step by step. This is a debug build of the driver. All the prints are redirected to debugger. I know my DPC is not running.

I am no sure how this is possible or what am I missing here.

Any ideas highly appreciated.

-Aj

Debug build may not be enough

https://learn.microsoft.com/en-us/windows-hardware/drivers/wdf/verify-is-irql-passive-level
The VERIFY_IS_IRQL_PASSIVE_LEVEL code breaks into a kernel debugger if one of the following is true:

  • DbgBreakOnError is set to a non-zero value in the registry.
  • VerifierOn is set to a non-zero value and DbgBreakOnError is not set.
  • Driver Verifier is enabled, the driver was built with framework version 1.9 or later, and neither VerifierOn nor DbgBreakOnError is set.

My Cancellation routine is being called at Dispatch level. Not sure why. I need it to be called at IRQL passive level. Is this because I set the WdfSynchronizationScopeQueue when I create my FDO (WdfDeviceCreate)?
-Aj

Cancellation routines are always called at dispatch level, because they hold the “cancel spin lock”. In a WDF driver, you can call IoReleaseCancelSpinLock to shift back down to passive.

https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iosetcancelroutine

@Tim_Roberts

When framework calls the “CancelRoutine” with “CancelSpinLock” held, Wouldn’t it try to release the SpinLock when I return from the Cancel Routine? If my cancel routine releases the Spinlock IoReleaseCancelSpinLock and returns, it would be a problem isn’t it? So before returning I will have to acquire the spin lock again, isn’t it?

Thanks
Aj

@Tim_Roberts

To avoid meddling with Cancel Spin lock I am using WdfWorkItemEnqueue to enqueue a work item to perform the abort operation.
This I think should work. But not sure which approach of the two is better. [WorkItem Vs Releasing the SpinLock].
Any thoughts appreciated!!

-Aj

A WDM cancel handler is always supposed to call IoReleaseCancelSpinLock – every time. With KMDF, you can use synchronization scope, but if the work item works in your case, that’s easier.