Working with Registry Keys

[Previous] [Next]

This section describes functions implemented by the system that can be used to access the system registry. Before discussing specific functions, however, I would like to make a distinction between two sets of functions: the registry functions, and the shell registry functions.

Registry and Shell Registry Functions

Registry functions are a basic set of functions, implemented by the system, for accessing the system registry. These functions have existed since the creation of the Win32 programming interface and reside in a DLL named AdvAPI32.dll. Anything that can be done with the registry can be implemented using the registry functions. They are characterized by the three-character prefix Reg—for example, RegOpenKeyEx.

Shell registry functions are built on these "regular" registry functions and provide extended or simplified functionality. Shell registry functions are intended to ease access to the registry, as well as to enforce a more uniform usage of the registry by applications. These functions are available only when Microsoft Internet Explorer 4.0 or later is installed on the system.

To use the shell functions, you have to include the ShlWAPI.h header file in your source code as well as the ShlWAPI.lib file with your linker options. The regular registry functions do not require any special inclusions.

The shell functions are characterized by simpler parameter lists as well as the two-character prefix SH—for example, SHCopyKey.

Because the regular registry functions provide the base interface to the registry, I will be focusing on them in this chapter. However, I will make occasional mention of shell functions where appropriate.

Opening Registry Keys

Before you can begin storing and retrieving information in registry values, you must obtain a handle to a registry key. You can obtain a handle to a registry key in two basic ways: open an existing key or create a new key. The RegOpenKeyEx function should be used to open existing registry keys. It is prototyped as follows:

 LONG RegOpenKeyEx( HKEY hkeyRoot, PCTSTR pszSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); 

NOTE
The RegOpenKey function can also be used to obtain a handle to a registry key. However, you should always use the Ex version of a registry function, if it exists.

To open a subkey, you pass the handle of the root key for the hkeyRoot parameter. The handle should be either the parent of the subkey you want to open or some grandparent of the desired subkey. The system also allows you to pass any of the predefined root key values as listed in Table 5-1 to hkeyRoot. Typically, an application will have to make at least one call to RegOpenKeyEx, passing HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER as the hkeyRoot parameter.

The pszSubKey parameter is the textual name of the key that you want to open. This name must include all keys between the desired key and the root, separated with backslash characters. For example, if you wanted to obtain a handle with read access to the HKEY_LOCAL_MACHINE\Software\Microsoft\Windows subkey, your call to RegOpenKeyEx would look something like the following:

 HKEY hkeyWindows; LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows"), NULL, KEY_READ, &hkeyWindows); 

If you are opening a key that is an immediate subkey of the specified root key, you don't need to include parent key names or backslashes in the pszSubKey parameter; include only the name of the desired key. If you pass an empty string or a NULL value as the pszSubKey parameter, the system returns a new handle to the specified root key. Pass NULL to pszSubKey when you need a handle with security access that is different from that of the original root key handle.

The ulOptions parameter is currently unused and reserved for future use. For now, you should always pass zero for this parameter.

The samDesired parameter describes what your application intends to do with the requested registry key, and can be any combination of the flags described in Table 5-3. Avoid the temptation to pass KEY_ALL_ACCESS, because your application might have limited security access to a given registry key. Requesting only the access your application intends to use increases the odds of a successful call to RegOpenKeyEx.

Table 5-3. Flags that can be passed to RegOpenKeyEx's samDesired parameter

Registry Access Flags Description
KEY_ALL_ACCESS Combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, KEY_CREATE_SUB_KEY, KEY_CREATE_LINK, and KEY_SET_VALUE access
KEY_CREATE_LINK Permission to create a symbolic link
KEY_CREATE_SUB_KEY Permission to create subkeys
KEY_ENUMERATE_SUB_KEYS Permission to enumerate subkeys
KEY_EXECUTE Permission for read access
KEY_NOTIFY Permission for change notifications
KEY_QUERY_VALUE Permission to query subkey data
KEY_READ Combination of KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY access
KEY_SET_VALUE Permission to set subkey data
KEY_WRITE Combination of KEY_SET_VALUE and KEY_CREATE_SUB_KEY access

You should pass the address of an HKEY variable as the value of the phkResult parameter. The system fills this variable with the handle of the open key, if RegOpenKeyEx succeeds. The RegOpenKeyEx function returns ERROR_SUCCESS if it is successful and ERROR_FILE_NOT_FOUND if the key does not exist.

NOTE
Unlike most other Windows functions, the registry functions return error codes. You should not call GetLastError to get more specific error information for a registry function.

Creating Registry Keys

The RegCreateKeyEx function allows you to create a key. You can also use the RegCreateKeyEx function to retrieve a handle to a key. Unlike RegOpenKeyEx, however, RegCreateKeyEx will not automatically fail if the key does not exist. Instead, it will attempt to create a new key with the name you provide. RegCreateKeyEx is prototyped as follows:

 LONG RegCreateKeyEx( HKEY hkeyRoot, PCTSTR pszSubKey, DWORD Reserved, PTSTR pszClass, DWORD dwOptions, REGSAM samDesired, PSECURITY_ATTRIBUTES psa, PHKEY phkResult, PDWORD pdwDisposition); 

You will recognize the hkeyRoot, pszSubKey, samDesired, and phkResult parameters from the RegOpenKeyEx function. These parameters are used identically to those for RegCreateKeyEx, but with one noteworthy exception: if the key specified in the pszSubKey parameter does not already exist, the system attempts to create a new subkey to complete the request.

