Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results
The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.
Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/
I am looking at the documentation for WdfObjectDelete
, which says:
The WdfObjectDelete method must be called at IRQL <= DISPATCH_LEVEL. If your driver is deleting a control device object, WdfObjectDelete must be called at IRQL = PASSIVE_LEVEL. Similarly, if your driver is deleting a common buffer, WdfObjectDelete must be called at IRQL = PASSIVE_LEVEL.
I am wondering what a common buffer is?
Is there any thing I need to keep in mind when calling WdfObjectDelete
with memory received by WdfUsbTargetDeviceCreateIsochUrb
?
I am experiencing some issues (stack trace below) when WdfObjectDelete
is called in my EvtDestroyCallback
. The object that I pass to WdfObjectDelete
is memory received in WdfUsbTargetDeviceCreateIsochUrb
.
00 fffffb89`bed69748 fffff805`2bb162f2 nt!DbgBreakPointWithStatus 01 fffffb89`bed69750 fffff805`2bb158d6 nt!KiBugCheckDebugBreak+0x12 02 fffffb89`bed697b0 fffff805`2b9fbda7 nt!KeBugCheck2+0x946 03 fffffb89`bed69ec0 fffff805`2ba17dab nt!KeBugCheckEx+0x107 04 fffffb89`bed69f00 fffff805`2b9cfbc2 nt!PspSystemThreadStartup$filt$0+0x44 05 fffffb89`bed69f40 fffff805`2ba06392 nt!_C_specific_handler+0xa2 06 fffffb89`bed69fb0 fffff805`2b8e58c7 nt!RtlpExecuteHandlerForException+0x12 07 fffffb89`bed69fe0 fffff805`2b8e7896 nt!RtlDispatchException+0x297 08 fffffb89`bed6a700 fffff805`2ba0fe6c nt!KiDispatchException+0x186 09 fffffb89`bed6adc0 fffff805`2ba0b45a nt!KiExceptionDispatch+0x12c 0a fffffb89`bed6afa0 fffff805`2f643f74 nt!KiGeneralProtectionFault+0x31a 0b fffffb89`bed6b130 fffff805`2f643eee Wdf01000!FxObjectHandleGetPtrQI+0x40 [minkernel\wdf\framework\shared\object\handleapi.cpp @ 376] 0c (Inline Function) --------`-------- Wdf01000!FxObjectHandleGetPtr+0x39 [minkernel\wdf\framework\shared\inc\private\common\fxhandle.h @ 345] 0d (Inline Function) --------`-------- Wdf01000!FxObjectHandleGetPtrAndGlobals+0x39 [minkernel\wdf\framework\shared\inc\private\common\fxhandle.h @ 449] 0e fffffb89`bed6b1a0 fffff805`3eddeffe Wdf01000!imp_WdfObjectDelete+0x4e [minkernel\wdf\framework\shared\object\fxobjectapi.cpp @ 299]
Upcoming OSR Seminars | ||
---|---|---|
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead! | ||
Kernel Debugging | 13-17 May 2024 | Live, Online |
Developing Minifilters | 1-5 Apr 2024 | Live, Online |
Internals & Software Drivers | 11-15 Mar 2024 | Live, Online |
Writing WDF Drivers | 26 Feb - 1 Mar 2024 | Live, Online |
Comments
Bent from my phone.
________________________________
From: tuple_cat
Sent: Friday, June 16, 2023 7:16:42 AM
To: Doron_Holan
Subject: [NTDEV] When can I call WdfObjectDelete with memory received in WdfUsbTargetDeviceCreateIsochUrb
OSR https://na01.safelinks.protection.outlook.com/?url=https://community.osr.com/&data=05|01||da61efa1a34242b3faf508db6e745012|84df9e7fe9f640afb435aaaaaaaaaaaa|1|0|638225218058229565|Unknown|TWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0=|3000|||&sdata=uKO8c42ZdKYKZSpftxSbCPB7BBoqrLRzf44GjR+Oe+c=&reserved=0
tuple_cat Started a new discussion. When can I call WdfObjectDelete with memory received in WdfUsbTargetDeviceCreateIsochUrb
I am looking at the documentation for WdfObjectDelete, which says:
The WdfObjectDelete method must be called at IRQL <= DISPATCH_LEVEL. If your driver is deleting a control device object, WdfObjectDelete must be called at IRQL = PASSIVE_LEVEL. Similarly, if your driver is deleting a common buffer, WdfObjectDelete must be called at IRQL = PASSIVE_LEVEL.
I am wondering what a common buffer is?
Is there any thing I need to keep in mind when calling WdfObjectDelete with memory received by WdfUsbTargetDeviceCreateIsochUrb?
I am experiencing some issues (stack trace below) when WdfObjectDelete is called in my EvtDestroyCallback. The object that I pass to WdfObjectDelete is memory received in WdfUsbTargetDeviceCreateIsochUrb.
00 fffffb89`bed69748 fffff805`2bb162f2 nt!DbgBreakPointWithStatus
01 fffffb89`bed69750 fffff805`2bb158d6 nt!KiBugCheckDebugBreak+0x12
02 fffffb89`bed697b0 fffff805`2b9fbda7 nt!KeBugCheck2+0x946
03 fffffb89`bed69ec0 fffff805`2ba17dab nt!KeBugCheckEx+0x107
04 fffffb89`bed69f00 fffff805`2b9cfbc2 nt!PspSystemThreadStartup$filt$0+0x44
05 fffffb89`bed69f40 fffff805`2ba06392 nt!_C_specific_handler+0xa2
06 fffffb89`bed69fb0 fffff805`2b8e58c7 nt!RtlpExecuteHandlerForException+0x12
07 fffffb89`bed69fe0 fffff805`2b8e7896 nt!RtlDispatchException+0x297
08 fffffb89`bed6a700 fffff805`2ba0fe6c nt!KiDispatchException+0x186
09 fffffb89`bed6adc0 fffff805`2ba0b45a nt!KiExceptionDispatch+0x12c
0a fffffb89`bed6afa0 fffff805`2f643f74 nt!KiGeneralProtectionFault+0x31a
0b fffffb89`bed6b130 fffff805`2f643eee Wdf01000!FxObjectHandleGetPtrQI+0x40 [minkernel\wdf\framework\shared\object\handleapi.cpp @ 376]
0c (Inline Function) --------`-------- Wdf01000!FxObjectHandleGetPtr+0x39 [minkernel\wdf\framework\shared\inc\private\common\fxhandle.h @ 345]
0d (Inline Function) --------`-------- Wdf01000!FxObjectHandleGetPtrAndGlobals+0x39 [minkernel\wdf\framework\shared\inc\private\common\fxhandle.h @ 449]
0e fffffb89`bed6b1a0 fffff805`3eddeffe Wdf01000!imp_WdfObjectDelete+0x4e [minkernel\wdf\framework\shared\object\fxobjectapi.cpp @ 299]
That sentence raises huge alarm bells. Can you describe the exact circumstances here? If this is memory you received from some other source that you did not allocate, then you have no business deleting it.
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.
@Doron_Holan
I create the memory like this:
Maybe I need to set
WDF_OBJECT_ATTRIBUTES::ParentObject
toNULL
if I want to callWdfObjectDelete
withurbMemory
at a later stage. Is that correct?@Tim_Roberts
The memory that I pass to
WdfObjectDelete
is theurbMemory
in the above code. The documentation says "A pointer to a WDFMEMORY-typed location that receives a handle to a framework memory object".If I can get the parent oject correctly set, shouldn't I be able to delete this with
WdfObjectDelete
?You're right, that is all legitimate. So, backing up, where are you deleting this? Is it in a callback? ARE you at a raised IRQL?
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.
I am deleting in the
EvtDestroyCallback
for my USB device... so in the below stacktrace,USBDriverDeviceDestroy
is theEvtDestroyCallback
that I have specified in theWDF_OBJECT_ATTRIBUTES
passed toWdfDeviceCreate
.Reading about this it says that:
Typically, the framework calls the EvtDestroyCallback callback function at IRQL <= DISPATCH_LEVEL. However, the framework calls the callback function at IRQL = PASSIVE_LEVEL in the following situations:
... so the IRQL should be Passive level.
One stacktrace looks like this:
Why aren't you deleting this memory in the completion routine for the URB you submit? Is this memory you use over and over?
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.
As with almost all WDF objects where you don't specify the parent explicitly, the framework will parent the object to the most appropriate object. Usually the default parent is the first object (handle) passed in to the function. In this case, the WDFMEMORY/Urb will be parented to the WDFUSBDEVICE (the sample code on the doc page for WdfUsbTargetDeviceCreateIsochUrb explicitly sets the parent to WDFUSBDEVICE). So why is the delete call blowing up in EvtDestroy? it is too late with respect to the automatic cleanup. When WDFDEVICE is cleaned up, first all of its children will be cleaned up. WDFUSBDEVICE is one of the children. The tree walk is recursive, so when WDFUSBDEVICE is cleaned, all of its children (including the URB WDFMEMORY) are cleaned up. Once the tree is cleaned up, the tree is destroyed.
So either you trust WDF and let it auto cleanup the URB WDFMEMORY as WDF's object lifetime management matches how you use the URB (you reuse it repeatedly until the WDFDEVICE is removed) or delete it earlier in its lifetime based on a different usage pattern.
@Tim_Roberts Yes, I use the memory again.
@Doron_Holan Ok, thanks! Can the same thing be said about any object that is passed to
WdfObjectDelete
, i.e that the object should have it's parent set toNULL
.Or maybe I misunderstood you @Doron_Holan ... would it be fine to delete the memory in the destroy callback if I set the memorys parent to NULL?
I am beginning to think that that is not the case. Even if I set the memorys parent to NULL, I got another bug check with stack trace:
Ok, so there is no way to have no parent set for an object?
I am reading here:
When a driver creates an object, it sometimes allocates object-specific memory buffers and stores the buffer pointers in the object's context space. The driver's EvtCleanupCallback or EvtDestroyCallback callback function can deallocate these memory buffers.
My problem appears in the
EvtDestroyCallback
for a device (not for the drivers, which is mentioned in the above text). Is the above true only for memory that does not have a parent. For example memory that is allocated withExAllocatePoolZero
?@Doron_Holan Is it correct to say that no object that has the
WDFUSBDEVICE
as parent should be deleted in theEvtDestroyCallback
for theWDFUSBDEVICE
or theEvtDestroyCallback
of the parent of theWDFUSBDEVICE
?you are working on incomplete knowledge. Every object has a parent. If you don't specify a parent object, kmdf assigns the default. This will almost always root up to the WDFDEVICE, the ones that default to the WDFDRIVER as a parent do not have a KMDF parent handle in the WdfXxxCreate call (like WdfStringCreate).
So, again, I will ask the question: what is the usage lifetime of the isoch URB and the associated WDFMEMORY? if it is the lifetime of the parent WDFDEVICE you DO NOT NEEED TO MANUALLY DELETE THE WDFMEMORY, KMDF will delete the WDFMEMORY when it deletes the WDFDEVICE (which will delete the WDFUSBDEVICE which will delete the WDFMEMORY).
Memory allocated with ExAllocatePoolZero is not a KMDF object. KMDF has no idea it exists nor how to track it. There is no WDFMEMORY for it by default. You must manage this memory on its own and free it at the appropriate time. This is why WDFMEMORY exists, to provide you with a way for KMDF to manage the lifetime of the buffer on your driver's behalf and remove the need for your code to track it's lifetime.
I have a class named
AudioTransfer
. I pass the URB and the associatedWDFMEMORY
to this class. I also pass theWDFMEMORY
that is used as a data buffer, and also theWDFREQUEST
that is used to send the urb. This class is used to send audio data from and to the USB device.I create this class when a user mode app sends a certain message to the driver to start audio streaming. When the user mode app no longer want to receive data, then the user mode app can send another message, which will stop the streaming from the device.
The user mode app can configure the driver to ask the USB device for a different number of audio channels. This means that the data buffer that is used to send/receive data from the device needs to be changed to accomodate the new number of bytes that corresponds to the amount of audio channels that the user want to send/receive.
If the user mode app sends another message to start audio streaming, then the previous instance of the
AudioTransfer
is deleted, and I recreate a new one , corresponding to the amount of channels that the user mode app want to use. When theAudioTransfer
instance is deleted, thenWdfObjectDelete
is called with the urb memory, the wdfrequest and the wdf memory that holds the data buffers.I want to delete the old instance of
AudioTransfer
before I create a new one, otherwise the memory wont be given back until the USB device is disconnected.Does this describe the lifetime of the urb? please let me know if you want more info!
I'm thinking about if I should delete the
AudioTransfer
instance inUSBDriverEvtDeviceSelfManagedIoSuspend
instead, after I have made sure that no transfer is active to/from the device.WdfObjectDelete
needs to the called at Passive level andUSBDriverEvtDeviceSelfManagedIoSuspend
is called at passive level.Another solution could be to refactor so that I only replace the data buffer when the number of audio channels is changed, and then let KMDF delete all the objects when the
WDFDEVICE
goes out of scope.You can set the parent when you call WdfUsbTargetDeviceCreateIsochUrb. If you have already created the WDFREQUEST you will use, then just make that the parent of the URB memory. When the request is reclaimed, the URB will also be reclaimed.
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.
Great idea!
WdfRequestCreate
does not have a KMDF parent handle that one needs to pass so it will get the driver as parent as default.One thing that I still don't understand is why I don't get the bugcheck everytime I detach the USB device. The bug check appears very rarely (I have a programmable/automatable USB Hub that switches devices on and off, and it can run for days without this happening).
Would it be possible to add a check to Driver verifier that tells you if you call
WdfObjectDelete
on some object that has theWDFDEVICE
as parent, and that this call is coming from theEvtDestroyCallback
of theWDFDEVICE
.