reactos/rosapps/sysutils/regexpl/RegistryTree.cpp
Nedko Arnaudov a248f1e7c3 GPL sync + delete value implemented
svn path=/trunk/; revision=1419
2000-10-24 20:17:42 +00:00

446 lines
11 KiB
C++

/* $Id: RegistryTree.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
*
* regexpl - Console Registry Explorer
*
* Copyright (C) 2000 Nedko Arnaoudov <nedkohome@atia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
// RegistryTree.cpp: implementation of the CRegistryTree class.
//
//////////////////////////////////////////////////////////////////////
#include "ph.h"
#include "RegistryTree.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CRegistryTree::CRegistryTree(unsigned int nMaxPathSize)
{
m_pszMachineName = NULL;
m_samDesiredOpenKeyAccess = 0;
m_pCurrentKey = m_pRoot = NULL;
m_ErrorMsg[ERROR_MSG_BUFFER_SIZE] = 0;
m_ChangeKeyBuffer = new TCHAR[nMaxPathSize];
//#ifdef _DEBUG
m_nMaxPathSize = nMaxPathSize;
//#endif
}
CRegistryTree::CRegistryTree(const CRegistryTree& Tree)
{
m_pszMachineName = NULL;
m_samDesiredOpenKeyAccess = Tree.GetDesiredOpenKeyAccess();
m_pCurrentKey = m_pRoot = NULL;
m_ErrorMsg[ERROR_MSG_BUFFER_SIZE] = 0;
m_ChangeKeyBuffer = new TCHAR[m_nMaxPathSize = Tree.m_nMaxPathSize];
_tcscpy(m_ChangeKeyBuffer,Tree.GetCurrentPath());
ChangeCurrentKey(m_ChangeKeyBuffer);
}
CRegistryTree::~CRegistryTree()
{
if (m_pszMachineName)
delete m_pszMachineName;
CRegistryKey *pNode;
while(m_pRoot)
{
pNode = m_pRoot;
m_pRoot = m_pRoot->GetChild();
delete pNode;
}
delete [] m_ChangeKeyBuffer;
}
const TCHAR * CRegistryTree::GetCurrentPath() const
{
ASSERT(m_nMaxPathSize > 0);
unsigned int nBufferSize = m_nMaxPathSize;
CRegistryKey *pNode = m_pRoot;
nBufferSize--;
m_ChangeKeyBuffer[nBufferSize] = 0;
TCHAR *pchCurrentOffset = m_ChangeKeyBuffer;
if (m_pszMachineName)
{
size_t m = _tcslen(m_pszMachineName+2);
if (m > nBufferSize)
{ // No enough space in buffer to store machine name
ASSERT(FALSE);
}
else
{
_tcscpy(pchCurrentOffset,m_pszMachineName+2);
pchCurrentOffset += m;
nBufferSize -= m;
}
}
if (2 > nBufferSize)
{ // No enough space in buffer to store '\\'
ASSERT(FALSE);
}
else
{
*pchCurrentOffset = _T('\\');
pchCurrentOffset++;
nBufferSize--;
}
while(pNode)
{
TCHAR *pchKeyName = pNode->GetKeyName();
unsigned int nKeyNameLength = _tcslen(pchKeyName);
if ((nKeyNameLength+1) > nBufferSize)
{ // No enough space in buffer to store key name + '\\'
ASSERT(FALSE);
break;
}
_tcscpy(pchCurrentOffset,pchKeyName);
pchCurrentOffset[nKeyNameLength] = '\\';
pchCurrentOffset += nKeyNameLength+1;
nBufferSize -= nKeyNameLength+1;
pNode = pNode->GetChild();
}
*pchCurrentOffset = 0;
return m_ChangeKeyBuffer;
}
BOOL CRegistryTree::IsCurrentRoot()
{
return m_pRoot == NULL;
}
// returns TRUE on success and FALSE on fail
// on fail, extended information can be received by calling GetLastErrorDescription();
BOOL CRegistryTree::ChangeCurrentKey(const TCHAR *pchRelativePath)
{
if (*pchRelativePath == _T('\\'))
{
CRegistryKey *pNode;
while(m_pRoot)
{
pNode = m_pRoot;
m_pRoot = m_pRoot->GetChild();
delete pNode;
}
m_pCurrentKey = NULL;
}
TCHAR *pchSeps = _T("\\");
ASSERT(_tcslen(pchRelativePath) <= m_nMaxPathSize);
_tcscpy(m_ChangeKeyBuffer,pchRelativePath);
TCHAR *pchNewKey = _tcstok(m_ChangeKeyBuffer,pchSeps);
if ((!pchNewKey)&&((*pchRelativePath != _T('\\'))||(*(pchRelativePath+1) != 0)))
{
_tcscpy(m_ErrorMsg,_T("Invalid key name"));
return FALSE;
};
while (pchNewKey)
{
HKEY hNewKey;
if (m_pRoot == NULL)
{ // if this is the root key there are limations
if ((_tcsicmp(pchNewKey,_T("HKCR")) == 0)||
(_tcsicmp(pchNewKey,_T("HKEY_CLASSES_ROOT")) == 0))
{
hNewKey = HKEY_CLASSES_ROOT;
}
else if ((_tcsicmp(pchNewKey,_T("HKCU")) == 0)||
(_tcsicmp(pchNewKey,_T("HKEY_CURRENT_USER")) == 0))
{
hNewKey = HKEY_CURRENT_USER;
}
else if ((_tcsicmp(pchNewKey,_T("HKLM")) == 0)||
(_tcsicmp(pchNewKey,_T("HKEY_LOCAL_MACHINE")) == 0))
{
hNewKey = HKEY_LOCAL_MACHINE;
}
else if ((_tcsicmp(pchNewKey,_T("HKU")) == 0)||
(_tcsicmp(pchNewKey,_T("HKEY_USERS")) == 0))
{
hNewKey = HKEY_USERS;
}
else if ((_tcsicmp(pchNewKey,_T("HKPD")) == 0)||
(_tcsicmp(pchNewKey,_T("HKEY_PERFORMANCE_DATA")) == 0))
{
hNewKey = HKEY_PERFORMANCE_DATA;
}
else if ((_tcsicmp(pchNewKey,_T("HKDD")) == 0)||
(_tcsicmp(pchNewKey,_T("HKEY_DYN_DATA")) == 0))
{
hNewKey = HKEY_DYN_DATA;
}
else if ((_tcsicmp(pchNewKey,_T("HKCC")) == 0)||
(_tcsicmp(pchNewKey,_T("HKEY_CURRENT_CONFIG")) == 0))
{
hNewKey = HKEY_CURRENT_CONFIG;
}
else
{
_tcscpy(m_ErrorMsg,_T("Invalid key name."));
return FALSE;
}
// Ok. Key to open is in hNewKey
int nErr = ConnectRegistry(hNewKey);
if (nErr)
{
_stprintf(m_ErrorMsg,_T("Cannot connect registry. Error is %d"),nErr);
return FALSE;
}
} // if (m_pRoot == NULL)
else
{ // current key is not root key
if (_tcsicmp(pchNewKey,_T("..")) == 0)
{
m_pCurrentKey = m_pCurrentKey->UpOneLevel();
if (m_pCurrentKey == NULL)
{
m_pRoot = NULL;
}
}
else
{ // Normal key name
CRegistryKey *pNewKey = new CRegistryKey(pchNewKey,m_pCurrentKey);
//RegOpenKeyExW(*m_pCurrentKey,pchNewKey,0,KEY_EXECUTE,&hNewKey)
DWORD dwError = pNewKey->Open(m_samDesiredOpenKeyAccess);
if (dwError != ERROR_SUCCESS)
{
TCHAR *pchPreErrorMsg = _T("Cannot open key : "), *pchCurrentOffset = m_ErrorMsg;
_tcscpy(pchCurrentOffset,pchPreErrorMsg);
pchCurrentOffset += _tcslen(pchPreErrorMsg);
_tcscpy(pchCurrentOffset,pchNewKey);
pchCurrentOffset += _tcslen(pchNewKey);
TCHAR *pchMsg = _T("\nError ");
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
TCHAR Buffer[256];
_tcscpy(pchCurrentOffset,_itot(dwError,Buffer,10));
pchCurrentOffset += _tcslen(Buffer);
pchMsg = _T("\n");
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
switch(dwError)
{
case 5:
pchMsg = _T("(Access denied)");
break;
case 2:
pchMsg = _T("(The system cannot find the key specified)");
break;
}
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
delete pNewKey;
return FALSE;
}
pNewKey->LinkParent();
m_pCurrentKey = pNewKey;
}
}
// Get next key name
pchNewKey = _tcstok(NULL,pchSeps);
}
return TRUE;
}
TCHAR * CRegistryTree::GetLastErrorDescription()
{
return m_ErrorMsg;
}
CRegistryKey * CRegistryTree::GetCurrentKey()
{
return m_pCurrentKey;
}
void CRegistryTree::SetDesiredOpenKeyAccess(REGSAM samDesired)
{
m_samDesiredOpenKeyAccess = samDesired;
}
REGSAM CRegistryTree::GetDesiredOpenKeyAccess() const
{
return m_samDesiredOpenKeyAccess;
}
int CRegistryTree::ConnectRegistry(HKEY hKey)
{
CRegistryKey *pKey = new CRegistryKey(hKey,m_pszMachineName);
int ret = pKey->Open(m_samDesiredOpenKeyAccess);
if (ret == 0)
{
CRegistryKey *pNode;
while(m_pRoot)
{
pNode = m_pRoot;
m_pRoot = m_pRoot->GetChild();
delete pNode;
}
m_pCurrentKey = NULL;
m_pRoot = m_pCurrentKey = pKey;
}
else
{
delete pKey;
}
return ret;
}
void CRegistryTree::SetMachineName(LPCTSTR pszMachineName)
{
if (m_pszMachineName)
delete m_pszMachineName;
if (pszMachineName == NULL)
{
m_pszMachineName = NULL;
return;
}
while ((*pszMachineName)&&(*pszMachineName == _T('\\')))
pszMachineName++;
if (*pszMachineName == 0)
{
ASSERT(FALSE);
}
m_pszMachineName = new TCHAR[_tcslen(pszMachineName)+3];
_tcscpy(m_pszMachineName,_T("\\\\"));
_tcscpy(m_pszMachineName+2,pszMachineName);
_tcsupr(m_pszMachineName+2);
}
BOOL CRegistryTree::NewKey(const TCHAR *pchKeyName, BOOL blnVolatile)
{
CRegistryKey *pNewKey = new CRegistryKey(pchKeyName,m_pCurrentKey);
DWORD dwDisposition;
DWORD dwError = pNewKey->Create(0,&dwDisposition,blnVolatile);
switch (dwDisposition)
{
case REG_OPENED_EXISTING_KEY:
_sntprintf(m_ErrorMsg,ERROR_MSG_BUFFER_SIZE,_T("A key \"%s\" already exists."),pchKeyName);
delete pNewKey;
return FALSE;
case REG_CREATED_NEW_KEY:
break;
default:
ASSERT(FALSE);
}
if (dwError != ERROR_SUCCESS)
{
TCHAR *pchCurrentOffset = m_ErrorMsg;
TCHAR *pchPreErrorMsg = _T("Cannot create key : ");
_tcscpy(pchCurrentOffset,pchPreErrorMsg);
pchCurrentOffset += _tcslen(pchPreErrorMsg);
_tcscpy(pchCurrentOffset,pchKeyName);
pchCurrentOffset += _tcslen(pchKeyName);
TCHAR *pchMsg = _T("\nError ");
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
TCHAR Buffer[256];
_tcscpy(pchCurrentOffset,_itot(dwError,Buffer,10));
pchCurrentOffset += _tcslen(Buffer);
pchMsg = _T("\n");
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
switch(dwError)
{
case 5:
pchMsg = _T("(Access denied)");
break;
case 2:
pchMsg = _T("(The system cannot find the key specified)");
break;
}
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
delete pNewKey;
return FALSE;
}
delete pNewKey;
return TRUE;
}
BOOL CRegistryTree::DeleteKey(const TCHAR *pchKeyName, BOOL blnRecursive)
{
DWORD dwError = m_pCurrentKey->DeleteSubkey(pchKeyName,blnRecursive);
if (dwError != ERROR_SUCCESS)
{
TCHAR *pchPreErrorMsg = _T("Cannot open key : "), *pchCurrentOffset = m_ErrorMsg;
_tcscpy(pchCurrentOffset,pchPreErrorMsg);
pchCurrentOffset += _tcslen(pchPreErrorMsg);
_tcscpy(pchCurrentOffset,pchKeyName);
pchCurrentOffset += _tcslen(pchKeyName);
TCHAR *pchMsg = _T("\nError ");
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
TCHAR Buffer[256];
_tcscpy(pchCurrentOffset,_itot(dwError,Buffer,10));
pchCurrentOffset += _tcslen(Buffer);
pchMsg = _T("\n");
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
switch(dwError)
{
case 5:
pchMsg = _T("(Access denied)");
break;
case 2:
pchMsg = _T("(The system cannot find the key specified)");
break;
}
_tcscpy(pchCurrentOffset,pchMsg);
pchCurrentOffset += _tcslen(pchMsg);
return FALSE;
}
return TRUE;
}