Advanced Windows Registry Access

Published on April 12, 2008
This article was written back when Visual Studio 6 was new. As such, I cannot guarantee that the content of this article still applies in modern Windows environments.

If you are interested in how to access arbitrary locations in the Windows registry, this is the article for you. However, if you would prefer to learn a simpler method of registry access to store and retrieve program settings, consult my simple registry access article.

Opening (Reading) Keys

Unlike the simpler, application based method, we don’t need to enable registry access via a special function call. Instead, the functions we will be using interface directly with the registry itself. Let’s look at the code required to open an arbitrary key value:

HKEY hKey;
RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"),
             0, KEY_QUERY_VALUE, &hKey);

As you can see, we are using the RegOpenKeyEx() function. Let’s take a look at its various parameters:

  • Parameter 1: A handle to a currently open key or any of the following predefined reserved handle values:
    • HKEY_CLASSES_ROOT
    • HKEY_CURRENT_CONFIG
    • HKEY_CURRENT_USER
    • HKEY_LOCAL_MACHINE
    • HKEY_USERS
    • HKEY_PERFORMANCE_DATA (Windows NT only)
    • HKEY_DYN_DATA (Windows 95 and 98 only)
  • Parameter 2: A pointer to a null-terminated string that specifies the name of the sub-key to open.
  • Parameter 3: Must be 0. This is a reserved value.
  • Parameter 4: Specifies an access mask that describes the security access for the new key. Take a look at the MFC documentation for all the possible values.
  • Parameter 5: Pointer to a variable that receives the handle of the open key.

As can be seen in the example code provided above, we are opening a registry key in the HKEY_CURRENT_USER branch. What’s more is that we’re explicitly opening the "Control Panel\Desktop" sub-key. We want to have permission to query sub-key data values (hence the value of KEY_QUERY_VALUE for parameter 4), and we store the resulting handle in the hKey variable.

The RegOpenKeyEx() method returns a value indicating success or failure, so make sure you test it appropriately. Let’s assume that the key was opened successfully and see how to query its value:

unsigned char buffer[_MAX_PATH];
unsigned long datatype;
unsigned long bufferlength = sizeof(buffer);

RegQueryValueEx(hKey, "Wallpaper", NULL, &datatype, buffer, &bufferlength);

Again, let’s take a look at the parameters for this new RegQueryValueEx() function:

  • Parameter 1: A handle to a currently open key.
  • Parameter 2: A pointer to a null-terminated string that specifies the name of the value to be queried.
  • Parameter 3: Must be NULL. This is a reserved value.
  • Parameter 4: Pointer to a variable that receives the type of data associated with the specified value. Check out the MFC documentation to see what possible values are stored in this variable. This isn’t too critical, so you can just skip over it for now.
  • Parameter 5: Pointer to a buffer that will receive the value’s data.
  • Parameter 6: Pointer to a variable that specifies the size, in bytes, of the available buffer.

The first parameter accepts the same handle we got from the RegOpenKeyEx() function. The second parameter in this example is the string "Wallpaper", which means this is the specific key we will be querying. The fourth parameter is an unsigned long that accepts the data type, but we won’t ever actually use its value. Next is an unsigned character buffer, into which the value of the registry key will be read. I use the Windows constant _MAX_PATH to create a buffer large enough to store the longest possible file path (since this particular key I’m querying stores a file path value). We finally pass in the length of the buffer that we just created.

One last step is required before we can successfully say we have read a registry key. The key that got opened must be closed (after we read its value, of course), so that its handle gets freed. The code we use to do this is:

RegCloseKey(hKey);

Using all of the methods just mentioned, you can read any value from the registry.

Creating (Writing) Keys

So now we know how to read a value. But what about writing a value? The process is slightly different. First, we open the key we want to write (whether it exists or not) using the RegCreateKeyEx() function:

HKEY hKey;
unsigned long dwDisp;

RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Control Panel\\Desktop"),
               0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
               NULL, &hKey, &dwDisp);

Let’s examine this function’s parameters:

  • Parameter 1: A handle to a currently open key or any of the following predefined reserved handle values:
    • HKEY_CLASSES_ROOT
    • HKEY_CURRENT_CONFIG
    • HKEY_CURRENT_USER
    • HKEY_LOCAL_MACHINE
    • HKEY_USERS
    • HKEY_PERFORMANCE_DATA (Windows NT only)
    • HKEY_DYN_DATA (Windows 95 and 98 only)
  • Parameter 2: A pointer to a null-terminated string that specifies the name of the sub-key to open.
  • Parameter 3: Must be 0. This is a reserved value.
  • Parameter 4: A pointer to a null-terminated string that specifies the class (object type) of this key. If the key already exists, this parameter is ignored. For our purposes, just set it to a value of NULL.
  • Parameter 5: Set this parameter to REG_OPTION_NON_VOLATILE for our purposes.
  • Parameter 6: Specifies an access mask that describes the security access for the new key. Take a look at the MFC documentation for all of the possible values.
  • Parameter 7: Set this parameter to NULL for our purposes.
  • Parameter 8: Pointer to a variable that receives the handle of the opened or created key.
  • Parameter 9: A pointer to a variable that receives a disposition value of the key. Either the value will be REG_CREATED_NEW_KEY (a new key was created) or REG_OPENED_EXISTING_KEY (the key was already there and has been opened).

Once the desired key is opened, we can set its value with the RegSetValueEx() function:

unsigned char tilewallpaper[2];
tilewallpaper[0] = '0';
tilewallpaper[1] = '\0';

RegSetValueEx(hKey, TEXT("TileWallpaper"), NULL, REG_SZ, tilewallpaper, 1);

Let’s look a little closer at this final function’s parameter list:

  • Parameter 1: A handle to a currently open key.
  • Parameter 2: A pointer to a null-terminated string that specifies the name of the value to be set.
  • Parameter 3: Must be NULL. This is a reserved value.
  • Parameter 4: Pointer to a variable that specifies that type of data that will be written. We use REG_SZ since we will be writing a null-terminated string.
  • Parameter 5: Pointer to a buffer that contains the data to be written.
  • Parameter 6: Pointer to a variable that specifies the size, in bytes, of the buffer.

Here we are explicitly writing a value to the TileWallpaper key (we are going to write a value of ‘0’ so that our wallpaper is not tiled). We use the hKey as before, and an unsigned character buffer. Fairly straightforward.

Don’t forget to close the key once you’ve finished:

RegCloseKey(hKey);

I’ve now shown you how to read and write to any location in the registry. This is a powerful means of programming, so be careful! You don’t want to accidentally remove or overwrite anything that you shouldn’t.

Comments are closed.

Copyright © 2004-2018 Jonah Bishop. Hosted by DreamHost.