links77
links77

Reputation: 819

Win API wrapper classes for handles

Writing a wrapper class for a handle that only gets passed by value is relatively easy. I am trying to determine what the best way is to encapsulate handles that need to be passed by address.

For example, writing a wrapper for something like SC_HANDLE that gets passed by value to QueryServiceConfig() is not that difficult. One can either implement a member function like .GetHandle() or implement operator().

The problem (for me at least) is API functions like RegOpenKeyEx() that wants the address of a HKEY.

I've read that overloading operator & is generally a bad idea. What is the recommended way to keep encapsulation (or as much of it as possible) and especially resource collection while allowing API functions access?

Upvotes: 8

Views: 1963

Answers (1)

Johann Gerell
Johann Gerell

Reputation: 25591

You can always add another layer of indirection to avoid the awful overloading of operator& and ugly Attach or Detach and return a pre-wrapped instance from there.

If you can use C++0x in VS2010 or gcc, or have other ways of accessing std::unique_ptr<>, then you can do this (error checking omitted for brevity):

struct hkey_deleter
{
    void operator()(HKEY hkey)
    {
        ::RegCloseKey(hkey);
    }
};

typedef std::unique_ptr<HKEY__, hkey_deleter> regkey;

regkey MyRegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired)
{
    HKEY hOpenedKey = NULL;
    ::RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, &hOpenedKey);

    return regkey(hOpenedKey);
}

void SomewhereElse()
{
    ...
    regkey r = MyRegOpenKeyEx(HKEY_CLASSES_ROOT, nullptr, 0, KEY_READ);
    ...
}

The hkey_deleter will make sure that the registry key gets closed when the scope is exited or regkey::reset() is called.

Upvotes: 4

Related Questions