[CRegistry : A wrapper around the Registry API's] | |||
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 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); ....