windows-nt/Source/XPSP1/NT/net/ias/mmc/nap/tregkey.cpp
2020-09-26 16:20:57 +08:00

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