Object Creation


Within each framework, drivers follow these consistent patterns to create objects:

  •  UMDF  UMDF drivers create a callback object, if required, and then call a method to create the corresponding framework object.

  •  KMDF  KMDF drivers initialize an object attributes structure and an object configuration structure and then call a method to create the object.

UMDF Object Creation

UMDF provides object-specific creation methods for device, file, I/O request, memory, and queue objects. To create a framework object, a UMDF driver:

  1. Allocates a new instance of the corresponding callback object, if the driver supports event callbacks for the framework object.

  2. Creates the corresponding framework object and associates it with the callback object.

UMDF drivers allocate a callback object and then create a corresponding framework object by calling a CreateObject method, where Object indicates a UMDF-defined object type, such as Device. The CreateObject methods are supported by interfaces that the default parent framework objects expose. The creation methods require a pointer to the callback object's IUnknown interface so that the framework can determine which callback interfaces the callback object supports.

The example in Listing 5-1 shows how the Fx2_Driver creates a queue object. This example is based on code in the ControlQueue.cpp file.

Listing 5-1: Creating callback and framework objects in a UMDF driver

image from book
 queue = new CMyControlQueue(Device);  . . . //Code omitted IUnknown *callback = QueryIUnknown(); hr = m_Device->GetFxDevice()->CreateIoQueue( callback,                                              Default,                                              DispatchType,                                              PowerManaged,                                              FALSE,                                              &fxQueue                                              ); callback->Release(); if (FAILED(hr))  {     . . . //Error handling omitted;     } fxQueue->Release(); 
image from book

The listing shows the basic pattern that a UMDF driver follows to create a callback object and an associated framework object. First the driver uses the new operator to create the callback object, and then retrieves an interface pointer for the queue callback object. To create the framework queue object, the driver calls IWDFDevice::CreateIoQueue, passing the callback object interface pointer, four queue-specific parameters, and a pointer to a variable that receives the address of the IWDFIoQueue interface for the created framework object.

The driver then releases the reference that QueryIUnknown took on the IUnknown interface because the framework's device object keeps a reference on it. Assuming that object creation succeeded, the driver also releases the reference that CreateIoQueue took on the fxQueue object. The framework's object tree maintains a reference on this object, so the driver does not require an additional reference.

KMDF Object Creation

To create a KMDF object, a driver:

  1. Initializes the configuration structure for the object, if one exists.

  2. Initializes the attributes structure for the object, if necessary.

  3. Calls an object creation method to create the object.

KMDF Object Configuration Structure

KMDF defines configuration structures named WDF_Object_CONFIG for most objects. The object configuration structure holds pointers to object-specific information, such as the driver's event callback functions for the object. The driver fills in this structure and then passes it to the framework when it calls the object creation method. The framework uses the information from the configuration structure to initialize the object. For example, the WDFDRIVER object requires a pointer to the driver's EvtDriverDeviceAdd callback function, which KMDF invokes when a Plug and Play add-device event occurs.

KMDF defines functions named WDF_Object_CONFIG_INIT to initialize the configuration structures, where Object represents the name of the object type. Not all object types have configuration structures or the corresponding initialization functions.

KMDF Object Attributes Structure

Every KMDF object has a set of attributes, which are listed in Table 5-4. When a KMDF driver creates an object, the driver passes a pointer to an attributes structure that supplies values for the object's attributes. Not all attributes apply to all objects.

Table 5-4: KMDF Object Attributes
Open table as spreadsheet

Field

Description

ContextSizeOverride

Size of the context area, which overrides the value in ContextTypeInfo>ContextSize. This field is useful for context areas that have variable sizes.

ContextTypeInfo

Pointer to the type information for the object context area.

EvtCleanupCallback

Pointer to a callback routine that is invoked to clean up the object before it is deleted. The object might still have references.

EvtDestroyCallback

Pointer to a callback routine that is invoked when the reference count reaches zero for an object that is marked for deletion.

ExecutionLevel

Maximum IRQL at which KMDF can invoke certain object callbacks.

ParentObject

Handle for the object's parent.

Size

Size of the structure in bytes.

SynchronizationScope

Level at which certain callbacks for this object are synchronized. This field applies only to driver, device, and file objects.

A driver supplies attributes in a WDF_OBJECT_ATTRIBUTES structure. KMDF defines the following functions and macros for use in initializing this structure:

  • WDF_OBJECT_ATTRIBUTES_INIT

  • WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE

  • WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE

The WDF_OBJECT_ATTRIBUTES_INIT function sets values for synchronization and execution level, which determine which of the driver's callbacks KMDF invokes concurrently and the highest IRQL at which they can be called. By default, both of these attributes are set to match those of the parent object. The two context-type initialization macros set information about the object's context area, which is described in "Object Context Areas" later in this chapter.

Although attributes can apply to any type of object, the defaults are typically acceptable for most objects. To accept the defaults, a driver specifies WDF_NO_OBJECT_ATTRIBUTES, which WDF defines as NULL. However, if the driver defines a context area for an object, it must also specify attributes, because the attributes structure includes the size and type of the context area.

KMDF Object Creation Methods

After initializing the configuration and attributes structures, the driver creates the object by calling the WdfObjectCreate method, where Object indicates the type of object.

The creation method returns a handle for the created object. The driver subsequently uses the handle to refer to the object. Internally, the creation methods:

  • Allocate memory from nonpaged pool for the object and its context areas.

  • Initialize the object's attributes with default values and the driver's specifications-if any.

  • Zero the object's context areas.

  • Configure the object by storing pointers to its event callbacks and setting other object-specific characteristics.

If object initialization fails, the framework deletes the object.

Listing 5-2 shows how to create an object in a KMDF driver. This example is from the Device.c source file in the Osrusbfx2 driver.

Listing 5-2: Creating an object in a KMDF driver

image from book
 NTSTATUS                       status = STATUS_SUCCESS; WDFDEVICE                      device; WDF_IO_QUEUE_CONFIG            ioQueueConfig; WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoRead = OsrFxEvtIoRead; ioQueueConfig.EvtIoStop = OsrFxEvtIoStop; status = WdfIoQueueCreate( device,                            &ioQueueConfig,                            WDF_NO_OBJECT_ATTRIBUTES,                            &queue // queue handle                          ); if (!NT_SUCCESS (status)) {     . . . //Error handling omitted } 
image from book

The listing shows how the Osrusbfx2 driver creates a queue object. The following discussion focuses on the basic patterns and omits the queue-specific details.

The driver initializes a queue object configuration structure by calling WDF_IO_QUEUE_CONFIG_INIT, passing a pointer to the structure and a queue-specific parameter that describes how the queue dispatches requests. Next, the driver registers event callbacks for the queue object in two additional fields of the configuration structure. For this particular queue object, the driver does not change the default parent or set any other object attributes, so it is unnecessary to initialize an object attributes structure.

Finally, the driver calls WdfIoQueueCreate to create the queue object. It passes the following four parameters:

  • A handle to the framework device object with which the queue is associated.

  • A pointer to the initialized queue configuration structure.

  • The WDF_NO_OBJECT_ATTRIBUTES constant to accept the default attributes.

  • A location in which the method returns a handle for the queue.

Tip 

Chapter 24, "Static Driver Verifier," describes how to annotate your driver's callback functions so that SDV can analyze compliance with KMDF rules that specify that the driver always calls DDIs for device object initialization before it creates the device object.




Developing Drivers with the Microsoft Windows Driver Foundation
Developing Drivers with the Windows Driver Foundation (Pro Developer)
ISBN: 0735623740
EAN: 2147483647
Year: 2007
Pages: 224

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net