Back to Amir Israeli Homepage

[CRegistry : A wrapper around the Registry API's]

This article was contributed by Amir Israeli Amir Israeli.
Amir Israeli Web Site

Environment: Win 95/98 VC6 SP4 Updates include :
*)All path functions are located in different object ("CPath")
*)Use of references instead of pointers in most places .
*)Overload GetValue, SetValue etc. (single name)
*)Some fixed bugs (for example : IsExistValue())

Using the registry might be a tedious job , especially when an application has a lot of persistent data to save somewhere . The usage of API's requires a lot of effort : to open keys , get information , close them . Installing and especially UnInstalling requires additional work . Giving an app a full persistence in and out takes a few days . This Article describes a class which is a wrapper of API's built for those who whouldn't like to mess up with keys , data types etc. This article includes a small dialog app that does the basic functions of loading , saving , installing and uninstalling keys and values on your computer.

In the begining there was the HKEY . HKEY made us all unhappy , we had to open it , close , query for it , query for its' values , find it , enumerate it , create it , delete it . We also had to remember an already defined HKEY's (respect them) we had to use sub path's in addition to predifined keys , Why simply not using a full path ?

CRegistry class contains several groups of functions :
Simple path functions : appending paths , separating path parts , get some level of path (all treat registry path as directory path) for example 'FormulatePath' which separates a full path (arrives in 'CString *strRegPath' to 2 parts : the main key (such as HKEY_LOCAL_MACHINE) and the sub key. All Path functions are located now in "CPath" object.

BOOL CPath::FormulatePath( CString &strRegPath, HKEY &hKey)
{
	CString strPath = strRegPath;
	Trim(strPath);

	int place = strPath.Find(_T('\\'));
	if (place==-1) 
		place = strPath.GetLength(); //only includes a root item
	CString strRoot = strPath.Left(place);
	if (!StringRoot2key( strRoot, hKey))	{

#ifdef _DEBUG  //debug version writes an error
		CMessage::Error("contains no such root");
#endif

		return FALSE;
	}

	strRegPath = strPath.Mid(place);
	Trim(strRegPath);
	return TRUE;
}
// AppendPath also writes the path (got) in debug ver.
BOOL CPath::AppendPath(CString &strRegTarget,LPCTSTR lpszRegSrc)
{
    Trim(strRegTarget);
    CString src = lpszRegSrc;
	Trim(src);
	strRegTarget += _T('\\');
	strRegTarget += src;
	Trim(strRegTarget);
#ifdef _DEBUG
	CMessage::msg(strRegTarget);
#endif
	return TRUE;
}
//functions to count number of levels and getting some ...
int CPath::CountLevels( LPCTSTR lpszRegPath);
BOOL CPath::GetLevel( int iLevel, LPCTSTR lpszRegPath, CString &strRegOut);

Enumeration functions : to enumerate keys , multi-level enumeration (means all "sub-directories" of a keys , function may return full paths in an array or relative paths to the key being enumerated.

Wrappers of basic functions : Open ,Close ... : In general the functions that accept a full key path are fublic and the call internal functions that make use of the HKEY : see Open example.

BOOL CRegistry::DeleteKey( LPCTSTR lpszRegPath ) //This is public
BOOL CRegistry::DeleteKey( HKEY &hKey, LPCTSTR lpszRegPath) 

BOOL CRegistry::Open( LPCTSTR lpszRegPath, HKEY &hNewKey, REGSAM samDesired)
{
	HKEY hRootKey;
	CString strPath = lpszRegPath;
	if (!GetPathObj().FormulatePath( strPath, hRootKey))
		return FALSE;
	return Open( hRootKey, strPath, hNewKey, samDesired);	
}
BOOL CRegistry::Open( HKEY &hKey, LPCTSTR lpszRegPath, HKEY &hNewKey, REGSAM samDesired)
{
	//hNewKey=NULL;
	LONG lResult = ERROR_SUCCESS;
	if (::lstrlen(lpszRegPath)>0) //not in root key (need to open)
		  lResult = ::RegOpenKeyEx( hKey, lpszRegPath, 0, samDesired, &hNewKey);
	else  hNewKey = hKey;//we are in root key dont need to open
	return (lResult==ERROR_SUCCESS);
}

If you watch close you find there a flag that indicates whether to flush a key whenever it's closed

BOOL CRegistry::Close(HKEY &hKey)
{
	LONG lResult=ERROR_SUCCESS;
	if (bAutoFlush) Flush(hKey);//flushing this key
	if (!IsRoot(hKey)) //closing only is this is not the root
		lResult = RegCloseKey(hKey);
	return (lResult == ERROR_SUCCESS);
}
more examples:
BOOL CRegistry::IsKeyHasSubKeys( LPCTSTR lpszRegPath) //public
int CRegistry::GetSubKeyCount( LPCTSTR lpszRegPath) //public
BOOL CRegistry::IsKeyHasSubKeys( HKEY &hRegKey) //private
int CRegistry::GetSubKeyCount(HKEY &hKey) //private

Conversion functions : from string representation of HKEY's to the HKEY struct(DWORD). for example 'Rootkey2String' converts HKEY->string representation.
///////// Conversion between strings that represent root-keys
//to root keys and vice-versa. (protected functions)
BOOL CPath::RootKey2String( CString &strRegSrc,HKEY &hKey)
{
	if (hKey == HKEY_CLASSES_ROOT) {
		strRegSrc = _T("HKEY_CLASSES_ROOT");
		return TRUE;
	}	
	else if (hKey == HKEY_CURRENT_CONFIG) {
		strRegSrc = _T("HKEY_CURRENT_CONFIG");
		return TRUE;
	}	
	else if (hKey == HKEY_CURRENT_USER)	{
	...
}

IsExist... functions : check for existence of keys and values.

Function to set/get values : high level functons : such as

BOOL CRegistry::SetValue( LPCTSTR lpszRegPath, LPCTSTR lpszValueName, LPCTSTR pData) //sets a string value
{
	return SetValue(lpszRegPath, lpszValueName, (LPBYTE)pData, ::lstrlen(pData), REG_SZ);
}
BOOL CRegistry::SetValue( LPCTSTR lpszRegPath, LPCTSTR lpszValueName, DWORD *pData) 
{
	return SetValue(lpszRegPath, lpszValueName, (LPBYTE)pData, sizeof(DWORD), REG_DWORD);
}
BOOL CRegistry::SetValue( LPCTSTR lpszRegPath, LPCTSTR lpszValueName, int *pData)
{
....
}
high level functions call a low level one 'SetValue' that does the conversion form full string path to HKEY and sub path . There are also functions to create keys (high level functions for pre-defined types and low level)
BOOL GetValue( LPCTSTR lpszRegPath, LPCTSTR lpszValueName, CString *pData);
BOOL GetValue( LPCTSTR lpszRegPath, LPCTSTR lpszValueName, DWORD *pData);
BOOL GetValue( LPCTSTR lpszRegPath, LPCTSTR lpszValueName, int *pData);
BOOL GetValue( LPCTSTR lpszRegPath, LPCTSTR lpszValueName, float *pData);
....

Multiple-level key enumeration is used when implementing some Shell searches (as in the case of creating the New File Menu)

Downloads

Download demo project - 115 Kb
Download source - 9 Kb

History

Date Posted: July 20, 2000
Updated August 25, 2000

Home  |  Links  |  About