|
|
//
// Registry.cpp
//
// Wrapper class to make the registry less painful.
//
// 3/04/1998 KenSh Created
// 3/28/1999 KenSh Added DeleteAllValues, CloneSubKey
//
#include "stdafx.h"
#include "Registry.h"
#ifdef _DEBUG
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
#ifndef ASSERT
#define ASSERT(x)
#endif
#ifndef _countof
#define _countof(ar) (sizeof(ar) / sizeof((ar)[0]))
#endif
CRegistry::CRegistry(HKEY hkeyParent, LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/, BOOL bCreateIfMissing /*=TRUE*/) { m_hKey = NULL;
ASSERT(hkeyParent != NULL); ASSERT(pszKey != NULL);
if (bCreateIfMissing) CreateKey(hkeyParent, pszKey, dwAccessFlags); else OpenKey(hkeyParent, pszKey, dwAccessFlags); }
CRegistry::~CRegistry() { CloseKey(); }
void CRegistry::CloseKey() { if (m_hKey != NULL) { RegCloseKey(m_hKey); m_hKey = NULL; } }
BOOL CRegistry::OpenKey(HKEY hkeyParent, LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/) { CloseKey(); return (ERROR_SUCCESS == RegOpenKeyEx(hkeyParent, pszKey, 0, dwAccessFlags, &m_hKey)); }
BOOL CRegistry::CreateKey(HKEY hkeyParent, LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/) { DWORD dwDisposition; CloseKey(); return (ERROR_SUCCESS == RegCreateKeyEx(hkeyParent, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, dwAccessFlags, NULL, &m_hKey, &dwDisposition)); }
BOOL CRegistry::OpenSubKey(LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/) { BOOL bResult = FALSE;
if (m_hKey) { HKEY hkey = m_hKey; m_hKey = NULL; bResult = OpenKey(hkey, pszKey, dwAccessFlags); RegCloseKey(hkey); }
return bResult; }
BOOL CRegistry::CreateSubKey(LPCTSTR pszKey, REGSAM dwAccessFlags /*=KEY_ALL_ACCESS*/) { BOOL bResult = FALSE;
if (m_hKey) { HKEY hkey = m_hKey; m_hKey = NULL; bResult = CreateKey(hkey, pszKey, dwAccessFlags); RegCloseKey(hkey); }
return bResult; }
DWORD RegDeleteSubKey(HKEY hkey, LPCTSTR pszSubKey) { { HKEY hSubKey; LONG err = RegOpenKeyEx(hkey, pszSubKey, 0, KEY_ALL_ACCESS, &hSubKey); if (ERROR_SUCCESS == err) { DWORD dwNumSubKeys; RegQueryInfoKey(hSubKey, NULL, NULL, NULL, &dwNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); for (DWORD iSubKey = dwNumSubKeys; iSubKey > 0; iSubKey--) { TCHAR szSubKey[260]; DWORD cchSubKey = _countof(szSubKey); if (ERROR_SUCCESS == RegEnumKeyEx(hSubKey, iSubKey-1, szSubKey, &cchSubKey, NULL, NULL, NULL, NULL)) { RegDeleteSubKey(hSubKey, szSubKey); } } RegCloseKey(hSubKey); } }
return RegDeleteKey(hkey, pszSubKey); }
BOOL CRegistry::DeleteSubKey(LPCTSTR pszKey) { if (m_hKey && RegDeleteSubKey(m_hKey, pszKey) == ERROR_SUCCESS) { return TRUE; } else { return FALSE; } }
// Zero is returned if and only if the value does not exist.
DWORD CRegistry::GetValueSize(LPCTSTR pszValueName) { DWORD dwSize = 0; if (m_hKey) RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, NULL, &dwSize); return dwSize; }
#ifdef _AFX
BOOL CRegistry::QueryStringValue(LPCTSTR pszValueName, CString& strResult) { BOOL bSuccess = FALSE;
if (m_hKey) { TCHAR szBuf[50]; // default buffer for short strings
DWORD dwSize = sizeof(szBuf); LONG lResult;
#if _REG_STRONGTYPES
DWORD dwType; lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)szBuf, &dwSize); if ((lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA) && dwType == REG_SZ) #else
lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)szBuf, &dwSize); if (lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA) #endif
{ if (lResult == ERROR_SUCCESS) { strResult = szBuf; bSuccess = TRUE; } else { int cch = (dwSize / sizeof(TCHAR)) - 1; LPTSTR psz = strResult.GetBufferSetLength(cch); bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)psz, &dwSize)); strResult.ReleaseBuffer(cch); } } }
if (!bSuccess) { strResult.Empty(); }
return bSuccess; } #endif // _AFX
#ifdef _AFX
CString CRegistry::QueryStringValue(LPCTSTR pszValueName) { CString str; QueryStringValue(pszValueName, str); return str; } #endif // _AFX
#ifdef _AFX
BOOL CRegistry::SetStringValue(LPCTSTR pszValueName, const CString& strData) { return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_SZ, (LPBYTE)(LPCTSTR)strData, (DWORD)strData.GetLength() + 1)); } #endif // _AFX
BOOL CRegistry::QueryStringValue(LPCTSTR pszValueName, LPTSTR pszBuf, int cchBuf, int* pNumCharsWritten) { BOOL bSuccess = FALSE; if (m_hKey) { #if _REG_STRONGTYPES
DWORD dwType; bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)pszBuf, (DWORD*)&cchBuf) && dwType == REG_SZ); #else
bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)pszBuf, (DWORD*)&cchBuf)); #endif
if (pNumCharsWritten != NULL) { if (!bSuccess) *pNumCharsWritten = 0; else *pNumCharsWritten = (int)((DWORD)cchBuf / sizeof(TCHAR)) - 1; } }
return bSuccess; }
// string is allocated with new TCHAR[], use delete[] to delete it.
#if _REG_ALLOCMEM
LPTSTR CRegistry::QueryStringValue(LPCTSTR pszValueName, int* pNumCharsWritten /*=NULL*/) { LPTSTR pszResult = NULL; int cch = 0;
if (m_hKey) { TCHAR szBuf[50]; // default buffer for short strings
DWORD dwSize = sizeof(szBuf); LONG lResult;
#if _REG_STRONGTYPES
DWORD dwType; lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)szBuf, &dwSize); if ((lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA) && dwType == REG_SZ) #else
lResult = RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)szBuf, &dwSize); if (lResult == ERROR_SUCCESS || lResult == ERROR_MORE_DATA) #endif
{ cch = (dwSize / sizeof(TCHAR)) - 1; pszResult = new TCHAR[cch+1];
if (pszResult != NULL) { if (lResult == ERROR_SUCCESS) { memcpy(pszResult, szBuf, dwSize); } else { if (ERROR_SUCCESS != RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)pszResult, &dwSize)) { delete [] pszResult; pszResult = NULL; cch = 0; } } } } } if (pNumCharsWritten != NULL) *pNumCharsWritten = cch;
return pszResult; } #endif // _REG_ALLOCMEM
BOOL CRegistry::SetStringValue(LPCTSTR pszValueName, LPCTSTR pszData) { return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_SZ, (LPBYTE)pszData, (DWORD)(lstrlen(pszData)+1) * sizeof(TCHAR))); }
BOOL CRegistry::QueryDwordValue(LPCTSTR pszValueName, DWORD* pVal) { BOOL bSuccess = FALSE;
if (m_hKey) { DWORD dwSize = sizeof(DWORD);
#if _REG_STRONGTYPES
DWORD dwType; if (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, (LPBYTE)pVal, &dwSize)) { if (dwType == REG_DWORD || (dwType == REG_BINARY && dwSize == sizeof(DWORD))) bSuccess = TRUE; } #else
bSuccess = (ERROR_SUCCESS == RegQueryValueEx(m_hKey, pszValueName, NULL, NULL, (LPBYTE)pVal, &dwSize)); #endif
}
return bSuccess; }
BOOL CRegistry::SetDwordValue(LPCTSTR pszValueName, DWORD dwVal) { return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_DWORD, (LPBYTE)&dwVal, sizeof(DWORD))); }
BOOL CRegistry::SetBinaryValue(LPCTSTR pszValueName, LPCVOID pvData, DWORD cbData) { return m_hKey && (ERROR_SUCCESS == RegSetValueEx(m_hKey, pszValueName, 0, REG_BINARY, (LPBYTE)pvData, cbData)); }
BOOL CRegistry::DeleteAllValues() { if (m_hKey) { TCHAR szValueName[MAX_PATH]; for (;;) { DWORD cbValueName = _countof(szValueName); if (ERROR_SUCCESS != RegEnumValue(m_hKey, 0, szValueName, &cbValueName, NULL, NULL, NULL, NULL)) return TRUE; if (!DeleteValue(szValueName)) return FALSE; } } return TRUE; }
// Copies the named subkey from this registry key to the named subkey in the target registry key.
BOOL CRegistry::CloneSubKey(LPCTSTR pszExistingSubKey, CRegistry& regDest, BOOL bRecursive) { ASSERT(pszExistingSubKey != NULL);
if (!m_hKey || !regDest.m_hKey) return FALSE;
CRegistry regSrc; if (!regSrc.OpenKey(m_hKey, pszExistingSubKey, KEY_READ)) { ASSERT(FALSE); return FALSE; }
DWORD cbAlloc = 256; HANDLE hHeap = GetProcessHeap(); BYTE* pbData = (BYTE*)HeapAlloc(hHeap, 0, cbAlloc); if (pbData) { // Copy values first
for (DWORD iValue = 0; ; iValue++) { TCHAR szValueName[MAX_PATH]; DWORD cbValueName = _countof(szValueName); DWORD dwType; DWORD cbData;
if (ERROR_SUCCESS != RegEnumValue(regSrc.m_hKey, iValue, szValueName, &cbValueName, NULL, &dwType, NULL, &cbData)) break;
if (cbData > cbAlloc) { BYTE* pbDataNew = (BYTE*)HeapReAlloc(hHeap, 0, pbData, cbData + 256); if (pbDataNew == NULL) { HeapFree(hHeap, 0, pbData); return FALSE; } pbData = pbDataNew; cbAlloc = cbData + 256; }
if (ERROR_SUCCESS != RegQueryValueEx(regSrc.m_hKey, szValueName, NULL, NULL, pbData, &cbData)) break; // REVIEW: return FALSE?
if (ERROR_SUCCESS != RegSetValueEx(regDest.m_hKey, szValueName, 0, dwType, pbData, cbData)) break; // REVIEW: return FALSE? (need to free memory)
}
HeapFree(hHeap, 0, pbData); }
// Copy subkeys
if (bRecursive) { for (DWORD iSubKey = 0; ; iSubKey++) { TCHAR szKeyName[MAX_PATH]; DWORD cbKeyName = _countof(szKeyName); if (ERROR_SUCCESS != RegEnumKeyEx(regSrc.m_hKey, iSubKey, szKeyName, &cbKeyName, NULL, NULL, NULL, NULL)) break;
CRegistry regDest2; if (!regDest2.CreateKey(regDest.m_hKey, szKeyName, KEY_ALL_ACCESS)) return FALSE;
if (!regSrc.CloneSubKey(szKeyName, regDest2, TRUE)) return FALSE; } }
return TRUE; }
// Copies the named subkey to a new subkey of this registry class, with a new name.
BOOL CRegistry::CloneSubKey(LPCTSTR pszExistingSubKey, LPCTSTR pszNewSubKey, BOOL bRecursive) { ASSERT(pszExistingSubKey != NULL); ASSERT(pszNewSubKey != NULL); ASSERT(0 != lstrcmpi(pszExistingSubKey, pszNewSubKey)); // names can't be the same
CRegistry regDest; if (!m_hKey || !regDest.CreateKey(m_hKey, pszNewSubKey, KEY_ALL_ACCESS)) { return FALSE; }
return CloneSubKey(pszExistingSubKey, regDest, bRecursive); }
|