Registry Access


Drivers can use the registry to obtain information about their devices and to store information that must persist from one system reboot to the next. UMDF and KMDF provide the following ways for a driver to read and write the registry:

  • A UMDF driver uses a device property store.

  • A KMDF driver uses a registry key object.

UMDF Device Property Store

The device property store is an area in the registry where a UMDF driver can maintain information about the characteristics of its device, such as time-out values or device configuration settings for a particular device-in short, any device-specific information that the driver stores for use each time the system or device starts.

Each property store has a name, which is the same as that of the registry key that maintains the information. By default, the key has the same name as the driver. A property store contains one or more named string, integer, or binary values. To read information from the property store, a UMDF driver must have both the name of the property store and the name of the value that contains the data.

The property store provides a secure way for UMDF driver to write data to the registry and insulates drivers from the actual location of the data. A UMDF driver should not try to read or write property store data by accessing a specific registry location, and conversely, a UMDF driver cannot use the property store methods to read or write data such as device parameters that are recorded in other parts of the registry. To obtain information from elsewhere in the registry, drivers should use the Windows Registry API or Setup API. However, a UMDF driver runs in the LocalService security context, which restricts the areas of the registry that the driver can read and write.

A UMDF driver can create a new device property store or retrieve an existing property store by calling the RetrieveDevicePropertyStore method on either of the following interfaces:

  • IWDFDeviceInitialize during device initialization.

  • IWDFDevice after creation of the device object.

The RetrieveDevicePropertyStore method returns a pointer to an IWDFNamedPropertyStore helper interface through which the driver can set and get the values of device properties. This method has the following four parameters:

  • pcwszServiceName

    A pointer to a NULL-terminated string that represents the name of the device property store, or NULL to use the name of the calling driver in the WUDF services list.

  • Flags

    A WDF_PROPERTY_STORE_RETRIEVE_FLAGS value:

    • WdfPropertyStoreNormal does not create the property store if it does not already exist.

    • WdfPropertyStoreCreateIfMissing creates a property store if the requested property store does not exist.

  • ppPropStore

    A pointer to a location in which the method returns a pointer to the IWDFNamedPropertyStore interface.

  • pDisposition

    A pointer to a variable in which the method returns one of the following WDF_PROPERTY_STORE_DISPOSITION values:

    • CreatedNewStore means that the framework created a new store.

    • OpenedExistingStore means that the framework opened an existing store.

After the driver creates or retrieves the property store, it uses the IWDFNamedPropertyStore interface to get and set the values in the store. Table 12-3 summarizes the methods of the IWDFNamedPropertyStore interface.

Table 12-3: IWDFNamedPropertyStore Methods
Open table as spreadsheet

Method

Description

GetNameAt

Retrieves the name of a property, given the index of the property.

GetNameCount

Retrieves the number of properties in the property store.

GetNamedValue

Retrieves the value of a property given the name of the value.

SetNamedValue

Sets the value of a property.

The driver defines the format and contents of the property store. The property store persists in the registry until the device is uninstalled from the system. The framework saves the property store under the devnode, so the property store is deleted when the device is uninstalled. The device vendor is not required to supply an uninstall procedure. Listing 12-3 shows how a driver creates a named property store after it creates a device object. This example is excerpted from Sideshow\WSSDevice.cpp.

Listing 12-3: Creating a named property store

image from book
 hr = m_pWdfDevice->RetrieveDevicePropertyStore(NULL,           WdfPropertyStoreCreateIfMissing, &pStore, NULL); if (SUCCEEDED(hr)) {     hr = m_pBasicDriver->Initialize(pStore); } 
image from book

In the example, the m_pWdfDevice variable is a pointer to the IWDFDevice interface that the driver received when it created the framework device object. The driver passes NULL as the property store name and WdfPropertyStoreCreateIfMissing to request that the framework create a new property store with the default name. The driver also passes NULL for the pDisposition parameter because it does not require this information. The method returns a pointer to the IWDFNamedPropertyStore interface in pStore.

Listing 12-4 shows how the same sample driver gets a named value from the property store. This code is derived from Sideshow\BasicDDI.cpp.

Listing 12-4: Retrieving information from a property store

image from book
 PROPVARIANT pvBlob = {0}; PropVariantInit(&pvBlob); hr = m_pPropertyStore->GetNamedValue(wszKey, &pvBlob); if (SUCCEEDED(hr) &&         VT_BLOB == pvBlob.vt &&         0 == (pvBlob.blob.cbSize % sizeof(APPLICATION_ID)))     {         *pcAppIds = pvBlob.blob.cbSize / sizeof(APPLICATION_ID);         *ppAppIds = (APPLICATION_ID*)pvBlob.blob.pBlobData;     } 
