963 lines
21 KiB
C++
963 lines
21 KiB
C++
|
/**********************************************************************/
|
||
|
/** Microsoft Windows/NT **/
|
||
|
/** Copyright(c) Microsoft Corporation, 1995 - 1999 **/
|
||
|
/**********************************************************************/
|
||
|
|
||
|
/*
|
||
|
FILE HISTORY:
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <precompiled.h>
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <memory.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
//#include "tfschar.h"
|
||
|
#include "tregkey.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
// Convert a CStringList to the REG_MULTI_SZ format
|
||
|
DWORD StrList2MULTI_SZ(CStringList & strList, DWORD * pcbSize, BYTE ** ppbData)
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
|
||
|
POSITION pos ;
|
||
|
CString * pstr ;
|
||
|
int cbTotal = 0 ;
|
||
|
|
||
|
// Walk the list accumulating sizes
|
||
|
for ( pos = strList.GetHeadPosition() ;
|
||
|
pos != NULL && (pstr = & strList.GetNext( pos )) ; )
|
||
|
{
|
||
|
cbTotal += pstr->GetLength() + 1 ;
|
||
|
}
|
||
|
|
||
|
// Add on space for two NULL characters
|
||
|
cbTotal += 2;
|
||
|
|
||
|
// Allocate and fill a temporary buffer
|
||
|
if (*pcbSize = (cbTotal * sizeof(TCHAR) ) )
|
||
|
{
|
||
|
TRY
|
||
|
{
|
||
|
*ppbData = new BYTE[ *pcbSize] ;
|
||
|
|
||
|
// NULL out the data buffer
|
||
|
::ZeroMemory(*ppbData, *pcbSize);
|
||
|
|
||
|
BYTE * pbData = *ppbData ;
|
||
|
|
||
|
// Populate the buffer with the strings.
|
||
|
for ( pos = strList.GetHeadPosition() ;
|
||
|
pos != NULL && (pstr = & strList.GetNext( pos )) ; )
|
||
|
{
|
||
|
int cb = (pstr->GetLength() + 1) * sizeof(TCHAR) ;
|
||
|
::memcpy( pbData, (LPCTSTR) *pstr, cb ) ;
|
||
|
pbData += cb ;
|
||
|
}
|
||
|
|
||
|
// Assert that we have not passed the end of the buffer
|
||
|
_ASSERTE((pbData - *ppbData) < (int) *pcbSize);
|
||
|
|
||
|
// Assert that we have an extra NULL character
|
||
|
_ASSERTE(*((TCHAR *)pbData) == 0);
|
||
|
}
|
||
|
CATCH_ALL(e)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY ;
|
||
|
}
|
||
|
END_CATCH_ALL
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppbData = NULL;
|
||
|
}
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
// Convert a REG_MULTI_SZ format to the CStringList
|
||
|
DWORD MULTI_SZ2StrList(LPCTSTR pstrMulti_Sz, CStringList& strList)
|
||
|
{
|
||
|
DWORD dwErr = NOERROR;
|
||
|
|
||
|
strList.RemoveAll();
|
||
|
|
||
|
// Catch exceptions trying to build the list
|
||
|
TRY
|
||
|
{
|
||
|
if (pstrMulti_Sz)
|
||
|
{
|
||
|
while ( lstrlen(pstrMulti_Sz) )
|
||
|
{
|
||
|
strList.AddTail( pstrMulti_Sz ) ;
|
||
|
pstrMulti_Sz += lstrlen( pstrMulti_Sz ) + 1 ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
CATCH_ALL(e)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY ;
|
||
|
}
|
||
|
END_CATCH_ALL
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::RegKey
|
||
|
Constructor
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
RegKey::RegKey()
|
||
|
: m_hKey(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::~RegKey
|
||
|
Destructor
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
RegKey::~RegKey ()
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::Open
|
||
|
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::Open( HKEY hKeyParent,
|
||
|
LPCTSTR pszSubKey,
|
||
|
REGSAM regSam,
|
||
|
LPCTSTR pszServerName)
|
||
|
{
|
||
|
HKEY hkBase = NULL ;
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
Close();
|
||
|
|
||
|
// If we have a server name, try to open a remote connection
|
||
|
if ( pszServerName )
|
||
|
dwErr = ::RegConnectRegistry((LPTSTR) pszServerName, hKeyParent, &hkBase);
|
||
|
else
|
||
|
hkBase = hKeyParent ;
|
||
|
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
if ( pszSubKey )
|
||
|
{
|
||
|
dwErr = ::RegOpenKeyEx( hkBase, pszSubKey, 0, regSam, & m_hKey ) ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_hKey = hkBase ;
|
||
|
hkBase = NULL ; // set to NULL so that the key doesn't get closed
|
||
|
}
|
||
|
|
||
|
if ( hkBase && (hkBase != hKeyParent) )
|
||
|
::RegCloseKey( hkBase ) ;
|
||
|
}
|
||
|
|
||
|
if ( dwErr )
|
||
|
m_hKey = NULL ;
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::Create
|
||
|
-
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::Create(
|
||
|
HKEY hKeyBase,
|
||
|
LPCTSTR pszSubKey,
|
||
|
DWORD dwOptions,
|
||
|
REGSAM regSam,
|
||
|
LPSECURITY_ATTRIBUTES pSecAttr,
|
||
|
LPCTSTR pszServerName )
|
||
|
{
|
||
|
HKEY hkBase = NULL ;
|
||
|
LONG dwErr = 0;
|
||
|
DWORD dwDisposition;
|
||
|
|
||
|
Close();
|
||
|
|
||
|
if ( pszServerName )
|
||
|
{
|
||
|
// This is a remote connection.
|
||
|
dwErr = ::RegConnectRegistry( (LPTSTR) pszServerName, hKeyBase, &hkBase );
|
||
|
}
|
||
|
else
|
||
|
hkBase = hKeyBase ;
|
||
|
|
||
|
if (dwErr == 0)
|
||
|
{
|
||
|
LPTSTR szEmpty = _T("");
|
||
|
|
||
|
dwErr = ::RegCreateKeyEx( hkBase, pszSubKey,
|
||
|
0, szEmpty,
|
||
|
dwOptions, regSam, pSecAttr,
|
||
|
& m_hKey,
|
||
|
& dwDisposition ) ;
|
||
|
|
||
|
if ( hkBase && (hkBase != hKeyBase) )
|
||
|
::RegCloseKey( hkBase ) ;
|
||
|
}
|
||
|
|
||
|
if ( dwErr )
|
||
|
m_hKey = NULL ;
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::Close
|
||
|
-
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::Close()
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
if (m_hKey)
|
||
|
dwErr = ::RegCloseKey(m_hKey);
|
||
|
m_hKey = 0;
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::Detach
|
||
|
-
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HKEY RegKey::Detach()
|
||
|
{
|
||
|
HKEY hKey = m_hKey;
|
||
|
m_hKey = NULL;
|
||
|
return hKey;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::Attach
|
||
|
-
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
void RegKey::Attach(HKEY hKey)
|
||
|
{
|
||
|
_ASSERTE(m_hKey == NULL);
|
||
|
m_hKey = hKey;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::DeleteSubKey
|
||
|
-
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::DeleteSubKey(LPCTSTR lpszSubKey)
|
||
|
{
|
||
|
_ASSERTE(m_hKey != NULL);
|
||
|
return RegDeleteKey(m_hKey, lpszSubKey);
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::DeleteValue
|
||
|
-
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::DeleteValue(LPCTSTR lpszValue)
|
||
|
{
|
||
|
_ASSERTE(m_hKey != NULL);
|
||
|
return RegDeleteValue(m_hKey, (LPTSTR)lpszValue);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::RecurseDeleteKey
|
||
|
-
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::RecurseDeleteKey(LPCTSTR lpszKey)
|
||
|
{
|
||
|
RegKey key;
|
||
|
DWORD dwRes = key.Open(m_hKey, lpszKey, KEY_READ | KEY_WRITE);
|
||
|
if (dwRes != ERROR_SUCCESS)
|
||
|
return dwRes;
|
||
|
|
||
|
FILETIME time;
|
||
|
TCHAR szBuffer[256];
|
||
|
DWORD dwSize = 256;
|
||
|
|
||
|
while (RegEnumKeyEx(key, 0, szBuffer, &dwSize, NULL, NULL, NULL,
|
||
|
&time)==ERROR_SUCCESS)
|
||
|
{
|
||
|
dwRes = key.RecurseDeleteKey(szBuffer);
|
||
|
if (dwRes != ERROR_SUCCESS)
|
||
|
return dwRes;
|
||
|
dwSize = 256;
|
||
|
}
|
||
|
key.Close();
|
||
|
return DeleteSubKey(lpszKey);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::RecurseDeleteSubKeys
|
||
|
Deletes the subkeys of the current key.
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::RecurseDeleteSubKeys()
|
||
|
{
|
||
|
FILETIME time;
|
||
|
TCHAR szBuffer[256];
|
||
|
DWORD dwSize = 256;
|
||
|
DWORD dwRes;
|
||
|
|
||
|
while (RegEnumKeyEx(m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL,
|
||
|
&time)==ERROR_SUCCESS)
|
||
|
{
|
||
|
dwRes = RecurseDeleteKey(szBuffer);
|
||
|
if (dwRes != ERROR_SUCCESS)
|
||
|
return dwRes;
|
||
|
dwSize = 256;
|
||
|
}
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::PrepareValue
|
||
|
Prepare to read a value by finding the value's size. This will
|
||
|
allocate space for the data. The data needs to be freed separately
|
||
|
by 'delete'.
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::PrepareValue( LPCTSTR pszValueName,
|
||
|
DWORD * pdwType,
|
||
|
DWORD * pcbSize,
|
||
|
BYTE ** ppbData )
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
BYTE chDummy[2] ;
|
||
|
DWORD cbData = 0 ;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Set the resulting buffer size to 0.
|
||
|
*pcbSize = 0 ;
|
||
|
*ppbData = NULL ;
|
||
|
|
||
|
dwErr = ::RegQueryValueEx( m_hKey,
|
||
|
pszValueName,
|
||
|
0, pdwType,
|
||
|
chDummy, & cbData ) ;
|
||
|
|
||
|
// The only error we should get here is ERROR_MORE_DATA, but
|
||
|
// we may get no error if the value has no data.
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
cbData = sizeof (LONG) ; // Just a fudgy number
|
||
|
}
|
||
|
else
|
||
|
if ( dwErr != ERROR_MORE_DATA )
|
||
|
break ;
|
||
|
|
||
|
// Allocate a buffer large enough for the data.
|
||
|
|
||
|
*ppbData = new BYTE [ (*pcbSize = cbData) + sizeof (LONG) ] ;
|
||
|
_ASSERTE(*ppbData);
|
||
|
|
||
|
// Now that have a buffer, re-fetch the value.
|
||
|
|
||
|
dwErr = ::RegQueryValueEx( m_hKey,
|
||
|
pszValueName,
|
||
|
0, pdwType,
|
||
|
*ppbData, &cbData ) ;
|
||
|
|
||
|
} while ( FALSE ) ;
|
||
|
|
||
|
if ( dwErr )
|
||
|
{
|
||
|
delete [] *ppbData ;
|
||
|
*ppbData = NULL;
|
||
|
*pcbSize = 0;
|
||
|
}
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD RegKey::QueryTypeAndSize(LPCTSTR pszValueName, DWORD *pdwType, DWORD *pdwSize)
|
||
|
{
|
||
|
return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType,
|
||
|
NULL, pdwSize);
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::QueryValueExplicit(LPCTSTR pszValueName,
|
||
|
DWORD *pdwType,
|
||
|
DWORD *pdwSize,
|
||
|
LPBYTE *ppbData)
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
DWORD dwType;
|
||
|
DWORD cbData;
|
||
|
BYTE * pbData = NULL;
|
||
|
|
||
|
_ASSERTE(pdwType);
|
||
|
_ASSERTE(pdwSize);
|
||
|
_ASSERTE(ppbData);
|
||
|
|
||
|
dwErr = PrepareValue( pszValueName, &dwType, &cbData, &pbData );
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
if (dwType != REG_MULTI_SZ)
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pdwType = dwType;
|
||
|
*pdwSize = cbData;
|
||
|
*ppbData = pbData;
|
||
|
pbData = NULL;
|
||
|
}
|
||
|
}
|
||
|
delete pbData;
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
// Overloaded value query members; each returns ERROR_INVALID_PARAMETER
|
||
|
// if data exists but not in correct form to deliver into result object.
|
||
|
|
||
|
DWORD RegKey::QueryValue( LPCTSTR pszValueName, CString& strResult )
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
DWORD dwType ;
|
||
|
DWORD cbData ;
|
||
|
BYTE * pabData = NULL ;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if ( dwErr = PrepareValue( pszValueName, &dwType, &cbData, &pabData ) )
|
||
|
break ;
|
||
|
|
||
|
if (( dwType != REG_SZ ) && (dwType != REG_EXPAND_SZ))
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER ;
|
||
|
break ;
|
||
|
}
|
||
|
|
||
|
// Guarantee that the data looks like a string
|
||
|
pabData[cbData] = 0 ;
|
||
|
|
||
|
// Catch exceptions trying to assign to the caller's string
|
||
|
TRY
|
||
|
{
|
||
|
strResult = (LPCTSTR) pabData ;
|
||
|
}
|
||
|
CATCH_ALL(e)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY ;
|
||
|
}
|
||
|
END_CATCH_ALL
|
||
|
}
|
||
|
while ( FALSE ) ;
|
||
|
|
||
|
delete [] pabData ;
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD RegKey::QueryValue ( LPCTSTR pchValueName, CStringList & strList )
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
|
||
|
DWORD dwType ;
|
||
|
DWORD cbData ;
|
||
|
BYTE * pabData = NULL ;
|
||
|
LPTSTR pbTemp, pbTempLimit;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if ( dwErr = PrepareValue( pchValueName, & dwType, & cbData, & pabData ) )
|
||
|
break ;
|
||
|
|
||
|
if ( dwType != REG_MULTI_SZ )
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER ;
|
||
|
break ;
|
||
|
}
|
||
|
|
||
|
// Guarantee that the trailing data looks like a string
|
||
|
pabData[cbData] = 0 ;
|
||
|
pbTemp = (LPTSTR) pabData ;
|
||
|
pbTempLimit = & pbTemp[MaxCchFromCb(cbData)-1] ;
|
||
|
|
||
|
dwErr = MULTI_SZ2StrList(pbTemp, strList);
|
||
|
|
||
|
}
|
||
|
while ( FALSE ) ;
|
||
|
|
||
|
delete [] pabData ;
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKey::QueryValue
|
||
|
Gets the DWORD value for this key. Returns ERROR_INVALID_PARAMETER
|
||
|
if the value is not a REG_DWORD.
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
DWORD RegKey::QueryValue( LPCTSTR pszValueName, DWORD& dwResult )
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
DWORD cbData = sizeof(DWORD);
|
||
|
DWORD dwType = REG_DWORD;
|
||
|
|
||
|
dwErr = ::RegQueryValueEx( m_hKey,
|
||
|
pszValueName,
|
||
|
0, &dwType,
|
||
|
(LPBYTE) &dwResult, &cbData ) ;
|
||
|
|
||
|
if ((dwErr == ERROR_SUCCESS) && (dwType != REG_DWORD))
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
|
||
|
if ( dwErr )
|
||
|
dwResult = 0;
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::QueryValue ( LPCTSTR pchValueName, LPTSTR pszDestBuffer, DWORD cchSize, BOOL fExpandSz)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
DWORD cbData = MinCbNeededForCch(cchSize);
|
||
|
DWORD dwType = REG_SZ;
|
||
|
TCHAR * pszBuffer = (TCHAR *) _alloca(MinCbNeededForCch(cchSize));
|
||
|
|
||
|
dwErr = ::RegQueryValueEx( m_hKey,
|
||
|
pchValueName,
|
||
|
0, &dwType,
|
||
|
(LPBYTE) pszBuffer, &cbData ) ;
|
||
|
|
||
|
if ((dwErr == ERROR_SUCCESS) &&
|
||
|
(dwType != REG_SZ) &&
|
||
|
(dwType != REG_EXPAND_SZ) &&
|
||
|
(dwType != REG_MULTI_SZ))
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
if ((dwType == REG_EXPAND_SZ) && fExpandSz)
|
||
|
ExpandEnvironmentStrings(pszBuffer, pszDestBuffer, cchSize);
|
||
|
else
|
||
|
::CopyMemory(pszDestBuffer, pszBuffer, cbData);
|
||
|
}
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD RegKey::QueryValue ( LPCTSTR pszValueName, CByteArray & abResult )
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
|
||
|
DWORD dwType ;
|
||
|
DWORD cbData ;
|
||
|
BYTE * pabData = NULL ;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if ( dwErr = PrepareValue( pszValueName, & dwType, & cbData, & pabData ) )
|
||
|
break ;
|
||
|
|
||
|
if ( dwType != REG_BINARY )
|
||
|
{
|
||
|
dwErr = ERROR_INVALID_PARAMETER ;
|
||
|
break ;
|
||
|
}
|
||
|
|
||
|
// Catch exceptions trying to grow the result array
|
||
|
TRY
|
||
|
{
|
||
|
abResult.SetSize( cbData ) ;
|
||
|
}
|
||
|
CATCH_ALL(e)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY ;
|
||
|
}
|
||
|
END_CATCH_ALL
|
||
|
|
||
|
if ( dwErr )
|
||
|
break ;
|
||
|
|
||
|
// Move the data to the result array.
|
||
|
for ( DWORD i = 0 ; i < cbData ; i++ )
|
||
|
{
|
||
|
abResult[i] = pabData[i] ;
|
||
|
}
|
||
|
}
|
||
|
while ( FALSE ) ;
|
||
|
|
||
|
// Memory leak....
|
||
|
//if ( dwErr )
|
||
|
//{
|
||
|
delete [] pabData ;
|
||
|
//}
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::QueryValue ( LPCTSTR pszValueName, void * pvResult, DWORD cbSize )
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
DWORD dwType = REG_BINARY;
|
||
|
|
||
|
dwErr = ::RegQueryValueEx( m_hKey,
|
||
|
pszValueName,
|
||
|
0, &dwType,
|
||
|
(LPBYTE) pvResult, &cbSize ) ;
|
||
|
|
||
|
if ((dwErr == ERROR_SUCCESS) && (dwType != REG_BINARY))
|
||
|
dwErr = ERROR_INVALID_PARAMETER;
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::SetValueExplicit(LPCTSTR pszValueName,
|
||
|
DWORD dwType,
|
||
|
DWORD dwSize,
|
||
|
LPBYTE pbData)
|
||
|
{
|
||
|
return ::RegSetValueEx( *this,
|
||
|
pszValueName,
|
||
|
0,
|
||
|
dwType,
|
||
|
pbData,
|
||
|
dwSize);
|
||
|
}
|
||
|
|
||
|
// Overloaded value setting members.
|
||
|
DWORD RegKey::SetValue ( LPCTSTR pszValueName, LPCTSTR pszValue,
|
||
|
BOOL fRegExpand)
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
DWORD dwType = fRegExpand ? REG_EXPAND_SZ : REG_SZ;
|
||
|
|
||
|
dwErr = ::RegSetValueEx( *this,
|
||
|
pszValueName,
|
||
|
0,
|
||
|
dwType,
|
||
|
(const BYTE *) pszValue,
|
||
|
// This is not the correct string length
|
||
|
// for DBCS strings
|
||
|
pszValue ? CbStrLen(pszValue) : 0);
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::SetValue ( LPCTSTR pszValueName, CStringList & strList )
|
||
|
{
|
||
|
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
DWORD cbSize ;
|
||
|
BYTE * pbData = NULL ;
|
||
|
|
||
|
dwErr = FlattenValue( strList, & cbSize, & pbData ) ;
|
||
|
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
dwErr = ::RegSetValueEx( *this,
|
||
|
pszValueName,
|
||
|
0,
|
||
|
REG_MULTI_SZ,
|
||
|
pbData,
|
||
|
cbSize ) ;
|
||
|
}
|
||
|
|
||
|
delete pbData ;
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::SetValue ( LPCTSTR pszValueName, DWORD & dwResult )
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
dwErr = ::RegSetValueEx( *this,
|
||
|
pszValueName,
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(const BYTE *) & dwResult,
|
||
|
sizeof dwResult ) ;
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::SetValue ( LPCTSTR pszValueName, CByteArray & abResult )
|
||
|
{
|
||
|
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
DWORD cbSize ;
|
||
|
BYTE * pbData = NULL ;
|
||
|
|
||
|
dwErr = FlattenValue( abResult, & cbSize, & pbData ) ;
|
||
|
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
dwErr = ::RegSetValueEx( *this,
|
||
|
pszValueName,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
pbData,
|
||
|
cbSize ) ;
|
||
|
}
|
||
|
|
||
|
delete pbData ;
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::SetValue ( LPCTSTR pszValueName, void * pvResult, DWORD cbSize )
|
||
|
{
|
||
|
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
dwErr = ::RegSetValueEx( *this,
|
||
|
pszValueName,
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
(const BYTE *)pvResult,
|
||
|
cbSize ) ;
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::FlattenValue (
|
||
|
CStringList & strList,
|
||
|
DWORD * pcbSize,
|
||
|
BYTE ** ppbData )
|
||
|
{
|
||
|
return StrList2MULTI_SZ(strList, pcbSize, ppbData);
|
||
|
}
|
||
|
|
||
|
DWORD RegKey::FlattenValue (
|
||
|
CByteArray & abData,
|
||
|
DWORD * pcbSize,
|
||
|
BYTE ** ppbData )
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
|
||
|
DWORD i ;
|
||
|
|
||
|
// Allocate and fill a temporary buffer
|
||
|
if (*pcbSize = (DWORD)abData.GetSize())
|
||
|
{
|
||
|
TRY
|
||
|
{
|
||
|
*ppbData = new BYTE[*pcbSize] ;
|
||
|
|
||
|
for ( i = 0 ; i < *pcbSize ; i++ )
|
||
|
{
|
||
|
(*ppbData)[i] = abData[i] ;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
CATCH_ALL(e)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY ;
|
||
|
}
|
||
|
END_CATCH_ALL
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppbData = NULL;
|
||
|
}
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD RegKey::QueryKeyInfo ( CREGKEY_KEY_INFO * pRegKeyInfo )
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
|
||
|
pRegKeyInfo->dwClassNameSize = sizeof pRegKeyInfo->chBuff - 1 ;
|
||
|
|
||
|
dwErr = ::RegQueryInfoKey( *this,
|
||
|
pRegKeyInfo->chBuff,
|
||
|
& pRegKeyInfo->dwClassNameSize,
|
||
|
NULL,
|
||
|
& pRegKeyInfo->dwNumSubKeys,
|
||
|
& pRegKeyInfo->dwMaxSubKey,
|
||
|
& pRegKeyInfo->dwMaxClass,
|
||
|
& pRegKeyInfo->dwMaxValues,
|
||
|
& pRegKeyInfo->dwMaxValueName,
|
||
|
& pRegKeyInfo->dwMaxValueData,
|
||
|
& pRegKeyInfo->dwSecDesc,
|
||
|
& pRegKeyInfo->ftKey ) ;
|
||
|
|
||
|
return dwErr ;
|
||
|
}
|
||
|
|
||
|
|
||
|
RegValueIterator::RegValueIterator()
|
||
|
: m_pRegKey( NULL ),
|
||
|
m_pszBuffer( NULL ),
|
||
|
m_cbBuffer( 0 )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
HRESULT RegValueIterator::Init(RegKey *pRegKey)
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
RegKey::CREGKEY_KEY_INFO regKeyInfo ;
|
||
|
|
||
|
Reset() ;
|
||
|
|
||
|
m_pRegKey= pRegKey;
|
||
|
|
||
|
dwErr = pRegKey->QueryKeyInfo( & regKeyInfo ) ;
|
||
|
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
m_cbBuffer = regKeyInfo.dwMaxValueName + sizeof (DWORD) ;
|
||
|
delete [] m_pszBuffer;
|
||
|
m_pszBuffer = new TCHAR [ m_cbBuffer ] ;
|
||
|
_ASSERTE(m_pszBuffer);
|
||
|
}
|
||
|
return HRESULT_FROM_WIN32(dwErr);
|
||
|
}
|
||
|
|
||
|
RegValueIterator::~RegValueIterator()
|
||
|
{
|
||
|
delete [] m_pszBuffer ;
|
||
|
}
|
||
|
|
||
|
HRESULT RegValueIterator::Next( CString * pstrName, DWORD * pdwType )
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
|
||
|
DWORD dwNameLength = m_cbBuffer ;
|
||
|
|
||
|
dwErr = ::RegEnumValue( *m_pRegKey,
|
||
|
m_dwIndex,
|
||
|
m_pszBuffer,
|
||
|
& dwNameLength,
|
||
|
NULL,
|
||
|
pdwType,
|
||
|
NULL,
|
||
|
NULL ) ;
|
||
|
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
m_dwIndex++ ;
|
||
|
|
||
|
*pstrName = m_pszBuffer ;
|
||
|
}
|
||
|
|
||
|
return HRESULT_FROM_WIN32(dwErr) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
RegKeyIterator::RegKeyIterator()
|
||
|
: m_pregkey(NULL),
|
||
|
m_pszBuffer(NULL),
|
||
|
m_cbBuffer( 0 )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
HRESULT RegKeyIterator::Init(RegKey *pregkey)
|
||
|
{
|
||
|
DWORD dwErr = 0 ;
|
||
|
RegKey::CREGKEY_KEY_INFO regKeyInfo ;
|
||
|
|
||
|
Reset() ;
|
||
|
|
||
|
m_pregkey= pregkey;
|
||
|
|
||
|
dwErr = pregkey->QueryKeyInfo( & regKeyInfo ) ;
|
||
|
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
m_cbBuffer = regKeyInfo.dwMaxSubKey + sizeof(DWORD);
|
||
|
delete [] m_pszBuffer;
|
||
|
m_pszBuffer = new TCHAR[m_cbBuffer];
|
||
|
}
|
||
|
|
||
|
return HRESULT_FROM_WIN32(dwErr);
|
||
|
}
|
||
|
|
||
|
RegKeyIterator::~RegKeyIterator ()
|
||
|
{
|
||
|
delete [] m_pszBuffer ;
|
||
|
}
|
||
|
|
||
|
HRESULT RegKeyIterator::Reset()
|
||
|
{
|
||
|
m_dwIndex = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!--------------------------------------------------------------------------
|
||
|
RegKeyIterator::Next
|
||
|
Returns the name (and optional last write time) of the next key.
|
||
|
Return S_FALSE if there are no other items to be returned.
|
||
|
Author: KennT
|
||
|
---------------------------------------------------------------------------*/
|
||
|
HRESULT RegKeyIterator::Next ( CString * pstrName, CTime * pTime )
|
||
|
{
|
||
|
DWORD dwErr = 0;
|
||
|
|
||
|
FILETIME ftDummy ;
|
||
|
DWORD dwNameSize = m_cbBuffer;
|
||
|
|
||
|
dwErr = ::RegEnumKeyEx( *m_pregkey,
|
||
|
m_dwIndex,
|
||
|
m_pszBuffer,
|
||
|
& dwNameSize,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
& ftDummy ) ;
|
||
|
if ( dwErr == 0 )
|
||
|
{
|
||
|
m_dwIndex++ ;
|
||
|
|
||
|
if ( pTime )
|
||
|
{
|
||
|
*pTime = ftDummy ;
|
||
|
}
|
||
|
|
||
|
if (pstrName)
|
||
|
{
|
||
|
*pstrName = m_pszBuffer ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (dwErr == ERROR_NO_MORE_ITEMS) ? S_FALSE : HRESULT_FROM_WIN32(dwErr);
|
||
|
}
|
||
|
|