Windows System Programming: Working with Windows Registries
Tags: systemprogrammng, windows, cpp
Published: 2020-09-05 08:59:51

Hi, today I will show you how to create and set values in the windows registries. But first of all, let me introduce to you "what are registries windows systems"

A registry is centralised storage of application / system configurations. The data structure used by registry hives is known as **graph**, which means it's a hierarchical data structure where each key in the registry can have one or more values. You can read more about it from [here](https://en.wikipedia.org/wiki/Windows_Registry)

There are different types of registry keys on top level
+ **HKEY_LOCAL_MACHINE** &rarr; It is also known as `HKLM`. It stores physical information about the system and installed softwares.
+ **HKEY_USERS** &rarr; It stores user level configurations
+ **HKEY_CURRENT_CONFIG** &rarr; It contains current settings of users such as fonts and resolutions
+ **HKEY_CLASSES_ROOT** &rarr; It contains mapping information of file extensions with classes.
+ **HKEY_CURRENT_USER** &rarr; It contains users specific configurations.

In this post, I will be using `HKEY_CURRENT_USER`.

You can use `regedit.exe` tool to open / search / modify the registries

First of all, you need to create/open the new/existing key in the registry. This can be done by using [**RegCreateKeyA**](https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regcreatekeya) function declared in [_winreg.h_](https://docs.microsoft.com/en-us/windows/win32/api/winreg/) header file.
```cpp
LSTATUS RegCreateKeyA(
  HKEY   hKey,
  LPCSTR lpSubKey,
  PHKEY  phkResult
);
```
Function parameters definition as follows
+ **hKey** &rarr; A handle to an open registry key or the following predefined keys
    + HKEY_CLASSES_ROOT
    + HKEY_CURRENT_CONFIG
    + HKEY_CURRENT_USER
    + HKEY_LOCAL_MACHINE
    + HKEY_USERS
+ **lpSubKey** &rarr; The name of a key that this function opens or creates. If `hKey` is one of the [predefined keys](https://docs.microsoft.com/en-us/windows/desktop/SysInfo/predefined-keys), `lpSubKey` may be NULL. In that case, `phkResult` receives the same `hKey` handle passed in to the function.
+ **phkResult** &rarr; A pointer to a variable that receives a handle to the opened or created key.

**NOTE**: They keys are not case sensitive.

Once the function will return `ERROR_SUCCESS`, you can use the key handle (as passed in third argument) to make set / get values from the registries. So, to set a value you can use [**RegSetValueA**](https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvaluea). 
```cpp
LSTATUS RegSetValueA(
  HKEY   hKey,
  LPCSTR lpSubKey,
  DWORD  dwType,
  LPCSTR lpData,
  DWORD  cbData
);
```
+ **hKey** &rarr; A handle to an open registry key or the following predefined keys
    + HKEY_CLASSES_ROOT
    + HKEY_CURRENT_CONFIG
    + HKEY_CURRENT_USER
    + HKEY_LOCAL_MACHINE
    + HKEY_USERS
+ **lpSubKey** &rarr; The name of a subkey of the `hKey` parameter.  If `lpSubKey` does not exist, the function creates it. If this parameter is `NULL` or points to an empty string, the function sets the default value of the key identified by `hKey`. 
+ **dwType** &rarr; This parameter must be the REG_SZ type. To store other data types, use the [**RegSetValueExA**](https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexa) function.
+ **lpData** &rarr; The data to be stored. This parameter cannot be `NULL`.
+ **cbData** &rarr; The length of `lpData` to be written in the registry.

After doing every work or if you get any error make sure you close the key handle. This can be done by [**RegCloseKey**](https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey).
```cpp
LSTATUS RegCloseKey(
  HKEY hKey
);
```
It accepts only one parameter, that is the "handle to key".

Complete source code as follows
```cpp
#include <Windows.h>
#include <string>
#include <iostream>
#include <winreg.h>

int main(int argc, char**argv)
{
	if (argc < 3) {
		printf("usage: %s <key-name> <key-value>\n", argv[0]);
		return 1;
	}

	// create a new or open exisiting key
	HKEY key;
	// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regcreatekeya
	LSTATUS statKey = RegCreateKeyA(HKEY_CURRENT_USER, argv[1], &key);

	if (statKey != ERROR_SUCCESS) {
		printf("Unable to create key. Error Code: %d", GetLastError());
		// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
		RegCloseKey(key);
		return 1;
	}
	else {
		// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvaluea
		LSTATUS statVal = RegSetValueA(key, argv[1], REG_SZ, argv[2], strlen(argv[2]));
		if (statVal != ERROR_SUCCESS) {
			printf("Unable to set value to key. Error Code: %d", GetLastError());
			RegCloseKey(key);
			return 1;
		}
		else {
			printf("Check the regedit.exe and verify the value\n");
			printf("You can find the value in Computer\\HKEY_CURRENT_USER\\%s\\%s", argv[1], argv[1]);
			RegCloseKey(key);
			return 0;
		}
	}
}
```