February 27, 2021
Hot Topics:

Accessing And Enumerating Registry Keys

  • By Nancy Nicolaisen
  • Send Email »
  • More Articles »

Enumerating Registry Values

By its nature, the content of the registry is somewhat dynamic. Used in the conservative fashion, the values of your application's registry keys will depend on the state the application was in when it was last used. Keys have a possible set of values, which may or may not be present. To find out which values are present, you use RegEnumValue() to enumerate the value set of a key. In the RegDemo example, we do this in the HKeyN2ValuesDlg(). Let's dissect the value enumeration process.

First, you must open the key that owns the value with at least KEY_ENUMERATE_SUB_KEYS access permission.

rc = RegOpenKeyEx (
     TEXT ("Software\\n2"), 

If we successfully open the key, we set up for enumeration. Notice that value of the variable i was initialized at the top of the function:

INT i = 0, rc;

Next, we initialize dwNSize with the size, in Unicode characters, of the value name buffer. We initialize dwDSize with the size, in bytes, of the value data buffer.

//set up to enumerate values
dwNSize = dim(szName);
dwDSize = sizeof(bData);

Now, we make the initial call to RegEnumValue:

rc = RegEnumValue(hKeyN2, i, szName, 
                  &dwNSize, NULL,
                  &dwType, (PBYTE)&bData, 
                  &dwDSize );

The parameters, in the order shown, are the handle to the key that owns this value, the index of the value to retrieve, a buffer to hold the returned name of the value, the size of the buffer in Unicode characters, including the terminal null, a NULL place holder, the address of a DWORD in which the registry data type of this value is returned, the address of the data buffer, and the size of the data buffer in bytes. We capture the return of this call in the variable rc, and test it to determine when we have reached the end of the value list for this key. We loop over all of the values in order to initialize the list box:

while (rc == ERROR_SUCCESS)

First, we insert the value name. The name was returned in a Unicode string, and so can be directly inserted into the list box.

ListBox_InsertString(hWndList, -1, szName);

The key data is returned as a byte string, and is essentially "typeless" when we get it. In order to use the data, we have to discriminate its type, and then use a type cast to correctly translate the bytes into the proper format for their given type.

//distinguish between key types
memset( bBuffer, 0x0, sizeof(bBuffer));
if( dwType == REG_BINARY )
  wsprintf( (LPTSTR)&bBuffer,TEXT("  %s Data:%x "),
           TEXT("REG_BINARY"), *bData );

In the call to wsprintf() shown above, we print the first byte of the data buffer, two hex digits, into the string that will be inserted into the list box. In this case, we simply provide the address of the first byte of the data buffer. If we wanted to print more of the hex digits, we could use a call such as this:

//just a code fragment, not part of RegDemo
  wsprintf( (LPTSTR)&bBuffer,TEXT("  %s Data:%x%x%x"), 
           TEXT("REG_BINARY"), *bData, *bData[1], *bData[2] );

When we want to manipulate other registry data types, we need to take a little more care.

if( dwType == REG_DWORD )
  dwDatum = (DWORD)(bData);
  iTest = (int)dwDatum;
  wsprintf( (LPTSTR)&bBuffer, TEXT("  %s Data:%x "),
             TEXT("REG_DWORD"), *(int*)bData );

Notice that in the wsprintf() call that displays the REG_DWORD data, we first cast the address of the data buffer to an integer pointer, and then dereference that pointer. Most numeric types are stored in memory with the low order bytes stored at the lowest address ( LOWORD/HIWORD). For this reason, if you simply copy the correct number of bytes out of the data buffer and into a variable, you won't get the correct value.

ListBox_InsertString(hWndList, -1, bBuffer);

dwNSize = dim(szName);
dwDSize = sizeof(bData);
rc = RegEnumValue(hKeyN2, ++i, szName, &dwNSize, NULL,
                  &dwType, (PBYTE)&bData, &dwDSize );

We increment the variable i on each call to RegEnumValue() and continue looping until the function return indicates there are no more values.

Looking Ahead

In the next installment, we'll learn how to manipulate individual key values by adding, modifying and deleting them.

About the Author

Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, and entry time data validation.

In addition to writing for Developer.com, she has written several books, including Making Win 32 Applications Mobile.

# # #

Page 2 of 2

This article was originally published on November 20, 2003

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date