65.9K
CodeProject is changing. Read more.
Home

Happy Registry: A Quick Wrapper for the Win32 Database

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (10 votes)

Oct 17, 2015

CPOL

1 min read

viewsIcon

17232

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