A general object-also called a base object-is a driver-defined object that supports a reference count, an object context area, a parent object, and an object deletion callback. A driver can use a general object to take advantage of the framework's object parenting and callback model for data that is not supported by any particular WDF object type and does not belong in the context area of another object.
For example, a KMDF driver can use a general object to manage the lifetime of a resource that is shared by several work items, DPCs, or other asynchronous units of execution. The driver creates a general object that has a context area and an EvtDestroyCallback, allocates the resource, and stores a pointer to the resource in the context area. Each time the driver spawns an asynchronous execution unit, the driver takes out a reference on the object on behalf of the execution unit. Each execution unit drops the reference when it has finished using the resource. After the driver has spawned the last execution unit, the driver can delete the general object. The object persists until the last execution unit has dropped its reference. At that point, the framework calls the EvtDestroyCallback, which frees the resource.
Both UMDF drivers and KMDF drivers can create general objects.
To create a general object, a UMDF driver creates a callback object that has driver-specific functionality and then calls IWDFDriver::CreateWdfObject to create a corresponding framework object. The driver passes the following three parameters:
pCallbackInterface
A pointer to the callback object's IUnknown interface.
pParentObject
A pointer to the IWDFObject interface for the parent object, or NULL to accept the driver object as the default.
ppWdfObject
A location to receive a pointer to the IWDFObject interface for the newly created framework object.
The framework uses the IUnknown pointer to query for the IObjectCleanup interface on the callback object. If the driver implements an IObjectCleanup interface, the framework calls the OnCleanup method to notify the driver when the object is about to be destroyed.
The driver can associate a context area with the framework object or supply a different IObjectCleanup interface by using the IWDFObject::AssignContext method.
The example in Listing 12-7 shows how a UMDF driver creates a general object that has the driver object as its parent.
Listing 12-7: Creating a general object in a UMDF driver
myObject = new CMyObject(); if (NULL == myObject){ return E_OUTOFMEMORY; } hr = this->QueryInterface(__uuidof(IUnknown), (void **)unknown); hr = pWdfDriver->CreateWdfObject( unknown, NULL, &fxWdfObject); unknown->Release(); fxWdfobject->Release()
First, the driver queries for the IUnknown pointer. It then calls CreateWdfObject, passing the IUnknown pointer, a NULL pointer to accept the driver object as the default parent object, and a pointer to a variable that receives the address of the IWDFObject interface for the created framework object.
A KMDF driver creates a general object by calling WdfObjectCreate, as listing 12-8 shows.
Listing 12-8: Creating a general object in a KMDF driver
WDF_OBJECT_ATTRIBUTES attributes; WDFOBJECT myObject; . . .//Code omitted WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.EvtCleanupCallback = MyEvtCleanupCallback; status = WdfObjectCreate(&attributes, &myObject);
The driver declares variables for the attributes structure and the object. It initializes the attributes structure, registers a cleanup callback in the structure, and then calls WdfObjectCreate to create the object. Upon return from this call, myObject holds a handle to the newly created object. The framework will call the cleanup callback before it deletes the object.
A KMDF driver can set the passive-level execution constraint in the object attributes structure for a general object. This constraint causes the framework to invoke the driver's EvtCleanupCallback and EvtDestroyCallback functions at IRQL PASSIVE_LEVEL. This setting can be useful if the driver must wait for asynchronous operations to complete before cleaning up the object.
Chapter 10, "Synchronization," discusses execution level in KMDF drivers.