WdfIoTargetQueryForInterface API crashing before reaching the target driver

I’m trying to access the device interface in the device driver from a different device stack from my kernel driver. As a learning exercise, I first tried to access the device interface from the toaster driver (Toaster example, GUID_TOASTER_INTERFACE_STANDARD) and this worked just fine, I was able to call GetCrispinessLevel and obtain the correct value.
Then, I used basically identical code (only the device path and interface GUID and type changed) to do the same, but this time, I got a crash, and the stack looks as if I haven’t even reached the other driver. So, the crash info looks like this:

SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e)
This is a very common bugcheck.  Usually the exception address pinpoints
the driver/function that caused the problem.  Always note this address
as well as the link date of the driver/image that contains this address.
Arguments:
Arg1: ffffffffc0000005, The exception code that was not handled
Arg2: fffff8045a49be60, The address that the exception occurred at
Arg3: ffffbb82bb266778, Exception Record Address
Arg4: ffffbb82bb265fc0, Context Record Address

and the stack:

PROCESS_NAME:  System
READ_ADDRESS:  ffffffffffffffff 
ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.
EXCEPTION_CODE_STR:  c0000005
EXCEPTION_PARAMETER1:  0000000000000000
EXCEPTION_PARAMETER2:  ffffffffffffffff
EXCEPTION_STR:  0xc0000005
LOCK_ADDRESS:  fffff80457a41ee0 -- (!locks fffff80457a41ee0)
Resource @ nt!PiEngineLock (0xfffff80457a41ee0)    Exclusively owned
	Contention Count = 30
	 Threads: ffffab02a8cbb140-01<*> 
1 total locks

PNP_TRIAGE_DATA: 
	Lock address  : 0xfffff80457a41ee0
	Thread Count  : 1
	Thread address: 0xffffab02a8cbb140
	Thread wait   : 0x2947

