#include "pch.h" #pragma hdrstop #include "registry.h" RegKey::RegKey( void ) : m_hkeyRoot(NULL), m_hkey(NULL) { DBGTRACE((DM_REG, DL_MID, TEXT("RegKey::RegKey [default]"))); } RegKey::RegKey( HKEY hkeyRoot, LPCTSTR pszSubKey ) : m_hkeyRoot(hkeyRoot), m_hkey(NULL), m_strSubKey(pszSubKey) { DBGTRACE((DM_REG, DL_MID, TEXT("RegKey::RegKey"))); // // Nothing to do. // } RegKey::~RegKey( void ) { DBGTRACE((DM_REG, DL_MID, TEXT("RegKey::~RegKey"))); Close(); } HRESULT RegKey::Open( REGSAM samDesired, // Access mask (i.e. KEY_READ, KEY_WRITE etc.) bool bCreate // Create key if it doesn't exist? ) const { DBGTRACE((DM_REG, DL_HIGH, TEXT("RegKey::Open"))); DBGPRINT((DM_REG, DL_HIGH, TEXT("\thkeyRoot = 0x%08X, SubKey = \"%s\""), m_hkeyRoot, m_strSubKey.Cstr())); DWORD dwResult = ERROR_SUCCESS; Close(); if (bCreate) { DWORD dwDisposition; dwResult = RegCreateKeyEx(m_hkeyRoot, (LPCTSTR)m_strSubKey, 0, NULL, 0, samDesired, NULL, &m_hkey, &dwDisposition); } else { dwResult = RegOpenKeyEx(m_hkeyRoot, (LPCTSTR)m_strSubKey, 0, samDesired, &m_hkey); } return HRESULT_FROM_WIN32(dwResult); } void RegKey::Attach( HKEY hkey ) { Close(); m_strSubKey.Empty(); m_hkeyRoot = NULL; m_hkey = hkey; } void RegKey::Detach( void ) { m_hkey = NULL; } void RegKey::Close( void ) const { DBGTRACE((DM_REG, DL_HIGH, TEXT("RegKey::Close"))); DBGPRINT((DM_REG, DL_HIGH, TEXT("\thkeyRoot = 0x%08X, SubKey = \"%s\""), m_hkeyRoot, m_strSubKey.Cstr())); if (NULL != m_hkey) { // // Do this little swap so that the m_hkey member is NULL // when the actual key is being closed. This lets the async // change proc determine if it was signaled because of a true // change or because the key was being closed. // HKEY hkeyTemp = m_hkey; m_hkey = NULL; RegCloseKey(hkeyTemp); } } // // This is the basic form of GetValue. All other forms of // GetValue() call into this one. // HRESULT RegKey::GetValue( LPCTSTR pszValueName, DWORD dwTypeExpected, LPBYTE pbData, int cbData ) const { DWORD dwType; DWORD dwResult = RegQueryValueEx(m_hkey, pszValueName, 0, &dwType, pbData, (LPDWORD)&cbData); if (ERROR_SUCCESS == dwResult && dwType != dwTypeExpected) dwResult = ERROR_INVALID_DATATYPE; return HRESULT_FROM_WIN32(dwResult); } // // Get a DWORD value (REG_DWORD). // HRESULT RegKey::GetValue( LPCTSTR pszValueName, DWORD *pdwDataOut ) const { return GetValue(pszValueName, REG_DWORD, (LPBYTE)pdwDataOut, sizeof(DWORD)); } // // Get a byte buffer value (REG_BINARY). // HRESULT RegKey::GetValue( LPCTSTR pszValueName, LPBYTE pbDataOut, int cbDataOut ) const { return GetValue(pszValueName, REG_BINARY, pbDataOut, cbDataOut); } // // Get a text string value (REG_SZ) and write it to a CString object. // HRESULT RegKey::GetValue( LPCTSTR pszValueName, CString *pstrDataOut ) const { HRESULT hr = E_FAIL; int cch = GetValueBufferSize(pszValueName) / sizeof(TCHAR); if (NULL != pstrDataOut && 0 < cch) { // // Get a buffer 1 character larger than needed. Zero-out // the entire buffer in case the data in the registry is not // nul-terminated. // LPTSTR pszBuffer = pstrDataOut->GetBuffer(cch + 1); ZeroMemory(pszBuffer, pstrDataOut->SizeBytes()); hr = GetValue(pszValueName, REG_SZ, (LPBYTE)pszBuffer, pstrDataOut->SizeBytes()); pstrDataOut->ReleaseBuffer(); } return hr; } // // Get a multi-text string value (REG_MULTI_SZ) and write it to a CArray object. // HRESULT RegKey::GetValue( LPCTSTR pszValueName, CArray *prgstrOut ) const { HRESULT hr = E_FAIL; int cb = GetValueBufferSize(pszValueName); if (NULL != prgstrOut && 0 < cb) { // // Allocate a buffer one character larger than what we need // and then zero-init that buffer. This is in case the data in the // registry is not nul-terminated. // const size_t cch = cb / sizeof(TCHAR); array_autoptr ptrTemp(new TCHAR[cch + 1]); LPTSTR psz = ptrTemp.get(); ZeroMemory(psz, (cch + 1) * sizeof(TCHAR)); hr = GetValue(pszValueName, REG_MULTI_SZ, (LPBYTE)psz, cb); if (SUCCEEDED(hr)) { while(psz && TEXT('\0') != *psz) { prgstrOut->Append(CString(psz)); psz += lstrlen(psz) + 1; } } } return hr; } // // Return the required buffer size for a given registry value. // int RegKey::GetValueBufferSize( LPCTSTR pszValueName ) const { DWORD dwType; int cbData = 0; DWORD dwDummy; DWORD dwResult = RegQueryValueEx(m_hkey, pszValueName, 0, &dwType, (LPBYTE)&dwDummy, (LPDWORD)&cbData); if (ERROR_MORE_DATA != dwResult) cbData = 0; return cbData; } // // This is the basic form of SetValue. All other forms of // SetValue() call into this one. // HRESULT RegKey::SetValue( LPCTSTR pszValueName, DWORD dwValueType, const LPBYTE pbData, int cbData ) { DWORD dwResult = RegSetValueEx(m_hkey, pszValueName, 0, dwValueType, pbData, cbData); return HRESULT_FROM_WIN32(dwResult); } // // Set a DWORD value (REG_DWORD). // HRESULT RegKey::SetValue( LPCTSTR pszValueName, DWORD dwData ) { return SetValue(pszValueName, REG_DWORD, (const LPBYTE)&dwData, sizeof(dwData)); } // // Set a byte buffer value (REG_BINARY). // HRESULT RegKey::SetValue( LPCTSTR pszValueName, const LPBYTE pbData, int cbData ) { return SetValue(pszValueName, REG_BINARY, pbData, cbData); } // // Set a text string value (REG_SZ). // HRESULT RegKey::SetValue( LPCTSTR pszValueName, LPCTSTR pszData ) { return SetValue(pszValueName, REG_SZ, (const LPBYTE)pszData, (lstrlen(pszData) + 1) * sizeof(TCHAR)); } // // Set a text string value (REG_MULTI_SZ). // HRESULT RegKey::SetValue( LPCTSTR pszValueName, const CArray& rgstrSrc ) { array_autoptr ptrValues(CreateDoubleNulTermList(rgstrSrc)); int cch = 1; int n = rgstrSrc.Count(); for (int i = 0; i < n; i++) cch += rgstrSrc[i].Length() + 1; return SetValue(pszValueName, REG_MULTI_SZ, (const LPBYTE)ptrValues.get(), cch * sizeof(TCHAR)); } LPTSTR RegKey::CreateDoubleNulTermList( const CArray& rgstrSrc ) const { int cEntries = rgstrSrc.Count(); size_t cch = 1; // Account for 2nd nul term. int i; for (i = 0; i < cEntries; i++) cch += rgstrSrc[i].Length() + 1; LPTSTR pszBuf = new TCHAR[cch]; LPTSTR pszWrite = pszBuf; for (i = 0; i < cEntries; i++) { CString& s = rgstrSrc[i]; StringCchCopyEx(pszWrite, cch, s, &pszWrite, &cch, 0); // // Advance one beyond terminating nul. // pszWrite++; cch--; } DBGASSERT((1 == cch)); *pszWrite = TEXT('\0'); // Double nul term. return pszBuf; }