[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); ....