KMDF Collection Objects


A collection object is a linked list of KMDF objects. The objects in the collection can all be of the same type or can be of various types. An object can be in more than one collection.

Collections are useful when a driver must keep track of several related objects, particularly if the objects do not require service in a predictable order. For example:

  • A driver that breaks a request to read or write a large amount of data into several smaller requests creates a collection that contains all of the smaller I/O requests for a large request.

  • A driver that handles requests for more than one device creates a collection of device objects.

  • A driver for a device that supports message-signaled interrupts creates a collection of interrupt objects, where each object represents one message.

Collection objects have several advantages over simple driver-implemented linked lists:

  • Every time a driver adds an item to the collection, KMDF increments the item's reference count, so that the item's handle remains valid as long as the item is in the collection.

  • KMDF implements all the list-tracking and management code, so that drivers are not required to store a link or index in each object's context area.

However, collection objects have one significant disadvantage compared with linked lists: adding an object to a collection can fail if insufficient memory is available. Your driver should always check for such errors. Generally, you should avoid using collection objects in critical paths that cannot tolerate failure.

Collection Methods

The KMDF collection object supports methods that add and delete items from the collection, return an item from the collection, and return the number of items in the collection. Table 12-6 lists the collection object methods.

Table 12-6: Collection Object Methods
Open table as spreadsheet

Method

Description

WdfCollectionAdd

Adds an object to a collection.

WdfCollectionCreate

Creates a collection object.

WdfCollectionGetCount

Returns the number of objects in the collection.

WdfCollectionGetFirstItem

Returns the handle of the first object in the collection.

WdfCollectionGetItem

Returns the handle of an object in the collection, given the index to the object in the collection.

WdfCollectionGetLastItem

Returns a handle for the last object in the collection.

WdfCollectionRemove

Removes an object from the collection, based on the object's handle.

WdfCollectionRemoveItem

Removes an object from the collection, based on the object's index in the collection.

KMDF does not provide any synchronization for the collection object, so if more than one driver function can simultaneously access the collection, the driver must create and acquire its own lock for the collection object.

The objects in the collection are indexed starting at zero, and a driver can retrieve or remove an object by specifying the index. A driver can also remove an object by supplying a handle to the object. When the framework removes an object from the collection, the framework adjusts the indices. For example, if a driver removes the nth object from the collection, object n+1 becomes object n and so forth.

The framework increments the object's reference count when a driver adds the object to a collection and decrements the reference count when a driver removes the object from the collection.

Example: Creating and Using a Collection

The Toastmon driver uses a collection to store information about the Toaster devices attached to the system. Each time a Toaster device interface arrives, the driver creates a corresponding I/O target object and adds it to a collection of Toaster I/O targets. Each time a Toaster device interface is removed, the driver removes it from the collection. More than one driver function accesses the collection, so the driver creates a WDF wait lock to serialize access. The driver never accesses the collection at IRQL DISPATCH_LEVEL or greater, so a spin lock is not required.

Listing 12-9 shows how the Toastmon driver creates the collection and the lock in the Toaster\Toastmon\Toastmon.c file.

Listing 12-9: Creating a collection object in a KMDF driver

image from book
 WDF_OBJECT_ATTRIBUTES          attributes; NTSTATUS                       status = STATUS_SUCCESS; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfCollectionCreate(&attributes,               &deviceExtension->TargetDeviceCollection); if (!NT_SUCCESS(status)) {     . . . //Error handling code omitted } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfWaitLockCreate(&attributes,               &deviceExtension->TargetDeviceCollectionLock); if (!NT_SUCCESS(status)) {     . . . //Error handling code omitted } 
image from book

In the listing, the device variable contains a handle to the WDFDEVICE object, and deviceExtension contains a pointer to the context area for the device object. The context area is defined as follows:

 typedef struct _DEVICE_EXTENSION {     WDFDEVICE     WdfDevice;     WDFIOTARGET   ToasterTarget;     PVOID         NotificationHandle; // Interface notification handle     WDFCOLLECTION TargetDeviceCollection;     WDFWAITLOCK   TargetDeviceCollectionLock;     PVOID         WMIDeviceArrivalNotificationObject; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; 

Before the driver creates the collection object, it initializes an object attributes structure and sets the device object as the collection's parent. The call to WdfCollectionCreate creates the collection object and returns the object's handle in the device object context area at TargetDeviceCollection.

To create the lock, the driver proceeds similarly. It initializes the object attributes structure, sets the Parent field to the device object, and calls WdfWaitLockCreate to create the wait lock object. The driver stores the handle to the lock in the device object context area at TargetDeviceCollectionLock.

Chapter 10, "Synchronization," provides more information on wait locks.

When a new device interface arrives, the Toastmon driver creates an I/O target object to represent the interface. As Listing 12-10 shows, the driver adds the I/O target object to the collection.

Listing 12-10: Adding an object to a collection

image from book
 WdfWaitLockAcquire(deviceExtension->TargetDeviceCollectionLock, NULL); status = WdfCollectionAdd(deviceExtension->TargetDeviceCollection, ioTarget); if (!NT_SUCCESS(status)) {     . . . //Error handling code omitted } WdfWaitLockRelease(deviceExtension->TargetDeviceCollectionLock); 
image from book

The driver acquires the lock that protects the collection by calling WdfWaitLockAcquire, passing NULL for the time-out value to indicate that the driver will wait indefinitely for the lock to become available. The driver then adds the object to the collection by calling WdfCollectionAdd, passing a handle to the collection and a handle to the object. When the driver has finished accessing the collection, it calls WdfWaitLockRelease to release the lock.

Listing 12-11 shows how the driver removes an object from the collection.

Listing 12-11: Removing an object from a collection

image from book
 WdfWaitLockAcquire(deviceExtension->TargetDeviceCollectionLock, NULL); WdfCollectionRemove(deviceExtension->TargetDeviceCollection, IoTarget); WdfWaitLockRelease(deviceExtension->TargetDeviceCollectionLock); 
image from book

Removal is a simple matter of acquiring the lock, calling WdfCollectionRemove, and releasing the lock, as the listing shows. A driver can remove an object from a collection by specifying the object's handle, as in the example, or by specifying the object's index in the collection.

The driver does not delete the collection, because the framework automatically deletes the collection when it deletes the device object, which is the parent of the collection 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