The WDF object model defines a set of objects that represent common driver constructs such as devices, memory, queues, I/O requests, and the driver itself. Framework objects have well-defined life cycles and contracts, and a WDF driver interacts with them through well-defined interfaces. UMDF objects are implemented as COM objects, whereas KMDF objects are implemented as a combination of opaque "handles" and functions that operate on those handles. However, at a conceptual level, the WDF object models for KMDF and UMDF are similar.
Framework objects are created by both the framework and the client WDF driver. Whether the framework or the driver creates the object depends on the particular object and its intended use:
Objects such as the file object are created by the framework and passed to the WDF driver.
Objects such as the device object must be created by the WDF driver.
Objects such as I/O request or memory objects can be created by either the framework or the WDF driver, depending on the circumstances.
A framework object exposes a programming interface that consists of properties, methods, and events:
Properties Properties represent the characteristics of an object. Each property has an associated method that gets the property value and, if relevant, a separate method that sets the value.
Methods Methods perform actions on the object itself or direct the object to perform actions.
Events Events are object-related occurrences that the WDF driver can choose to respond to, such as the arrival of an I/O request or a change in power state.
To handle an event, a WDF driver implements a callback and registers it with the framework:
A UMDF driver implements COM-based callback objects, which expose callback interfaces to handle the events.
A KMDF driver implements callback functions.
Regardless of how they are implemented, both types of callbacks work in much the same way. Because the framework implements default handlers for all events, WDF drivers register callbacks only for those events that are relevant to their device. When an event occurs:
If a WDF driver has registered a callback for an event, the framework invokes the callback and the driver handles the event.
If a WDF driver has not registered a callback for an event, the framework invokes the default event handler and applies default processing.
Framework objects are organized in a hierarchy, which the frameworks use to manage issues such as object lifetime, object cleanup, and synchronization scope. For example, if an object has descendants, all descendants are deleted when the object is deleted. The hierarchy is not based on inheritance relationships between the various framework objects-it is based on the scope of the various objects and the order in which they must be destroyed. The hierarchy is defined as follows:
The framework driver object is the root of the hierarchy; all other objects are its descendants.
Some objects, such as queue objects, must always be children of the device object or of an object that is a descendant of the device object.
Some objects, such as memory objects, can have one of several parents.
Chapter 5, "WDF Object Model," discusses the WDF object model in detail.
Managing concurrent operations is an issue for most programs. WDF simplifies the issue by implementing several internal synchronization mechanisms. In particular, a driver can direct the framework to hold a lock when the framework invokes a callback. The WDF object hierarchy supports a feature called synchronization scope-also called the locking constraint-that allows the WDF driver to specify which object's lock should be acquired when the framework calls the driver's I/O event callbacks.
Chapter 10, "Synchronization," discusses synchronization issues in general and synchronization scope in particular.
If you're writing a KMDF driver, you should also be familiar with IRQLs and kernel-mode synchronization and locking mechanisms. Chapter 15, "Scheduling, Thread Context, and IRQL," discusses these issues.