2951 lines
77 KiB
C++
2951 lines
77 KiB
C++
//***************************************************************************
|
|
|
|
//
|
|
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// cregcls.cpp
|
|
//
|
|
// Purpose: registry wrapper class
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
#pragma warning( disable : 4290 )
|
|
#include <CHString.h>
|
|
|
|
#include <stdio.h>
|
|
#include "CRegCls.h"
|
|
#include <malloc.h>
|
|
#include <cnvmacros.h>
|
|
|
|
|
|
DWORD CRegistry::s_dwPlatform = CRegistry::GetPlatformID () ;
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
CRegistry::CRegistry()
|
|
: m_fFromCurrentUser(false)
|
|
{
|
|
|
|
// Set the key to null so that if the caller does not open the key
|
|
// but still tries to use it we can return an error
|
|
|
|
hKey = (HKEY)NULL;
|
|
hSubKey = (HKEY)NULL;
|
|
hRootKey = (HKEY)NULL;
|
|
|
|
// To prevent garbage values being returned if they try to get
|
|
// some information before they open the class
|
|
|
|
SetDefaultValues();
|
|
}
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
CRegistry::~CRegistry()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
void CRegistry::SetDefaultValues()
|
|
{
|
|
// Information inited here rather than constructor so that this instance
|
|
// can be reused
|
|
|
|
ClassName[0] = '\0';
|
|
dwcClassLen = MAX_PATH; // Length of class string.
|
|
dwcSubKeys = NULL_DWORD; // Number of sub keys.
|
|
dwcMaxSubKey = NULL_DWORD; // Longest sub key size.
|
|
dwcMaxClass = NULL_DWORD; // Longest class string.
|
|
dwcValues = NULL_DWORD; // Number of values for this key.
|
|
dwcMaxValueName = NULL_DWORD; // Longest Value name.
|
|
dwcMaxValueData = NULL_DWORD; // Longest Value data.
|
|
RewindSubKeys(); // Rewind the index to zero
|
|
|
|
RootKeyPath.Empty();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// Function: EnumerateAndGetValues
|
|
// Description: This function enumerates the values under the
|
|
// specified key and gets the value, keeps on
|
|
// going and going... until there aren't any more
|
|
// values to get. The first call must set the
|
|
// value index to 0, this indicates for the function
|
|
// to start over;
|
|
//
|
|
//
|
|
// NOTE!!!! The USER has the responsibility of deleting the
|
|
// allocated memory for pValueName and pValueData
|
|
//
|
|
//
|
|
// Arguments:
|
|
// Returns: Standard return value from registry open function
|
|
// Inputs:
|
|
// Outputs:
|
|
// Caveats:
|
|
// Raid:
|
|
////////////////////////////////////////////////////////////////
|
|
LONG CRegistry::EnumerateAndGetValues (
|
|
|
|
DWORD &dwIndexOfValue,
|
|
WCHAR *&pValueName,
|
|
BYTE *&pValueData
|
|
)
|
|
{
|
|
DWORD dwIndex = dwIndexOfValue, dwType;
|
|
DWORD dwValueNameSize = dwcMaxValueName + 2; // add extra for null
|
|
DWORD dwValueDataSize = dwcMaxValueData + 2; // add extra for null
|
|
|
|
// If this is the first time we have come thru, then we
|
|
// need to get the max size of things.
|
|
|
|
pValueName = new WCHAR[dwValueNameSize + 2];
|
|
if ( ! pValueName )
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
// We have to use WCHAR's since for 9x, we'll be converting the
|
|
// data from chars to WCHARs.
|
|
pValueData = (LPBYTE) new WCHAR[dwValueDataSize + 2];
|
|
if ( ! pValueData )
|
|
{
|
|
delete [] pValueName ;
|
|
pValueName = NULL;
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
LONG lRc = ERROR_SUCCESS ;
|
|
|
|
try
|
|
{
|
|
lRc = myRegEnumValue (
|
|
|
|
hKey, // handle of key to query
|
|
dwIndex, // index of value to query
|
|
pValueName, // address of buffer for value string
|
|
&dwValueNameSize, // address for size of value buffer
|
|
0, // reserved
|
|
&dwType, // address of buffer for type code
|
|
pValueData, // address of buffer for value data
|
|
&dwValueDataSize
|
|
) ;
|
|
|
|
dwIndexOfValue = dwIndex;
|
|
|
|
if ( lRc != ERROR_SUCCESS )
|
|
{
|
|
delete[] pValueName;
|
|
pValueName = NULL ;
|
|
|
|
delete[] pValueData;
|
|
pValueData = NULL ;
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete[] pValueName;
|
|
pValueName = NULL ;
|
|
|
|
delete[] pValueData;
|
|
pValueData = NULL ;
|
|
|
|
throw ; // throw the exception up
|
|
}
|
|
|
|
return lRc ;
|
|
}
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: LONG CRegistry::OpenCurrentUser(LPCWSTR lpszSubKey, REGSAM samDesired)
|
|
Description:
|
|
Arguments:
|
|
Returns: Standard return value from registry open function
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
DWORD CRegistry::OpenCurrentUser (
|
|
LPCWSTR lpszSubKey, // address of name of subkey to open
|
|
REGSAM samDesired) // Access mask
|
|
{
|
|
LONG RetValue = ERROR_SUCCESS;
|
|
|
|
// If we have a key value, we are open, so lets cleanup the previous
|
|
// use of this instance
|
|
PrepareToReOpen();
|
|
|
|
RetValue = ::RegOpenCurrentUser(
|
|
samDesired,
|
|
&hRootKey);
|
|
|
|
m_fFromCurrentUser = true;
|
|
|
|
if(RetValue == ERROR_SUCCESS)
|
|
{
|
|
// Just return the value and the hKey value never gets changed from NULL
|
|
//======================================================================
|
|
|
|
RetValue = myRegOpenKeyEx (
|
|
|
|
hRootKey,
|
|
lpszSubKey, // address of name of subkey to open
|
|
(DWORD) 0, // reserved
|
|
samDesired, // security access mask
|
|
(PHKEY)&hKey // address of handle of open key
|
|
|
|
);
|
|
|
|
// If we are not successful, then return the registry error
|
|
//=========================================================
|
|
|
|
if(RetValue == ERROR_SUCCESS)
|
|
{
|
|
dwcClassLen = sizeof(ClassName);
|
|
|
|
// Get the key information now, so it's available
|
|
// this is not critical, so we won't fail the open if this fails
|
|
//===============================================
|
|
|
|
myRegQueryInfoKey (
|
|
|
|
hKey, // Key handle.
|
|
ClassName, // Buffer for class name.
|
|
&dwcClassLen, // Length of class string.
|
|
NULL, // Reserved.
|
|
&dwcSubKeys, // Number of sub keys.
|
|
&dwcMaxSubKey, // Longest sub key size.
|
|
&dwcMaxClass, // Longest class string.
|
|
&dwcValues, // Number of values for this key.
|
|
&dwcMaxValueName, // Longest Value name.
|
|
&dwcMaxValueData, // Longest Value data.
|
|
&dwcSecDesc, // Security descriptor.
|
|
&ftLastWriteTime // Last write time.
|
|
|
|
);
|
|
|
|
RootKeyPath = lpszSubKey; // Assign
|
|
}
|
|
}
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: LONG CRegistry::Open(HKEY hKey, LPCWSTR lpszSubKey, REGSAM samDesired)
|
|
Description:
|
|
Arguments:
|
|
Returns: Standard return value from registry open function
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
LONG CRegistry::Open(
|
|
|
|
HKEY hInRootKey,
|
|
LPCWSTR lpszSubKey,
|
|
REGSAM samDesired
|
|
)
|
|
{
|
|
LONG RetValue;
|
|
|
|
// If we have a key value, we are open, so lets cleanup the previous
|
|
// use of this instance
|
|
|
|
if(hKey != NULL)
|
|
{
|
|
PrepareToReOpen();
|
|
}
|
|
|
|
hRootKey = hInRootKey;
|
|
|
|
// Just return the value and the hKey value never gets changed from NULL
|
|
//======================================================================
|
|
|
|
RetValue = myRegOpenKeyEx (
|
|
|
|
hRootKey,
|
|
lpszSubKey, // address of name of subkey to open
|
|
(DWORD) 0, // reserved
|
|
samDesired, // security access mask
|
|
(PHKEY)&hKey // address of handle of open key
|
|
|
|
);
|
|
|
|
// If we are not successful, then return the registry error
|
|
//=========================================================
|
|
|
|
if(RetValue != ERROR_SUCCESS)
|
|
{
|
|
return RetValue;
|
|
}
|
|
|
|
dwcClassLen = sizeof(ClassName);
|
|
|
|
// Get the key information now, so it's available
|
|
// this is not critical, so we won't fail the open if this fails
|
|
//===============================================
|
|
|
|
myRegQueryInfoKey (
|
|
|
|
hKey, // Key handle.
|
|
ClassName, // Buffer for class name.
|
|
&dwcClassLen, // Length of class string.
|
|
NULL, // Reserved.
|
|
&dwcSubKeys, // Number of sub keys.
|
|
&dwcMaxSubKey, // Longest sub key size.
|
|
&dwcMaxClass, // Longest class string.
|
|
&dwcValues, // Number of values for this key.
|
|
&dwcMaxValueName, // Longest Value name.
|
|
&dwcMaxValueData, // Longest Value data.
|
|
&dwcSecDesc, // Security descriptor.
|
|
&ftLastWriteTime // Last write time.
|
|
|
|
);
|
|
|
|
RootKeyPath = lpszSubKey; // Assign
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: LONG CRegistry::CreateOpen(HKEY hInRootKey,
|
|
LPCWSTR lpszSubKey,
|
|
LPSTR lpClass = NULL,
|
|
DWORD dwOptions = REG_OPTION_NON_VOLATILE,
|
|
REGSAM samDesired = KEY_ALL_ACCESS,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttrib = NULL
|
|
LPDWORD pdwDisposition = NULL );
|
|
Description:
|
|
Arguments: lpClass, dwOptions, samDesired and lpSecurityAttrib have signature defaults
|
|
Returns: Standard return value from registry RegCreateKeyEx function
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
History: a-peterc 28-Jul-1998 Created
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
LONG CRegistry::CreateOpen (
|
|
|
|
HKEY hInRootKey,
|
|
LPCWSTR lpszSubKey,
|
|
LPWSTR lpClass,
|
|
DWORD dwOptions,
|
|
REGSAM samDesired,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttrib,
|
|
LPDWORD pdwDisposition
|
|
)
|
|
{
|
|
LONG RetValue;
|
|
DWORD dwDisposition;
|
|
|
|
// If we have a key value, we are open, so lets cleanup the previous
|
|
// use of this instance
|
|
if(hKey != NULL)
|
|
{
|
|
PrepareToReOpen();
|
|
}
|
|
|
|
hRootKey = hInRootKey;
|
|
|
|
// Just return the value and the hKey value never gets changed from NULL
|
|
//======================================================================
|
|
RetValue = myRegCreateKeyEx (
|
|
|
|
hRootKey,
|
|
lpszSubKey, // address of name of subkey to open
|
|
(DWORD) 0, // reserved
|
|
lpClass, // address of the object class string
|
|
dwOptions, // special options flag
|
|
samDesired, // security access mask
|
|
lpSecurityAttrib, // address of the key security structure
|
|
(PHKEY)&hKey, // address of handle of open key
|
|
&dwDisposition // address of the disposition value buffer
|
|
);
|
|
|
|
// If we are not successful, then return the registry error
|
|
//=========================================================
|
|
|
|
if(RetValue != ERROR_SUCCESS)
|
|
{
|
|
return RetValue;
|
|
}
|
|
|
|
if( pdwDisposition )
|
|
{
|
|
*pdwDisposition = dwDisposition;
|
|
}
|
|
|
|
// Get the key information now, so it's available
|
|
// this is not critical, so we won't fail the open if this fails
|
|
//===============================================
|
|
|
|
myRegQueryInfoKey (
|
|
|
|
hKey, // Key handle.
|
|
ClassName, // Buffer for class name.
|
|
&dwcClassLen, // Length of class string.
|
|
NULL, // Reserved.
|
|
&dwcSubKeys, // Number of sub keys.
|
|
&dwcMaxSubKey, // Longest sub key size.
|
|
&dwcMaxClass, // Longest class string.
|
|
&dwcValues, // Number of values for this key.
|
|
&dwcMaxValueName, // Longest Value name.
|
|
&dwcMaxValueData, // Longest Value data.
|
|
&dwcSecDesc, // Security descriptor.
|
|
&ftLastWriteTime // Last write time.
|
|
);
|
|
|
|
RootKeyPath = lpszSubKey; // Assign
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: DWORD CRegistry::DeleteKey( CHString* pchsSubKeyPath = NULL )
|
|
|
|
Description: deletes the specified subkey or the Rootkey specified in the open
|
|
|
|
Arguments: pchsSubKeyPath has signature default of NULL,
|
|
specifying the RootKeyPath by default
|
|
|
|
Returns: Standard return value from registry RegDeleteKey function
|
|
Inputs:
|
|
Outputs:
|
|
Caveats: A deleted key is not removed until the last handle to it has been closed.
|
|
Subkeys and values cannot be created under a deleted key.
|
|
Raid:
|
|
History: a-peterc 28-Jul-1998 Created
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
LONG CRegistry::DeleteKey( CHString* pchsSubKeyPath )
|
|
{
|
|
CHString* pSubKey = pchsSubKeyPath ? pchsSubKeyPath : &RootKeyPath;
|
|
|
|
return myRegDeleteKey( hKey, pSubKey->GetBuffer(0) );
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: DWORD CRegistry::DeleteValue( LPCWSTR pValueName )
|
|
|
|
Description: deletes the specified value in the createopen
|
|
|
|
Arguments: pValueName to be deleted
|
|
|
|
Returns: Standard return value from registry RegDeleteValue function
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
History: a-peterc 30-Sep-1998 Created
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
LONG CRegistry::DeleteValue( LPCWSTR pValueName )
|
|
{
|
|
return myRegDeleteValue( hKey, pValueName );
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: LONG CRegistry::OpenAndEnumerateSubKeys(HKEY hKey, LPCWSTR lpszSubKey, REGSAM samDesired)
|
|
Description:
|
|
Arguments:
|
|
Returns: Standard return value from registry open function
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
LONG CRegistry::OpenAndEnumerateSubKeys (
|
|
|
|
HKEY hInRootKey,
|
|
LPCWSTR lpszSubKey,
|
|
REGSAM samDesired
|
|
)
|
|
{
|
|
return (Open( hInRootKey, lpszSubKey, samDesired | KEY_ENUMERATE_SUB_KEYS));
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
//
|
|
// This function opens and enumerates a key, then gets the requested
|
|
// value
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
LONG CRegistry::OpenLocalMachineKeyAndReadValue(
|
|
|
|
LPCWSTR lpszSubKey,
|
|
LPCWSTR pValueName,
|
|
CHString &DestValue
|
|
)
|
|
{
|
|
LONG lRc;
|
|
|
|
//===============================================
|
|
// Open the key. Note, if it is already in use
|
|
// the current key will be closed and everything
|
|
// reinitilized by the Open call
|
|
//===============================================
|
|
|
|
lRc = Open( HKEY_LOCAL_MACHINE,lpszSubKey,KEY_READ );
|
|
if( lRc != ERROR_SUCCESS )
|
|
{
|
|
return lRc;
|
|
}
|
|
|
|
//===============================================
|
|
// Get the value
|
|
//===============================================
|
|
return( GetCurrentKeyValue( pValueName, DestValue ));
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentRawKeyValue (
|
|
|
|
HKEY UseKey,
|
|
LPCWSTR pValueName,
|
|
void *pDestValue,
|
|
LPDWORD pValueType,
|
|
LPDWORD pSizeOfDestValue
|
|
)
|
|
{
|
|
DWORD RetValue;
|
|
|
|
|
|
// If subkey is open then get value
|
|
// ================================
|
|
|
|
RetValue = myRegQueryValueEx(
|
|
|
|
UseKey, // handle of key to query
|
|
pValueName, // address of name of value to query
|
|
NULL, // reserved
|
|
pValueType, // address of buffer for value type
|
|
(LPBYTE) pDestValue, // address of data buffer
|
|
(LPDWORD)pSizeOfDestValue // address of data buffer size
|
|
);
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentKeyValue (
|
|
|
|
HKEY UseKey,
|
|
LPCWSTR pValueName,
|
|
CHString &DestValue
|
|
)
|
|
{
|
|
DWORD SizeOfValue = 0L;
|
|
DWORD TypeOfValue;
|
|
LPBYTE pValue = NULL ; // Pointer to buffer for value
|
|
|
|
DestValue = L"";
|
|
|
|
LONG t_Status = myRegQueryValueEx(
|
|
|
|
UseKey, // handle of key to query
|
|
pValueName, // address of name of value to query
|
|
NULL, // reserved
|
|
(LPDWORD)&TypeOfValue, // address of buffer for value type
|
|
(LPBYTE) NULL, // address of data buffer NULL to force size being returned
|
|
(LPDWORD)&SizeOfValue // Get the size of the buffer we need
|
|
) ;
|
|
|
|
if( t_Status != ERROR_SUCCESS )
|
|
{
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
if( SizeOfValue <= 0 )
|
|
{
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
// Allow extra room for strings -- query doesn't include room for NULLs
|
|
// a-jmoon 8/19/97
|
|
//=====================================================================
|
|
|
|
if(TypeOfValue == REG_SZ ||
|
|
TypeOfValue == REG_EXPAND_SZ ||
|
|
TypeOfValue == REG_MULTI_SZ)
|
|
{
|
|
SizeOfValue += 2 ;
|
|
}
|
|
|
|
pValue = new BYTE[SizeOfValue];
|
|
if( ! pValue )
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
try
|
|
{
|
|
///////////////////////////////////////////////////////////////////
|
|
// Get the value in its RAW format
|
|
///////////////////////////////////////////////////////////////////
|
|
if( GetCurrentRawKeyValue(UseKey, pValueName, pValue, (LPDWORD)&TypeOfValue, (LPDWORD)&SizeOfValue) != ERROR_SUCCESS )
|
|
{
|
|
delete []pValue;
|
|
pValue = NULL;
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
// If the type is a null termiated string
|
|
// then assign it to the CHString
|
|
// ======================================
|
|
|
|
switch(TypeOfValue)
|
|
{
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ:
|
|
{
|
|
DestValue = (LPCWSTR)pValue; // Move string in
|
|
}
|
|
break;
|
|
|
|
case REG_MULTI_SZ:
|
|
{
|
|
WCHAR *ptemp = (WCHAR *) pValue;
|
|
int stringlength;
|
|
stringlength = wcslen((LPCWSTR)ptemp);
|
|
while(stringlength)
|
|
{
|
|
DestValue += (LPCWSTR)ptemp; // Move string in
|
|
DestValue += L"\n"; // Linefeed as separator
|
|
ptemp += stringlength+1;
|
|
stringlength = wcslen((LPCWSTR)ptemp);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case REG_DWORD:
|
|
{
|
|
LPWSTR pTemp = new WCHAR[MAX_SUBKEY_BUFFERSIZE];
|
|
if(pTemp)
|
|
{
|
|
try
|
|
{
|
|
swprintf(pTemp, L"%ld", *((DWORD*)pValue));
|
|
DestValue = pTemp;
|
|
delete []pTemp;
|
|
pTemp = NULL;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] pTemp ;
|
|
pTemp = NULL;
|
|
throw ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case REG_BINARY:
|
|
{
|
|
DestValue.Empty();
|
|
|
|
// copy into DestValue, Creating a byte buffer wide enough.
|
|
// Note: SizeOfValue is in bytes, while GetBuffer() returns wide char allocation.
|
|
|
|
DWORD t_dwResidual = ( SizeOfValue % 2 ) ;
|
|
DWORD t_dwWideSize = ( SizeOfValue / 2 ) + t_dwResidual ;
|
|
|
|
memcpy( DestValue.GetBuffer( t_dwWideSize ), pValue, SizeOfValue );
|
|
|
|
// cap the byte blob
|
|
if( t_dwResidual )
|
|
{
|
|
*( (LPBYTE)((LPCWSTR) DestValue) + SizeOfValue ) = NULL;
|
|
}
|
|
|
|
DestValue.GetBufferSetLength( t_dwWideSize ) ;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
delete []pValue;
|
|
pValue = NULL;
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete []pValue;
|
|
pValue = NULL;
|
|
throw;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
delete []pValue;
|
|
|
|
return (DWORD)ERROR_SUCCESS;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentKeyValue(LPCWSTR pValueName, CHString &DestValue)
|
|
{
|
|
return( GetCurrentKeyValue(hKey, pValueName, DestValue));
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentKeyValue(HKEY UseKey, LPCWSTR pValueName, CHStringArray &DestValue)
|
|
{
|
|
DWORD SizeOfValue = 0L;
|
|
DWORD TypeOfValue;
|
|
LPBYTE pValue; // Pointer to buffer for value
|
|
|
|
DestValue.RemoveAll();
|
|
|
|
// Get the size of the buffer we need
|
|
|
|
LONG t_Status = myRegQueryValueEx(
|
|
|
|
UseKey, // handle of key to query
|
|
pValueName, // address of name of value to query
|
|
NULL, // reserved
|
|
(LPDWORD)&TypeOfValue, // address of buffer for value type
|
|
(LPBYTE) NULL, // address of data buffer NULL to force size being returned
|
|
(LPDWORD)&SizeOfValue
|
|
) ;
|
|
|
|
if( t_Status != ERROR_SUCCESS )
|
|
{
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
if (( SizeOfValue <= 0 ) || (TypeOfValue != REG_MULTI_SZ))
|
|
{
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
SizeOfValue += 2 ;
|
|
|
|
pValue = new BYTE[SizeOfValue];
|
|
if( !pValue )
|
|
{
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Get the value in its RAW format
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
try {
|
|
|
|
if( GetCurrentRawKeyValue(UseKey, pValueName, pValue, (LPDWORD)&TypeOfValue, (LPDWORD)&SizeOfValue) != ERROR_SUCCESS )
|
|
{
|
|
delete []pValue;
|
|
pValue = NULL;
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
|
|
// If the type is a null termiated string
|
|
// then assign it to the CHString
|
|
// ======================================
|
|
|
|
switch(TypeOfValue)
|
|
{
|
|
case REG_MULTI_SZ:
|
|
{
|
|
LPCWSTR ptemp = (LPCWSTR)pValue;
|
|
int stringlength;
|
|
stringlength = wcslen(ptemp);
|
|
while(stringlength)
|
|
{
|
|
DestValue.Add(ptemp); // Move string in
|
|
ptemp += stringlength+1;
|
|
stringlength = wcslen(ptemp);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
delete [] pValue;
|
|
pValue = NULL;
|
|
return (DWORD) REGDB_E_INVALIDVALUE;
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] pValue ;
|
|
pValue = NULL;
|
|
throw ;
|
|
}
|
|
|
|
delete [] pValue;
|
|
pValue = NULL;
|
|
return (DWORD)ERROR_SUCCESS;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
CHStringArray &DestValue
|
|
)
|
|
{
|
|
return GetCurrentKeyValue (
|
|
|
|
hKey,
|
|
pValueName,
|
|
DestValue
|
|
);
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentKeyValue (
|
|
|
|
HKEY UseKey,
|
|
LPCWSTR pValueName,
|
|
DWORD &DestValue
|
|
)
|
|
{
|
|
DWORD SizeOfValue = MAX_SUBKEY_BUFFERSIZE;
|
|
long RetValue;
|
|
DWORD TypeOfValue;
|
|
LPBYTE pValue; // Pointer to buffer for value
|
|
|
|
pValue = new BYTE[MAX_SUBKEY_BUFFERSIZE];
|
|
if(pValue)
|
|
{
|
|
try
|
|
{
|
|
// Get the value in its RAW format
|
|
// ===============================
|
|
RetValue = GetCurrentRawKeyValue (
|
|
|
|
UseKey,
|
|
pValueName,
|
|
pValue,
|
|
(LPDWORD)&TypeOfValue,
|
|
(LPDWORD)&SizeOfValue
|
|
);
|
|
|
|
if( ERROR_SUCCESS == RetValue )
|
|
{
|
|
// If the type is a null termiated string
|
|
// then assign it to the CHString
|
|
// ======================================
|
|
switch(TypeOfValue)
|
|
{
|
|
case REG_SZ:
|
|
{
|
|
DestValue = atol((LPSTR)pValue);
|
|
}
|
|
break;
|
|
|
|
case REG_DWORD:
|
|
{
|
|
DestValue = *((DWORD*)(pValue));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
DestValue = (DWORD)0L;
|
|
RetValue = REGDB_E_INVALIDVALUE; // Invalid value
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
delete[] pValue;
|
|
pValue = NULL;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] pValue ;
|
|
pValue = NULL;
|
|
throw ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
DWORD &DestValue
|
|
)
|
|
{
|
|
return( GetCurrentKeyValue(hKey, pValueName, DestValue));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Added support for Binary Type
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD CRegistry::GetCurrentBinaryKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
CHString &chsDest
|
|
)
|
|
{
|
|
DWORD dwType = REG_BINARY;
|
|
DWORD dwRc;
|
|
WCHAR szDest[_MAX_PATH+2], ByteBuf[_MAX_PATH];
|
|
BYTE bRevision[_MAX_PATH+2];
|
|
DWORD dwSize = _MAX_PATH;
|
|
|
|
dwRc = GetCurrentRawKeyValue (
|
|
|
|
hKey,
|
|
pValueName,
|
|
bRevision,
|
|
&dwType,
|
|
&dwSize
|
|
);
|
|
|
|
if( dwRc != ERROR_SUCCESS )
|
|
{
|
|
return dwRc;
|
|
}
|
|
|
|
wcscpy( szDest, QUOTE );
|
|
|
|
for( DWORD i=0; i<dwSize; i++ )
|
|
{
|
|
swprintf( ByteBuf, L"%02x", bRevision[i]);
|
|
wcscat( szDest, ByteBuf );
|
|
}
|
|
|
|
wcscat(szDest, QUOTE);
|
|
chsDest = szDest;
|
|
|
|
return dwRc;
|
|
}
|
|
|
|
DWORD CRegistry::GetCurrentBinaryKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
LPBYTE pbDest,
|
|
LPDWORD pSizeOfDestValue
|
|
)
|
|
{
|
|
DWORD dwType = 0 ;
|
|
|
|
return GetCurrentRawKeyValue (
|
|
|
|
hKey,
|
|
pValueName,
|
|
pbDest,
|
|
&dwType,
|
|
&(*pSizeOfDestValue)
|
|
) ;
|
|
}
|
|
|
|
DWORD CRegistry::GetCurrentBinaryKeyValue (
|
|
HKEY UseKey ,
|
|
LPCWSTR pValueName ,
|
|
LPBYTE pbDest ,
|
|
LPDWORD pSizeOfDestValue )
|
|
{
|
|
DWORD dwType = 0 ;
|
|
|
|
return GetCurrentRawKeyValue (
|
|
|
|
UseKey,
|
|
pValueName,
|
|
pbDest,
|
|
&dwType,
|
|
&(*pSizeOfDestValue)
|
|
) ;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentSubKeyName (
|
|
|
|
CHString &DestSubKeyName
|
|
)
|
|
{
|
|
WCHAR KeyName[MAX_SUBKEY_BUFFERSIZE];
|
|
DWORD RetValue;
|
|
|
|
// and don't bother having RegEnumKey error out
|
|
if(CurrentSubKeyIndex >= dwcSubKeys)
|
|
{
|
|
// If we have exceeded the number of subkeys available tell the caller
|
|
return( ERROR_NO_MORE_ITEMS );
|
|
}
|
|
|
|
RetValue = myRegEnumKey (
|
|
|
|
hKey,
|
|
CurrentSubKeyIndex,
|
|
KeyName,
|
|
MAX_SUBKEY_BUFFERSIZE
|
|
);
|
|
|
|
// If we are successfull reading the name
|
|
//=======================================
|
|
if(ERROR_SUCCESS == RetValue)
|
|
{
|
|
DestSubKeyName = KeyName;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise clear the string so we don't leave garbage
|
|
//=====================================================
|
|
|
|
DestSubKeyName.Empty();
|
|
}
|
|
|
|
return RetValue; // In either event, return the value RegEnumKey returned
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentSubKeyPath (
|
|
|
|
CHString &DestSubKeyPath
|
|
)
|
|
{
|
|
CHString TempName;
|
|
DWORD dwRet;
|
|
|
|
dwRet = GetCurrentSubKeyName(TempName);
|
|
if (dwRet == ERROR_SUCCESS)
|
|
{
|
|
DestSubKeyPath = RootKeyPath+"\\";
|
|
DestSubKeyPath += TempName;
|
|
}
|
|
else
|
|
{
|
|
DestSubKeyPath.Empty();
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
void CRegistry::Close(void)
|
|
{
|
|
if(hSubKey != NULL)
|
|
{
|
|
RegCloseKey(hSubKey) ;
|
|
hSubKey = NULL ;
|
|
}
|
|
|
|
if(hKey != NULL)
|
|
{
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
|
|
if(hRootKey != NULL && m_fFromCurrentUser)
|
|
{
|
|
RegCloseKey(hRootKey);
|
|
hRootKey = NULL;
|
|
}
|
|
|
|
SetDefaultValues(); // Reset all the member vars for next
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::OpenSubKey(void)
|
|
{
|
|
CHString SubKeyPath;
|
|
LONG RetValue;
|
|
|
|
// If they try and open the same subkey again then
|
|
// leave things alone, otherwise open the subkey
|
|
|
|
if(hSubKey)
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// Get the current subkey path
|
|
//============================
|
|
GetCurrentSubKeyPath(SubKeyPath);
|
|
|
|
|
|
// Just return the value and the hKey value never gets changed from NULL
|
|
//======================================================================
|
|
|
|
RetValue = myRegOpenKeyEx (
|
|
|
|
hRootKey,
|
|
(LPCWSTR)SubKeyPath, // address of name of subkey to open
|
|
(DWORD) 0, // reserved
|
|
KEY_READ, // security access mask
|
|
(PHKEY)&hSubKey // address of handle of open key
|
|
);
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
void CRegistry::RewindSubKeys(void)
|
|
{
|
|
CurrentSubKeyIndex = 0;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
void CRegistry::CloseSubKey(void)
|
|
{
|
|
if(hSubKey != NULL)
|
|
{
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
hSubKey = NULL; // Only Close once
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentRawSubKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
void *pDestValue,
|
|
LPDWORD pValueType,
|
|
LPDWORD pSizeOfDestValue
|
|
)
|
|
{
|
|
// Try and open subkey
|
|
// and set hSubKey variable
|
|
// ========================
|
|
DWORD RetValue = OpenSubKey();
|
|
|
|
// If subkey is open then get value
|
|
// ================================
|
|
if(ERROR_SUCCESS == RetValue)
|
|
{
|
|
RetValue = GetCurrentRawKeyValue (
|
|
|
|
hSubKey,
|
|
pValueName,
|
|
pDestValue,
|
|
pValueType,
|
|
pSizeOfDestValue
|
|
);
|
|
}
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentSubKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
void *pDestValue,
|
|
LPDWORD pSizeOfDestValue
|
|
)
|
|
{
|
|
DWORD RetValue;
|
|
|
|
// Try and open subkey
|
|
// and set hSubKey variable
|
|
// ========================
|
|
RetValue = OpenSubKey();
|
|
|
|
// If subkey is open then get value
|
|
// ================================
|
|
if(ERROR_SUCCESS == RetValue)
|
|
{
|
|
RetValue = GetCurrentRawSubKeyValue (
|
|
|
|
pValueName,
|
|
pDestValue,
|
|
NULL,
|
|
pSizeOfDestValue
|
|
);
|
|
}
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentSubKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
CHString &DestValue
|
|
)
|
|
{
|
|
DWORD RetValue;
|
|
|
|
// Try and open subkey
|
|
// and set hSubKey variable
|
|
// ========================
|
|
RetValue = OpenSubKey();
|
|
|
|
// If subkey is open then get value
|
|
// ================================
|
|
if(ERROR_SUCCESS == RetValue)
|
|
{
|
|
RetValue = GetCurrentKeyValue (
|
|
|
|
hSubKey,
|
|
pValueName,
|
|
DestValue
|
|
);
|
|
}
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::GetCurrentSubKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
DWORD &DestValue
|
|
)
|
|
{
|
|
DWORD RetValue;
|
|
|
|
// Try and open subkey
|
|
// and set hSubKey variable
|
|
// ========================
|
|
RetValue = OpenSubKey();
|
|
|
|
// If subkey is open then get value
|
|
// ================================
|
|
if(ERROR_SUCCESS == RetValue)
|
|
{
|
|
RetValue = GetCurrentKeyValue (
|
|
|
|
hSubKey,
|
|
pValueName,
|
|
DestValue
|
|
);
|
|
}
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::NextSubKey(void)
|
|
{
|
|
if (CurrentSubKeyIndex >= dwcSubKeys)
|
|
{
|
|
return( ERROR_NO_MORE_ITEMS );
|
|
}
|
|
|
|
// Close the currently opened subkey
|
|
CloseSubKey();
|
|
|
|
if(++CurrentSubKeyIndex >= dwcSubKeys)
|
|
{
|
|
// CurrentSubKeyIndex is 0 based, dwcSubKeys is one based
|
|
return( ERROR_NO_MORE_ITEMS );
|
|
}
|
|
else
|
|
{
|
|
return (ERROR_SUCCESS);
|
|
}
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
void CRegistry::PrepareToReOpen(void)
|
|
{
|
|
Close();
|
|
SetDefaultValues();
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValueString(LPCSTR pValueName, CHString &DestValue)
|
|
Description: sets registry string using REG_SZ
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::SetCurrentKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
CHString &DestValue
|
|
)
|
|
{
|
|
DWORD dwResult;
|
|
|
|
if(DestValue.Find(_T('%')) != -1)
|
|
{
|
|
dwResult = SetCurrentKeyValueExpand (
|
|
|
|
hKey,
|
|
pValueName,
|
|
DestValue
|
|
);
|
|
}
|
|
else
|
|
{
|
|
dwResult = SetCurrentKeyValue (
|
|
|
|
hKey,
|
|
pValueName,
|
|
DestValue
|
|
);
|
|
}
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function:
|
|
Description:
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::SetCurrentKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
DWORD &DestValue
|
|
)
|
|
{
|
|
DWORD dwResult = SetCurrentKeyValue (
|
|
|
|
hKey,
|
|
pValueName,
|
|
DestValue
|
|
);
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValue(LPCSTR pValueName, CHStringArray &DestValue)
|
|
Description: sets registry string using REG_MULIT_SZ
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::SetCurrentKeyValue (
|
|
|
|
LPCWSTR pValueName,
|
|
CHStringArray &DestValue
|
|
)
|
|
{
|
|
DWORD dwResult = SetCurrentKeyValue (
|
|
|
|
hKey,
|
|
pValueName,
|
|
DestValue
|
|
);
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHString &DestValue)
|
|
Description: sets registry string using REG_MULIT_SZ
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::SetCurrentKeyValue (
|
|
|
|
HKEY hUseKey,
|
|
LPCWSTR pValueName,
|
|
CHString &DestValue
|
|
)
|
|
{
|
|
DWORD dwResult = myRegSetValueEx (
|
|
|
|
hUseKey, // key handle
|
|
pValueName, // name of value
|
|
0, // reserved -- must be zero
|
|
REG_SZ, // data type
|
|
(const BYTE*)(LPCWSTR)DestValue,
|
|
( DestValue.GetLength() + 1 ) * sizeof ( WCHAR )
|
|
);
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, DWORD &DestValue)
|
|
Description: sets registry string using REG_MULIT_SZ
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::SetCurrentKeyValue (
|
|
|
|
HKEY hUseKey,
|
|
LPCWSTR pValueName,
|
|
DWORD &DestValue
|
|
)
|
|
{
|
|
DWORD dwResult = myRegSetValueEx (
|
|
|
|
hUseKey, // key handle
|
|
pValueName, // name of value
|
|
0, // reserved -- must be zero
|
|
REG_DWORD, // data type
|
|
(const BYTE*)&DestValue,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHStringArray &DestValue)
|
|
Description: sets registry string using REG_MULIT_SZ
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::SetCurrentKeyValue (
|
|
|
|
HKEY hUseKey,
|
|
LPCWSTR pValueName,
|
|
CHStringArray &DestValue
|
|
)
|
|
{
|
|
DWORD dwResult = ERROR_SUCCESS;
|
|
|
|
DWORD dwArrayChars = 0;
|
|
for ( LONG Index = 0; Index < DestValue.GetSize(); Index++ )
|
|
{
|
|
CHString chsTemp = DestValue.GetAt(Index);
|
|
|
|
dwArrayChars += ( chsTemp.GetLength() + 1 ) * sizeof(WCHAR);
|
|
}
|
|
|
|
// Add room for the trailing wide character null
|
|
dwArrayChars += 2;
|
|
|
|
WCHAR* pValue = new WCHAR[dwArrayChars];
|
|
if( !pValue )
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
try
|
|
{
|
|
memset( pValue, 0, dwArrayChars*sizeof(WCHAR) );
|
|
|
|
DWORD dwCharCount = 0;
|
|
for ( Index = 0; Index < DestValue.GetSize(); Index++ )
|
|
{
|
|
CHString chsTemp = DestValue.GetAt(Index);
|
|
|
|
wcscpy(&pValue[dwCharCount], chsTemp.GetBuffer(0));
|
|
|
|
dwCharCount += ( chsTemp.GetLength() + 1 ) ;
|
|
}
|
|
|
|
dwResult = myRegSetValueEx (
|
|
|
|
hUseKey, // key handle
|
|
pValueName, // name of value
|
|
0, // reserved -- must be zero
|
|
REG_MULTI_SZ, // data type
|
|
(const BYTE *)pValue,
|
|
dwArrayChars
|
|
);
|
|
|
|
delete [] pValue;
|
|
pValue = NULL;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] pValue;
|
|
pValue = NULL;
|
|
throw ;
|
|
}
|
|
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValueExpand(HKEY UseKey, LPCSTR pValueName, CHString &DestValue)
|
|
Description: sets registry string using REG_EXPAND_SZ, required when the string contains variables (e.g., %SystemRoot%)
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::SetCurrentKeyValueExpand (
|
|
|
|
HKEY hUseKey,
|
|
LPCWSTR pValueName,
|
|
CHString &DestValue
|
|
)
|
|
{
|
|
DWORD dwResult = myRegSetValueEx (
|
|
|
|
hUseKey, // key handle
|
|
pValueName, // name of value
|
|
0, // reserved -- must be zero
|
|
REG_EXPAND_SZ, // data type
|
|
(const BYTE*)(LPCWSTR)DestValue,
|
|
( DestValue.GetLength() + 1 ) * sizeof ( WCHAR )
|
|
);
|
|
|
|
return dwResult ;
|
|
}
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHStringArray &DestValue)
|
|
Description: sets registry string using REG_MULIT_SZ
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::DeleteCurrentKeyValue (
|
|
|
|
LPCWSTR pValueName
|
|
)
|
|
{
|
|
return myRegDeleteValue (
|
|
|
|
hKey,
|
|
pValueName
|
|
);
|
|
}
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHStringArray &DestValue)
|
|
Description: sets registry string using REG_MULIT_SZ
|
|
Arguments:
|
|
Returns:
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Raid:
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
DWORD CRegistry::DeleteCurrentKeyValue (
|
|
|
|
HKEY UseKey,
|
|
LPCWSTR pValueName
|
|
)
|
|
{
|
|
return myRegDeleteValue (
|
|
|
|
UseKey,
|
|
pValueName
|
|
);
|
|
}
|
|
|
|
//*****************************************************************
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Class: CRegistrySearch
|
|
//
|
|
// This class searches through the registry for matching Values,
|
|
// Keys and Partial Keys
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
//*****************************************************************
|
|
CRegistrySearch::CRegistrySearch()
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
CRegistrySearch::~CRegistrySearch()
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// void CRegistrySearch::CheckAndAddToList( CRegistry * pReg,
|
|
// CHString chsSubKey,
|
|
// CHString chsFullKey,
|
|
// CHPtrArray & chpaList,
|
|
// CHString chsSearchString,
|
|
// int nSearchType)
|
|
//
|
|
// Desc: This function performs the requested search on the
|
|
// current key and if it matches, then adds it to the
|
|
// CHPtrArray
|
|
//
|
|
// Parameters:
|
|
// pReg - The current registry class
|
|
// chsSubKey - The current Key
|
|
// chsFullKey - The complete key
|
|
// chpaList - The target CHPtrArray
|
|
// chsSearchString - The string to search for
|
|
// nSearchType - The type of search, the following are
|
|
// supported:
|
|
// KEY_FULL_MATCH_SEARCH
|
|
// Only keys that match the chsSearchString
|
|
// KEY_PARTIAL_MATCH_SEARCH
|
|
// Keys that have chsSearchString anywhere in them
|
|
// VALUE_SEARCH
|
|
// Values that match chsSearchString
|
|
//
|
|
// History
|
|
// Initial coding jennymc 10/10/96
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
void CRegistrySearch::CheckAndAddToList (
|
|
|
|
CRegistry * pReg,
|
|
CHString chsSubKey,
|
|
CHString chsFullKey,
|
|
CHPtrArray & chpaList,
|
|
CHString chsSearchString,
|
|
CHString chsValue,
|
|
int nSearchType
|
|
)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
|
|
//====================================================
|
|
// We need to check out the current key to see if it
|
|
// matches any of our criteria.
|
|
//====================================================
|
|
|
|
if( nSearchType == VALUE_SEARCH )
|
|
{
|
|
//====================================================
|
|
// If it is a Value search, then let us try to open
|
|
// the value.
|
|
//====================================================
|
|
|
|
CHString chsTmp ;
|
|
|
|
if( pReg->GetCurrentSubKeyValue(chsValue, chsTmp) == ERROR_SUCCESS)
|
|
{
|
|
if( chsSearchString.CompareNoCase(chsTmp) == 0 )
|
|
{
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else if( nSearchType == KEY_FULL_MATCH_SEARCH )
|
|
{
|
|
if( chsSearchString == chsSubKey )
|
|
{
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( chsSubKey.Find(chsSearchString) )
|
|
{
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
//====================================================
|
|
// If it was found, then record the key location
|
|
//====================================================
|
|
if( bFound )
|
|
{
|
|
CHString *pchsPtr = new CHString;
|
|
if ( pchsPtr )
|
|
{
|
|
try
|
|
{
|
|
*pchsPtr = chsFullKey;
|
|
chpaList.Add( pchsPtr );
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete pchsPtr ;
|
|
pchsPtr = NULL;
|
|
throw ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Public function: Documented in cregcls.h
|
|
//
|
|
// History
|
|
// Initial coding jennymc 10/10/96
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
BOOL CRegistrySearch::SearchAndBuildList (
|
|
|
|
CHString chsRootKey,
|
|
CHPtrArray & cpaList,
|
|
CHString chsSearchString,
|
|
CHString chsValue,
|
|
int nSearchType,
|
|
HKEY hkDefault
|
|
)
|
|
{
|
|
BOOL bRc;
|
|
|
|
//=======================================================
|
|
// Allocate a registry class to open and enumerate the
|
|
// requested key.
|
|
//=======================================================
|
|
|
|
CRegistry *pReg = new CRegistry;
|
|
if( !pReg )
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
try
|
|
{
|
|
//=======================================================
|
|
// If the key cannot be opened, then cleanup and back
|
|
// out.
|
|
//=======================================================
|
|
if( pReg->OpenAndEnumerateSubKeys(hkDefault,chsRootKey, KEY_READ ) != ERROR_SUCCESS )
|
|
{
|
|
delete pReg ;
|
|
pReg = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
try
|
|
{
|
|
CHString chsSubKey ;
|
|
|
|
//=======================================================
|
|
// As long as there are subkeys under this key,
|
|
// let us open and enumerate each one, each time
|
|
// checking if it has the value or part of the
|
|
// string we want.
|
|
//
|
|
// The GetCurrentSubKeyName function only returns the
|
|
// current key, we have to add it to the end of the
|
|
// Parent key in order to get the full key name.
|
|
//=======================================================
|
|
while ( pReg->GetCurrentSubKeyName(chsSubKey) == ERROR_SUCCESS )
|
|
{
|
|
CHString chsFullKey ;
|
|
CHString chsSlash = L"\\";
|
|
|
|
chsFullKey = chsRootKey + chsSlash + chsSubKey;
|
|
|
|
CheckAndAddToList (
|
|
|
|
pReg,
|
|
chsSubKey,
|
|
chsFullKey,
|
|
cpaList,
|
|
chsSearchString,
|
|
chsValue,
|
|
nSearchType
|
|
);
|
|
|
|
pReg->NextSubKey();
|
|
|
|
bRc = SearchAndBuildList (
|
|
|
|
chsFullKey,
|
|
cpaList,
|
|
chsSearchString,
|
|
chsValue,
|
|
nSearchType
|
|
);
|
|
}
|
|
|
|
//=======================================================
|
|
// Close the current key and delete the registry pointer
|
|
//=======================================================
|
|
pReg->Close();
|
|
|
|
}
|
|
catch ( ... )
|
|
{
|
|
pReg->Close();
|
|
|
|
throw ;
|
|
}
|
|
|
|
delete pReg;
|
|
pReg = NULL;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete pReg ;
|
|
pReg = NULL;
|
|
throw ;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
BOOL CRegistrySearch::FreeSearchList (
|
|
|
|
int nType,
|
|
CHPtrArray & cpaList
|
|
)
|
|
{
|
|
BOOL bRc;
|
|
int i;
|
|
int nNum = cpaList.GetSize();
|
|
|
|
switch( nType )
|
|
{
|
|
case CSTRING_PTR:
|
|
{
|
|
CHString *pPtr;
|
|
for ( i=0; i < nNum; i++ )
|
|
{
|
|
pPtr = ( CHString * ) cpaList.GetAt(i);
|
|
delete pPtr;
|
|
pPtr = NULL;
|
|
}
|
|
bRc = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
bRc = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( bRc )
|
|
{
|
|
cpaList.RemoveAll();
|
|
}
|
|
|
|
return bRc;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FUNCTION : MOPropertySet_DevMem::LocateNTOwnerDevice
|
|
//
|
|
// DESCRIPTION : Helper function for locating a key of the specified
|
|
// name, or a key containg the specified value name.
|
|
//
|
|
// INPUTS : HKEY hKeyParent - Parent Key
|
|
// LPCWSTR pszKeyName - Name of Key to open
|
|
// LPCWSTR pszSubKeyName - Name of SubKey to Find
|
|
// LPCWSTR* ppszValueNames - Array of Value Names
|
|
// DWORD dwNumValueNames - Number of names in array
|
|
//
|
|
// OUTPUTS : CHString& strFoundKeyName - Storage for name of key if found.
|
|
// CHString& strFoundKeyPath - Storage for pathed key name
|
|
//
|
|
// RETURNS : nothing
|
|
//
|
|
// COMMENTS : Recursively Enumerates the registry from a specified
|
|
// starting point until it locates a subkey matching either
|
|
// a supplied subkey name or a value name matching one of
|
|
// the supplied names.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CRegistrySearch::LocateKeyByNameOrValueName(
|
|
|
|
HKEY hKeyParent,
|
|
LPCWSTR pszKeyName,
|
|
LPCWSTR pszSubKeyName,
|
|
LPCWSTR* ppszValueNames,
|
|
DWORD dwNumValueNames,
|
|
CHString& strFoundKeyName,
|
|
CHString& strFoundKeyPath
|
|
)
|
|
{
|
|
CRegistry reg;
|
|
BOOL fFound = FALSE;
|
|
|
|
// Get out of here if we got garbage parameters
|
|
if ( NULL == pszSubKeyName && NULL == ppszValueNames )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Open the key for enumeration and go through the sub keys.
|
|
|
|
LONG t_Status = reg.OpenAndEnumerateSubKeys (
|
|
|
|
hKeyParent,
|
|
pszKeyName,
|
|
KEY_READ
|
|
) ;
|
|
|
|
if ( ERROR_SUCCESS == t_Status )
|
|
{
|
|
try
|
|
{
|
|
CHString strSubKeyName;
|
|
DWORD dwValueBuffSize = 0;
|
|
|
|
// As long as we can get sub keys, we can try to find values.
|
|
|
|
while ( !fFound && ERROR_SUCCESS == reg.GetCurrentSubKeyName( strSubKeyName ) )
|
|
{
|
|
|
|
// First check if the specified sub key name matches the sub key name.
|
|
// If not, then check for the value names.
|
|
|
|
if ( NULL != pszSubKeyName && strSubKeyName == pszSubKeyName )
|
|
{
|
|
fFound = TRUE;
|
|
}
|
|
else if ( NULL != ppszValueNames )
|
|
{
|
|
// Enumerate the value names in the array until one is found.
|
|
|
|
for ( DWORD dwEnum = 0; !fFound && dwEnum < dwNumValueNames; dwEnum++ )
|
|
{
|
|
t_Status = reg.GetCurrentSubKeyValue(
|
|
|
|
ppszValueNames[dwEnum],
|
|
NULL,
|
|
&dwValueBuffSize
|
|
) ;
|
|
|
|
if ( ERROR_SUCCESS == t_Status )
|
|
{
|
|
fFound = TRUE;
|
|
}
|
|
|
|
} // FOR dwEnum
|
|
|
|
} // IF NULL != ppszValueNames
|
|
|
|
// Check if one of the methods located the key. If so, store all
|
|
// the current values.
|
|
|
|
if ( !fFound )
|
|
{
|
|
//
|
|
// No success, so recurse (WOOHOO!)
|
|
//
|
|
|
|
fFound = LocateKeyByNameOrValueName (
|
|
|
|
reg.GethKey(),
|
|
strSubKeyName,
|
|
pszSubKeyName,
|
|
ppszValueNames,
|
|
dwNumValueNames,
|
|
strFoundKeyName,
|
|
strFoundKeyPath
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// Store the actual key name in both the single
|
|
// name and path. We will build the full path
|
|
// as we slide back up the recursive chain.
|
|
|
|
strFoundKeyName = strSubKeyName;
|
|
strFoundKeyPath = strSubKeyName;
|
|
}
|
|
|
|
// Lastly, since fFound may now have been set by recursion, we will
|
|
// want to attach the current key path to the key name we've opened
|
|
// so when we return out of here, we get the full path to the
|
|
// located key name stored correctly.
|
|
|
|
if ( fFound )
|
|
{
|
|
CHString strSavePath( strFoundKeyPath );
|
|
strFoundKeyPath.Format(L"%s\\%s", (LPCWSTR) pszKeyName, (LPCWSTR) strSavePath );
|
|
}
|
|
else
|
|
{
|
|
// Not found yet, so go to the next key.
|
|
reg.NextSubKey();
|
|
}
|
|
|
|
} // While !Found
|
|
|
|
reg.Close();
|
|
}
|
|
catch ( ... )
|
|
{
|
|
reg.Close () ;
|
|
|
|
throw ;
|
|
}
|
|
|
|
} // If OpenAndEnumerateSubKeys
|
|
|
|
return fFound;
|
|
|
|
}
|
|
|
|
//========================================================================================
|
|
// These routines are for the multiplatform support
|
|
DWORD CRegistry::GetPlatformID(void)
|
|
{
|
|
OSVERSIONINFOA OsVersionInfoA;
|
|
|
|
OsVersionInfoA.dwOSVersionInfoSize = sizeof (OSVERSIONINFOA) ;
|
|
GetVersionExA(&OsVersionInfoA);
|
|
|
|
return OsVersionInfoA.dwPlatformId;
|
|
}
|
|
|
|
LONG CRegistry::myRegCreateKeyEx (
|
|
|
|
HKEY hKey,
|
|
LPCWSTR lpwcsSubKey,
|
|
DWORD Reserved,
|
|
LPWSTR lpwcsClass,
|
|
DWORD dwOptions,
|
|
REGSAM samDesired,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
PHKEY phkResult,
|
|
LPDWORD lpdwDisposition
|
|
)
|
|
{
|
|
if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
return RegCreateKeyExW (
|
|
|
|
hKey,
|
|
lpwcsSubKey,
|
|
Reserved,
|
|
lpwcsClass,
|
|
dwOptions,
|
|
samDesired,
|
|
lpSecurityAttributes,
|
|
phkResult,
|
|
lpdwDisposition
|
|
);
|
|
}
|
|
else
|
|
{
|
|
char *szSubKey = NULL ;
|
|
bool t_ConversionFailure = false ;
|
|
|
|
WCSTOANSISTRING ( lpwcsSubKey , szSubKey , t_ConversionFailure ) ;
|
|
|
|
if (t_ConversionFailure)
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
char *lpClass = NULL ;
|
|
t_ConversionFailure = false ;
|
|
|
|
WCSTOANSISTRING ( lpwcsClass , lpClass , t_ConversionFailure );
|
|
|
|
if (t_ConversionFailure)
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
return RegCreateKeyExA (
|
|
|
|
hKey,
|
|
szSubKey,
|
|
Reserved,
|
|
lpClass,
|
|
dwOptions,
|
|
samDesired,
|
|
lpSecurityAttributes,
|
|
phkResult,
|
|
lpdwDisposition
|
|
);
|
|
}
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
LONG CRegistry::myRegSetValueEx (
|
|
|
|
HKEY hKey,
|
|
LPCWSTR lpwcsSubKey,
|
|
DWORD Reserved,
|
|
DWORD dwType,
|
|
CONST BYTE *lpData,
|
|
DWORD cbData
|
|
)
|
|
{
|
|
LONG lRet;
|
|
|
|
if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
lRet = RegSetValueExW (
|
|
|
|
hKey,
|
|
lpwcsSubKey,
|
|
Reserved,
|
|
dwType,
|
|
lpData,
|
|
cbData
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// First convert the key name
|
|
|
|
bool t_ConversionFailure = false ;
|
|
char *pName = NULL ;
|
|
|
|
if ( lpwcsSubKey != NULL )
|
|
{
|
|
WCSTOANSISTRING ( lpwcsSubKey , pName , t_ConversionFailure ) ;
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( ! pName )
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION ;
|
|
}
|
|
}
|
|
|
|
// Now, we may need to convert the data
|
|
|
|
BYTE *pMyData = NULL ;
|
|
|
|
try
|
|
{
|
|
DWORD dwMySize = 0 ;
|
|
|
|
bool bDoit = false ;
|
|
|
|
switch ( dwType )
|
|
{
|
|
case REG_EXPAND_SZ:
|
|
case REG_SZ:
|
|
{
|
|
// If it's a simple string, convert it
|
|
|
|
t_ConversionFailure = false ;
|
|
|
|
WCHAR *pStrUnicode = ( WCHAR * ) lpData ;
|
|
char *pStrAnsi = NULL ;
|
|
|
|
WCSTOANSISTRING ( pStrUnicode , pStrAnsi , t_ConversionFailure ) ;
|
|
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( pStrAnsi != NULL )
|
|
{
|
|
pMyData = ( BYTE * ) pStrAnsi ;
|
|
dwMySize = strlen ( pStrAnsi ) ;
|
|
|
|
bDoit = true ;
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case REG_MULTI_SZ:
|
|
{
|
|
// If it's a multi-sz, it take a little more
|
|
|
|
int nLen = ::WideCharToMultiByte (
|
|
|
|
CP_ACP ,
|
|
0 ,
|
|
( const WCHAR *) lpData ,
|
|
cbData ,
|
|
NULL ,
|
|
0 ,
|
|
NULL ,
|
|
NULL
|
|
);
|
|
|
|
if ( nLen > 0 )
|
|
{
|
|
pMyData = new BYTE [ nLen ] ;
|
|
if ( pMyData != NULL )
|
|
{
|
|
dwMySize = WideCharToMultiByte (
|
|
|
|
CP_ACP ,
|
|
0,
|
|
( const WCHAR * ) lpData ,
|
|
cbData ,
|
|
( char * )pMyData ,
|
|
nLen ,
|
|
NULL ,
|
|
NULL
|
|
) ;
|
|
|
|
bDoit = true;
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_NO_UNICODE_TRANSLATION ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
// All other types, just write it
|
|
|
|
pMyData = ( BYTE * ) lpData ;
|
|
dwMySize = cbData ;
|
|
bDoit = true;
|
|
}
|
|
break ;
|
|
}
|
|
|
|
if ( bDoit )
|
|
{
|
|
lRet = RegSetValueExA (
|
|
|
|
hKey,
|
|
pName,
|
|
Reserved,
|
|
dwType,
|
|
pMyData,
|
|
dwMySize
|
|
);
|
|
}
|
|
|
|
if ( ( dwType == REG_MULTI_SZ ) && ( pMyData != NULL ) )
|
|
{
|
|
delete [] pMyData ;
|
|
pMyData = NULL;
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if ( ( dwType == REG_MULTI_SZ ) && ( pMyData != NULL ) )
|
|
{
|
|
delete [] pMyData ;
|
|
pMyData = NULL;
|
|
}
|
|
|
|
throw ;
|
|
}
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
LONG CRegistry::myRegQueryValueEx (
|
|
|
|
HKEY hKey,
|
|
LPCWSTR lpwcsSubKey,
|
|
LPDWORD Reserved,
|
|
LPDWORD dwType,
|
|
LPBYTE lpData,
|
|
LPDWORD cbData
|
|
)
|
|
{
|
|
LONG lRet;
|
|
|
|
if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
lRet = RegQueryValueExW (
|
|
|
|
hKey,
|
|
lpwcsSubKey,
|
|
Reserved,
|
|
dwType,
|
|
lpData,
|
|
cbData
|
|
);
|
|
}
|
|
else
|
|
{
|
|
bool t_ConversionFailure = false ;
|
|
char *pName = NULL ;
|
|
|
|
if ( lpwcsSubKey != NULL )
|
|
{
|
|
WCSTOANSISTRING ( lpwcsSubKey , pName , t_ConversionFailure ) ;
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( ! pName )
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION ;
|
|
}
|
|
}
|
|
|
|
BYTE *pMyData = NULL ;
|
|
|
|
try
|
|
{
|
|
if ( lpData != NULL )
|
|
{
|
|
pMyData = new BYTE [ *cbData ] ;
|
|
if ( ! pMyData )
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
|
|
if ( ( pMyData != NULL ) || (lpData == NULL))
|
|
{
|
|
DWORD dwMySize = *cbData;
|
|
|
|
lRet = RegQueryValueExA (
|
|
|
|
hKey,
|
|
pName,
|
|
Reserved,
|
|
dwType,
|
|
pMyData,
|
|
& dwMySize
|
|
) ;
|
|
|
|
// If it worked, we may need to convert the strings
|
|
|
|
if ( lRet == ERROR_SUCCESS )
|
|
{
|
|
switch ( *dwType )
|
|
{
|
|
case REG_EXPAND_SZ:
|
|
case REG_SZ:
|
|
{
|
|
// If lpData is null, there isn't any way to say for sure how long the target string needs
|
|
// to be. However, it can't be more than twice as long (it can be less).
|
|
|
|
if (lpData == NULL)
|
|
{
|
|
*cbData = dwMySize * 2;
|
|
}
|
|
else
|
|
{
|
|
int nLen = ::MultiByteToWideChar (
|
|
|
|
CP_ACP,
|
|
0,
|
|
(const char *)pMyData,
|
|
-1,
|
|
(WCHAR *)lpData,
|
|
*cbData
|
|
);
|
|
// Convert to bytes
|
|
*cbData = nLen * 2;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case REG_MULTI_SZ:
|
|
{
|
|
// If lpData is null, there isn't any way to say for sure how long the target string needs
|
|
// to be. However, it can't be more than twice as long (it can be less).
|
|
|
|
if (lpData == NULL)
|
|
{
|
|
*cbData = dwMySize * 2;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwConverted = MultiByteToWideChar (
|
|
|
|
CP_ACP,
|
|
0,
|
|
(const char *)pMyData,
|
|
dwMySize,
|
|
(WCHAR *)lpData,
|
|
*cbData
|
|
);
|
|
}
|
|
}
|
|
break ;
|
|
|
|
default:
|
|
{
|
|
// All other types are handled in RegQueryValue
|
|
|
|
*cbData = dwMySize ;
|
|
|
|
if( NULL != lpData )
|
|
{
|
|
memcpy ( lpData , pMyData , *cbData ) ;
|
|
}
|
|
}
|
|
break ;
|
|
}
|
|
}
|
|
|
|
delete [] pMyData;
|
|
pMyData = NULL;
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] pMyData ;
|
|
pMyData = NULL;
|
|
throw ;
|
|
}
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
LONG CRegistry::myRegEnumKey (
|
|
|
|
HKEY hKey,
|
|
DWORD dwIndex,
|
|
LPWSTR lpwcsName,
|
|
DWORD cbData
|
|
)
|
|
{
|
|
if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
return RegEnumKeyW (
|
|
|
|
hKey,
|
|
dwIndex,
|
|
lpwcsName,
|
|
cbData
|
|
);
|
|
}
|
|
else
|
|
{
|
|
char szName[_MAX_PATH];
|
|
|
|
LONG lRet = RegEnumKeyA (
|
|
|
|
hKey,
|
|
dwIndex,
|
|
szName,
|
|
cbData
|
|
);
|
|
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
bool t_ConversionFailure = false ;
|
|
WCHAR *pName = NULL ;
|
|
ANSISTRINGTOWCS ( szName , pName , t_ConversionFailure ) ;
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( pName )
|
|
{
|
|
wcscpy(lpwcsName, pName);
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION ;
|
|
}
|
|
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
}
|
|
|
|
LONG CRegistry::myRegDeleteValue (
|
|
|
|
HKEY hKey,
|
|
LPCWSTR lpwcsName
|
|
)
|
|
{
|
|
if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
return RegDeleteValueW (
|
|
|
|
hKey,
|
|
lpwcsName
|
|
);
|
|
}
|
|
else
|
|
{
|
|
bool t_ConversionFailure = false ;
|
|
char *pName = NULL ;
|
|
WCSTOANSISTRING ( lpwcsName, pName , t_ConversionFailure ) ;
|
|
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( pName )
|
|
{
|
|
return RegDeleteValueA (
|
|
|
|
hKey,
|
|
pName
|
|
);
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION ;
|
|
}
|
|
}
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
LONG CRegistry::myRegDeleteKey (
|
|
|
|
HKEY hKey,
|
|
LPCWSTR lpwcsName
|
|
)
|
|
{
|
|
if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
return RegDeleteKeyW (
|
|
|
|
hKey,
|
|
lpwcsName
|
|
);
|
|
}
|
|
else
|
|
{
|
|
bool t_ConversionFailure = false ;
|
|
char *pName = NULL ;
|
|
WCSTOANSISTRING ( lpwcsName, pName , t_ConversionFailure ) ;
|
|
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( pName )
|
|
{
|
|
return RegDeleteKeyA (
|
|
|
|
hKey,
|
|
pName
|
|
);
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION ;
|
|
}
|
|
}
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
LONG CRegistry::myRegOpenKeyEx (
|
|
|
|
HKEY hKey,
|
|
LPCWSTR lpwcsSubKey,
|
|
DWORD ulOptions,
|
|
REGSAM samDesired,
|
|
PHKEY phkResult
|
|
)
|
|
{
|
|
if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
return RegOpenKeyExW (
|
|
|
|
hKey,
|
|
lpwcsSubKey,
|
|
ulOptions,
|
|
samDesired,
|
|
phkResult
|
|
);
|
|
}
|
|
|
|
char *pName = NULL ;
|
|
bool t_ConversionFailure = false ;
|
|
|
|
WCSTOANSISTRING ( lpwcsSubKey, pName , t_ConversionFailure );
|
|
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( pName )
|
|
{
|
|
return RegOpenKeyExA (
|
|
|
|
hKey,
|
|
pName,
|
|
ulOptions,
|
|
samDesired,
|
|
phkResult
|
|
);
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
LONG CRegistry::myRegQueryInfoKey (
|
|
|
|
HKEY hKey,
|
|
LPWSTR lpwstrClass,
|
|
LPDWORD lpcbClass,
|
|
LPDWORD lpReserved,
|
|
LPDWORD lpcSubKeys,
|
|
LPDWORD lpcbMaxSubKeyLen,
|
|
LPDWORD lpcbMaxClassLen,
|
|
LPDWORD lpcValues,
|
|
LPDWORD lpcbMaxValueNameLen,
|
|
LPDWORD lpcbMaxValueLen,
|
|
LPDWORD lpcbSecurityDescriptor,
|
|
PFILETIME lpftLastWriteTime
|
|
)
|
|
{
|
|
if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
return RegQueryInfoKeyW (
|
|
|
|
hKey,
|
|
lpwstrClass,
|
|
lpcbClass,
|
|
lpReserved,
|
|
lpcSubKeys,
|
|
lpcbMaxSubKeyLen,
|
|
lpcbMaxClassLen,
|
|
lpcValues,
|
|
lpcbMaxValueNameLen,
|
|
lpcbMaxValueLen,
|
|
lpcbSecurityDescriptor,
|
|
lpftLastWriteTime
|
|
);
|
|
}
|
|
else
|
|
{
|
|
bool t_ConversionFailure = false ;
|
|
char *pName = NULL ;
|
|
WCSTOANSISTRING ( lpwstrClass, pName, t_ConversionFailure );
|
|
|
|
if ( ! t_ConversionFailure )
|
|
{
|
|
if ( pName )
|
|
{
|
|
|
|
return RegQueryInfoKeyA (
|
|
|
|
hKey,
|
|
pName,
|
|
lpcbClass,
|
|
lpReserved,
|
|
lpcSubKeys,
|
|
lpcbMaxSubKeyLen,
|
|
lpcbMaxClassLen,
|
|
lpcValues,
|
|
lpcbMaxValueNameLen,
|
|
lpcbMaxValueLen,
|
|
lpcbSecurityDescriptor,
|
|
lpftLastWriteTime
|
|
) ;
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
}
|
|
return ERROR_NO_UNICODE_TRANSLATION;
|
|
}
|
|
|
|
LONG CRegistry::myRegEnumValue (
|
|
|
|
HKEY hKey,
|
|
DWORD dwIndex,
|
|
LPWSTR lpValueName,
|
|
LPDWORD lpcbValueName,
|
|
LPDWORD lpReserved,
|
|
LPDWORD lpType,
|
|
LPBYTE lpData,
|
|
LPDWORD lpcbData
|
|
)
|
|
{
|
|
if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
return RegEnumValueW (
|
|
|
|
hKey,
|
|
dwIndex,
|
|
lpValueName,
|
|
lpcbValueName,
|
|
lpReserved,
|
|
lpType,
|
|
lpData,
|
|
lpcbData
|
|
);
|
|
}
|
|
else
|
|
{
|
|
char szData[MAX_PATH * 2];
|
|
|
|
LONG lRet = RegEnumValueA (
|
|
|
|
hKey,
|
|
dwIndex,
|
|
szData,
|
|
lpcbValueName,
|
|
lpReserved,
|
|
lpType,
|
|
lpData,
|
|
lpcbData
|
|
);
|
|
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
// Get the name.
|
|
mbstowcs(lpValueName, szData, lstrlenA(szData) + 1);
|
|
|
|
// Get the value if the data is a string.
|
|
if (*lpType == REG_SZ || *lpType == REG_MULTI_SZ)
|
|
{
|
|
lstrcpyA(szData, (LPSTR) lpData);
|
|
mbstowcs((LPWSTR) lpData, szData, lstrlenA(szData) + 1);
|
|
*lpcbData = (lstrlenW((LPWSTR) lpData) + 1) * sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
}
|