driver's IRQL already 2 when calling WdfDeviceAddQueryInterface?

I’m a newbie with kernel drivers, but not a total one. I wrote a non-PnP driver that works and I’m trying to now add access to driver’s interface. I’m calling WdfDeviceAddQueryInterface right after successfully creating the device, but the driver keeps crashing because it appear IRQL is already 2 - don’t quite understand why and whether the message is maybe misleading. This is from the MEMORY.DMP:

IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 00000000000000b0, memory referenced
Arg2: 0000000000000002, IRQL
Arg3: 0000000000000001, bitfield :
bit 0 : value 0 = read operation, 1 = write operation
bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: fffff8017340b52e, address which referenced memory

And the call stack is:

_STACK_TEXT:
ffff9a878bba2fd8 fffff80173609269 : 000000000000000a 00000000000000b0 0000000000000002 0000000000000001 : nt!KeBugCheckEx
ffff9a878bba2fe0 fffff80173605569 : 000a99928bbaffff 00000000000000ff 00000000ffffffff ffffe18300000000 : nt!KiBugCheckDispatch+0x69
ffff9a878bba3120 fffff8017340b52e : 0000000000000000 0000000000000fff 0000000000000103 0000000000000000 : nt!KiPageFault+0x469
ffff9a878bba32b0 fffff801765aecf2 : 00000000000000b0 ffffe18300000000 0000000000000000 fffff801765a9300 : nt!KeWaitForSingleObject+0x18e
ffff9a878bba33a0 fffff8017661e947 : 0000000000000000 0000000000000000 ffffe183b6dae250 fffff80100000000 : Wdf01000!FxWaitLockInternal::AcquireLock+0x56 [minkernel\wdf\framework\shared\inc\private\common\FxWaitLock.hpp @ 266]
ffff9a878bba33e0 fffff801765e0a11 : 0000000000000000 ffff9a878bba3510 ffff9a878bba3510 ffffe183b05ca230 : Wdf01000!FxPkgPnp::AddQueryInterface+0x27 [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpnp.cpp @ 5417]
ffff9a878bba3410 fffff80170f42516 : ffffe183b75d1ce0 0000000000000000 0000000000000000 0000000000000000 : Wdf01000!imp_WdfDeviceAddQueryInterface+0x2d1 [minkernel\wdf\framework\kmdf\src\support\fxqueryinterfaceapi.cpp @ 219]
ffff9a878bba3490 fffff80170f4156a : 00001e7c48a2e318 ffff9a878bba3510 fffff80170f440c0 0000000000000000 : KMDF_RTC!WdfDeviceAddQueryInterface+0x46 [C:\Program Files (x86)\Windows Kits\10\Include\wdf\kmdf\1.15\WdfQueryInterface.h @ 175]
ffff9a878bba34d0 fffff80170f41140 : 00001e7c48a2e318 ffff9a878bba36c8 ffff9a878bba3698 0000000000000000 : KMDF_RTC!SetupDeviceInterface+0x13a [C:\Users\durovicm\source\repos\KMDF_RTC\KMDF_RTC\KRTCTimer.cpp @ 78] _

The driver code that leads up to this unfortunate outcome is:

_PAGED_CODE();
RTCTIMER_INTERFACE timerInterface;
WDF_QUERY_INTERFACE_CONFIG timerInterfaceConfig;
RtlZeroMemory(&timerInterface, sizeof(timerInterface));
timerInterface.InterfaceHeader.Size = sizeof(timerInterface);
timerInterface.InterfaceHeader.Version = 1;
timerInterface.InterfaceHeader.Context = device;
timerInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
timerInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
timerInterface.intValue = 1789;
timerInterface.TimerName.Buffer = timerInterface.TimerNameStr;
timerInterface.TimerName.MaximumLength = sizeof(timerInterface.TimerNameStr) / sizeof(timerInterface.TimerNameStr[0]) - 1;
DECLARE_CONST_UNICODE_STRING(movie, L"Good, bad, ugly");
RtlCopyUnicodeString(&timerInterface.TimerName, &movie);
WDF_QUERY_INTERFACE_CONFIG_INIT(&timerInterfaceConfig, (PINTERFACE)&timerInterface,
	&GUID_RTCTIMER_INTERFACE_STANDARD,
	NULL);