image from book

The sample code calls IWDFNamedPropertyStore::GetNamedValue to retrieve the value of the key that the wszKey string describes. The value is returned as a binary value of variant type VT_BLOB, which the driver then parses and evaluates. Note that PropVariantInit is a COM function that initializes a variant property structure.

 Tip  See "PropVariantInit" on MSDN for more information-online at http://go.microsoft.com/fwlink/?LinkId=79586.

Listing 12-5 shows how the Sideshow sample driver sets a named value in the property store. This code is also derived from Sideshow\BasicDDI.cpp.

Listing 12-5: Setting information in a property store

image from book
 PROPVARIANT pvBlob = {0}; PropVariantInit(&pvBlob); pvBlob.vt = VT_BLOB; pvBlob.blob.cbSize = cApps * sizeof(APPLICATION_ID); pvBlob.blob.pBlobData = (BYTE*)pApps; hr = m_pPropertyStore->SetNamedValue(wszKey, &pvBlob); 
image from book

In Listing 12-5, the sample driver writes an application ID to the property store as binary data. The sample fills a PROPVARIANT variable with a value of variant type VT_BLOB and then calls the IWDFNamedPropertyStore::SetNamedValue method to save the value in the key named by the wszKey string.

KMDF Registry Objects and Methods

KMDF includes numerous methods with which a driver can read and write the registry. These methods enable the driver to create, open, and close a registry key and to query, change, and delete the values of keys and individual data items within them.

A driver can access the registry entry for a driver or device either before or after creating the device object. If your driver requires information from the registry before it creates the device object, your driver can use the WdfFdoInitXxx methods to get the value of individual device properties or to retrieve the entire device hardware key or driver software key. After creating the device object, the driver uses WdfDeviceXxx methods. Table 12-4 summarizes the methods that query individual device properties and open registry keys.

Table 12-4: KMDF Methods to Query and Open Registry Keys
Open table as spreadsheet

Method

Description

WdfDeviceAllocAndQueryProperty

Allocates a buffer and retrieves a device property from the registry, given a handle to a WDFDEVICE object.

WdfDeviceQueryProperty

Retrieves a device property from the registry, given a handle to a WDFDEVICE object.

WdfDeviceOpenRegistryKey

Opens the registry hardware key for a device or the software key for a driver and creates a framework registry-key object that represents the key.

WdfFdoInitAllocAndQueryProperty

Allocates a buffer and retrieves a device property from the registry, given a pointer to a WDFDEVICE_INIT structure.

WdfFdoInitOpenRegistryKey

Opens a device's hardware key or a driver's software key in the registry and creates a registry-key object that represents the registry key, given a pointer to a WDFDEVICE_INIT structure.

WdfFdoInitQueryProperty

Retrieves a device property from the registry, given a pointer to a WDFDEVICE_INIT structure.

To read the value of a registry key, a driver opens the registry key and then calls a method that queries the registry for data. The WdfFdoInitOpenRegistryKey and WdfRegistryOpenKey methods open a registry key. Both of these methods have the following five parameters:

  • DeviceInit - or - Device

    • A pointer to a WDFDEVICE_INIT structure for WdfFdoInitOpenRegistryKey.

    • - Or -

    • A handle to a WDFDEVICE object for WdfRegistryOpenKey.

  • DeviceInstanceKeyType

    • A ULONG value that identifies the key to open.

  • DesiredAccess

    • A bit mask that indicates the type of required access.

  • KeyAttributes

    • An optional attribute structure.

  • Key

    • A location to receive a handle to a WDFKEY object.

To get or set the value of a single setting within the key, the driver must use one of the WdfRegistryXxx methods, which are listed in Table 12-5. When the driver has completed using the registry, the driver calls WdfRegistryClose to close and delete the key.

Table 12-5: KMDF Registry Key Methods
Open table as spreadsheet

Method

Description

WdfRegistryAssignMemory

Assigns data from a memory buffer to a value name in the registry.

WdfRegistryAssignMultiString

Assigns a set of strings from a collection of string objects to a value name in the registry.

WdfRegistryAssignString

Assigns a string from a string object to a value name in the registry.

WdfRegistryAssignULong

Assigns an unsigned long word value to a value name in the registry.

