Click here to Skip to main content
15,896,118 members
Articles / Programming Languages / C++

Simple Stack-Based Wrapper for Windows and XML Registries

Rate me:
Please Sign up or sign in to vote.
4.19/5 (14 votes)
9 Aug 20049 min read 73.8K   796   19  
Left to my own devices, I tend to leak handles, leave keys open too long, close and re-open keys too often, and generally make a mess of the whole thing. And frankly, so do most of you (no insult intended).
#include <windows.h>
#include "Registry.h"
#include "RegistryImpl.h"

////////////////////////////////////////////////////////////////////////////////
// class ValueImpl
//

ValueImpl::ValueImpl(KeyImpl* pSuper, LPCTSTR name)
	:	m_refCount(0),
		m_pSuperKey(pSuper)
{
	_tcscpy(m_name, name);
	if (m_pSuperKey) m_pSuperKey->Hello(this);
}

ValueImpl::~ValueImpl()
{
	if (m_pSuperKey) m_pSuperKey->Goodbye(this);
	m_pSuperKey = NULL;
}

////////////////////////////////////////////////////////////////////////////////
// class RegKey
//

RegKey::RegKey(const RegKey& other)
:	m_pImpl(NULL)
{
	if (m_pImpl) m_pImpl->DecRef();
	m_pImpl = other.m_pImpl;
	m_pImpl->IncRef();
}

RegKey::RegKey(KeyImpl* pImpl)
:	m_pImpl(NULL)
{
	m_pImpl = pImpl;
	m_pImpl->IncRef();
}

RegKey::~RegKey()
{
	m_pImpl->DecRef();
	m_pImpl = NULL;
}

RegKey& 
RegKey::operator=(const RegKey& rhs)
{
	m_pImpl->DecRef();
	m_pImpl = rhs.m_pImpl;
	m_pImpl->IncRef();
	
	return *this;
}

bool
RegKey::operator==(const RegKey& other) const
{
	return m_pImpl == other.m_pImpl;
}

RegKey RegKey::Key(LPCTSTR name) const
{
	static TCHAR sep = TCHAR('\\');
	LPCTSTR next = _tcschr(name, sep);

	if (next) {
		TCHAR first[MAX_PATH];
		ZeroMemory(first, MAX_PATH);
		_tcsncpy(first, name, next - name);
		return RegKey(m_pImpl->GetSubKeyImpl(first)).Key(++next);
	} else {
		return RegKey(m_pImpl->GetSubKeyImpl(name));
	}
}

RegValue RegKey::Value(LPCTSTR name) const
{
	return RegValue(m_pImpl->GetValueImpl(name));
}

bool RegKey::IsValid() const
{
	return (m_pImpl != NULL);
}

////////////////////////////////////////////////////////////////////////////////
// class RegValue
//

RegValue::RegValue(const RegValue& other)
{
	if (m_pImpl) m_pImpl->DecRef();
	m_pImpl = other.m_pImpl;
	m_pImpl->IncRef();
}

RegValue::RegValue(ValueImpl* pImpl)
{
	m_pImpl = pImpl;
	m_pImpl->IncRef();
}

RegValue::~RegValue()
{
	m_pImpl->DecRef();
	m_pImpl = NULL;
}

RegValue& 
RegValue::operator=(const RegValue& rhs)
{
	m_pImpl->DecRef();
	m_pImpl = rhs.m_pImpl;
	m_pImpl->IncRef();

	return *this;
}

bool
RegValue::operator==(const RegValue& other) const
{
	return m_pImpl == other.m_pImpl;
}

bool 
RegValue::Get(bool& out)
{
	int temp;
	bool ret = m_pImpl->Get(temp);
	if (ret) {
		out = (temp != 0);
	}
	return ret;
}

bool 
RegValue::Set(const bool& in)
{
	int temp = in ? 1 : 0;
	return m_pImpl->Set(in);
}

bool 
RegValue::Get(int& out)
{
	return m_pImpl->Get(out);
}

bool 
RegValue::Set(const int& in)
{
	return m_pImpl->Set(in);
}

bool 
RegValue::Get(double& out)
{
	return m_pImpl->Get(out);
}

bool 
RegValue::Set(const double& in)
{
	return m_pImpl->Set(in);
}

bool 
RegValue::Get(LPTSTR out, int size)
{
	return m_pImpl->Get(out, size);
}

bool 
RegValue::Set(LPCTSTR in)
{
	return m_pImpl->Set(in);
}

bool 
RegValue::Get(void* out, int size, unsigned long& out_count)
{
	return m_pImpl->Get(out, size, out_count);
}

bool 
RegValue::Set(void* in, int size)
{
	return m_pImpl->Set(in, size);
}


////////////////////////////////////////////////////////////////////////////////
// testing
//

struct TEST_STRUCT {
	bool		bTest : 1;
	char		cTest : 7;
	float		fTest;
	double		dTest;
	char		csTest[16];
};

#ifdef TEST_REGISTRY
static RegKey TestReg()
{
	bool result = false;
	RegKey hkcu = RegKey::FromHKEY(HKEY_CURRENT_USER, result);
	RegKey autodesk = hkcu.Key("Software").Key("Autodesk");
	if (result) {
		RegKey software = hkcu.Key(_T("Software"));
		
		RegValue value = software.Value("Hello");
		VERIFY(value.Set("World"));

		TCHAR buf[MAX_PATH];
		if (value.Get(buf, MAX_PATH))
		{
			ASSERT(_tcscmp(buf, "World") == 0);
		}

		int val = -1;
		if (hkcu.Key("Software").Key("Autodesk").Key("Autodesk Mechanical")
			.Key("Mechanical Desktop").Key("3").Value("AMLOFTCHECK").Get(val))
		{
			ASSERT(val == 1);
		}

		bool val1 = false;
		if (hkcu.Key("Software").Key("Autodesk").Key("Autodesk Mechanical")
			.Key("Mechanical Desktop").Key("3").Value("AMLOPCHECK").Get(val1))
		{
			ASSERT(val1 == true);
		}
	}
	
	VERIFY(autodesk.Value("Hello").Set("World"));

	TEST_STRUCT test, test2;
	test.bTest = true;
	test.cTest = 'a';
	test.fTest = 3.14159f;
	test.dTest = 3.14159 * 2;
	strcpy(test.csTest, "abcdefghijlkmno");

	ZeroMemory(&test2, sizeof(TEST_STRUCT));

	VERIFY(autodesk.Value("Test").SetT(test));
	VERIFY(autodesk.Value("Test").GetT(test2));

	VERIFY(memcmp(&test, &test2, sizeof(TEST_STRUCT)) == 0);

	RegKey hkcu2 = RegKey::FromHKEY(HKEY_CURRENT_USER, result);
	if (result) {
		int count = 0;
		VERIFY(hkcu2.Key("Matter and Motion, Inc.").Key("Registry").Value("Count").Get(count));
		++count;
		VERIFY(hkcu2.Key("Matter and Motion, Inc.\\Registry").Value("Count").Set(count));
	}

	return autodesk;
}
#endif

// static RegKey test = TestReg();

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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
United States United States
A compiler warns of bogasity, ignore it at your peril. Unless you've done the compiler's job yourself, don't criticize it.

Comments and Discussions