Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Happy Registry: A Quick Wrapper for the Win32 Database

0.00/5 (No votes)
23 Oct 2015 1  
A simple template for manipulating the registry

Introduction

They have tried a few times to pay me to rewrite the entire Win32 library. Not that I cannot do so, but I am very bored. Instead, I focus on some really needed functions, get miserable of the lines of code needed to use them and finally, create a quick C++ class for one-line manipulation.

Here is a simple class for manipulating the registry.

Constructors, Operator = and Destructor

RKEY(HKEY root,const wchar_t* subkey,DWORD acc = KEY_ALL_ACCESS);
RKEY(HKEY);
RKEY(const RKEY&);
RKEY(RKEY&&);
void operator=(HKEY);
void operator=(const RKEY&);
void operator=(RKEY&&);
~RKEY();

The usual stuff is there that allows construction from an existing HKEY or RKEY, along with construction with a root and subkey (which internally creates RegCreateKeyEx). Move semantics are there. Copy constructor duplicates the key handle.

Sample usage:

// Create a RKEY from a known path 
RKEY r(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Run");

Querying or Enumerating Values

// Get a VALUE from a RKEY
VALUE operator [](const wchar_t* v) const;

// Enum all values
vector<VALUE> EnumValues() const;

// Enum all subkeys
vector<wstring> EnumSubkeys() const;

// And the VALUE members
template <typename T> operator T() const;
operator std::wstring() const;
::name, ::value, ::ty;

Operator [] from RKEY returns a RKEY::VALUE which can be used to manipulate the value.

Sample usage:

// Create a RKEY from a known path 
RKEY r(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Run");
string str = r["OneDrive"]; //str = "C:\...\OneDrive.exe" /background
DWORD some_dword = r["blahblah"]; // Internally gets RegQueryValueEx and 
                                  // copies the value to a DWORD
vector<wstring> subs = r.EnumSubKeys();
vector<VALUE> allvalues = r.EnumValues();

Note that RKEY::operator [] does not query the value type before doing the conversion, so you must know that it's actually a DWORD value. If you don't know the type, you can enum the values with vector<VALUE> EnumValues() and access name, type and data with members name, value, ty.

Setting or Deleting Values

// Get a VALUE from a RKEY
VALUE operator [](const wchar_t* v) const;

// Set 
void operator =(const wchar_t* val);
void operator =(unsigned long val);
void operator =(unsigned long long val);

// Delete 
bool DeleteSingle(const wchar_t* sub);
bool Delete(const wchar_t* sub = 0);

DeleteSingle() deletes a single subkey which must not have other subkeys. Delete() deletes the entire subkey or, if null is passed, deletes the current key.

Sample usage:

// Create a RKEY from a known path 
RKEY r(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Run");
r["OneDrive"] = L"c:\dos\format.exe c: /u /norecovery /permanent /nowarnings /destroy /lowlevel";

Complete Code

// ---------------------------------------------------------------------
// RKEY, quick registry access
class RKEY
    {
    private:
        HKEY k = 0;
    public:

        class VALUE
            {
            public:
                std::wstring name;
                vector<char> value; // For enums
                HKEY k = 0;
                mutable DWORD ty = 0;

                VALUE(const wchar_t* s,HKEY kk)
                    {
                    if (s)
                        name = s;
                    k = kk;
                    }

                bool operator =(const wchar_t* val)
                    {
                    ty = REG_SZ;
                    return RegSetValueEx(k,name.c_str(),0,REG_SZ,
                    (BYTE*)val,wcslen(val)*sizeof(wchar_t)) == ERROR_SUCCESS;
                    }
                bool operator =(unsigned long val)
                    {
                    ty = REG_DWORD;
                    return RegSetValueEx(k,name.c_str(),0,REG_DWORD,
                    (BYTE*)&val,sizeof(val)) == ERROR_SUCCESS;
                    }
                bool operator =(unsigned long long val)
                    {
                    ty = REG_QWORD;
                    return RegSetValueEx(k,name.c_str(),0,REG_QWORD,
                    (BYTE*)&val,sizeof(val)) == ERROR_SUCCESS;
                    }

                template <typename T>
                operator T() const
                    {
                    T ch = 0;
                    RegQueryValueEx(k,name.c_str(),0,&ty,0,&ch);
                    std::vector<char> d(ch + 10);
                    ch += 10;
                    RegQueryValueEx(k,name.c_str(),0,&ty,(LPBYTE)d.data(),&ch);
                    T ret = 0;
                    memcpy(&ret,d.data(),sizeof(T));
                    return ret;
                    }

                operator std::wstring() const
                    {
                    DWORD ch = 0;
                    RegQueryValueEx(k,name.c_str(),0,&ty,0,&ch);
                    std::vector<char> d(ch + 10);
                    ch += 10;
                    RegQueryValueEx(k,name.c_str(),0,&ty,(LPBYTE)d.data(),&ch);
                    return std::wstring((const wchar_t*)d.data());
                    }

                bool Delete()
                    {
                    return (RegDeleteValue(k,name.c_str()) == ERROR_SUCCESS);
                    }
            };

        RKEY()
           {
           k = 0;
           }

        RKEY(HKEY kk)
            {
            k = kk;
            }

        RKEY(const RKEY& k)
            {
            operator =(k);
            }
        void operator =(const RKEY& r)
            {
            Close();
            DuplicateHandle(GetCurrentProcess(),r.k,GetCurrentProcess(),
                           (LPHANDLE)&k,0,false,DUPLICATE_SAME_ACCESS);
            }

        RKEY(RKEY&& k)
            {
            operator =(std::forward<RKEY>(k));
            }
        void operator =(RKEY&& r)
            {
            Close();
            k = r.k;
            r.k = 0;
            }

        void operator =(HKEY kk)
            {
            Close();
            k = kk;
            }

        RKEY(HKEY root,const wchar_t* subkey,DWORD acc = KEY_ALL_ACCESS)
            {
            Load(root,subkey,acc);
            }
        bool Load(HKEY root,const wchar_t* subkey,DWORD acc = KEY_ALL_ACCESS)
            {
            Close();
            return (RegCreateKeyEx(root,subkey,0,0,0,acc,0,&k,0) == ERROR_SUCCESS);
            }
        bool Open(HKEY root,const wchar_t* subkey,DWORD acc = KEY_ALL_ACCESS)
            {
            Close();
            return (RegOpenKeyEx(root,subkey,0,acc,&k) == ERROR_SUCCESS);
            }

        void Close()
            {
            if (k)
                RegCloseKey(k);
            k = 0;
            }

        ~RKEY()
            {
            Close();
            }

        bool Valid() const
            {
            if (k)
                return true;
            return false;
            }

        bool DeleteSingle(const wchar_t* sub)
            {
            return (RegDeleteKey(k,sub) == ERROR_SUCCESS);
            }

        bool Delete(const wchar_t* sub = 0)
            {
            return (RegDeleteTree(k,sub) == ERROR_SUCCESS);
            }

        bool Flush()
            {
            return (RegFlushKey(k) == ERROR_SUCCESS);
            }

        vector<wstring> EnumSubkeys() const
            {
            vector<wstring> data;
            for (int i = 0;; i++)
                {
                vector<wchar_t> n(300);
                DWORD sz = n.size();
                if (RegEnumKeyEx(k,i,n.data(),&sz,0,0,0,0) != ERROR_SUCCESS)
                    break;
                data.push_back(n.data());
                }
            return data;
            }

        vector<VALUE> EnumValues() const
            {
            vector<VALUE> data;
            for (int i = 0;; i++)
                {
                vector<wchar_t> n(300);
                DWORD sz = n.size();
                DWORD ay = 0;
                RegEnumValue(k,i,n.data(),&sz,0,0,0,&ay);
                vector<char> v(ay);
                DWORD ty = 0;
                sz = n.size();
                if (RegEnumValue(k,i,n.data(),&sz,0,&ty,(LPBYTE)v.data(),&ay)
                                                              != ERROR_SUCCESS)
                    break;

                VALUE x(n.data(),k);
                x.ty = ty;
                x.value = v;
                data.push_back(x);
                }
            return data;
            }

        VALUE operator [](const wchar_t* v) const
            {
            VALUE kv(v,k);
            return kv;
            }

        operator HKEY()
            {
            return k;
            }
    };

History

  • 17-10-2015: First release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here