Getting Device Relations pointer from IRP_MN_DEVICE_QUERY_RELATIONS

Hi :slight_smile:
I am trying to print out all the USB devices connected to my system using an upper filter driver.
I have registered myself as an upper filter driver for the class HKEY_LOCAL_MACHINE.…\Class{36fc9e60-c465-11cf-8056-444553540000}

The problem I am facing is that the driver BSODs with 0x0000a.
Here is the output of my !analyze -v

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: ffffcf818abf0d32, memory referenced
Arg2: 0000000000000002, IRQL
Arg3: 0000000000000000, 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: fffff8005cdb6491, address which referenced memory

Debugging Details:

DUMP_CLASS: 1

DUMP_QUALIFIER: 0

BUILD_VERSION_STRING: 10.0.10240.16384 (th1.150709-1700)

DUMP_TYPE: 0

BUGCHECK_P1: ffffcf818abf0d32

BUGCHECK_P2: 2

BUGCHECK_P3: 0

BUGCHECK_P4: fffff8005cdb6491

READ_ADDRESS: ffffcf818abf0d32 Special pool

CURRENT_IRQL: 2

FAULTING_IP:
nt!IovpCompleteRequest4+71
fffff800`5cdb6491 8a4342 mov al,byte ptr [rbx+42h]

CPU_COUNT: 1

CPU_MHZ: cdd

CPU_VENDOR: GenuineIntel

CPU_FAMILY: 6

CPU_MODEL: 3a

CPU_STEPPING: 9

CPU_MICROCODE: 6,3a,9,0 (F,M,S,R) SIG: 19’00000000 (cache) 19’00000000 (init)

DEFAULT_BUCKET_ID: WIN8_DRIVER_FAULT

BUGCHECK_STR: AV

PROCESS_NAME: System

ANALYSIS_SESSION_HOST: HARSHAD

ANALYSIS_SESSION_TIME: 08-01-2017 13:59:27.0722

ANALYSIS_VERSION: 10.0.14321.1024 amd64fre

TRAP_FRAME: ffffd001d2208ac0 – (.trap 0xffffd001d2208ac0)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000002 rbx=0000000000000000 rcx=ffffe00157b19378
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff8005cdb6491 rsp=ffffd001d2208c50 rbp=0000000000000000
r8=fffff800200e1000 r9=ffffd001d2208e50 r10=fffff8005cdde800
r11=ffffe001578159b0 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl nz ac pe cy
nt!IovpCompleteRequest4+0x71:
fffff8005cdb6491 8a4342 mov al,byte ptr [rbx+42h] ds:0000000000000042=??
Resetting default scope

LOCK_ADDRESS: fffff8005c9bf6a0 – (!locks fffff8005c9bf6a0)

Resource @ nt!PiEngineLock (0xfffff8005c9bf6a0) Exclusively owned
Contention Count = 2
NumberOfExclusiveWaiters = 1
Threads: ffffe001572d6040-01<*>
Threads Waiting On Exclusive Access:
ffffe00155a97040

1 total locks, 1 locks currently held

PNP_TRIAGE:
Lock address : 0xfffff8005c9bf6a0
Thread Count : 1
Thread address: 0xffffe001572d6040
Thread wait : 0x1cd

IP_IN_FREE_BLOCK: 0

LAST_CONTROL_TRANSFER: from fffff8005c8764a2 to fffff8005c7d4300

STACK_TEXT:
ffffd001d22081c8 fffff8005c8764a2 : 000000000000000a 0000000000000003 ffffd001d2208330 fffff8005c70a888 : nt!DbgBreakPointWithStatus
ffffd001d22081d0 fffff8005c875dd2 : 0000000000000003 ffffd001d2208330 fffff8005c7db710 000000000000000a : nt!KiBugCheckDebugBreak+0x12
ffffd001d2208230 fffff8005c7ced24 : fffff8005c8fdc88 fffff8005cdb0000 ffffcf818abf0cf0 fffff800200e1000 : nt!KeBugCheck2+0x93e
ffffd001d2208940 fffff8005c7d95a9 : 000000000000000a ffffcf818abf0d32 0000000000000002 0000000000000000 : nt!KeBugCheckEx+0x104
ffffd001d2208980 fffff8005c7d7dc8 : ffffcf818abf0f70 fffff8005cdb0a3f ffffcf818abf0f70 ffffe00157ae4850 : nt!KiBugCheckDispatch+0x69
ffffd001d2208ac0 fffff8005cdb6491 : ffffe00157ae4850 ffffd001d2208c20 fffff8005c74d5e8 00000000e000071b : nt!KiPageFault+0x248
ffffd001d2208c50 fffff8005cdb0a3f : ffffcf818abf0ee0 ffffcf818abf0cf0 0000000000000000 ffffd001d2208e78 : nt!IovpCompleteRequest4+0x71
ffffd001d2208d00 fffff8005c6cd36d : ffffcf818abf0cf0 ffffe00100000000 0000000000000007 ffffd001d2208d80 : nt!IovpLocalCompletionRoutine+0x197
ffffd001d2208d60 fffff8005cdb028d : ffffcf818abf0e50 ffffcf818abf0c00 ffffe001572d5060 0000000000000000 : nt!IopfCompleteRequest+0x20d
ffffd001d2208e20 fffff8001e911695 : ffffe001572d5060 0000000000000000 0000000000000000 ffffcf818abf0cf0 : nt!IovCompleteRequest+0x1c1
ffffd001d2208f00 fffff8005cdb0044 : ffffcf818abf0cf0 ffffe001572d5060 0000000000000002 ffffe001579108d0 : pci!PciDispatchPnpPower+0xc5
ffffd001d2208f40 fffff8005c714252 : ffffe00157a6db50 ffffe00157a75020 0000000000000000 ffffe001579108d0 : nt!IovCallDriver+0x3d8
ffffd001d2208fa0 fffff8001e63e38d : 0000000000000001 ffffd001d22090a0 ffffe00157a75d40 ffffe00157a75d40 : nt!IofCallDriver+0x72
ffffd001d2208fe0 fffff8001e621347 : ffffe00157a75020 0000000000000007 0000000000000000 fffff8005cdb5844 : Wdf01000!FxPkgFdo::_PnpQueryDeviceRelations+0xad [d:\th\minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgfdo.cpp @ 394]
ffffd001d2209030 fffff8001e62197e : ffffcf818abf0cf0 ffffcf818abf0cf0 0000000000000002 fffff8005cdbc239 : Wdf01000!FxPkgPnp::Dispatch+0xb7 [d:\th\minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpnp.cpp @ 658]
ffffd001d22090a0 fffff8005cdb0044 : ffffe00157a75a30 0000000000000002 fffff8005cdcd97e ffffcf818abf0cf0 : Wdf01000!FxDevice::DispatchWithLock+0x10e [d:\th\minkernel\wdf\framework\shared\core\fxdevice.cpp @ 1402]
ffffd001d22090f0 fffff8005c714252 : ffffcf818abf0cf0 ffffe00157a7ebc0 ffffe00157a7ebc0 ffffe00157951930 : nt!IovCallDriver+0x3d8
ffffd001d2209150 fffff8005cdcd97e : ffffcf818abf0cf0 ffffe00157a7ebc0 ffffe00157a7ebc0 0000000000000000 : nt!IofCallDriver+0x72
ffffd001d2209190 fffff8005cdb0044 : ffffe00157a7ed10 ffffcf818abf0cf0 ffffe00157a7ebc0 0000000000000002 : nt!ViFilterDispatchPnp+0x1a2
ffffd001d22091d0 fffff8005c714252 : ffffe00157a7f080 ffffe00157a80080 0000000000000000 ffffe0015791a390 : nt!IovCallDriver+0x3d8
ffffd001d2209230 fffff8001e63e38d : 0000000000000000 ffffd001d2209330 ffffe00157a80c20 0000000000000000 : nt!IofCallDriver+0x72
ffffd001d2209270 fffff8001e621347 : ffffe00157a80080 0000000000000000 0000000000000000 ffffcf818abf0f70 : Wdf01000!FxPkgFdo::_PnpQueryDeviceRelations+0xad [d:\th\minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgfdo.cpp @ 394]
ffffd001d22092c0 fffff8001e621ede : ffffcf818abf0cf0 ffffe00157a7f080 ffffe00157a6c6f0 ffff3b471c956d8a : Wdf01000!FxPkgPnp::Dispatch+0xb7 [d:\th\minkernel\wdf\framework\shared\irphandlers\pnp\fxpkgpnp.cpp @ 658]
ffffd001d2209330 fffff800200e1453 : ffffcf818abf0cf0 0000000100000000 000000000000001b ffffe00157a7f080 : Wdf01000!imp_WdfDeviceWdmDispatchPreprocessedIrp+0x11e [d:\th\minkernel\wdf\framework\shared\core\km\fxdeviceapikm.cpp @ 257]
ffffd001d2209390 fffff800200e6204 : 00001ffea8580f78 ffffcf818abf0cf0 fffff800200e62e0 0000000000000001 : HelloWorld!WdfDeviceWdmDispatchPreprocessedIrp+0x33 [c:\program files (x86)\windows kits\10\include\wdf\kmdf\1.15\wdfdevice.h @ 2101]
ffffd001d22093c0 fffff8001e621a61 : 00001ffea8580f78 ffffcf818abf0cf0 ffffe00157a807a0 ffffe00157a81940 : HelloWorld!SetCompletionFunction+0xc4 [c:\users\atharva\documents\visual studio 2015\projects\helloworld\helloworld\driver.c @ 75]
ffffd001d2209420 fffff8001e5ae030 : ffffd001d22094a0 ffffe00157a807a0 fffff8005cdcd97e fffff8001e621870 : Wdf01000!FxDevice::DispatchWithLock+0x1f1 [d:\th\minkernel\wdf\framework\shared\core\fxdevice.cpp @ 1402]
ffffd001d2209470 fffff8005cdb0044 : ffffcf818abf0cf0 0000000000000002 0000000000000000 fffff8005cdc5de6 : VerifierExt!xdv_IRP_MJ_PNP_wrapper+0xe0
ffffd001d22094d0 fffff8005c714252 : ffffcf818abf0cf0 ffffe00157a81940 ffffe00157a81940 ffffe00157919cb0 : nt!IovCallDriver+0x3d8
ffffd001d2209530 fffff8005cdcd97e : ffffcf818abf0cf0 ffffe00157a81940 ffffe00157a81940 0000000000000000 : nt!IofCallDriver+0x72
ffffd001d2209570 fffff8005cdb0044 : ffffe00157a81a90 ffffcf818abf0cf0 ffffe00157a81940 0000000000000002 : nt!ViFilterDispatchPnp+0x1a2
ffffd001d22095b0 fffff8005c714252 : ffffcf818abf0cf0 ffffd001d22096c0 ffffe00157a81940 ffffe0015788d010 : nt!IovCallDriver+0x3d8
ffffd001d2209610 fffff8005cb76b05 : 0000000000000000 ffffd001d22096c0 ffffe00157a81940 ffffe001572d5060 : nt!IofCallDriver+0x72
ffffd001d2209650 fffff8005cb7695c : 0000000000000000 ffffd001d22096e9 fffff8005c74d5e8 fffff8005c9dcd80 : nt!PnpAsynchronousCall+0xe5
ffffd001d2209690 fffff8005cb76721 : ffffe00157ae4850 ffffe00157ae4850 ffffe00155af8c70 ffffe00155af8c70 : nt!PnpQueryDeviceRelations+0x8c
ffffd001d2209750 fffff8005cad50b7 : ffffe001572eaa50 ffffe001572eaa50 0000000000000002 0000000000000000 : nt!PipEnumerateDevice+0xe9
ffffd001d22097d0 fffff8005cc1cf4f : 0000000000000000 0000000000000001 0000000000000000 fffff8005cad596e : nt!PipProcessDevNodeTree+0x19f
ffffd001d2209a50 fffff8005c74876a : 0000000100000003 0000000000000000 fffff8005c9be140 00000000009f72bc : nt!PiProcessStartSystemDevices+0x87
ffffd001d2209aa0 fffff8005c6fa7a9 : ffffe001572d6040 fffff8005c9be140 fffff8005ca5b340 ffffe00157201148 : nt!PnpDeviceActionWorker+0x436
ffffd001d2209b70 fffff8005c7676d8 : 03f893ff30244489 0000000000000080 fffff8005ca5b340 ffffe001572d6040 : nt!ExpWorkerThread+0xe9
ffffd001d2209c00 fffff8005c7d3d06 : fffff8005c9e5180 ffffe001572d6040 ffffe00155b19040 7208fb83c3ffd572 : nt!PspSystemThreadStartup+0x58
ffffd001d2209c60 0000000000000000 : ffffd001d220a000 ffffd001d2204000 0000000000000000 0000000000000000 : nt!KiStartSystemThread+0x16

STACK_COMMAND: kb

THREAD_SHA1_HASH_MOD_FUNC: de3d2b4db6b43a8b13e12ff1dfa3dab628435874

THREAD_SHA1_HASH_MOD_FUNC_OFFSET: fb4c50e6b867dfa21df2112f8299b28cf3f25204

THREAD_SHA1_HASH_MOD: 83b844ff1ca16382f4e1fbac2099ac154f144e47


running !ln at my address gives me
ln 0xFFFFF8005CDB6491
(fffff8005cdb6420) nt!IovpCompleteRequest4+0x71 | (fffff8005cdb6558) nt!IovpExamineDevObjForwarding


!pool ffffcf818abf0d32
Pool page ffffcf818abf0d32 region is Special pool
CompressedPageDataReader warning: failed to get _SM_PAGE_KEY symbol.
ffffcf818abf0000: Unable to get contents of special pool block


!pte ffffcf818abf0d32
VA ffffcf818abf0d32
PXE at FFFFF6FB7DBEDCF8 PPE at FFFFF6FB7DB9F030 PDE at FFFFF6FB73E062A8 PTE at FFFFF6E7C0C55F80
contains 0000000003D41863 contains 0000000003B40863 contains 0000000004ECF863 contains 78005C9C40000000
pfn 3d41 —DA–KWEV pfn 3b40 —DA–KWEV pfn 4ecf —DA–KWEV not valid
Page has been freed


So i am referencing a page that is freed?
And Finally here are the relevant parts of the code

NTSTATUS EvtDeviceAdd(In WDFDRIVER Driver, Inout PWDFDEVICE_INIT DeviceInit)
{

UCHAR minorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
PAGED_CODE();
WdfFdoInitSetFilter(DeviceInit);

status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit, &SetCompletionFunction, IRP_MJ_PNP, &minorFunction, 1);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, “preprocessor callback declaration failed\n”));
return status;
}
else
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, “After declarin preprocessor callback\n”));

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, “Device Creation failed\n”));
return status;
}
else
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, “After device creation\n”));

return status;
}

NTSTATUS
SetCompletionFunction(WDFDEVICE Device, PIRP Irp)
/*
This Function is invoked whenever the specific IRP is called
This function is responsible for setting the function to be called after completion of the specific IRP
*/
{

PAGED_CODE();

KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, “callback function started\n”));
pStackLocation = IoGetCurrentIrpStackLocation(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);

if (pStackLocation->Parameters.QueryDeviceRelations.Type == BusRelations) {
IoSetCompletionRoutine(Irp, &GetDeviceRelationPointer, NULL, TRUE, TRUE, FALSE);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, “Inside callback function\n”));
}
status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
KdBreakPoint();
return status;
}

And finally the completin routine

NTSTATUS
GetDeviceRelationPointer(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{

if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}

else if (Irp->IoStatus.Status == STATUS_SUCCESS) {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// Get Device relation pointer here.
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}


I am really stumped here, I am probably doing something silly.
If anyone could help me out I would be really grateful.

Thanks in advance.

There is no logic in GetDeviceRelationPointer which is an IRP completion routine.

  • You should not return STATUS_PENDING from the completion routine as it doesn’t make sense.
  • You should not call IoCompleteRequest in the completion routine if STATUS_MORE_PROCESSING_REQUIRED is not returned. What you are doing results in a double Irp completion BSOD.

Completion routine should return STATUS_SUCCESS or STATUS_MORE_PROCESSING_REQUIRED.

There is no need to do this in completion routine.
On completion Irp->IoStatus.Information for IRP_MN_QUERY_DEVICE_RELATIONS contains a pointer to an allocated DEVICE_RELATIONS structure with PDOs. You must not set it to NULL.

You musn’t complete in the completion handler based on how you have things
setup. It is handled automagically. Just return STATUS_SUCCESS.

On Tue, Aug 1, 2017 at 1:46 PM xxxxx@hotmail.com
wrote:

>


>
> There is no need to do this in completion routine.
> On completion Irp->IoStatus.Information for IRP_MN_QUERY_DEVICE_RELATIONS
> contains a pointer to an allocated DEVICE_RELATIONS structure with PDOs.
> You must not set it to NULL.
>
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

Also, PAGED_CODE() in completion handler will BSOD. Completion handlers are
called at a raised IRQL, not PASSIVE level.

On Tue, Aug 1, 2017 at 2:32 PM Jamey Kirby wrote:

> You musn’t complete in the completion handler based on how you have things
> setup. It is handled automagically. Just return STATUS_SUCCESS.
>
>
> On Tue, Aug 1, 2017 at 1:46 PM xxxxx@hotmail.com
> wrote:
>
>>


>>
>> There is no need to do this in completion routine.
>> On completion Irp->IoStatus.Information for IRP_MN_QUERY_DEVICE_RELATIONS
>> contains a pointer to an allocated DEVICE_RELATIONS structure with PDOs.
>> You must not set it to NULL.
>>
>>
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> Visit the list online at: <
>> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>>
>> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
>> software drivers!
>> Details at http:
>>
>> To unsubscribe, visit the List Server section of OSR Online at <
>> http://www.osronline.com/page.cfm?name=ListServer&gt;
>>
></http:>

Thanks guys, that was mighty stupid of me.

I have one more question though, now after I get the pointer to the device relations structure in the completion routine I want to print the device VID/PIDs onto my debugger but I dont want to do the further processing at dispatch_level.

Is there any way to specify functions to by called after completion function which will not run at dispatch_level?

Huh, the pointer I’m getting from Irp->Iostatus.Infomation in STATUS_SUCESS seems to be a NULL pointer.

You do not need to do this in completion. IRP_MN_QUERY_DEVICE_RELATIONS is sent at PASSIVE_LEVEL so you can synchronize completion with the dispatch routine and process PDOs after WdfDeviceWdmDispatchPreprocessedIrp.

{
status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
if( STATUS_PENDING == status ){
// synchronize with completion
KeWaitForSingleObject(Event);
status = Irp->IoStatus.Status;
}

// process Irp->IoStatus.Information

// continue completion
IoCompleteRequest( Irp );
return status;
}

In the completion routine always return STATUS_MORE_PROCESSING_REQUIRED and set the synchronization event in a signal state.

Nothing to report for this relation type ( see DEVICE_RELATION_TYPE ). The same as DEVICE_RELATIONS.Count == 0 .

Irp->Iostatus.Infomation is a ULONG_PTR. 99.99999% of the time, it
represents a value, not a pointer. It should contain the number of bytes
returned from the operation. a NULL means zero bytes returned.

On Wed, Aug 2, 2017 at 7:22 AM xxxxx@hotmail.com
wrote:

>


>
> Nothing to report for this relation type ( see DEVICE_RELATION_TYPE ). The
> same as DEVICE_RELATIONS.Count == 0 .
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

xxxxx@gmail.com xxxxx@lists.osr.com wrote:

I have one more question though, now after I get the pointer to the device relations structure in the completion routine I want to print the device VID/PIDs onto my debugger but I dont want to do the further processing at dispatch_level.

How do you intend to do that? There are several way, each with their
own problems. Do you intend to fetch the hardware IDs and reverse
engineer them? Or do you expect to fetch the device descriptors?

I would also point out that if all you want is to monitor the comings
and goings of all of the USB devices, that can be done easily in user
mode, no driver required.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi guys thanks for all your help.

Tim,
What I was planning to do was to intercept all the read/write irp callbacks for the usb storage media.
Now after reading around I realize that a driver between DISK and USBSTOR would be a way to go about this.

Anyways , Thank you all for your help I realize now that I should really read a book before diving into all this