You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
512 lines
14 KiB
512 lines
14 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 1998
|
|
*
|
|
* TITLE: SIMREG.CPP
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* AUTHOR: ShaunIv
|
|
*
|
|
* DATE: 5/12/1998
|
|
*
|
|
* DESCRIPTION: Simple registry access class
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include <simreg.h>
|
|
|
|
CSimpleReg::CSimpleReg( HKEY hkRoot, const CSimpleString &strSubKey, bool bCreate, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpsa )
|
|
: m_strKeyName(strSubKey),
|
|
m_hRootKey(hkRoot),
|
|
m_hKey(NULL),
|
|
m_bCreate(bCreate),
|
|
m_lpsaSecurityAttributes(lpsa),
|
|
m_samDesiredAccess(samDesired)
|
|
{
|
|
Open();
|
|
}
|
|
|
|
CSimpleReg::CSimpleReg(void)
|
|
: m_strKeyName(TEXT("")),
|
|
m_hRootKey(NULL),
|
|
m_hKey(NULL),
|
|
m_bCreate(false),
|
|
m_lpsaSecurityAttributes(NULL),
|
|
m_samDesiredAccess(0)
|
|
{
|
|
}
|
|
|
|
CSimpleReg::CSimpleReg(const CSimpleReg &other)
|
|
: m_strKeyName(other.GetSubKeyName()),
|
|
m_hRootKey(other.GetRootKey()),
|
|
m_hKey(NULL),
|
|
m_bCreate(other.GetCreate()),
|
|
m_lpsaSecurityAttributes(other.GetSecurityAttributes()),
|
|
m_samDesiredAccess(other.DesiredAccess())
|
|
{
|
|
Open();
|
|
}
|
|
|
|
CSimpleReg::~CSimpleReg(void)
|
|
{
|
|
Close();
|
|
m_hRootKey = NULL;
|
|
m_lpsaSecurityAttributes = NULL;
|
|
}
|
|
|
|
CSimpleReg &CSimpleReg::operator=(const CSimpleReg &other )
|
|
{
|
|
if (this != &other)
|
|
{
|
|
Close();
|
|
m_strKeyName = other.GetSubKeyName();
|
|
m_hRootKey = other.GetRootKey();
|
|
m_bCreate = other.GetCreate();
|
|
m_lpsaSecurityAttributes = other.GetSecurityAttributes();
|
|
m_samDesiredAccess = other.DesiredAccess();
|
|
Open();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool CSimpleReg::Open(void)
|
|
{
|
|
HKEY hkKey = NULL;
|
|
LONG nRet;
|
|
DWORD bCreatedNewKey = 0;
|
|
|
|
Close();
|
|
if (m_bCreate)
|
|
{
|
|
nRet = RegCreateKeyEx( m_hRootKey, m_strKeyName.String(), 0, TEXT(""), REG_OPTION_NON_VOLATILE, m_samDesiredAccess?m_samDesiredAccess:KEY_ALL_ACCESS, m_lpsaSecurityAttributes, &hkKey, &bCreatedNewKey );
|
|
}
|
|
else
|
|
{
|
|
nRet = RegOpenKeyEx( m_hRootKey, m_strKeyName.String(), 0, m_samDesiredAccess ? m_samDesiredAccess : KEY_ALL_ACCESS, &hkKey );
|
|
}
|
|
|
|
if (nRet == ERROR_SUCCESS)
|
|
{
|
|
m_hKey = hkKey;
|
|
}
|
|
|
|
return m_hKey != NULL;
|
|
}
|
|
|
|
bool CSimpleReg::Close(void)
|
|
{
|
|
//
|
|
// In case the key was closed by someone else
|
|
//
|
|
__try
|
|
{
|
|
if (OK())
|
|
{
|
|
RegCloseKey(m_hKey);
|
|
}
|
|
}
|
|
__except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
#ifdef DBG
|
|
OutputDebugString(TEXT("CSimpleReg::Close(): An exception occurred while closing the handle. Make sure the handle wasn't already freed."));
|
|
DebugBreak();
|
|
#endif
|
|
}
|
|
m_hKey = NULL;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CSimpleReg::Flush(void)
|
|
{
|
|
if (!OK())
|
|
{
|
|
return false;
|
|
}
|
|
return (ERROR_SUCCESS == RegFlushKey(m_hKey));
|
|
}
|
|
|
|
bool CSimpleReg::IsStringValue( DWORD nType )
|
|
{
|
|
if (nType != REG_SZ && nType != REG_EXPAND_SZ && nType != REG_MULTI_SZ && nType != REG_LINK && nType != REG_RESOURCE_LIST)
|
|
{
|
|
return false;
|
|
}
|
|
else return true;
|
|
}
|
|
|
|
// Query functions
|
|
DWORD CSimpleReg::Size( const CSimpleString &strValueName ) const
|
|
{
|
|
if (!OK())
|
|
{
|
|
return 0;
|
|
}
|
|
DWORD nType;
|
|
DWORD nSize=0;
|
|
LONG Ret = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, NULL, &nSize);
|
|
if (Ret==ERROR_SUCCESS)
|
|
{
|
|
return nSize;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
DWORD CSimpleReg::Type( const CSimpleString &key ) const
|
|
{
|
|
if (!OK())
|
|
{
|
|
return 0;
|
|
}
|
|
DWORD dwType;
|
|
DWORD dwSize;
|
|
LONG Ret = RegQueryValueEx( m_hKey, key.String(), NULL, &dwType, NULL, &dwSize);
|
|
if (Ret==ERROR_SUCCESS)
|
|
{
|
|
return dwType;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
CSimpleString CSimpleReg::Query( const CSimpleString &strValueName, const CSimpleString &strDef ) const
|
|
{
|
|
// If the key is not open, or if this value is not a string type, return the default
|
|
if (!OK() || !IsStringValue(Type(strValueName)))
|
|
{
|
|
return strDef;
|
|
}
|
|
DWORD nSize = Size(strValueName) / sizeof(TCHAR);
|
|
//
|
|
// NOTE: There are some cases when components (e.g. usbscan.sys) write a string value to the registry,
|
|
// and dont NULL terminate it correctly. Now nSize contains the number of characters, NOT
|
|
// including the NULL terminator. To get around this, we actually allocate one more
|
|
// character than needed. Then, after reading in up to a maximum of nSize characters, we
|
|
// set the extra character to TEXT('\0), ensuring that our string is always NULL terminated
|
|
// correctly, without losing the last character (which would happen if we simply allocated
|
|
// nSize and set lpszTmp[nSize-1] to TEXT('\0')).
|
|
//
|
|
LPTSTR lpszTmp = nSize ? new TCHAR[nSize + 1] : NULL;
|
|
CSimpleString strTmp;
|
|
if (lpszTmp)
|
|
{
|
|
Query( strValueName, strDef, lpszTmp, nSize );
|
|
|
|
//
|
|
// Ensure that we are correctly NULL terminated. Note that we null out the extra character
|
|
// allocated for us - not any of the actual data.
|
|
//
|
|
lpszTmp[nSize] = TEXT('\0');
|
|
strTmp = lpszTmp;
|
|
|
|
delete[] lpszTmp;
|
|
}
|
|
return strTmp;
|
|
}
|
|
|
|
LPTSTR CSimpleReg::Query( const CSimpleString &strValueName, const CSimpleString &strDef, LPTSTR pszBuffer, DWORD nLen ) const
|
|
{
|
|
//
|
|
// If the programmer passes 0 for some reason, return NULL
|
|
//
|
|
if (!nLen)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Initialize the result
|
|
//
|
|
*pszBuffer = 0;
|
|
|
|
//
|
|
// If the key is not open, or if this value is not a string type, return the default
|
|
//
|
|
if (!OK() || !IsStringValue(Type(strValueName)))
|
|
{
|
|
//
|
|
// Make sure we have a valid default string
|
|
//
|
|
if (strDef.String())
|
|
{
|
|
lstrcpyn( pszBuffer, strDef.String(), nLen );
|
|
}
|
|
|
|
//
|
|
// Early return
|
|
//
|
|
return pszBuffer;
|
|
}
|
|
|
|
DWORD nSize = (DWORD)(nLen * sizeof(pszBuffer[0]));
|
|
DWORD nType;
|
|
LONG nRet = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, (PBYTE)pszBuffer, &nSize );
|
|
if (ERROR_SUCCESS != nRet)
|
|
{
|
|
lstrcpyn( pszBuffer, strDef.String(), nLen );
|
|
pszBuffer[nLen-1] = TEXT('\0');
|
|
}
|
|
return pszBuffer;
|
|
}
|
|
|
|
DWORD CSimpleReg::Query( const CSimpleString &strValueName, DWORD nDef ) const
|
|
{
|
|
if (!OK() || (REG_DWORD != Type(strValueName)) || (sizeof(DWORD) != Size(strValueName)))
|
|
{
|
|
return nDef;
|
|
}
|
|
DWORD nValue;
|
|
DWORD nType;
|
|
DWORD nSize = sizeof(DWORD);
|
|
LONG nRet;
|
|
nRet = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, (PBYTE)&nValue, &nSize);
|
|
if (ERROR_SUCCESS == nRet)
|
|
{
|
|
return nValue;
|
|
}
|
|
else
|
|
{
|
|
return nDef;
|
|
}
|
|
}
|
|
|
|
|
|
bool CSimpleReg::Set( const CSimpleString &strValueName, const CSimpleString &strValue, DWORD nType ) const
|
|
{ // Set a REG_SZ value for the specified key.
|
|
if (!OK())
|
|
{
|
|
return false;
|
|
}
|
|
LONG nRet;
|
|
nRet = RegSetValueEx( m_hKey, strValueName.String(), 0, nType, (PBYTE)strValue.String(), sizeof(strValue[0])*(strValue.Length()+1) );
|
|
return (ERROR_SUCCESS==nRet);
|
|
}
|
|
|
|
bool CSimpleReg::Set( const CSimpleString &strValueName, DWORD nValue ) const
|
|
{ // Set a REG_SZ value for the specified key.
|
|
if (!OK())
|
|
return false;
|
|
LONG nRet;
|
|
nRet = RegSetValueEx( m_hKey, strValueName.String(), 0, REG_DWORD, (PBYTE)&nValue, sizeof(DWORD) );
|
|
return (ERROR_SUCCESS==nRet);
|
|
}
|
|
|
|
DWORD CSimpleReg::QueryBin( const CSimpleString &strValueName, PBYTE pData, DWORD nMaxLen ) const
|
|
{
|
|
if (!OK())
|
|
{
|
|
return 0;
|
|
}
|
|
if (nMaxLen <= 0)
|
|
{
|
|
return Size(strValueName.String());
|
|
}
|
|
DWORD nType;
|
|
DWORD nSize = nMaxLen;
|
|
LONG nRet = RegQueryValueEx( m_hKey, strValueName.String(), NULL, &nType, pData, &nSize );
|
|
if (ERROR_SUCCESS!=nRet)
|
|
{
|
|
return 0;
|
|
}
|
|
return nSize;
|
|
}
|
|
|
|
bool CSimpleReg::SetBin( const CSimpleString &strValueName, const PBYTE pValue, DWORD nLen, DWORD dwType ) const
|
|
{
|
|
if (!OK())
|
|
return false;
|
|
LONG nRet = RegSetValueEx( m_hKey, strValueName.String(), 0, dwType, (PBYTE)pValue, nLen );
|
|
return (ERROR_SUCCESS==nRet);
|
|
}
|
|
|
|
DWORD CSimpleReg::SubKeyCount(void) const
|
|
{
|
|
TCHAR szClass[256]=TEXT("");
|
|
DWORD nClassSize = sizeof(szClass)/sizeof(szClass[0]);
|
|
DWORD nSubKeyCount=0;
|
|
RegQueryInfoKey(m_hKey,szClass,&nClassSize,NULL,&nSubKeyCount,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
|
return nSubKeyCount;
|
|
}
|
|
|
|
HKEY CSimpleReg::GetHkeyFromName( const CSimpleString &strName )
|
|
{
|
|
static const struct
|
|
{
|
|
LPCTSTR pszName;
|
|
HKEY hkKey;
|
|
} KeyNames[] =
|
|
{
|
|
{ TEXT("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT},
|
|
{ TEXT("HKEY_CURRENT_USER"), HKEY_CURRENT_USER},
|
|
{ TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE},
|
|
{ TEXT("HKEY_USERS"), HKEY_USERS},
|
|
{ TEXT("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG},
|
|
{ TEXT("HKEY_DYN_DATA"), HKEY_DYN_DATA},
|
|
{ TEXT("HKCR"), HKEY_CLASSES_ROOT},
|
|
{ TEXT("HKCU"), HKEY_CURRENT_USER},
|
|
{ TEXT("HKLM"), HKEY_LOCAL_MACHINE},
|
|
{ TEXT("HKU"), HKEY_USERS},
|
|
{ TEXT("HKCC"), HKEY_CURRENT_CONFIG},
|
|
{ TEXT("HKDD"), HKEY_DYN_DATA},
|
|
{ NULL, NULL}
|
|
};
|
|
for (int i=0;KeyNames[i].pszName;i++)
|
|
{
|
|
if (!lstrcmpi(strName.String(),KeyNames[i].pszName))
|
|
{
|
|
return KeyNames[i].hkKey;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool CSimpleReg::Delete( HKEY hkRoot, const CSimpleString &strKeyName )
|
|
{
|
|
return (RegDeleteKey(hkRoot, strKeyName.String()) == ERROR_SUCCESS);
|
|
}
|
|
|
|
bool CSimpleReg::Delete( const CSimpleString &strValue )
|
|
{
|
|
if (!OK())
|
|
{
|
|
return false;
|
|
}
|
|
return (RegDeleteValue( m_hKey, strValue.String() ) == ERROR_SUCCESS);
|
|
}
|
|
|
|
bool CSimpleReg::DeleteRecursively( HKEY hkRoot, const CSimpleString &strKeyName )
|
|
{
|
|
if (CSimpleReg( hkRoot, strKeyName ).RecurseKeys( DeleteEnumKeyProc, NULL, CSimpleReg::PostOrder ))
|
|
{
|
|
return CSimpleReg::Delete( hkRoot, strKeyName );
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CSimpleReg::EnumValues( SimRegValueEnumProc enumProc, LPARAM lParam )
|
|
{
|
|
TCHAR szName[256];
|
|
DWORD nSize;
|
|
DWORD nType;
|
|
bool bResult = true;
|
|
for (int i=0;;i++)
|
|
{
|
|
nSize = sizeof(szName) / sizeof(szName[0]);
|
|
if (RegEnumValue(m_hKey,i,szName,&nSize,NULL,&nType,NULL,NULL) != ERROR_SUCCESS)
|
|
break;
|
|
CValueEnumInfo info(*this,szName,nType,nSize,lParam);
|
|
if (enumProc)
|
|
{
|
|
if (!enumProc(info))
|
|
{
|
|
bResult = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
bool CSimpleReg::RecurseKeys( SimRegKeyEnumProc enumProc, LPARAM lParam, int recurseOrder, bool bFailOnOpenError ) const
|
|
{
|
|
return DoRecurseKeys(m_hKey, TEXT(""), enumProc, lParam, 0, recurseOrder, bFailOnOpenError );
|
|
}
|
|
|
|
bool CSimpleReg::EnumKeys( SimRegKeyEnumProc enumProc, LPARAM lParam, bool bFailOnOpenError ) const
|
|
{
|
|
return DoEnumKeys(m_hKey, TEXT(""), enumProc, lParam, bFailOnOpenError );
|
|
}
|
|
|
|
bool CSimpleReg::DoRecurseKeys( HKEY hkKey, const CSimpleString &root, SimRegKeyEnumProc enumProc, LPARAM lParam, int nLevel, int recurseOrder, bool bFailOnOpenError )
|
|
{
|
|
TCHAR szName[256]=TEXT("");
|
|
DWORD nNameSize;
|
|
TCHAR szClass[256]=TEXT("");
|
|
DWORD nClassSize;
|
|
FILETIME ftFileTime;
|
|
CSimpleReg reg(hkKey,root);
|
|
if (!reg.OK())
|
|
{
|
|
return (bFailOnOpenError ? false : true);
|
|
}
|
|
DWORD nSubKeyCount = reg.SubKeyCount();
|
|
for (DWORD i=nSubKeyCount;i>0;i--)
|
|
{
|
|
nNameSize = sizeof(szName)/sizeof(szName[0]);
|
|
nClassSize = sizeof(szClass)/sizeof(szClass[0]);
|
|
|
|
LONG lRes = RegEnumKeyEx(reg.GetKey(),i-1,szName,&nNameSize,NULL,szClass,&nClassSize,&ftFileTime);
|
|
if (lRes != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
CKeyEnumInfo EnumInfo;
|
|
EnumInfo.strName = szName;
|
|
EnumInfo.hkRoot = reg.GetKey();
|
|
EnumInfo.nLevel = nLevel;
|
|
EnumInfo.lParam = lParam;
|
|
if (enumProc && recurseOrder==PreOrder)
|
|
{
|
|
if (!enumProc(EnumInfo))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (!DoRecurseKeys(reg.GetKey(),szName,enumProc,lParam,nLevel+1,recurseOrder, bFailOnOpenError))
|
|
{
|
|
return false;
|
|
}
|
|
if (enumProc && recurseOrder==PostOrder)
|
|
{
|
|
if (!enumProc(EnumInfo))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CSimpleReg::DoEnumKeys( HKEY hkKey, const CSimpleString &root, SimRegKeyEnumProc enumProc, LPARAM lParam, bool bFailOnOpenError )
|
|
{
|
|
TCHAR szName[256]=TEXT("");
|
|
DWORD szNameSize;
|
|
TCHAR szClass[256]=TEXT("");
|
|
DWORD szClassSize;
|
|
FILETIME ftFileTime;
|
|
CSimpleReg reg(hkKey,root);
|
|
LONG lRes;
|
|
if (!reg.OK())
|
|
{
|
|
return (bFailOnOpenError ? false : true);
|
|
}
|
|
DWORD nSubKeyCount = reg.SubKeyCount();
|
|
for (DWORD i=nSubKeyCount;i>0;i--)
|
|
{
|
|
szNameSize = sizeof(szName)/sizeof(szName[0]);
|
|
szClassSize = sizeof(szClass)/sizeof(szClass[0]);
|
|
if ((lRes=RegEnumKeyEx(reg.GetKey(),i-1,szName,&szNameSize,NULL,szClass,&szClassSize,&ftFileTime)) != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
CKeyEnumInfo EnumInfo;
|
|
EnumInfo.strName = szName;
|
|
EnumInfo.hkRoot = reg.GetKey();
|
|
EnumInfo.nLevel = 0;
|
|
EnumInfo.lParam = lParam;
|
|
if (!enumProc(EnumInfo))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CSimpleReg::DeleteEnumKeyProc( CSimpleReg::CKeyEnumInfo &enumInfo )
|
|
{
|
|
return CSimpleReg::Delete( enumInfo.hkRoot, enumInfo.strName );
|
|
}
|
|
|