Click here to Skip to main content
Click here to Skip to main content

A set of template classes for working with the registry

, 3 Jul 2002
Rate this:
Please Sign up or sign in to vote.
Writing generic code with templates and the C++ standard library.
<!-- Download Links --> <!-- Add the rest of your HTML here -->

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

About the Author

Daniel Andersson
Web Developer
Sweden Sweden
No Biography provided

Comments and Discussions

 
GeneralRe: not working with CString PinmemberDaniel Andersson9-Jul-02 22:07 
GeneralRe: not working with CString PinmemberUrban Olars17-Jan-04 7:03 
GeneralRe: not working with CString PinmemberDaniel Andersson18-Jan-04 21:59 
Generalhow excellent! Pinmemberregale1-Aug-05 20:39 
GeneralSweet! PinmemberJFH1089-Jul-02 4:57 
GeneralGreat stuff! PinmemberJohn Johansson7-Jul-02 23:10 
Questionhow about security...? PinmemberMario M.6-Jul-02 3:41 
Generallink PinmemberSteveKing4-Jul-02 22:45 
the article you mentioned can be found here:
http://www.codeproject.com/useritems/RegistryVars.asp

Generalexcellent...one question PinmemberLi Lirong4-Jul-02 20:56 
GeneralRe: excellent...one question PinmemberDaniel Andersson4-Jul-02 21:39 
GeneralRaise abstraction level Pinmembertstih4-Jul-02 20:47 
GeneralRe: Raise abstraction level Pinmembertstih4-Jul-02 20:49 
GeneralRe: Raise abstraction level PinmemberDaniel Andersson4-Jul-02 21:43 
GeneralRe: Raise abstraction level PinmemberBrian D Pearson5-Jul-02 2:47 
GeneralNice Work! PinmemberYasuhiko Yoshimura4-Jul-02 14:00 
GeneralRe: Nice Work! PinmemberDaniel Andersson4-Jul-02 21:44 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 4 Jul 2002
Article Copyright 2002 by Daniel Andersson
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid