[Applies to KMDF and UMDF]

A driver's EvtCleanupCallback event callback function removes the driver's references on an object so that the object can be deleted.



VOID EvtCleanupCallback(
  _In_ WDFOBJECT Object
{ ... }


Object [in]

A handle to a framework object.

Return value



The driver can specify an EvtCleanupCallback callback function in a WDF_OBJECT_ATTRIBUTES structure. This structure is used as input to all of the framework methods that create framework objects, such as WdfDeviceCreate.

The framework calls the callback function when either the framework or a driver attempts to delete the object.

If the driver has called WdfObjectReference to increase the reference count of an object, the driver must provide an EvtCleanupCallback callback function that calls WdfObjectDereference. This call ensures that the object's reference count is decremented to zero and, as a result, the framework can call the driver's EvtDestroyCallback callback function and then delete the object.

If a driver supplies both an EvtCleanupCallback callback function and an EvtDestroyCallback callback function for a object, the framework calls the EvtCleanupCallback callback function first.

After the framework calls an object's EvtCleanupCallback callback function, the driver can access the object only from its EvtDestroyCallback callback function. However, a driver should not attempt to call methods on an object from its EvtDestroyCallback.

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.

Typically, if your driver does not call WdfObjectReference for an object, the object's EvtCleanupCallback callback function can deallocate object context allocations. In this case, the driver does not need an EvtDestroyCallback callback function for the object.

When an object is deleted, the framework also deletes the object's children. With one exception, the framework calls the EvtCleanupCallback routines of child objects before calling those of their parent objects, so drivers are guaranteed that the parent object still exists when a child's EvtCleanupCallback routine runs.

The exception to this guaranteed ordering applies to I/O requests that the driver completes at DISPATCH_LEVEL. If such an I/O request object has one or more children whose EvtCleanupCallback routines must be called at PASSIVE_LEVEL, the parent request might be deleted before one or more of its children. An object requires cleanup at PASSIVE_LEVEL if it must wait for something to complete or if it accesses paged memory.

If the driver attempts to delete such an object (or the parent of such an object) while it is running at DISPATCH_LEVEL, the framework queues the EvtCleanupCallback to a work item for later processing at PASSIVE_LEVEL and then calls the cleanup callback for the parent object without determining whether the callbacks for the children have run.

To avoid any problems that might result from this behavior, drivers should not set the request object as the parent for any object that requires cleanup at PASSIVE_LEVEL. By default, the parent for most objects is WDFDEVICE, so drivers should just accept the default. Generally, if the WDFDEVICE object is passed as a parameter (either directly or as part of a structure) to the method that creates the object, the WDFDEVICE is the default parent. For a complete list of default parents, see Summary of Framework Objects.

If the above exception does not apply, the framework calls the child object's EvtCleanupCallback callback functions before calling the parent object's EvtCleanupCallback callback function. Next, if the child's reference count is zero, the framework calls the child object's EvtDestroyCallback callback function. Finally, if the parent's reference count is zero, the framework calls the parent object's EvtDestroyCallback callback function.

For more information about deleting framework objects, see Framework Object Life Cycle.

Typically, the framework calls the EvtCleanupCallback callback function at IRQL <= DISPATCH_LEVEL. However, the framework calls the callback function at IRQL = PASSIVE_LEVEL in the following situations:


  • The object's handle type is WDFMEMORY or WDFLOOKASIDE, and the driver has specified PagedPool for the PoolType parameter to WdfMemoryCreate or WdfLookasideListCreate.

When a work-item object is deleted, either explicitly or because the work item's parent object is being deleted, then before calling the work item's EvtCleanupCallback callback function, the framework waits until all instances of the work item's EvtWorkItem callback function have returned. For more information, see WdfWorkItemEnqueue.

Similarly, when a timer object is deleted, either explicitly or because the timer's parent object is being deleted, then before calling the timer's EvtCleanupCallback callback function, the framework waits until all instances of the timer's EvtTimerFunc event callback function have returned.

Beginning with version 1.9 of the framework, the wdfroletypes.h header file contains some alternative, object type-specific, function types for the EvtCleanupCallback callback function. These alternative types help verification tools to determine whether the driver is properly using the callback function. Use the following table to determine which function type to use.

Object TypeFunction Type

Device object


I/O queue object


File object


All other objects




To define an EvtCleanupCallback callback function, you must first provide a function declaration that identifies the type of callback function you’re defining. Windows provides a set of callback function types for drivers. Declaring a function using the callback function types helps Code Analysis for Drivers, Static Driver Verifier (SDV), and other verification tools find errors, and it’s a requirement for writing drivers for the Windows operating system.

For example, to define an EvtCleanupCallback callback function that is named MyCleanupCallback, use the EVT_WDF_OBJECT_CONTEXT_CLEANUP type as shown in this code example:


Then, implement your callback function as follows:

 MyCleanupCallback (

The EVT_WDF_OBJECT_CONTEXT_CLEANUP function type is defined in the Wdfobject.h header file. To more accurately identify errors when you run the code analysis tools, be sure to add the _Use_decl_annotations_ annotation to your function definition. The _Use_decl_annotations_ annotation ensures that the annotations that are applied to the EVT_WDF_OBJECT_CONTEXT_CLEANUP function type in the header file are used. For more information about the requirements for function declarations, see Declaring Functions by Using Function Role Types for KMDF Drivers. For information about _Use_decl_annotations_, see Annotating Function Behavior.


Target platform


Minimum KMDF version


Minimum UMDF version



Wdfobject.h (include Wdf.h)


See Remarks section.

See also




Send comments about this topic to Microsoft