timerInterfaceConfig.ImportInterface = FALSE;
NTSTATUS status = WdfDeviceAddQueryInterface(device, &timerInterfaceConfig);_

The last line is the line 78 at which the crash happens.
I’m at my wits’ end trying to understand this error. The driver works fine without this code that attempts to add the ability to add query interface ability. Any help is much appreciated…

99% sure you can only call this API for a PNP WDFDEVICE as it requires supporting IRP_MJ_PNP underneath the covers. The control WDFDEVICE path doesn’t allocate a pnp package (m_PkgPnp), https://github.com/microsoft/Windows-Driver-Frameworks/blob/d9f66ca7ede31bc0745daad5c6f2aedb53795969/src/framework/shared/core/km/fxdevicekm.cpp#L403. m_PkgPnp is the MJ_PNP io handler.

The IRQL 2 is a side effect of a null +0xb0 offset deref

Arg1: 00000000000000b0, memory referenced

You didn’t include enough of the stack. What routine were you in when you called this? You called _PAGED_CODE(); ad the beginning, but that wouldn’t be true if the IRQL is really at DISPATCH_LEVEL.

Thank you for your prompt responses guys. @Doron_Holan , I’ll try to change the driver to be a PnP one. It’s strange that documentation doesn’t mention anything about this, nor I can think of a reason why would this be restricted to PnP supporting drivers. The message looks as if something is not quite initialized, but I can’t really see what. Everything looked normal under Windbg. I had a close look at several examples, including the Microsoft’s sample driver, “thermalclient” and it’s very similar.
@Tim_Roberts , the missing call stack looks like this:

fffff6821cc4c5b0 fffff8002e931140 : 00005d78ae27d318 fffff6821cc4c6c8 fffff6821cc4c698 0000000000000000 : KMDF_RTC!SetupDeviceInterface+0x137 [C:\Users\durovicm\source\repos\KMDF_RTC\KMDF_RTC\KRTCTimer.cpp @ 78]
fffff6821cc4c670 fffff8002e932111 : 00005d78ae3f5d98 0000000000000000 fffff6821cc4c848 fffff6821cc4c828 : KMDF_RTC!AddTimerDevice+0x140 [C:\Users\durovicm\source\repos\KMDF_RTC\KMDF_RTC\KRTCTimer.cpp @ 202]
fffff6821cc4c7e0 fffff8002e932ceb : ffffa28750d02e30 ffffa2874c327000 ffffa2874c327000 ffffa287510b9de0 : KMDF_RTC!DriverEntry+0x141 [C:\Users\durovicm\source\repos\KMDF_RTC\KMDF_RTC\KRTCTimer.cpp @ 248]

In terms of execution, SetupDeviceInterface was called immediately after a successful call to WdfDeviceCreate. So, from DriverEntry, I called AddTimerDevice, where I was actually creating the device, and then called SetupDeviceInterface from the point immediately after a successful call to WdfDeviceCreate. I’ve also tried calling it after WdfControlFinishInitializing, in case, as the dump showed, something else, hidden, needed to be properly set up, but it made no difference and the crash happened again when calling WdfDeviceAddQueryInterface

PS. seems like someone else faced exactly the same problem, in this forum: https://community.osr.com/discussion/292650/publishing-a-device-driver-interface-ddi-from-a-control-driver

… and looks like he got the same answer.

Since you fell into this hole, you might want to do a righteous act and file a bug in that doc page.

Peter

I shall. Thanks everyone for your help.

I wouldn’t make the driver pnp just for this feature, but maybe you have other reasons. You can add support by pre processing pnp tips and manually handling the query (and all the other random pnp requests that will come through). Why is it tied to a pnp WDF device? For the reasons stayed above AND if you look at how QI is used, the target is found through a device interface (pnp only) or sent by a driver in a pnp stack.