STACK_TEXT:  
ffffbb82`bb2669b8 fffff804`5a503420     : fffff804`5f44cb20 ffffab02`aac5e020 ffffbb82`bb266ad0 ffffab02`aabcfcf0 : Wdf01000!_guard_dispatch_icall_nop [minkernel\crts\crtw32\misc\amd64\guard_dispatch.asm @ 57] 
ffffbb82`bb2669c0 fffff804`5a4fc1ea     : ffffbb82`bb266ad0 fffff804`5a4ea540 ffffab02`00000000 00000000`00000000 : Wdf01000!FxPkgPnp::HandleQueryInterface+0x244 [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpnp.cpp @ 1804] 
ffffbb82`bb266a30 fffff804`5a482ef4     : ffffab02`aac5e020 ffffab02`ab413188 ffffab02`ab413100 00000000`00000000 : Wdf01000!FxPkgPdo::_PnpQueryInterface+0x1a [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpdo.cpp @ 546] 
ffffbb82`bb266a60 fffff804`5a481b73     : ffffab02`aa716cc0 ffffab02`aac7e810 ffffab02`aa716cc0 fffff804`5a485213 : Wdf01000!FxPkgPnp::Dispatch+0xb4 [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpnp.cpp @ 745] 
ffffbb82`bb266ad0 fffff804`57649109     : 00000000`0000001b ffffab02`aa716cc0 00000000`00000000 fffff804`5c995180 : Wdf01000!FxDevice::DispatchWithLock+0x113 [minkernel\wdf\framework\shared\core\fxdevice.cpp @ 1430] 
ffffbb82`bb266b30 fffff804`5a50767c     : ffffab02`ae5f000e ffffbb82`bb266bc8 00000000`00000004 00000000`00000000 : nt!IofCallDriver+0x59
ffffbb82`bb266b70 fffff804`5a50774f     : 00000000`c00000bb ffffbb82`bb266c50 ffffab02`ab4130d0 00000000`00000000 : Wdf01000!FxPkgFdo::_PnpPassDown+0x5c [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgfdo.cpp @ 336] 
ffffbb82`bb266ba0 fffff804`5a482ef4     : ffffab02`ab413000 ffffab02`ab4130d0 00000000`00000288 00000000`00000008 : Wdf01000!FxPkgFdo::_PnpQueryInterface+0x8f [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgfdo.cpp @ 531] 
ffffbb82`bb266be0 fffff804`5a481b73     : ffffab02`aa716cc0 ffffab02`ab943920 00000000`00000070 00001f80`00260020 : Wdf01000!FxPkgPnp::Dispatch+0xb4 [minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpnp.cpp @ 745] 
ffffbb82`bb266c50 fffff804`57649109     : ffffbb82`bb266ef0 00000000`00000070 00000000`00000003 fffff804`5c995180 : Wdf01000!FxDevice::DispatchWithLock+0x113 [minkernel\wdf\framework\shared\core\fxdevice.cpp @ 1430] 
ffffbb82`bb266cb0 fffff804`5a4c33f3     : ffffab02`ae5f4b00 00000000`00000003 ffffab02`aabcfcf0 00000000`00000070 : nt!IofCallDriver+0x59
ffffbb82`bb266cf0 fffff804`5a4c34c7     : ffffab02`aabcfcf0 fffff804`57615b2a ffffab02`aabcfcf0 00000000`00000000 : Wdf01000!FxIrp::SendIrpSynchronously+0x4f [minkernel\wdf\framework\shared\inc\private\km\fxirpkm.hpp @ 215] 
ffffbb82`bb266d50 fffff804`5a4e64f3     : ffffab02`aa716cc0 ffffbb82`bb266ef0 00000000`0000000c fffff804`5c992bd0 : Wdf01000!FxQueryInterface::_QueryForInterface+0x7f [minkernel\wdf\framework\kmdf\src\support\fxqueryinterface.cpp @ 142] 
ffffbb82`bb266d90 fffff804`5c992c1a     : ffffab02`adfa9dc0 000054fd`511a5b18 fffff804`5c994c00 fffff804`5c992b96 : Wdf01000!imp_WdfIoTargetQueryForInterface+0xa3 [minkernel\wdf\framework\shared\targets\general\km\fxiotargetapikm.cpp @ 237] 
ffffbb82`bb266dd0 fffff804`5c992188     : 000054fd`52056238 fffff804`5c995180 ffffbb82`bb266ef0 ffffab02`adc40070 : ExtrasBusDevice!WdfIoTargetQueryForInterface+0x7a [C:\Program Files (x86)\Windows Kits\10\Include\wdf\kmdf\1.15\wdfiotarget.h @ 742] 
ffffbb82`bb266e30 fffff804`5c998c2b     : 000054fd`55416898 ffffbb82`bb267080 ffffbb82`bb267068 00000000`00000000 : ExtrasBusDevice!GetBAR2Range+0x1d8 [C:\Users\durovicm\source\repos\DeviceExtras\ExtrasBusDevice\Device.c @ 83] 
ffffbb82`bb267040 fffff804`5c998daa     : 00000000`00000000 ffff9b01`00000001 f2cdb125`00000002 00000000`0000000d : ExtrasBusDevice!ExtrasBusDeviceCreateDevice+0x13b [C:\Users\durovicm\source\repos\DeviceExtras\ExtrasBusDevice\Device.c @ 203] 
ffffbb82`bb267160 fffff804`5a4d7821     : 000054fd`511a5b18 ffffbb82`bb267200 00000000`41706e50 fffff804`57cf1937 : ExtrasBusDevice!ExtrasBusDeviceEvtDeviceAdd+0xca [C:\Users\durovicm\source\repos\DeviceExtras\ExtrasBusDevice\Driver.c @ 115] 
ffffbb82`bb2671c0 fffff804`5a4d773c     : ffffab02`aeda7b60 00000000`00000000 ffffab02`aeda7b60 00000000`00000004 : Wdf01000!FxDriver::AddDevice+0xd1 [minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72] 
ffffbb82`bb2675e0 fffff804`5777adaf     : ffffab02`ab505cb0 ffffbb82`bb267760 00000000`00000000 fffff804`57964458 : Wdf01000!FxDriver::AddDevice+0x2c [minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 47] 
ffffbb82`bb267610 fffff804`57d098e6     : 00000000`00000000 00000000`00000003 ffffab02`ab505cb0 ffff9b01`8f5a9930 : nt!PpvUtilCallAddDevice+0x3b
ffffbb82`bb267650 fffff804`57cef57b     : 00000000`00000003 00000000`00000000 ffffbb82`bb2677e0 00000000`40000000 : nt!PnpCallAddDevice+0x56
ffffbb82`bb2676e0 fffff804`57cee40b     : ffffab02`ab505cb0 ffffbb82`bb267918 ffffab02`ab505cb0 00000000`00000000 : nt!PipCallDriverAddDevice+0xc2f
ffffbb82`bb2678a0 fffff804`57d5e83f     : ffffab02`ab505c00 ffffab02`ae5f4b01 ffffbb82`bb2679b0 ffffab02`00000000 : nt!PipProcessDevNodeTree+0x1af
ffffbb82`bb267960 fffff804`5776b2d1     : ffffab01`00000003 ffffab02`ab505cb0 ffffc081`00000000 00000000`00000000 : nt!PiRestartDevice+0xab
ffffbb82`bb2679b0 fffff804`5771934a     : ffffab02`a8cbb140 fffff804`57a40780 ffffab02`a8c63c40 ffffab02`00000000 : nt!PnpDeviceActionWorker+0x421
ffffbb82`bb267a70 fffff804`576ec675     : ffffab02`a8cbb140 ffffab02`a8c9d040 ffffab02`a8cbb140 00000000`00000000 : nt!ExpWorkerThread+0x16a
ffffbb82`bb267b10 fffff804`577cf90c     : ffffc081`6d820180 ffffab02`a8cbb140 fffff804`576ec620 00000000`00000000 : nt!PspSystemThreadStartup+0x55
ffffbb82`bb267b60 00000000`00000000     : ffffbb82`bb268000 ffffbb82`bb261000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x1c

