windows-nt/Source/XPSP1/NT/shell/ext/hnw/shared/registry.cpp
2020-09-26 16:20:57 +08:00

427 lines
12 KiB
C++

//
// 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);
}