Win32 Registry Wrapper

If you've ever had to work with Win32 Registry, you'd know that it is painful to remember how to access the registry, retrieve values and set values with Win32 API. This tutorial covers a wrapper class that allows you to manipulate string (REG_SZ or REG_EXPAND_SZ) values in the registry using C++ Win32.

The code use is very simple, just set the group of registry's name--your company or program name, and then use value() to retrieve strings, and setValue() to set new keys.

Header InfernoRegistry

The header file is a class that declares our prototypes. You can modify the header to suite the type of data you want to interact with, you don't have to use just strings, you can make overloaded functions for int or any other data type.

#ifndef ___INFERNO_DEVELOPMENT_REGISTRY___
#define ___INFERNO_DEVELOPMENT_REGISTRY___
#include <string.h>
#include <windows.h>
using namespace std;
/*
* InfernoRegistry code developed by InfernoDevelopment.com
*/


class InfernoRegistry {
  public:
    InfernoRegistry(string RegGroup, int debug, HKEY hk_local);
    ~InfernoRegistry();
    bool setValue(string key, string value);
    string value(string key);
  private:
    void Error(string error);
    int m_debug;
    HKEY m_hkey;
};

#endif

We have a constructor, for setting up the program group called RegGroup, an int debug for printing our error messages or not, and an HKEY starting point for HKEY_LOCAL_MACHINE or HKEY_CURRENT_USERS.

Error simply is the function to output error messages, which you can change.

HKEY m_hkey is our member key that we will use throughout the class.

Implementation C++ File

This is our implementation file.

#include <windows.h>
#include <string.h>
#include <iostream>
#include "InfernoRegistry.h"

using namespace std;

/*
* InfernoRegistry code developed by InfernoDevelopment.com
*/


InfernoRegistry::InfernoRegistry(string RegGroup, int debug = 0, HKEY hk_local = HKEY_LOCAL_MACHINE){
  if(RegGroup.empty()){
    Error("RegGroup is empty\n");
  }
  string Path = "Software\\"+RegGroup;
  DWORD dwDisp;
  m_debug = debug;

  if(RegCreateKeyEx(hk_local,
  Path.c_str(),
  0,
  NULL,
  REG_OPTION_NON_VOLATILE,
  KEY_WRITE|KEY_EXECUTE,
  NULL,
  &m_hkey,
  &dwDisp)){
    Error("Failed to create Key\n");
  } else {
    Error("Key Created\n");
  }
}

InfernoRegistry::~InfernoRegistry(){
  RegCloseKey(m_hkey);
}

bool InfernoRegistry::setValue(string key, string value){
  if(RegSetValueEx(m_hkey,
  key.c_str(),
  0,
  REG_EXPAND_SZ,
  (BYTE*) value.c_str(),
  (DWORD) (lstrlen(value.c_str())+1)*sizeof(TCHAR))){
    Error("Failed to write key "+key+" and value string: "+value+"\n");
    return false;
  } else {
    Error("Succeeded to write key "+key+" and value string: "+value+"\n");
    return true;
  }
}

void InfernoRegistry::Error(string error){
  if(m_debug > 0)cout << error;
}

string InfernoRegistry::value(string key){
    char buffer[255] = {0};
    DWORD BufferSize = sizeof(buffer);
    DWORD dwType = 0;
    DWORD dwRet;

    dwType = REG_EXPAND_SZ;
    dwRet = RegQueryValueEx( m_hkey,
                             key.c_str(),
                             0,
                             &dwType,
                             (LPBYTE)buffer,
                             &BufferSize );
    if( dwRet == ERROR_SUCCESS ){
      Error("Successfully queried value!");
    } else {
      Error("RegQueryValueEx failed!\n");
    }
    return string(buffer);
}

I use RegCreateKeyEx (), with the key local value, the path to start at, and with KEY_WRITE and KEY_EXECUTE (same as KEY_READ) permissions so that we can read and write to registry. You can change this if you think you are only going to read or write.

RegSetValueEx () will be used to set our value with the same key as a REG_EXPAND_SZ (similar to REG_SZ) which is just a string.

RegQueryValueEx () will query a value that is at most 255 characters long and place it in buffer. You can modify this to be longer or make a while loop to check for ERROR_MORE_DATA on the return and dynamically add more memory using malloc, realloc, and free.

How to Use Win32 Inferno Registry

In order to use InfernoRegistry class, we've set up a main function to show you a basic operation (you can check using regedit (start > run > regedit) to see if it worked).

#include "InfernoRegistry.h"

int main(){
  InfernoRegistry IR("InfernoProgram\\InfernoProgram", 1);
  if(IR.setValue("MainWindowSize", "500")){
    cout << "Written MainWindowSize.\n";
  }
  cout << "Value: " << IR.value("MainWindowSize") << endl;
  cin.get();
  return 0;
}

I compiled using Code::Blocks a free IDE. I set debug option to 1 for more printing and for debugging, I set a value MainWindwSize to the registry with value 500. Then I query it using value() and get the same value back, you can play around with this.

Here's the output:
Key Created
Succeeded to write key MainWindowSize and value string: 500
Written MainWindowSize.
Successfully queried value!Value: 500

This should help you C++ Win32 programmers to use Win32 Registry more easily.

Post new comment

The content of this field is kept private and will not be shown publicly. If you have a Gravatar account associated with the e-mail address you provide, it will be used to display your avatar.