Platform SDK: Registry

Retrieving Data from the Registry

To retrieve data from the registry, an application typically enumerates the subkeys of a key until it finds a particular one and then retrieves data from the value or values associated with it. An application can call either the RegEnumKey or RegEnumKeyEx function to enumerate the subkeys of a given key. RegEnumKeyEx returns a subkey and its class, but RegEnumKey returns only the subkey, not the class.

To retrieve detailed data about a particular subkey, an application can call the RegQueryInfoKey function. The RegGetKeySecurity function retrieves a copy of the security descriptor protecting a key.

An application can use the RegEnumValue function to enumerate the values for a given key, and the RegQueryValue or RegQueryValueEx function to retrieve a particular value for a key. An application typically calls RegEnumValue to determine the value names and then RegQueryValueEx to retrieve the data for the names.

RegQueryValue and RegQueryValueEx differ in how they treat unexpanded references to environment variables. If an unnamed value contains an unexpanded environment variable (for example, %PATH%), RegQueryValue expands the variable into the storage buffer provided as one of its parameters. RegQueryValueEx, however, does not expand these references. (Applications can also use the ExpandEnvironmentStrings function to expand environment variables.)

The RegQueryMultipleValues function retrieves the type and data for a list of value names associated with an open registry key. This function is useful for dynamic key providers because it assures consistency of data by retrieving multiple values in an atomic operation. This is more efficient than calling RegQueryValue multiple times, particularly across a network, because it can retrieve the values with one network transaction.

The RegNotifyChangeKeyValue function notifies the calling thread through an event when changes to the attributes or contents of a specified registry key are made. The function does not notify the caller if the key is deleted. If the thread that calls RegNotifyChangeKeyValue exits, the notification event is signaled and the monitoring of the registry key is stopped.

You can control or specify what changes should be reported through the use of a notify filter or flag. Usually, changes are reported by signaling an event that you specify to the function. Note that the RegNotifyChangeKeyValue function does not work with remote handles.

The following example code uses the registry interface functions described in this section to determine which variant of Windows NT/Windows 2000—Server or Workstation—is running by querying the ProductType subkey of the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ProductOptions key.

#define RTN_UNKNOWN 0
#define RTN_SERVER 1
#define RTN_WORKSTATION 2
#define RTN_NTAS 3
#define RTN_ERROR 13

DWORD GetWindowsVariant(void)
{
    #define MY_BUFSIZE 32    // Arbitrary initial value. 
                             // Dynamic allocation will be used.
    HKEY hKey;
    TCHAR szProductType[MY_BUFSIZE];
    DWORD dwBufLen = MY_BUFSIZE;
    LONG lRet;

    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
                    0,
                    KEY_QUERY_VALUE,
                    &hKey) != ERROR_SUCCESS) return RTN_ERROR;

    lRet = RegQueryValueEx(hKey,
                    TEXT("ProductType"),
                    NULL,
                    NULL,
                    (LPBYTE)szProductType,
                    &dwBufLen);

    RegCloseKey(hKey);

    if(lRet != ERROR_SUCCESS) return RTN_ERROR;

    // check product options, in order of likelihood
    if(lstrcmpi(TEXT("WINNT"), szProductType) == 0) 
         return RTN_WORKSTATION;
    if(lstrcmpi(TEXT("SERVERNT"), szProductType) == 0) 
         return RTN_SERVER;
    if(lstrcmpi(TEXT("LANMANNT"), szProductType) == 0) 
         return RTN_NTAS;
    // else return "unknown variant" code
    else return RTN_UNKNOWN;
}