// // MODULE: "RegUtil.cpp" // // PURPOSE: class CRegUtil // Encapsulates access to system registry. // This is intended as generic access to the registry, independent of any particular // application. // // PROJECT: first developed as part of Belief Network Editing Tools ("Argon") // Later modified to provide more extensive features as part of version 3.0 of the // Online Troubleshooter (APGTS) // // AUTHOR: Lonnie Gerrald (LDG), Oleg Kalosha, Joe Mabel // // ORIGINAL DATE: 3/25/98 // // NOTES: // 1. The Create, Open, and Close functions support a model where m_hKey represents a // "position" in the registry. Successive calls to Create() or Open() migrate deeper // into the registry hierarchy. Close closes all keys encountered on the way down to // the current m_hKey. // // // Version Date By Comments //-------------------------------------------------------------------- // V0.1(Argon) 3/25/98 LDG // V3.0 8/??/98 OK // V3.0 9/9/98 JM // #include "stdafx.h" #include "regutil.h" #include "event.h" #include "baseexception.h" #include "CharConv.h" ////////////////////////////////////////////////////////////////////// // CRegUtil ////////////////////////////////////////////////////////////////////// CRegUtil::CRegUtil() : m_hKey(NULL), m_WinError(ERROR_SUCCESS) { } CRegUtil::CRegUtil(HKEY key) : m_hKey(key), m_WinError(ERROR_SUCCESS) { } CRegUtil::~CRegUtil() { Close(); } // creates the specified key. If the key already exists in the registry, the function opens it. // returns true on success, false otherwise. bool CRegUtil::Create(HKEY hKeyParent, const CString& strKeyName, bool* bCreatedNew, REGSAM access /*=KEY_ALL_ACCESS*/) { HKEY hRetKey = NULL; DWORD dwDisposition = 0; m_WinError = ::RegCreateKeyEx( hKeyParent, strKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, access, NULL, &hRetKey, &dwDisposition ); if(m_WinError == ERROR_SUCCESS) { m_hKey = hRetKey; *bCreatedNew = dwDisposition == REG_CREATED_NEW_KEY ? true : false; try { m_arrKeysToClose.push_back(hRetKey); } catch (exception& x) { CString str; // Note STL exception in event log. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), CCharConversion::ConvertACharToString(x.what(), str), _T(""), EV_GTS_STL_EXCEPTION ); } return true; } return false; } // Unlike CRegUtil::Create, CRegUtil::Open does not create the specified key if the key does not // exist in the registry. Thus it can be used to test whether the key exists. // returns true on success, false otherwise. bool CRegUtil::Open(HKEY hKeyParent, const CString& strKeyName, REGSAM access /*=KEY_ALL_ACCESS*/) { HKEY hRetKey = NULL; m_WinError = ::RegOpenKeyEx( hKeyParent, strKeyName, 0, access, &hRetKey ); if(m_WinError == ERROR_SUCCESS) { m_hKey = hRetKey; try { m_arrKeysToClose.push_back(hRetKey); } catch (exception& x) { CString str; // Note STL exception in event log. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), CCharConversion::ConvertACharToString(x.what(), str), _T(""), EV_GTS_STL_EXCEPTION ); } return true; } return false; } // creates the specified subkey of m_hKey. If the key already exists in the registry, the function opens it. // returns true on success, false otherwise. bool CRegUtil::Create(const CString& strKeyName, bool* bCreatedNew, REGSAM access /*=KEY_ALL_ACCESS*/) { return Create(m_hKey, strKeyName, bCreatedNew, access); } // opens the specified subkey of m_hKey. // Unlike CRegUtil::Create, CRegUtil::Open does not create the specified key if the key does not // exist in the registry. Thus it can be used to test whether the key exists. // returns true on success, false otherwise. bool CRegUtil::Open(const CString& strKeyName, REGSAM access /*=KEY_ALL_ACCESS*/) { return Open(m_hKey, strKeyName, access); } // Close all keys encountered on the way down to the current m_hKey. void CRegUtil::Close() { for (vector::reverse_iterator i = m_arrKeysToClose.rbegin(); i != m_arrKeysToClose.rend(); i++) ::RegCloseKey( *i ); m_arrKeysToClose.clear(); } bool CRegUtil::DeleteSubKey(const CString& strSubKey) { // What does m_hKey point to after a successful deletion? RAB-981116. m_WinError = ::RegDeleteKey(m_hKey, strSubKey); if (m_WinError == ERROR_SUCCESS) return true; return false; } bool CRegUtil::DeleteValue(const CString& strValue) { m_WinError = ::RegDeleteValue(m_hKey, strValue); if (m_WinError == ERROR_SUCCESS) return true; return false; } bool CRegUtil::SetNumericValue(const CString& strValueName, DWORD dwValue) { BYTE* pData = (BYTE*)&dwValue; m_WinError = ::RegSetValueEx( m_hKey, strValueName, 0, REG_DWORD, pData, sizeof(DWORD) ); if (m_WinError == ERROR_SUCCESS) return true; return false; } bool CRegUtil::SetStringValue(const CString& strValueName, const CString& strValue) { BYTE* pData = (BYTE*)(LPCTSTR)strValue; m_WinError = ::RegSetValueEx( m_hKey, strValueName, 0, REG_SZ, pData, strValue.GetLength()+sizeof(TCHAR) ); if (m_WinError == ERROR_SUCCESS) return true; return false; } bool CRegUtil::SetBinaryValue(const CString& strValueName, char* buf, long buf_len) { BYTE* pData = (BYTE*)buf; m_WinError = ::RegSetValueEx( m_hKey, strValueName, 0, REG_BINARY, pData, buf_len ); if (m_WinError == ERROR_SUCCESS) return true; return false; } bool CRegUtil::GetNumericValue(const CString& strValueName, DWORD& dwValue) { DWORD tmp = 0; BYTE* pData = (BYTE*)&tmp; DWORD type = 0; DWORD size = sizeof(DWORD); m_WinError = ::RegQueryValueEx( m_hKey, strValueName, NULL, &type, pData, &size ); if (type != REG_DWORD) return false; if (m_WinError == ERROR_SUCCESS) { dwValue = tmp; return true; } return false; } bool CRegUtil::GetStringValue(const CString& strValueName, CString& strValue) { BYTE* pData = NULL; DWORD type = 0; DWORD size = 0; // determine data size m_WinError = ::RegQueryValueEx( m_hKey, strValueName, NULL, &type, NULL, &size ); if (m_WinError != ERROR_SUCCESS) return false; if (type != REG_SZ && type != REG_EXPAND_SZ) return false; bool bRet = false; // should be only one return from here down: we're about to // alloc pData and must make sure it's correctly cleaned up. try { pData = new BYTE[size]; } catch (bad_alloc&) { return false; } memset(pData, 0, size); m_WinError = ::RegQueryValueEx( m_hKey, strValueName, NULL, &type, pData, &size ); if (m_WinError == ERROR_SUCCESS) { if (type == REG_EXPAND_SZ ) { BYTE* pDataExpanded = NULL; DWORD dwExpandedSize; // first we call ExpandEnvironmentStrings just to get the length // casting away unsignedness dwExpandedSize = ::ExpandEnvironmentStrings( reinterpret_cast(pData), reinterpret_cast(pDataExpanded), 0); if (dwExpandedSize > 0) { try { pDataExpanded = new BYTE[dwExpandedSize]; // then we call ExpandEnvironmentStrings again to get the expanded value // casting away unsignedness if (::ExpandEnvironmentStrings( reinterpret_cast(pData), reinterpret_cast(pDataExpanded), dwExpandedSize)) { strValue = (LPTSTR)pDataExpanded; delete [] pDataExpanded; bRet = true; } } catch (bad_alloc&) { // Note memory failure in event log. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), _T(""), _T(""), EV_GTS_CANT_ALLOC ); } } } else { strValue = (LPTSTR)pData; bRet = true; } } delete [] pData; return bRet; } // The second parameter should be passed in as the address of a char *. // Note that if this returns true, *ppBuf will point to a new buffer on the heap. // The caller of this function is responsible for deleting that. bool CRegUtil::GetBinaryValue(const CString& strValueName, char** ppBuf, long* pBufLen) { BYTE* pData = NULL; DWORD type = 0; DWORD size = 0; // determine data size m_WinError = ::RegQueryValueEx( m_hKey, strValueName, NULL, &type, NULL, &size ); if (m_WinError != ERROR_SUCCESS || type != REG_BINARY) return false; try { // Increase the buffer size by one over what we need. Small price to // pay for processing convenience elsewhere. pData = new BYTE[size+1]; } catch (bad_alloc&) { return false; } memset(pData, 0, size); m_WinError = ::RegQueryValueEx( m_hKey, strValueName, NULL, &type, pData, &size ); if (m_WinError == ERROR_SUCCESS) { // Null terminate the binary string for processing convenience elsewhere. pData[size]= 0; *ppBuf = (char*)pData; *pBufLen = size; return true; } delete [] pData; return false; }