959 lines
24 KiB
C++
959 lines
24 KiB
C++
|
//****************************************************************************
|
||
|
//
|
||
|
// Copyright (c) 1993, Microsoft Corp.
|
||
|
//
|
||
|
// File: DOMDLGS.H
|
||
|
//
|
||
|
// Implementation file for registry management classes
|
||
|
//
|
||
|
// History:
|
||
|
// Scott V. Walker 10/5/94
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#include "portable.h"
|
||
|
|
||
|
#include "regkey.h"
|
||
|
|
||
|
|
||
|
BOOL g_bLostConnection = FALSE;
|
||
|
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue Implementation
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
|
||
|
IMPLEMENT_DYNAMIC(CRegistryValue, CObject)
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue::CRegistryValue
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
CRegistryValue::CRegistryValue()
|
||
|
{
|
||
|
m_dwType = REG_NONE;
|
||
|
m_dwDataLength = 0;
|
||
|
m_pData = NULL;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue::CRegistryValue
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
CRegistryValue::CRegistryValue(LPCTSTR pszName, DWORD dwType,
|
||
|
DWORD dwDataLength, LPBYTE pData)
|
||
|
{
|
||
|
Set(pszName, dwType, dwDataLength, pData);
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue::~CRegistryValue
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
CRegistryValue::~CRegistryValue()
|
||
|
{
|
||
|
Empty();
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue::Set
|
||
|
//
|
||
|
// Sets the value data fields. The data pointed to by pData is COPIED!
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
void CRegistryValue::Set(LPCTSTR pszName, DWORD dwType,
|
||
|
DWORD dwDataLength, LPBYTE pData)
|
||
|
{
|
||
|
Empty();
|
||
|
|
||
|
m_sName = pszName;
|
||
|
m_dwType = dwType;
|
||
|
m_dwDataLength = dwDataLength;
|
||
|
if (dwDataLength == 0 || pData == NULL)
|
||
|
m_pData = NULL;
|
||
|
else
|
||
|
{
|
||
|
m_pData = new BYTE[dwDataLength];
|
||
|
memcpy(m_pData, pData, dwDataLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue::Get
|
||
|
//
|
||
|
// Gets the value data fields. The data pointed to by m_pData is COPIED
|
||
|
// into the buffer pointed to by pData... this buffer better be big enough!
|
||
|
// If pData is NULL, no copy is performed.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
void CRegistryValue::Get(CString &sName, DWORD &dwType,
|
||
|
DWORD &dwDataLength, LPBYTE pData)
|
||
|
{
|
||
|
sName = m_sName;
|
||
|
dwType = m_dwType;
|
||
|
dwDataLength = m_dwDataLength;
|
||
|
if (dwDataLength != 0 && pData != NULL)
|
||
|
memcpy(pData, m_pData, m_dwDataLength);
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue::Empty
|
||
|
//
|
||
|
// Clear the value data and deletes its data buffer.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
void CRegistryValue::Empty()
|
||
|
{
|
||
|
m_sName.Empty();
|
||
|
m_dwType = REG_NONE;
|
||
|
m_dwDataLength = 0;
|
||
|
if (m_pData != NULL)
|
||
|
delete m_pData;
|
||
|
m_pData = NULL;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryValue::operator=
|
||
|
//
|
||
|
// Assignment operator. Copies CRegistryValue object.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
const CRegistryValue& CRegistryValue::operator=(CRegistryValue &other)
|
||
|
{
|
||
|
Set(other.m_sName, other.m_dwType, other.m_dwDataLength, other.m_pData);
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey Implementation
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
|
||
|
IMPLEMENT_DYNAMIC(CRegistryKey, CObject)
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::CRegistryKey
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
CRegistryKey::CRegistryKey()
|
||
|
{
|
||
|
// The lost connection status is initialized only once so that if a connection
|
||
|
// is ever lost we won't waste any time trying to close keys.
|
||
|
|
||
|
Initialize();
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::Initialize
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
void CRegistryKey::Initialize()
|
||
|
{
|
||
|
m_bConnected = FALSE;
|
||
|
m_bOpen = FALSE;
|
||
|
m_bLocal = TRUE;
|
||
|
m_bDirty = FALSE;
|
||
|
|
||
|
m_hkeyConnect = NULL;
|
||
|
m_hkeyRemote = NULL;
|
||
|
m_hkeyOpen = NULL;
|
||
|
m_Sam = 0;
|
||
|
|
||
|
m_dwSubKeys = 0;
|
||
|
m_dwMaxSubKey = 0;
|
||
|
m_dwMaxClass = 0;
|
||
|
m_dwValues = 0;
|
||
|
m_dwMaxValueName = 0;
|
||
|
m_dwMaxValueData = 0;
|
||
|
m_dwSecurityDescriptor = 0;
|
||
|
|
||
|
m_ftLastWriteTime.dwLowDateTime = 0;
|
||
|
m_ftLastWriteTime.dwHighDateTime = 0;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::~CRegistryKey
|
||
|
//
|
||
|
// Destructor.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
CRegistryKey::~CRegistryKey()
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
// If we lost the registry connection, it will be useless to do anything.
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If we're currently open, then close.
|
||
|
if (m_bOpen)
|
||
|
Close(TRUE);
|
||
|
|
||
|
// If we're currently connected, then disconnect.
|
||
|
if (m_bConnected)
|
||
|
Disconnect(TRUE);
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::Connect
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
LONG CRegistryKey::Connect(LPCTSTR pszComputer, HKEY hkey)
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
return RPC_S_SERVER_UNAVAILABLE;
|
||
|
}
|
||
|
|
||
|
TCHAR szName[MAX_COMPUTERNAME_LENGTH + 1];
|
||
|
CString sComputer;
|
||
|
HKEY hkeyRemote;
|
||
|
DWORD dwNumChars;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (m_bConnected)
|
||
|
{
|
||
|
m_lResult = Disconnect(TRUE);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
// Is this the local machine?
|
||
|
|
||
|
dwNumChars = MAX_COMPUTERNAME_LENGTH + 1;
|
||
|
|
||
|
sComputer = pszComputer;
|
||
|
GetComputerName(szName, &dwNumChars);
|
||
|
if (sComputer.IsEmpty() || !lstrcmpi(pszComputer, szName))
|
||
|
{
|
||
|
// Local
|
||
|
|
||
|
m_bLocal = TRUE;
|
||
|
hkeyRemote = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Remote
|
||
|
|
||
|
m_bLocal = FALSE;
|
||
|
m_lResult = RegConnectRegistry(pszComputer, hkey, &hkeyRemote);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
lstrcpy(szName, pszComputer);
|
||
|
}
|
||
|
|
||
|
m_bConnected = TRUE;
|
||
|
m_hkeyConnect = hkey;
|
||
|
m_hkeyRemote = hkeyRemote;
|
||
|
m_sComputer = szName;
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::Disconnect
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
LONG CRegistryKey::Disconnect(BOOL bForce)
|
||
|
{
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (m_bConnected)
|
||
|
{
|
||
|
// Close the open key
|
||
|
if (m_bOpen)
|
||
|
{
|
||
|
m_lResult = Close(bForce);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!bForce && m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
// Close the remote connection
|
||
|
if (!g_bLostConnection) {
|
||
|
if (!m_bLocal)
|
||
|
{
|
||
|
m_lResult = RegCloseKey(m_hkeyRemote);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (!bForce && m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
Initialize();
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::Create
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
LONG CRegistryKey::Create(LPCTSTR pszKeyName, DWORD &dwDisposition,
|
||
|
LPCTSTR pszClass, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecAttr)
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
return RPC_S_SERVER_UNAVAILABLE;
|
||
|
}
|
||
|
|
||
|
HKEY hkeyOpen, hkey;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
dwDisposition = 0;
|
||
|
|
||
|
if (m_bOpen)
|
||
|
{
|
||
|
m_lResult = Close(TRUE);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
// If not connected, default to \\Local_Machine\HKEY_LOCAL_MACHINE
|
||
|
if (!m_bConnected)
|
||
|
{
|
||
|
m_lResult = Connect();
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
// Attempt to create the specified subkey
|
||
|
if (m_bLocal)
|
||
|
hkey = m_hkeyConnect;
|
||
|
else
|
||
|
hkey = m_hkeyRemote;
|
||
|
|
||
|
m_lResult = RegCreateKeyEx(hkey, pszKeyName, 0, (LPTSTR)pszClass,
|
||
|
REG_OPTION_NON_VOLATILE, samDesired, lpSecAttr, &hkeyOpen,
|
||
|
&dwDisposition);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
|
||
|
m_lResult = RegCloseKey(hkeyOpen);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
return Open(pszKeyName, samDesired);
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::Open
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
LONG CRegistryKey::Open(LPCTSTR pszKeyName, REGSAM samDesired)
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
return RPC_S_SERVER_UNAVAILABLE;
|
||
|
}
|
||
|
|
||
|
|
||
|
HKEY hkeyOpen, hkey;
|
||
|
CString sWork;
|
||
|
int nPos;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (m_bOpen)
|
||
|
{
|
||
|
m_lResult = Close(TRUE);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
// If not connected, default to \\Local_Machine\HKEY_LOCAL_MACHINE
|
||
|
if (!m_bConnected)
|
||
|
{
|
||
|
m_lResult = Connect();
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
// Attempt to open the specified subkey
|
||
|
if (m_bLocal)
|
||
|
hkey = m_hkeyConnect;
|
||
|
else
|
||
|
hkey = m_hkeyRemote;
|
||
|
m_lResult = RegOpenKeyEx(hkey, pszKeyName, 0, samDesired, &hkeyOpen);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
|
||
|
// Attempt to get info about this key.
|
||
|
|
||
|
TCHAR szBuffer[1024 + 1];
|
||
|
DWORD dwClass, dwSubKeys, dwMaxSubKey, dwMaxClass, dwValues;
|
||
|
DWORD dwMaxValueName, dwMaxValueData, dwSecurityDescriptor;
|
||
|
FILETIME ftLastWriteTime;
|
||
|
|
||
|
dwClass = 1024 + 1;
|
||
|
m_lResult = RegQueryInfoKey(hkeyOpen, szBuffer, &dwClass, 0, &dwSubKeys,
|
||
|
&dwMaxSubKey, &dwMaxClass, &dwValues, &dwMaxValueName,
|
||
|
&dwMaxValueData, &dwSecurityDescriptor, &ftLastWriteTime);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
RegCloseKey(hkeyOpen);
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
// Success! save all the data.
|
||
|
|
||
|
m_sFullName = pszKeyName;
|
||
|
nPos = m_sFullName.ReverseFind('\\');
|
||
|
if (nPos >= 0)
|
||
|
m_sKeyName = m_sFullName.Mid(nPos + 1);
|
||
|
else
|
||
|
m_sKeyName = m_sFullName;
|
||
|
|
||
|
m_hkeyOpen = hkeyOpen;
|
||
|
m_bOpen = TRUE;
|
||
|
m_Sam = samDesired;
|
||
|
m_sClass = szBuffer;
|
||
|
m_dwSubKeys = dwSubKeys;
|
||
|
m_dwMaxSubKey = dwMaxSubKey;
|
||
|
m_dwMaxClass = dwMaxClass;
|
||
|
m_dwValues = dwValues;
|
||
|
m_dwMaxValueName = dwMaxValueName;
|
||
|
m_dwMaxValueData = dwMaxValueData;
|
||
|
m_dwSecurityDescriptor = dwSecurityDescriptor;
|
||
|
m_ftLastWriteTime = ftLastWriteTime;
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::Close
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
LONG CRegistryKey::Close(BOOL bForce)
|
||
|
{
|
||
|
if (!g_bLostConnection) {
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (!m_bOpen)
|
||
|
return ERROR_SUCCESS;
|
||
|
|
||
|
|
||
|
if (m_bDirty)
|
||
|
{
|
||
|
m_lResult = RegFlushKey(m_hkeyOpen);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!bForce && m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
|
||
|
if (!g_bLostConnection) {
|
||
|
m_lResult = RegCloseKey(m_hkeyOpen);
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!bForce && m_lResult != ERROR_SUCCESS)
|
||
|
return m_lResult;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_bDirty = FALSE;
|
||
|
|
||
|
m_hkeyOpen = NULL;
|
||
|
m_bOpen = FALSE;
|
||
|
m_sFullName.Empty();
|
||
|
m_sClass.Empty();
|
||
|
m_Sam = 0;
|
||
|
|
||
|
m_dwSubKeys = 0;
|
||
|
m_dwMaxSubKey = 0;
|
||
|
m_dwMaxClass = 0;
|
||
|
m_dwValues = 0;
|
||
|
m_dwMaxValueName = 0;
|
||
|
m_dwMaxValueData = 0;
|
||
|
m_dwSecurityDescriptor = 0;
|
||
|
|
||
|
m_ftLastWriteTime.dwLowDateTime = 0;
|
||
|
m_ftLastWriteTime.dwHighDateTime = 0;
|
||
|
|
||
|
if (g_bLostConnection) {
|
||
|
m_lResult = RPC_S_SERVER_UNAVAILABLE;
|
||
|
return RPC_S_SERVER_UNAVAILABLE;
|
||
|
}
|
||
|
else {
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::EnumValues
|
||
|
//
|
||
|
// Returns NULL if unsuccessful, returns empty array if successful but open
|
||
|
// key has no values.
|
||
|
// NOTE: Caller is responsible for deleting returned string array.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
CStringArray* CRegistryKey::EnumValues()
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
m_lResult = RPC_S_SERVER_UNAVAILABLE;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
TCHAR szBuffer[1024 + 1];
|
||
|
DWORD dwLength;
|
||
|
CStringArray *pArr;
|
||
|
int i;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (!m_bOpen || g_bLostConnection)
|
||
|
return NULL;
|
||
|
|
||
|
// Enumerate all the values into a string array
|
||
|
pArr = new CStringArray;
|
||
|
i = 0;
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
while (TRUE)
|
||
|
{
|
||
|
dwLength = 1024 + 1;
|
||
|
m_lResult = RegEnumValue(m_hkeyOpen, i, szBuffer, &dwLength, NULL,
|
||
|
NULL, NULL, NULL);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
break;
|
||
|
if (dwLength > 0)
|
||
|
pArr->Add(szBuffer);
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
// Did we find a normal end condition?
|
||
|
if (m_lResult == ERROR_NO_MORE_ITEMS)
|
||
|
return pArr;
|
||
|
|
||
|
delete pArr;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::EnumSubKeys
|
||
|
//
|
||
|
// Returns NULL if unsuccessful, returns empty array if successful but open
|
||
|
// key has no values.
|
||
|
// NOTE: Caller is responsible for deleting returned string array.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
CStringArray* CRegistryKey::EnumSubKeys()
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
m_lResult = RPC_S_SERVER_UNAVAILABLE;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
TCHAR szBuffer[1024 + 1];
|
||
|
DWORD dwLength;
|
||
|
CStringArray *pArr;
|
||
|
int i;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (!m_bOpen)
|
||
|
return NULL;
|
||
|
|
||
|
// Enumerate all the subkeys into a string array
|
||
|
pArr = new CStringArray;
|
||
|
i = 0;
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
dwLength = 1024 + 1;
|
||
|
m_lResult = RegEnumKeyEx(m_hkeyOpen, i, szBuffer, &dwLength, NULL,
|
||
|
NULL, NULL, NULL);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
break;
|
||
|
if (dwLength > 0)
|
||
|
pArr->Add(szBuffer);
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
// Did we find a normal end condition?
|
||
|
if (m_lResult == ERROR_NO_MORE_ITEMS)
|
||
|
return pArr;
|
||
|
|
||
|
delete pArr;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::GetValue
|
||
|
//
|
||
|
// Note: regval is always emptied regardless of success/failure
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
BOOL CRegistryKey::GetValue(LPCTSTR pszValue, CRegistryValue ®val)
|
||
|
{
|
||
|
|
||
|
DWORD dwLength, dwType;
|
||
|
BYTE *pBuffer;
|
||
|
|
||
|
regval.Empty();
|
||
|
|
||
|
if (g_bLostConnection) {
|
||
|
m_lResult = RPC_S_SERVER_UNAVAILABLE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!m_bOpen)
|
||
|
{
|
||
|
m_lResult = ERROR_INVALID_FUNCTION;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Find out how big the data is
|
||
|
m_lResult = RegQueryValueEx(m_hkeyOpen, (LPTSTR)pszValue, NULL, NULL,
|
||
|
NULL, &dwLength);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
|
||
|
if (dwLength == 0)
|
||
|
return TRUE;
|
||
|
|
||
|
// Now make a buffer big enough for it.
|
||
|
pBuffer = new BYTE[dwLength];
|
||
|
if (pBuffer == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
m_lResult = RegQueryValueEx(m_hkeyOpen, (LPTSTR)pszValue, NULL, &dwType,
|
||
|
pBuffer, &dwLength);
|
||
|
|
||
|
|
||
|
if (m_lResult == ERROR_SUCCESS)
|
||
|
regval.Set(pszValue, dwType, dwLength, pBuffer);
|
||
|
|
||
|
delete pBuffer;
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::SetValue
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
BOOL CRegistryKey::SetValue(CRegistryValue ®val)
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
m_lResult = RPC_S_SERVER_UNAVAILABLE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!m_bOpen)
|
||
|
{
|
||
|
m_lResult = ERROR_INVALID_FUNCTION;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (regval.m_sName.IsEmpty())
|
||
|
{
|
||
|
m_lResult = ERROR_INVALID_DATA;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
m_lResult = RegSetValueEx(m_hkeyOpen, regval.m_sName, 0, regval.m_dwType,
|
||
|
regval.m_pData, regval.m_dwDataLength);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
|
||
|
m_bDirty = TRUE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::GetSubKey
|
||
|
//
|
||
|
// Note: If successful, regkey is returned connected and open on the
|
||
|
// specified key. If failure, regkey is returned disconnected.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
BOOL CRegistryKey::GetSubKey(LPCTSTR pszSubKey, CRegistryKey ®key)
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
m_lResult = RPC_S_SERVER_UNAVAILABLE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
CString sSubKey;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (!m_bOpen)
|
||
|
return FALSE;
|
||
|
|
||
|
m_lResult = regkey.Disconnect(TRUE);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
|
||
|
// Try to connect and open same key
|
||
|
m_lResult = regkey.Connect(m_sComputer, m_hkeyConnect);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
sSubKey = pszSubKey;
|
||
|
m_lResult = regkey.Open(m_sFullName + "\\" + sSubKey, m_Sam);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
regkey.Disconnect(TRUE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::CreateSubKey
|
||
|
//
|
||
|
// Note: If successful, regkey is returned connected and open on the
|
||
|
// new key; if the key already existed, it is simply opened. If failure,
|
||
|
// regkey is returned disconnected.
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
BOOL CRegistryKey::CreateSubKey(
|
||
|
LPCTSTR pszSubKey,
|
||
|
CRegistryKey ®key,
|
||
|
LPCTSTR pszClass,
|
||
|
LPSECURITY_ATTRIBUTES lpSecAttr,
|
||
|
BOOL bIsVolatile)
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
m_lResult = RPC_S_SERVER_UNAVAILABLE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
CString sSubKey, sClass;
|
||
|
HKEY hkeyOpen;
|
||
|
DWORD dwDisposition;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
|
||
|
if (!m_bOpen)
|
||
|
return FALSE;
|
||
|
|
||
|
m_lResult = regkey.Disconnect(TRUE);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
|
||
|
// Try to connect and open same key
|
||
|
m_lResult = regkey.Connect(m_sComputer, m_hkeyConnect);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
sSubKey = pszSubKey;
|
||
|
sClass = pszClass;
|
||
|
DWORD dwRegOptions = bIsVolatile ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE;
|
||
|
m_lResult = RegCreateKeyEx(m_hkeyOpen, sSubKey, 0, (LPTSTR)(LPCTSTR)sClass,
|
||
|
dwRegOptions, m_Sam, lpSecAttr, &hkeyOpen, &dwDisposition);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
regkey.Disconnect(TRUE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
m_lResult = RegCloseKey(hkeyOpen);
|
||
|
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
return FALSE;
|
||
|
|
||
|
m_lResult = regkey.Open(m_sFullName + "\\" + sSubKey, m_Sam);
|
||
|
|
||
|
if (m_lResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
|
||
|
regkey.Disconnect(TRUE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
m_bDirty = TRUE;
|
||
|
if (dwDisposition == REG_CREATED_NEW_KEY)
|
||
|
regkey.m_bDirty = TRUE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//****************************************************************************
|
||
|
//
|
||
|
// CRegistryKey::DeleteSubKey
|
||
|
//
|
||
|
//****************************************************************************
|
||
|
BOOL CRegistryKey::DeleteSubKey(LPCTSTR pszSubKey)
|
||
|
{
|
||
|
if (g_bLostConnection) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
CString sSubKey;
|
||
|
CRegistryKey subkey;
|
||
|
int i;
|
||
|
|
||
|
m_lResult = ERROR_SUCCESS;
|
||
|
sSubKey = pszSubKey;
|
||
|
|
||
|
if (!m_bOpen)
|
||
|
return FALSE;
|
||
|
|
||
|
if (!GetSubKey(sSubKey, subkey))
|
||
|
return FALSE;
|
||
|
|
||
|
// Delete all subkeys of the specified subkey (RegDeleteKey limitation)
|
||
|
CStringArray *parr = subkey.EnumSubKeys();
|
||
|
for (i=0; i<parr->GetSize(); i++)
|
||
|
{
|
||
|
if (!subkey.DeleteSubKey(parr->GetAt(i)))
|
||
|
return FALSE;
|
||
|
}
|
||
|
delete parr;
|
||
|
|
||
|
subkey.Close(TRUE);
|
||
|
|
||
|
m_lResult = RegDeleteKey(m_hkeyOpen, sSubKey);
|
||
|
if (m_lResult != ERROR_SUCCESS) {
|
||
|
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) {
|
||
|
g_bLostConnection = TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|