The code in the driver looks like this:

static BOOLEAN GetBAR2Range(WDFDEVICE device) {
	WDF_OBJECT_ATTRIBUTES  ioTargetAttrib;
	WDFIOTARGET  ioTarget;
	WDF_IO_TARGET_OPEN_PARAMS  openParams;
	DECLARE_CONST_UNICODE_STRING(device_name, L"\\Device\\Serial0"); // any serial would do, and 0 should exist
	MK7ISER_INTERFACE_STANDARD mk7i_serial;

	WDF_OBJECT_ATTRIBUTES_INIT(&ioTargetAttrib);
	NTSTATUS status = WdfIoTargetCreate(device, &ioTargetAttrib, &ioTarget);
	if (!NT_SUCCESS(status)) {
		TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "Failed to create IO Target: %!STATUS!", status);
		return FALSE;
	}
	WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(&openParams, &device_name, STANDARD_RIGHTS_ALL);
	status = WdfIoTargetOpen(ioTarget, &openParams);
	if (!NT_SUCCESS(status)) {
		TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "Failed to open IO Target: %!STATUS!", status);
		WdfObjectDelete(ioTarget);
		return FALSE;
	}
	status = WdfIoTargetQueryForInterface(ioTarget, &GUID_MK7ISER_INTERFACE_STANDARD, (PINTERFACE)&mk7i_serial,
		sizeof(MK7ISER_INTERFACE_STANDARD), 1, NULL);

The crash happens on the last line and the call stack suggests that it didn’t even make it to the target driver (not sure about this, I’m a newbie). As I mentioned at the start, this code works fine with a toaster device, the only thing different is the device_name constant (seems to be OK, opening of IoTarget didn’t fail), the interface GUID and the interface type. I suppose if the target interface, for some reason, didn’t exist, I would get an error code, not a crash.

Any ideas? How’s one even supposed to debug these? Are the sources for wdf011000 library available somewhere?
Thanks in advance…

Yes, the WDF source code is in GitHub and with it you can (usually, pretty much) single step into the code.

Also, don’t forget the WDF Verifier and the IFR are always helpful.

Peter

… the call stack suggests that id didn’t even make it to the target driver …

Not so. There are two IofCallDriver calls in your stack, and each of those would be popping into a lower layer. The first should be going to your PDO, the second should be going to the FDO for the device. Plus, the crash is happening in FxPkgPnp::HandleQueryInterface, which is trying to HANDLE this request. So, you has passed from your KMDF device, through another KMDF device, into a third KMDF device.

Is \device\serial0 supposed to be a device you know? The QueryInterface concept only works with PnP devices. Although if that were the problem, you should have received STATUS_NOT_SUPPORTED.

_guard_dispatch_icall_nop is basically just a jump through a register (jmp rax), That shouldn’t go bad unless the driver it called was not fully configured. Odd.

Thanks @“Peter_Viscarola_(OSR)” . And @Tim_Roberts , well spotted, I must have been blind to miss those two calls to IoCallDriver. Yes, it’s a device I know, and I checked it existed. I have the source code for it and it seems to be doing the right thing, but this aspect of it, responding to interface query, hasn’t really been tested. It’s from the old code base and I sort of hoped it worked correctly, but it seems I’ll have to debug it further.

I suspected it was a framework problem simply because the call stack didn’t show any code outside of my driver and WDF library being involved in this crash. Is there a quick way to check if some driver supports a particular device interface and also supports query function?