WdfRegistryAssignUnicodeString

Assigns a Unicode string to a value name in the registry.

WdfRegistryAssignValue

Assigns data to a value name in the registry.

WdfRegistryClose

Closes the registry key that is associated with a registry-key object and then deletes the registry-key object.

WdfRegistryCreateKey

Creates and opens a registry key, or just opens the key if it already exists, and creates a registry-key object that represents the registry key.

WdfRegistryOpenKey

Opens a registry key and creates a registry-key object that represents the registry key.

WdfRegistryQueryMemory

Retrieves the data that is currently assigned to a registry value, stores the data in a framework-allocated buffer, and creates a memory object to represent the buffer.

WdfRegistryQueryMultiString

Retrieves the strings that are currently assigned to a multistring registry value, creates a framework string object for each string, and adds each string object to a collection.

WdfRegistryQueryString

Retrieves the string data that is currently assigned to a registry string value and assigns the string to a string object.

WdfRegistryQueryULong

Retrieves the unsigned long word (REG_DWORD) data that is currently assigned to a registry value and copies the data to a driver-specified location.

WdfRegistryQueryUnicodeString

Retrieves the string data that is currently assigned to a registry string value and copies the string to a UNICODE_STRING structure.

WdfRegistryQueryValue

Retrieves the data that is currently assigned to a registry value.

WdfRegistryRemoveKey

Removes the registry key that is associated with a framework registry-key object and then deletes the registry-key object.

WdfRegistryRemoveValue

Removes a value and its data from a registry key.

WdfRegistryWdmGetHandle

Returns a WDM handle to the registry key that a framework registry-key object represents.

 Sample code to read and write the registry  In the Pcidrv.c source file, the PCIDRV sample provides functions that:

  • Read a REG_DWORD registry value that was written by another user-mode or kernel-mode component.

  • Read a REG_DWORD registry value that was stored under the device key.

  • Write a REG_DWORD registry value that was stored under the device key.

The PCIDRV sample driver's PciDrvReadFdoRegistryKeyValue function is called from the EvtDriverDeviceAdd callback before the driver creates the device object. It reads a key, which the driver's INF wrote at installation, that indicates whether the driver was installed as an NDIS upper-edge miniport driver. This information is important because it determines whether the driver registers certain power policy and I/O event callbacks. If the driver was installed as an upper-edge miniport driver, it is not the power policy manager for its device; instead, NDIS manages power policy. Listing 12-6 shows the source code for this function.

Listing 12-6: Reading a registry key during device object initialization

image from book
 BOOLEAN PciDrvReadFdoRegistryKeyValue(     __in  PWDFDEVICE_INIT  DeviceInit,     __in  PWCHAR           Name,     __out PULONG           Value     ) {     WDFKEY      hKey = NULL;     NTSTATUS    status;     BOOLEAN     retValue = FALSE;     UNICODE_STRING  valueName;     PAGED_CODE();     *Value = 0;     status = WdfFdoInitOpenRegistryKey(DeviceInit,                  PLUGPLAY_REGKEY_DEVICE,                  STANDARD_RIGHTS_ALL,                  WDF_NO_OBJECT_ATTRIBUTES,                  &hKey);     if (NT_SUCCESS (status)) {         RtlInitUnicodeString (&valueName,Name);         status = WdfRegistryQueryULong (hKey,                   &valueName,                   Value);         if (NT_SUCCESS (status)) {            retValue = TRUE;         }     WdfRegistryClose(hKey);     }     return retValue; } 
image from book

First, the driver initializes the Value parameter that will receive the requested key value. Next, it opens the registry key by calling WdfFdoInitOpenRegistryKey, passing the five previously described parameters, and receiving a handle to the returned WDFKEY object in hKey. The PLUGPLAY_REGKEY_DEVICE constant specifies the device's hardware key. Although the sample requests all access rights to the registry by specifying STANDARD_RIGHTS_ALL, the driver only reads the key and does not write it, so STANDARD_RIGHTS_READ would also work.

If the driver successfully opens the hardware key, it queries the key for the requested value. The name of the value is passed into the PciDrvReadFdoRegistryKeyValue function as a pointer to a string. However, the KMDF query method requires the name in a counted Unicode string. Therefore, before querying for the value, the driver calls RtlInitUnicodeString to copy the input string into a string of the correct format.

The driver then calls WdfRegistryQueryUlong, which returns the ULONG value of the key in the Value parameter. The driver closes the key by calling WdfRegistryClose and the function returns.




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