The WDF object model defines a set of objects that represent common driver abstractions, such as a device, an I/O request, or a queue. Regardless of driver model, nearly every driver works with these same abstractions as either data structures or as internal patterns that the driver itself implements. In a WDM driver, for example, the IRP data structure represents an I/O operation and the driver manipulates the structure by using a combination of direct access and calls to the Windows I/O manager DDI. Likewise, WDM drivers create internal queues for managing the flow of I/O requests.
WDF differs from WDM and other driver models by defining formal objects to represent these data structures and patterns. A WDF I/O request object represents an I/O request, and a WDF I/O queue object represents a queue. WDF drivers interact with these objects only through the framework DDI.
All WDF objects have a basic set of properties and conform to consistent rules for lifetime management, context management, callback patterns, and object hierarchy. In the WDF object model:
Objects work as building blocks and are opaque to the driver.
A driver modifies these objects through well-defined interfaces.
Objects have methods, properties, and events.
The framework defines default behavior for each event. To support device-specific behavior, the driver includes event callbacks that override the defaults.
Objects are organized hierarchically and have well-defined life cycles.
Each object is deleted when its parent is deleted.
Any object can have a context area, where the driver stores information that it requires to service the object.
The format and contents of the context area are completely driver defined.
Drivers interact with WDF objects through methods (functions), properties (data), and object-specific events, for which drivers can provide event callbacks. Specifically:
Methods Perform actions on the object.
Properties Describe characteristics of the object. Each property is associated with methods that get and, if relevant, set the value of the property. Some properties can be read and written without failure, but other properties can sometimes fail. Functions with Set and Get in their names read and write fields without failure. Functions with Assign and Retrieve in their names can fail and return a status value.
Events Are messages that indicate that something has occurred for which a driver might be required to take action. Drivers can register callbacks for particular events that are important to their drivers. The framework invokes these callbacks and takes default actions for all other events.
We thought a great deal about method naming, and properties are a spot where we had to go back and forth a lot. For a while we considered having property functions validate the object handles and return errors when passed an invalid object. But that leads to either untested error handlers or ignored error codes.
We eventually had to split the properties into two groups-properties that can always be gotten or set, and those that cannot. We chose different names so that someone learning the interfaces can easily remember when they do or do not need to check the return value. Get and Set always work (assuming you provide valid input). Assign and Retrieve require that you check the return code.
-Peter Wieland, Windows Driver Foundation Team, Microsoft
Event callbacks provide device-specific and driver-specific responses to events. Each event callback is implemented for a specific object type. For example, device objects support Plug and Play events, and a driver can "register" for these events when it creates the device object. A driver-specific callback is required for a few events, such as the addition of a new device.
Event callbacks are triggered in the same way in both UMDF and KMDF, but UMDF and KMDF drivers implement and register them differently:
UMDF A UMDF driver creates and associates a callback object with each framework object. The callback object implements one or more callback interfaces. The framework defines the possible callback interfaces and uses the COM QueryInterface method to determine which interfaces the driver implements for a particular callback object.
KMDF A KMDF driver supports an event callback by implementing a callback function and supplying a pointer to the function when it initializes the corresponding object, typically in an object-specific configuration structure.
Thus, KMDF event callbacks are entries in a function table whereas UMDF driver callback functions are methods in an interface that is implemented on a callback object.
When the event occurs, the framework invokes the callback. For example, the unexpected removal of a device is a Plug and Play event. If a device can be removed unexpectedly, its driver can implement a callback for the surprise-remove event to perform any necessary operations. When the PnP manager sends a surprise-removal notification for the device, the framework calls the driver's surprise-remove event callback.
The WDF object model specifies a set of attributes that commonly apply to objects. The driver supplies values for the attributes-or accepts the framework's defaults-at object creation.
The following attributes can apply to both UMDF and KMDF objects:
The object that is the parent of the object.
The synchronization scope for certain I/O event callbacks.
An object context area.
A callback to release references before object deletion.
UMDF UMDF drivers specify attribute values as individual parameters in the pertinent object creation methods.
KMDF KMDF drivers supply attribute values in a separately initialized structure that is a parameter to every object creation method. The following additional attributes apply to some types of KMDF objects:
The maximum IRQL at which the framework invokes certain event callbacks.
Information about the context area, including its size and type.
A callback to free resources when the object is destroyed.
WDF objects are organized hierarchically. Except for the WDF driver object, every object has a parent, which is the next higher object in the hierarchy. The WDF driver object is the root object-all other objects are subordinate to it. For some object types, a driver can specify the parent when it creates the object. Other object types, however, have predefined parents that cannot be changed.
The WDF object model was designed so that drivers could rely on the frameworks to manage object lifetime, object cleanup, and object state with a minimum of required driver code. By setting the parent/child relationships appropriately, a driver can usually avoid taking out explicit references on related objects or explicitly deleting objects, and it can instead rely on the object hierarchy and the associated callbacks to delete the object at the appropriate time.
A key feature of the WDF object model is the object context area. The object context area is a driver-defined storage area for data that the driver uses with a particular object:
UMDF drivers typically store context data with the callback object.
KMDF drivers can create a context area that is part of the framework's object.
The driver determines the size and layout of the object context area. For example, a driver might create a context area for an I/O request that it receives from the framework and store a driver-allocated event that is used with the request in the context area.