Click here to Skip to main content
15,867,594 members
Articles / Programming Languages / C++
Article

A set of template classes for working with the registry

Rate me:
Please Sign up or sign in to vote.
4.93/5 (31 votes)
3 Jul 20023 min read 164.4K   1.1K   65   38
Writing generic code with templates and the C++ standard library.

Yet another registry class!? But why?

I recently read an article here on CodeProject that described a set of classes to work with the registry. A request for a template version of the classes inevitably popped up. The author of that article had a couple of reasons for not writing a template version. After thinking about it for a while I came to the conclusion that a template could indeed be made. So here it is.

Usage

The class is really three classes. However, instead of making one class for each type to store I made one template class for each type of data type that the registry supports. Well not really. Classes for string, dword and binary storage are provided. I feel that these three cover most things one would want to store in the registry.

So, say we want to store a string:

typedef registry_string<std::string> regstring;

regstring str("Software\\RegValueTest\\blah", HKEY_CURRENT_USER);

str = "Hello world!";
std::string stored = str;
std::cout << stored << std::endl;
First a convenience typedef. Our template type is std::string, that's the type we wish to load or store. Because we use the registry_string template the string will be stored with type REG_SZ in the registry. Storing is as easy as assigning to the registring object. Reading from the registry is also performed this way, simply create an object of the right type and assign from the regstring. All this is courtesy of operator= and operator T (conversion operator). If one doesn't like the use of a conversion operator (they're not exactly the best thing in the world) it's enough just to change the name of the functions.

To store a POINT:

typedef registry_binary<POINT> regpoint;

regpoint pnt("Software\\RegValueTest\\blah", HKEY_CURRENT_USER);

POINT p = {99,88};
pnt = p;
POINT stored = p;
std::cout << stored.x << "," << stored.y << std::endl;
The last class, registry_int, works the same way as the other two so an example should not be necessary. These three classes can be used to store a large number of classes. A few examples:
typedef registry_string<std::string>    regstring;
typedef registry_int<bool>              regbool;
typedef registry_binary<RECT>           regRECT;
typedef registry_string<double>         regdouble;

A double in a registry_string?

The registry_string template class is quite handy. To be able to store an arbitrary type in a string a
std::stringstream
is used. This enables the use of this template class with any type that can serialize itself to a stream. This includes the built in types; bool, double, char etc. The registry_string<double> will convert the double the user wishes to store into a textual representation of the value. This might be better than storing a binary version of the number (but if you want to store it in binary then it's as simple as making a registry_binary<double>).

The classes are also capable of some other nice things:

registry_value val("Software\\RegValueTest\\blah", HKEY_CURRENT_USER);

if(val.exists())
{
    val.remove_value();
    val.remove_key();
}
This would check if the value existed and if that was the case remove both the value and the key. The registry_value class is a base class for the other three. More on that in the next section.

Implementation

I put the functions that all three classes used in a common base class, registry_value. Here's a simplified overview of that class:
class registry_value
{
    public:
        registry_value(const std::string & name, HKEY base_);

        bool exists();
        void remove_value(void);
        void remove_key(void);

    protected:

        bool open(bool write_access);
        void close(void);
        bool query_value(DWORD * type, DWORD * size, void * buffer);
        bool set_value(DWORD type, DWORD size, const void * buffer);

    private:

        void make_path(const std::string & name);

        HKEY key;
        HKEY base;

        std::string valuename;
        std::string keyname;
};
Nothing spectacular here. The public interface consists of the three functions described above. The protected interface has functions for gaining access to a key and reading/writing. The private section includes a utility function and data that the other functions use. As described above, the class can be used on it's own to check if a value exists etc.

As clearly visible, registry_value is not a template class. Let's take a closer look at registry_binary.

template<class T>
class registry_binary : public registry_value
{
    public:
        registry_binary(const std::string & name, HKEY base) : 
            registry_value(name, base)
        {
        }
The constructor simply forwards the parameters to the base class.
operator T()
{
    T returnval = T();

    if(open(false) == true)
    {
        DWORD type, size = sizeof(T);
        if(query_value(&type, &size, &returnval) == true)
        {
            assert(type == REG_BINARY);
        }

        close();
    }

    return returnval;
}
The conversion operator handles reading from the registry. Nothing particularly noteworthy here except perhaps the initialization of the value we store the data in. The reason for '= T();' is that it ensures that returnval doesn't contain random crap data since this value is returned from the function unchanged if something goes wrong with the queries.
const registry_binary & operator=(const T & value)
{
    if(open(true) == true)
    {
        set_value(REG_BINARY, sizeof(T), &value);
        close();
    }

    return *this;
}
The operator= handles writing to the registry. The set_value function defined in registry_value and it wants a type, a size and a pointer to the data. That's all there is to registry_binary.

Closing words

This article is not so much about registry access itself but more about showing how templates can be used to get more functionality with less code.

As a side note: there is also a specialized version for registry_string<std::string> that omits the stringstream code that registry_string normally uses.

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


Written By
Web Developer
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionBest registry class ever used. Pin
Member 1486653818-Jun-20 0:14
Member 1486653818-Jun-20 0:14 
GeneralNice work Pin
CAThomas21-Feb-08 11:51
CAThomas21-Feb-08 11:51 
GeneralI love it! Pin
xcheap23-Aug-07 13:22
xcheap23-Aug-07 13:22 
GeneralUNICODE Pin
RedFraggle30-May-07 6:58
RedFraggle30-May-07 6:58 
GeneralRe: UNICODE Pin
cetcet21-Oct-09 11:30
cetcet21-Oct-09 11:30 
GeneralVery Good ... Pin
Dan Madden23-Jun-06 16:03
Dan Madden23-Jun-06 16:03 
GeneralGreat Article! Pin
Carlo McWhirter24-Aug-05 12:30
Carlo McWhirter24-Aug-05 12:30 
GeneralRead a String value Pin
Anonymous19-May-05 7:05
Anonymous19-May-05 7:05 
GeneralError using in MFC project Pin
Edward11110-May-05 14:26
Edward11110-May-05 14:26 
GeneralRe: Error using in MFC project Pin
Coruscant10-May-05 22:17
Coruscant10-May-05 22:17 
Generalsimply the best Pin
osy16-Feb-05 1:21
osy16-Feb-05 1:21 
GeneralGreat class! (and a small enhancement) Pin
mblais2-Dec-03 4:00
mblais2-Dec-03 4:00 
GeneralReally fantastic! Pin
Robert W.11-Apr-03 3:29
Robert W.11-Apr-03 3:29 
QuestionUNICODE support? Pin
ulion9-Apr-03 21:09
ulion9-Apr-03 21:09 
I wonder how registry_value support UNICODE?
GeneralWindows2000 registry Pin
Shabrawy9112-Apr-03 11:43
Shabrawy9112-Apr-03 11:43 
GeneralDayamn GOOD! Pin
nodman23-Mar-03 18:38
nodman23-Mar-03 18:38 
GeneralVery useful! Pin
jamiehale23-Sep-02 5:42
jamiehale23-Sep-02 5:42 
GeneralRe: Very useful! Pin
Daniel Andersson23-Sep-02 22:19
Daniel Andersson23-Sep-02 22:19 
GeneralOMG Thank you. Pin
daerid17-Sep-02 6:59
sussdaerid17-Sep-02 6:59 
QuestionHow to access default(unnamed) values? Pin
Jinhyuck Jung11-Jul-02 23:43
Jinhyuck Jung11-Jul-02 23:43 
AnswerRe: How to access default(unnamed) values? Pin
Daniel Andersson11-Jul-02 23:54
Daniel Andersson11-Jul-02 23:54 
Generalnot working with CString Pin
SteveKing9-Jul-02 7:49
SteveKing9-Jul-02 7:49 
GeneralRe: not working with CString Pin
Daniel Andersson9-Jul-02 22:07
Daniel Andersson9-Jul-02 22:07 
GeneralRe: not working with CString Pin
Urban Olars17-Jan-04 7:03
Urban Olars17-Jan-04 7:03 
GeneralRe: not working with CString Pin
Daniel Andersson18-Jan-04 21:59
Daniel Andersson18-Jan-04 21:59 

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.