In addition to the familiar parameters, RegCreateKeyEx has a pszClass parameter, which points to a zero-terminated string with a class name for the key. The class name is reserved, and you should always pass NULL for this parameter.

The dwOptions parameter can be any of the values in Table 5-4.

The psa parameter points to a SECURITY_ATTRIBUTES structure, which allows you to define the access rights for the newly created subkey. The security descriptor information is ignored if the subkey already exists. (For more information on security and the registry, see Chapter 10.)

Table 5-4. Values that can be passed for RegCreateKeyEx's dwOptions parameter

Option Values Description
REG_OPTION_NON_VOLATILE The key is created in the registry and is persistent on the system's hard disk.
REG_OPTION_VOLATILE The key is stored in memory and does not persist when the system is restarted.
REG_OPTION_BACKUP_RESTORE The key is used by backup software to back up and restore the registry.

NOTE
The typical registry key is nonvolatile. Volatile data is always deleted when the computer reboots. Volatile keys are convenient for avoiding clutter while using keys that are only temporarily necessary. Volatile keys can be used to efficiently exchange data between processes—the communication even works well for processes operating on different machines because the registry is remoteable. (See the RegConnectRegistry function discussed later in "Accessing the Registry Remotely.")

The pdwDisposition parameter is a pointer to a DWORD variable that the system fills with one of two values: REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY. Examining the variable when the function returns reveals whether the function created the subkey or simply opened the existing subkey. Most of the time, your software does not need to know whether it actually created the subkey and, therefore, RegCreateKeyEx allows you to pass NULL for this last parameter.

Software commonly uses RegCreateKeyEx to create and open its keys for configuration data, understanding that the system might have created a new key for the software on the spot. RegCreateKeyEx provides a convenient way for an application to rebuild necessary portions of its configuration information with default data in the event that a registry key is deleted, which the curious administrator has been known to do from time to time.

Whether you received your handle to an open registry key by making a call to RegCreateKeyEx or by making a call to RegOpenKeyEx, you should always pass your open registry handles to RegCloseKey when you are finished using them:

 LONG RegCloseKey(HKEY hkey); 

Enumerating Registry Keys

When software is being installed or configured, it typically knows the required registry key names. However, in some cases, the subkey names within an open key may not be known. The RegEnumKeyEx function can be used to enumerate subkeys. RegEnumKeyEx has the following prototype:

 LONG RegEnumKeyEx( HKEY hkey, DWORD dwIndex, PTSTR pszName, PDWORD pcbName, PDWORD pdwReserved, PTSTR pszClass, PDWORD pcbClass, PFILETIME pftLastWriteTime); 

Because your code must provide the buffers for the returned class name and key name values, it is your responsibility to pass buffers large enough to hold any subkey and class name; otherwise, the function will fail. To do this, you should make an initial call to RegQueryInfoKey to retrieve the length of the longest subkey and class names under the desired key. Your code must still be capable of handling an even longer subkey name, because a new subkey might be added between the times that your code calls RegQueryInfoKey and RegEnumKeyEx. The RegQueryInfoKey function is prototyped as follows:

 LONG RegQueryInfoKey( HKEY hkey, PTSTR pszClass, PDWORD pcbClass, PDWORD pdwReserved, PDWORD pcSubKeys, PDWORD pcbMaxSubKeyLen, PDWORD pcbMaxClassLen, PDWORD pcValues, PDWORD pcbMaxValueNameLen, PDWORD pcbMaxValueLen, PDWORD pcbSecurityDescriptor, PFILETIME pftLastWriteTime); 

The following code fragment illustrates how to enumerate subkey names under an arbitrary key:

 VOID PrintSubKeyNames(HKEY hkey) { // Get length of longest key name in characters DWORD dwMaxSubkeyLen; RegQueryInfoKey(hkey, NULL, NULL, NULL, NULL, &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL); // Add one for the NULL terminator dwMaxSubkeyLen++; // Allocate buffer for subkey names PTSTR pszKeyName = (PTSTR) _alloca(dwMaxSubkeyLen * sizeof(TCHAR)); // Store buffer length DWORD dwKeyNameLen = dwMaxSubkeyLen; // Start from the beginning DWORD dwIndex = 0; FILETIME ftLastWritten; // Loop until failure while (ERROR_SUCCESS == RegEnumKeyEx(hkey, dwIndex++, pszKeyName, &dwKeyNameLen, NULL, NULL, NULL, &ftLastWritten)) { // Print key name _tprintf(TEXT("%s\n"), pszKeyName); // Restore buffer length with each iteration dwKeyNameLen = dwMaxSubkeyLen; } } 

NOTE
The shell registry functions include two functions that parallel the functionality of RegQueryInfoKey and RegEnumKeyEx. They are defined as follows:

 DWORD SHQueryInfoKey( HKEY hkey, PDWORD pcSubKeys, PDWORD pcchMaxSubKeyLen, PDWORD pcValues, PDWORD pcchMaxValueNameLen);   

and

 DWORD SHEnumKeyEx( HKEY hkey, DWORD dwIndex, PTSTR pszName, PDWORD pcchName); 

Notice that the shell registry functions are simpler to use because infrequently needed parameters are not required.



Programming Server-Side Applications for Microsoft Windows 2000
Programming Server-Side Applications for Microsoft Windows 2000 (Microsoft Programming)
ISBN: 0735607532
EAN: 2147483647
Year: 2000
Pages: 126

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