1. Driver Callback Interfaces
The driver implements
callback interfaces to provide device-specific responses to events. Each
callback interface is implemented on a specific object type. For
example, Plug and Play callback interface (IPnpCallback, IPnpCallbackHardware, and IPnpCallbackSelfManagedIo) are implemented for device objects, and I/O queue callback interfaces (IQueueCallbackCreate, IQueueCallbackRead, and so forth) are implemented on I/O queue objects.
When a Plug and Play,
power management, or I/O request arrives, UMDF calls methods in the
driver’s callback interfaces to handle the associated events. For
example, when UMDF receives a read request, it calls methods in the
driver’s IQueueCallbackRead interface.
A driver implements
callback interfaces only for the events that are important to its
operation. When the event occurs for an object, the framework invokes
the callback for that object. For example, the unexpected removal of a
device is a Plug and Play event. If a device can be removed
unexpectedly, its driver should implement the IPnpCallback interface (which includes the OnSurpriseRemoval
method) to perform device-specific operations upon ejection. When the
Plug and Play manager sends a surprise-removal notification for the
device, UMDF calls the OnSurpriseRemoval method with a pointer to the IWDFDevice interface for the device that has been removed.
For most events, a driver
can either provide a callback interface or allow UMDF to perform a
default action in response. For a few events, however, a driver-specific
callback is required. For example, adding a device is an event for which every Plug and Play driver must include a callback. The driver object’s IDriverEntry::OnDeviceAdd callback creates the device object.
The names of the driver-implemented callback interfaces are generally in the form IObjectAction, where Object identifies the object to which the interface applies and Action indicates what the interface does. For example, the IQueueCallbackRead interface is implemented for I/O queues and contains methods called when a queue receives a read request.
Table 1 lists the possible callback interfaces a driver might implement.
Table 1. Driver Callback Objects and Interfaces
Type of Object | Callback Interfaces | Description |
---|
Base object, or any object that inherits from the base object type | IObjectCleanup | Provides process that is required before an object is deleted, typically releasing any references held on the object. |
Driver | IDriverEntry | Provides main entry point and methods to initialize the driver and add its devices. |
Device | IPnpCallback | Handles device stop, removal, and power state changes. |
| IPnpCallbackHardware | Provides hardware-related operations before device power-up and after device power-down. |
| IPnpCallbackSelfManagedIo | Provides driver, rather than framework, control over I/O operations at specific Plug and Play and power management states. |
| IFileCallbackCleanup | Handles clean-up requests for file objects on a specific device. |
| IFileCallbackClose | Handles close requests for file objects on a specific device. |
I/O queue | IQueueCallbackCreate | Handles file create requests. |
| IQueueCallbackDefaultIoHandler | Handles create, device I/O control, read, and write requests for which no other interface has been implemented. |
| IQueueCallbackDeviceIoControl | Handles device I/O control requests. |
| IQueueCallbackIoResume | Resumes processing an I/O request after its queue has been stopped. |
| IQueueCallbackIoStop | Stops processing an I/O request because its queue is stopping. |
| IQueueCallbackRead | Handles read requests. |
| IQueueCallbackWrite | Handles write requests. |
I/O request | IImpersonateCallback | Provides impersonation for certain Win32 I/O operations. |
| IRequestCallbackCancel | Handles cancellation of an I/O request. |
| IRequestCallbackRequestCompletion | Handles completion of an I/O request. |
2. UMDF Driver Features
UMDF drivers can call methods in the framework and can use the Win32 API and other Windows user mode features.
Every UMDF driver must do the following:
Support the DllGetClassObject export that is required by COM.
Implement the IClassFactory interface to create a driver object.
Implement the IDriverEntry interface on the driver class.
UMDF drivers are implemented as in-process COM servers. The COM run-time environment requires the DLL export DllGetClassObject, which must return an IClassFactory interface so that UMDF can create the driver callback object.
The IDriverEntry
interface includes methods that initialize and uninitialize the driver
and perform other required tasks when the device is added to the system.
UMDF calls these methods when the driver is loaded or unloaded and when the Plug and Play manager enumerates one of the driver’s devices. Every UMDF driver must implement the IDriverEntry interface on the driver class.
2.1. Impersonation
UMDF drivers run in
the LocalService security context. The LocalService context has minimum
security privileges on the local computer and presents anonymous
credentials on the network.
When necessary, a UMDF
driver can impersonate the client process to handle I/O requests, but
not Plug and Play, power, or other system requests. At driver
installation, the INF file specifies the maximum impersonation level that the driver can use.
When an application calls the CreateFile
function, it can specify the impersonation level for the driver. The
impersonation level determines the operations that the driver can
perform in the context of the application process. If the level that the
application specifies is different from the minimum that the INF provides, the reflector uses the lower of the two levels.
A driver requests impersonation by calling the IWDFIoRequest::Impersonate method with the required impersonation level and a pointer to the driver’s IImpersonateCallback interface. The IImpersonateCallback interface includes one method, OnImpersonation, which should implement the code that must be run during impersonation. To prevent security leaks, OnImpersonation
should perform only the tasks that require impersonation and should not
call any other framework methods. Properly handling impersonation is
key to writing a secure driver.
2.2. Device Property Store
The device property store is an
area in the registry where a UMDF driver can maintain information about
the properties of its device. A UMDF driver can create a device property
store (or retrieve an existing property store) during initialization by
calling the IWDFDeviceInitialize::RetrieveDevicePropertyStore method. This method returns a pointer to the IWDFNamedPropertyStore interface, through which the driver can set and get the values of device properties.
The
format and contents of the property store is driver defined. The
property store persists in the registry until the device is uninstalled
from the system.