1332 lines
24 KiB
C++
1332 lines
24 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
Registry
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements the CRegistry Class, simplifying access to the
|
||
|
Registry Database.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Win32, C++ w/ Exceptions
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
The only exceptions thrown are DWORDs, containing the error code.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#endif
|
||
|
#include <windows.h>
|
||
|
#include "SCardLib.h"
|
||
|
|
||
|
#define NTOHL HTONL
|
||
|
|
||
|
static inline DWORD
|
||
|
HTONL(
|
||
|
DWORD dwInVal)
|
||
|
{
|
||
|
DWORD dwOutVal;
|
||
|
LPBYTE pbIn = (LPBYTE)&dwInVal,
|
||
|
pbOut = (LPBYTE)&dwOutVal;
|
||
|
for (DWORD index = 0; index < sizeof(DWORD); index += 1)
|
||
|
pbOut[sizeof(DWORD) - 1 - index] = pbIn[index];
|
||
|
return dwOutVal;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
//==============================================================================
|
||
|
//
|
||
|
// CRegistry
|
||
|
//
|
||
|
|
||
|
/*++
|
||
|
|
||
|
CRegistry:
|
||
|
|
||
|
These routines provide for the construction and destruction of Objects of
|
||
|
this class.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
regBase - A CRegistry object to be used as a parent for this object.
|
||
|
|
||
|
hBase - A Registry key to be the parent of this object.
|
||
|
|
||
|
szName - The name of the Registry key, relative to the supplied parent.
|
||
|
|
||
|
samDesired - The desired SAM.
|
||
|
|
||
|
dwOptions - Any special creation optiopns.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
None. If the registry access fails, the error will be thrown on first use.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
CRegistry::CRegistry(
|
||
|
HKEY hBase,
|
||
|
LPCTSTR szName,
|
||
|
REGSAM samDesired,
|
||
|
DWORD dwOptions,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||
|
: m_bfResult()
|
||
|
{
|
||
|
m_hKey = NULL;
|
||
|
m_lSts = ERROR_BADKEY;
|
||
|
Open(hBase, szName, samDesired, dwOptions, lpSecurityAttributes);
|
||
|
}
|
||
|
|
||
|
CRegistry::CRegistry()
|
||
|
{
|
||
|
m_hKey = NULL;
|
||
|
m_lSts = ERROR_BADKEY;
|
||
|
}
|
||
|
|
||
|
CRegistry::~CRegistry()
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Open:
|
||
|
|
||
|
These methods allow a CRegistry object to attempt to access a given registry
|
||
|
entry.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
regBase - A CRegistry object to be used as a parent for this object.
|
||
|
|
||
|
hBase - A Registry key to be the parent of this object.
|
||
|
|
||
|
szName - The name of the Registry key, relative to the supplied parent.
|
||
|
|
||
|
samDesired - The desired SAM.
|
||
|
|
||
|
dwOptions - Any special creation optiopns.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
None -- errors are saved for follow-on operations, so that Open can be used
|
||
|
safely in a constructor.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 12/2/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void CRegistry::Open(
|
||
|
HKEY hBase,
|
||
|
LPCTSTR szName,
|
||
|
REGSAM samDesired,
|
||
|
DWORD dwOptions,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
||
|
{
|
||
|
Close();
|
||
|
if (REG_OPTION_EXISTS == dwOptions)
|
||
|
{
|
||
|
m_lSts = RegOpenKeyEx(
|
||
|
hBase,
|
||
|
szName,
|
||
|
0,
|
||
|
samDesired,
|
||
|
&m_hKey);
|
||
|
m_dwDisposition = REG_OPENED_EXISTING_KEY;
|
||
|
}
|
||
|
else
|
||
|
m_lSts = RegCreateKeyEx(
|
||
|
hBase,
|
||
|
szName,
|
||
|
0,
|
||
|
TEXT(""),
|
||
|
dwOptions,
|
||
|
samDesired,
|
||
|
lpSecurityAttributes,
|
||
|
&m_hKey,
|
||
|
&m_dwDisposition);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Close:
|
||
|
|
||
|
Shut down a CRegistry object, making it available for follow-on opens.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 12/2/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::Close(
|
||
|
void)
|
||
|
{
|
||
|
HRESULT hrSts;
|
||
|
|
||
|
if (NULL != m_hKey)
|
||
|
{
|
||
|
hrSts = RegCloseKey(m_hKey);
|
||
|
ASSERT(ERROR_SUCCESS == hrSts);
|
||
|
m_hKey = NULL;
|
||
|
}
|
||
|
m_lSts = ERROR_BADKEY;
|
||
|
m_bfResult.Reset();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Status:
|
||
|
|
||
|
This routine returns the status code from the construction routine. This is
|
||
|
useful to check for errors prior to having them thrown.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
fQuiet indicates whether or not to throw an error if the status is not
|
||
|
ERROR_SUCCESS.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The status code from the creation.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LONG
|
||
|
CRegistry::Status(
|
||
|
BOOL fQuiet)
|
||
|
const
|
||
|
{
|
||
|
if ((ERROR_SUCCESS != m_lSts) && !fQuiet)
|
||
|
throw (DWORD)m_lSts;
|
||
|
return m_lSts;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Empty:
|
||
|
|
||
|
This method cleans out the registry tree under the given key. All
|
||
|
underlying keys and values are removed. This does it's best -- if an error
|
||
|
occurs, the emptying operation stops, leaving the registry in an
|
||
|
indeterminate state.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors are thrown as DWORD status codes.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 1/16/1998
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::Empty(
|
||
|
void)
|
||
|
{
|
||
|
LPCTSTR szValue;
|
||
|
LPCTSTR szKey;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Go through all the values and delete them.
|
||
|
//
|
||
|
|
||
|
while (NULL != (szValue = Value(0)))
|
||
|
DeleteValue(szValue, TRUE);
|
||
|
|
||
|
|
||
|
#if 0 // Obsolete code
|
||
|
//
|
||
|
// Go through all the Keys and empty them.
|
||
|
//
|
||
|
|
||
|
DWORD dwIndex;
|
||
|
for (dwIndex = 0; NULL != (szKey = Subkey(dwIndex)); dwIndex += 1)
|
||
|
{
|
||
|
CRegistry regEmpty;
|
||
|
|
||
|
regEmpty.Open(*this, szKey);
|
||
|
regEmpty.Empty();
|
||
|
regEmpty.Close();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
//
|
||
|
// Now delete all the keys.
|
||
|
//
|
||
|
|
||
|
while (NULL != (szKey = Subkey(0)))
|
||
|
DeleteKey(szKey, TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Copy:
|
||
|
|
||
|
This method loads the current registry keys with all the subkeys and values
|
||
|
from the supplied key. Current keys and values of this key are deleted.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
regSrc supplies the source registry key from which values and keys will be
|
||
|
loaded.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors are thrown as DWORD status codes.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 1/16/1998
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::Copy(
|
||
|
CRegistry ®Src)
|
||
|
{
|
||
|
LPCTSTR szValue;
|
||
|
LPCTSTR szKey;
|
||
|
DWORD dwIndex, dwType;
|
||
|
CRegistry regSrcSubkey, regDstSubkey;
|
||
|
CBuffer bfValue;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Go through all the values and copy them.
|
||
|
//
|
||
|
|
||
|
for (dwIndex = 0; NULL != (szValue = regSrc.Value(dwIndex)); dwIndex += 1)
|
||
|
{
|
||
|
regSrc.GetValue(szValue, bfValue, &dwType);
|
||
|
SetValue(szValue, bfValue.Access(), bfValue.Length(), dwType);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Now copy all the keys.
|
||
|
//
|
||
|
|
||
|
for (dwIndex = 0; NULL != (szKey = regSrc.Subkey(dwIndex)); dwIndex += 1)
|
||
|
{
|
||
|
regSrcSubkey.Open(regSrc, szKey, KEY_READ);
|
||
|
regDstSubkey.Open(
|
||
|
*this,
|
||
|
szKey,
|
||
|
KEY_ALL_ACCESS,
|
||
|
REG_OPTION_NON_VOLATILE);
|
||
|
regDstSubkey.Status();
|
||
|
regDstSubkey.Copy(regSrcSubkey);
|
||
|
regDstSubkey.Close();
|
||
|
regSrcSubkey.Close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
DeleteKey:
|
||
|
|
||
|
This method deletes a subkey from this key.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKey supplies the name of the key to be deleted.
|
||
|
|
||
|
fQuiet supplies whether or not to suppress errors.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
if fQuiet is FALSE, then any errors encountered are thrown as a DWORD.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::DeleteKey(
|
||
|
LPCTSTR szKey,
|
||
|
BOOL fQuiet)
|
||
|
const
|
||
|
{
|
||
|
if (ERROR_SUCCESS == m_lSts)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
CRegistry regSubkey(m_hKey, szKey);
|
||
|
LPCTSTR szSubKey;
|
||
|
|
||
|
if (ERROR_SUCCESS == regSubkey.Status(TRUE))
|
||
|
{
|
||
|
while (NULL != (szSubKey = regSubkey.Subkey(0)))
|
||
|
regSubkey.DeleteKey(szSubKey, fQuiet);
|
||
|
}
|
||
|
}
|
||
|
catch (DWORD dwError)
|
||
|
{
|
||
|
if (!fQuiet)
|
||
|
throw dwError;
|
||
|
}
|
||
|
|
||
|
LONG lSts = RegDeleteKey(m_hKey, szKey);
|
||
|
if ((ERROR_SUCCESS != lSts) && !fQuiet)
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
else if (!fQuiet)
|
||
|
throw (DWORD)m_lSts;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
DeleteValue:
|
||
|
|
||
|
This method deletes a Value from this key.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szValue supplies the name of the Value to be deleted.
|
||
|
|
||
|
fQuiet supplies whether or not to suppress errors.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
if fQuiet is FALSE, then any errors encountered are thrown as a DWORD.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::DeleteValue(
|
||
|
LPCTSTR szValue,
|
||
|
BOOL fQuiet)
|
||
|
const
|
||
|
{
|
||
|
LONG lSts;
|
||
|
|
||
|
if (fQuiet)
|
||
|
{
|
||
|
if (ERROR_SUCCESS == m_lSts)
|
||
|
lSts = RegDeleteValue(m_hKey, szValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
lSts = RegDeleteValue(m_hKey, szValue);
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Subkey:
|
||
|
|
||
|
This method allows for iterating over the names of the subkeys of this key.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwIndex supplies the index into the set of subkeys.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The name of the indexed subkey, or NULL if none exists.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any error other than ERROR_NO_MORE_ITEMS is thrown.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LPCTSTR
|
||
|
CRegistry::Subkey(
|
||
|
DWORD dwIndex)
|
||
|
{
|
||
|
LONG lSts;
|
||
|
DWORD dwLen;
|
||
|
LPCTSTR szResult = NULL;
|
||
|
BOOL fDone = FALSE;
|
||
|
FILETIME ftLastWrite;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
m_bfResult.Presize(128);
|
||
|
while (!fDone)
|
||
|
{
|
||
|
dwLen = m_bfResult.Space() / sizeof(TCHAR);
|
||
|
lSts = RegEnumKeyEx(
|
||
|
m_hKey,
|
||
|
dwIndex,
|
||
|
(LPTSTR)m_bfResult.Access(),
|
||
|
&dwLen,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&ftLastWrite);
|
||
|
switch (lSts)
|
||
|
{
|
||
|
case ERROR_SUCCESS:
|
||
|
m_bfResult.Resize((dwLen + 1) * sizeof(TCHAR), TRUE);
|
||
|
szResult = (LPCTSTR)m_bfResult.Access();
|
||
|
fDone = TRUE;
|
||
|
break;
|
||
|
case ERROR_NO_MORE_ITEMS:
|
||
|
szResult = NULL;
|
||
|
fDone = TRUE;
|
||
|
break;
|
||
|
case ERROR_MORE_DATA:
|
||
|
m_bfResult.Presize((dwLen + 1) * sizeof(TCHAR));
|
||
|
continue;
|
||
|
default:
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return szResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Value:
|
||
|
|
||
|
This method allows for iterating over the names of the Values of this key.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
dwIndex supplies the index into the set of Values.
|
||
|
|
||
|
pdwType receives the type of the entry. This parameter may be NULL.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The name of the indexed Value, or NULL if none exists.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any error other than ERROR_NO_MORE_ITEMS is thrown.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LPCTSTR
|
||
|
CRegistry::Value(
|
||
|
DWORD dwIndex,
|
||
|
LPDWORD pdwType)
|
||
|
{
|
||
|
LONG lSts;
|
||
|
DWORD dwLen, dwType;
|
||
|
LPCTSTR szResult = NULL;
|
||
|
BOOL fDone = FALSE;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
m_bfResult.Presize(128); // Force it to not be zero length.
|
||
|
while (!fDone)
|
||
|
{
|
||
|
dwLen = m_bfResult.Space() / sizeof(TCHAR);
|
||
|
lSts = RegEnumValue(
|
||
|
m_hKey,
|
||
|
dwIndex,
|
||
|
(LPTSTR)m_bfResult.Access(),
|
||
|
&dwLen,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
switch (lSts)
|
||
|
{
|
||
|
case ERROR_SUCCESS:
|
||
|
m_bfResult.Resize((dwLen + 1) * sizeof(TCHAR), TRUE);
|
||
|
if (NULL != pdwType)
|
||
|
*pdwType = dwType;
|
||
|
szResult = (LPCTSTR)m_bfResult.Access();
|
||
|
fDone = TRUE;
|
||
|
break;
|
||
|
case ERROR_NO_MORE_ITEMS:
|
||
|
szResult = NULL;
|
||
|
fDone = TRUE;
|
||
|
break;
|
||
|
case ERROR_MORE_DATA:
|
||
|
if (dwLen == m_bfResult.Space())
|
||
|
throw (DWORD)ERROR_INSUFFICIENT_BUFFER; // Won't tell us how big.
|
||
|
m_bfResult.Presize((dwLen + 1) * sizeof(TCHAR));
|
||
|
break;
|
||
|
default:
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return szResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetValue:
|
||
|
|
||
|
These methods provide access to the values of the Value entries.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKeyValue supplies the name of the Value entry to get.
|
||
|
pszValue receives the value of the entry as a string.
|
||
|
pdwValue receives the value of the entry as a DWORD.
|
||
|
ppbValue receives the value of the entry as a Binary string.
|
||
|
pcbLength receives the length of the entry when it's a binary string.
|
||
|
pdwType receives the type of the registry entry.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any error encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::GetValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
CBuffer &bfValue,
|
||
|
LPDWORD pdwType)
|
||
|
{
|
||
|
LONG lSts;
|
||
|
DWORD dwLen, dwType = 0;
|
||
|
BOOL fDone = FALSE;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
while (!fDone)
|
||
|
{
|
||
|
dwLen = bfValue.Space();
|
||
|
lSts = RegQueryValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
bfValue.Access(),
|
||
|
&dwLen);
|
||
|
switch (lSts)
|
||
|
{
|
||
|
case ERROR_SUCCESS:
|
||
|
bfValue.Resize(dwLen, TRUE);
|
||
|
fDone = TRUE;
|
||
|
break;
|
||
|
case ERROR_MORE_DATA:
|
||
|
bfValue.Presize(dwLen);
|
||
|
break;
|
||
|
default:
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
}
|
||
|
if (NULL != pdwType)
|
||
|
*pdwType = dwType;
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
CRegistry::GetValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPTSTR *pszValue,
|
||
|
LPDWORD pdwType)
|
||
|
{
|
||
|
DWORD dwLen, dwType;
|
||
|
TCHAR chTmp;
|
||
|
CBuffer bfUnexpanded;
|
||
|
LONG lSts;
|
||
|
|
||
|
dwLen = 0;
|
||
|
lSts = RegQueryValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
NULL,
|
||
|
&dwLen);
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
switch (dwType)
|
||
|
{
|
||
|
case REG_EXPAND_SZ:
|
||
|
bfUnexpanded.Presize(dwLen);
|
||
|
GetValue(szKeyValue, bfUnexpanded, &dwType);
|
||
|
dwLen = ExpandEnvironmentStrings(
|
||
|
(LPTSTR)bfUnexpanded.Access(),
|
||
|
&chTmp,
|
||
|
0);
|
||
|
if (0 == dwLen)
|
||
|
throw GetLastError();
|
||
|
dwLen = ExpandEnvironmentStrings(
|
||
|
(LPTSTR)bfUnexpanded.Access(),
|
||
|
(LPTSTR)m_bfResult.Resize(dwLen),
|
||
|
dwLen);
|
||
|
if (0 == dwLen)
|
||
|
throw GetLastError();
|
||
|
break;
|
||
|
|
||
|
case REG_BINARY:
|
||
|
case REG_MULTI_SZ:
|
||
|
case REG_SZ:
|
||
|
m_bfResult.Presize(dwLen);
|
||
|
GetValue(szKeyValue, m_bfResult, &dwType);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
throw (DWORD)ERROR_BAD_FORMAT;
|
||
|
}
|
||
|
*pszValue = (LPTSTR)m_bfResult.Access();
|
||
|
if (NULL != pdwType)
|
||
|
*pdwType = dwType;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CRegistry::GetValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPDWORD pdwValue,
|
||
|
LPDWORD pdwType)
|
||
|
const
|
||
|
{
|
||
|
LONG lSts;
|
||
|
DWORD dwLen, dwType;
|
||
|
CBuffer szExpanded;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
dwLen = sizeof(DWORD);
|
||
|
lSts = RegQueryValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE)pdwValue,
|
||
|
&dwLen);
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
|
||
|
switch (dwType)
|
||
|
{
|
||
|
case REG_DWORD_BIG_ENDIAN:
|
||
|
*pdwValue = NTOHL(*pdwValue);
|
||
|
break;
|
||
|
case REG_DWORD:
|
||
|
// case REG_DWORD_LITTLE_ENDIAN:
|
||
|
break;
|
||
|
default:
|
||
|
throw (DWORD)ERROR_BAD_FORMAT;
|
||
|
}
|
||
|
if (NULL != pdwType)
|
||
|
*pdwType = dwType;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CRegistry::GetValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPBYTE *ppbValue,
|
||
|
LPDWORD pcbLength,
|
||
|
LPDWORD pdwType)
|
||
|
{
|
||
|
DWORD dwType;
|
||
|
|
||
|
GetValue(szKeyValue, m_bfResult, &dwType);
|
||
|
*ppbValue = m_bfResult.Access();
|
||
|
*pcbLength = m_bfResult.Length();
|
||
|
if (NULL != pdwType)
|
||
|
*pdwType = dwType;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
SetValue:
|
||
|
|
||
|
These methods provide write access to the values of the Value entries.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKeyValue supplies the name of the Value entry to set.
|
||
|
szValue supplies the new value of the entry as a string.
|
||
|
dwValue supplies the new value of the entry as a DWORD.
|
||
|
pbValue supplies the new value of the entry as a Binary string.
|
||
|
cbLength supplies the length of the entry when it's a binary string.
|
||
|
dwType supplies the registry type value.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any error encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/15/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::SetValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPCTSTR szValue,
|
||
|
DWORD dwType)
|
||
|
const
|
||
|
{
|
||
|
LONG lSts;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
lSts = RegSetValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
0,
|
||
|
dwType,
|
||
|
(LPBYTE)szValue,
|
||
|
(lstrlen(szValue) + 1) * sizeof(TCHAR));
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CRegistry::SetValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
DWORD dwValue,
|
||
|
DWORD dwType)
|
||
|
const
|
||
|
{
|
||
|
LONG lSts;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
if (REG_DWORD_BIG_ENDIAN == dwType)
|
||
|
dwValue = HTONL(dwValue);
|
||
|
lSts = RegSetValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
0,
|
||
|
dwType,
|
||
|
(LPBYTE)&dwValue,
|
||
|
sizeof(DWORD));
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CRegistry::SetValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPCBYTE pbValue,
|
||
|
DWORD cbLength,
|
||
|
DWORD dwType)
|
||
|
const
|
||
|
{
|
||
|
LONG lSts;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
lSts = RegSetValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
0,
|
||
|
dwType,
|
||
|
pbValue,
|
||
|
cbLength);
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetStringValue:
|
||
|
|
||
|
This is an alternate mechanism for obtaining a string value.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKeyValue supplies the name of the Key Value to obtain.
|
||
|
|
||
|
pdwType, if non-null, receives the type of registry entry.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The value of the registry entry as a string pointer.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/16/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LPCTSTR
|
||
|
CRegistry::GetStringValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPDWORD pdwType)
|
||
|
{
|
||
|
LPTSTR szResult;
|
||
|
GetValue(szKeyValue, &szResult, pdwType);
|
||
|
return szResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetNumericValue:
|
||
|
|
||
|
This is an alternate mechanism for obtaining a numeric value.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKeyValue supplies the name of the Key Value to obtain.
|
||
|
|
||
|
pdwType, if non-null, receives the type of registry entry.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The value of the registry entry as a DWORD.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/16/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD
|
||
|
CRegistry::GetNumericValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPDWORD pdwType)
|
||
|
const
|
||
|
{
|
||
|
DWORD dwResult;
|
||
|
GetValue(szKeyValue, &dwResult, pdwType);
|
||
|
return dwResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetBinaryValue:
|
||
|
|
||
|
This is an alternate mechanism for obtaining a binary value.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKeyValue supplies the name of the Key Value to obtain.
|
||
|
|
||
|
pdwType, if non-null, receives the type of registry entry.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The value of the registry entry as a binary pointer.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/16/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LPCBYTE
|
||
|
CRegistry::GetBinaryValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPDWORD pcbLength,
|
||
|
LPDWORD pdwType)
|
||
|
{
|
||
|
LPBYTE pbResult;
|
||
|
DWORD cbLength;
|
||
|
GetValue(szKeyValue, &pbResult, &cbLength, pdwType);
|
||
|
if (NULL != pcbLength)
|
||
|
*pcbLength = cbLength;
|
||
|
return pbResult;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetValueLength:
|
||
|
|
||
|
This routine is designed to work in conjunction with GetBinaryValue, but may
|
||
|
have other uses as well. It returns the length of the internal storage
|
||
|
area, in bytes. Note DWORDs are not stored internally, so this value will
|
||
|
not represent the size of a DWORD following a GetNumericValue call.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The length of the internal storage buffer, in bytes.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/16/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD
|
||
|
CRegistry::GetValueLength(
|
||
|
void)
|
||
|
const
|
||
|
{
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
return m_bfResult.Length();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
ValueExists:
|
||
|
|
||
|
This routine tests for the existance of a given value, and optionally
|
||
|
returns its type and length.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
A boolean indication as to whether or not the value exists.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/16/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
CRegistry::ValueExists(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPDWORD pcbLength,
|
||
|
LPDWORD pdwType)
|
||
|
const
|
||
|
{
|
||
|
LONG lSts;
|
||
|
DWORD dwLen, dwType;
|
||
|
BOOL fResult = FALSE;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
dwLen = 0;
|
||
|
lSts = RegQueryValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
NULL,
|
||
|
&dwLen);
|
||
|
if (ERROR_SUCCESS == lSts)
|
||
|
{
|
||
|
if (NULL != pcbLength)
|
||
|
*pcbLength = dwLen;
|
||
|
if (NULL != pdwType)
|
||
|
*pdwType = dwType;
|
||
|
fResult = TRUE;
|
||
|
}
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetDisposition:
|
||
|
|
||
|
This routine returns the disposition of creation.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The return disposition flag from creating the registry entry.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 7/16/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD
|
||
|
CRegistry::GetDisposition(
|
||
|
void)
|
||
|
const
|
||
|
{
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
return m_dwDisposition;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
SetMultiStringValue:
|
||
|
|
||
|
This method simplifies the work of adding a MultiString value to the
|
||
|
registry.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKeyValue supplies the name of the Value entry to set.
|
||
|
mszValue supplies the new value of the entry as a multi-string.
|
||
|
dwType supplies the registry type value.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered as a DWORD status value.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 11/6/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::SetMultiStringValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPCTSTR mszValue,
|
||
|
DWORD dwType)
|
||
|
const
|
||
|
{
|
||
|
LONG lSts;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
lSts = RegSetValueEx(
|
||
|
m_hKey,
|
||
|
szKeyValue,
|
||
|
0,
|
||
|
dwType,
|
||
|
(LPBYTE)mszValue,
|
||
|
MStrLen(mszValue) * sizeof(TCHAR));
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetMultiStringValue:
|
||
|
|
||
|
This method obtains a multi-string value from the registry.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
szKeyValue supplies the name of the Key Value to obtain.
|
||
|
|
||
|
pdwType, if non-null, receives the type of registry entry.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The registry value, as a multi-string.
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Any errors encountered as a DWORD status value.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 11/6/1996
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LPCTSTR
|
||
|
CRegistry::GetMultiStringValue(
|
||
|
LPCTSTR szKeyValue,
|
||
|
LPDWORD pdwType)
|
||
|
{
|
||
|
LPTSTR szResult;
|
||
|
GetValue(szKeyValue, &szResult, pdwType);
|
||
|
return szResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
SetAcls:
|
||
|
|
||
|
This method sets security attributes for a single key, or an entire key
|
||
|
branch.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SecurityInformation supplies the SECURITY_INFORMATION value (see
|
||
|
RegSetKeySecurity in the SDK documentation).
|
||
|
pSecurityDescriptor supplies the SECURITY_DESCRIPTOR value (see
|
||
|
RegSetKeySecurity in the SDK documentation).
|
||
|
fRecurse supplies an indicator as to whether to just set the ACL on this
|
||
|
key (FALSE), or this key and all subkeys (TRUE).
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Throws:
|
||
|
|
||
|
Errors are thrown as DWORD status codes.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Doug Barlow (dbarlow) 11/10/1998
|
||
|
|
||
|
--*/
|
||
|
|
||
|
void
|
||
|
CRegistry::SetAcls(
|
||
|
IN SECURITY_INFORMATION SecurityInformation,
|
||
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
||
|
IN BOOL fRecurse)
|
||
|
{
|
||
|
LONG lSts;
|
||
|
|
||
|
if (ERROR_SUCCESS != m_lSts)
|
||
|
throw (DWORD)m_lSts;
|
||
|
|
||
|
lSts = RegSetKeySecurity(
|
||
|
m_hKey,
|
||
|
SecurityInformation,
|
||
|
pSecurityDescriptor);
|
||
|
if (ERROR_SUCCESS != lSts)
|
||
|
throw (DWORD)lSts;
|
||
|
if (fRecurse)
|
||
|
{
|
||
|
CRegistry regSub;
|
||
|
LPCTSTR szSubKey;
|
||
|
DWORD dwIndex;
|
||
|
|
||
|
for (dwIndex = 0;
|
||
|
NULL != (szSubKey = Subkey(dwIndex));
|
||
|
dwIndex += 1)
|
||
|
{
|
||
|
regSub.Open(m_hKey, szSubKey);
|
||
|
regSub.SetAcls(
|
||
|
SecurityInformation,
|
||
|
pSecurityDescriptor);
|
||
|
regSub.Close();
|
||
|
}
|
||
|
}
|
||
|
}
|