Click here to Skip to main content
14,969,910 members
Articles / Desktop Programming / Win32
Article
Posted 16 Oct 2015

Stats

13.6K views
17 bookmarked

Happy Registry: A Quick Wrapper for the Win32 Database

Rate me:
Please Sign up or sign in to vote.
5.00/5 (9 votes)
23 Oct 2015CPOL1 min read
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

C++
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:

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

Querying or Enumerating Values

C++
// 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:

C++
// 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

C++
// 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:

C++
// 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

C++
// ---------------------------------------------------------------------
// 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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Michael Chourdakis
Software Developer
Greece Greece
I'm working in C++, PHP , Java, Windows, iOS, Android and Web (HTML/Javascript/CSS).

I 've a PhD in Digital Signal Processing and Artificial Intelligence and I specialize in Pro Audio and AI applications.

My home page: https://www.turbo-play.com

Comments and Discussions

 
QuestionHave you consider to post this as a tip? Pin
Nelek22-Oct-15 22:51
protectorNelek22-Oct-15 22:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.