Click here to Skip to main content
15,896,207 members
Articles / Programming Languages / C++

SetEnv

Rate me:
Please Sign up or sign in to vote.
4.70/5 (37 votes)
11 Feb 2008CPOL7 min read 488.9K   7.7K   97  
A free tool for setting/updating/deleting System Environment Variables.
// RegKey - ( Support for the Registry )
// See the "RegKey.h" header file for copyright and license details.

	// Includes
#include "RegKey.h"
using namespace xfc;

/*lint -e534 -e730 */
RegKey::RegKey()
	: iLastErrorCode_(ERROR_SUCCESS)
	, hTheKey_(NULL)
	, hBaseKey_(NULL)
	, bRemote_(false)
	, pszComputerName_(NULL)
{
	memset(&obLastWriteTime_, 0, sizeof(FILETIME));
}

/*lint -e1551 */
RegKey::~RegKey()
{
	if(hTheKey_)
		RegCloseKey(hTheKey_);

	hTheKey_ = NULL;

	if(bRemote_ || hBaseKey_) // Need to close remote connection ?
	{
		RegCloseKey(hBaseKey_);
		hBaseKey_ = NULL;
	}

	bRemote_ = false;

	if(pszComputerName_ != NULL)
	{
		delete [] pszComputerName_;
		pszComputerName_ = NULL;
	}
}
/*lint +e1551 */


/*lint -e731 */
	// Opens/Creates a key and make it the active key
bool RegKey::OpenKey(LPCTSTR pszKeyName, bool bCreateIfNoExist /* = false */, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remotely connected

		// If a computer name is specified, then connect to it...
	if(pszMachineName != NULL)
	{		// This will set up the base key to point to the remote machine
		if(ConnectRemote((HKEY)hBaseKey, pszMachineName) == false) // Try to connect
			return false;
	}
	else
		hBaseKey_ = hBaseKey; // Base key is same as the passed parameter

	LONG lRetValue = ERROR_SUCCESS;

	if(bCreateIfNoExist) // Create ?
	{
		DWORD dwDisp; // Disposition

		lRetValue = RegCreateKeyEx(hBaseKey_, pszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE
			, KEY_ALL_ACCESS, NULL, &hTheKey_, &dwDisp);
	}
	else
		lRetValue = RegOpenKeyEx(hBaseKey_, pszKeyName, NULL, KEY_ALL_ACCESS, &hTheKey_);

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		hTheKey_ = NULL;
		
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}
/*lint +e731 */

	// Creates AND opens a key - key becomes active key 
bool RegKey::CreateKey(LPCTSTR pszKeyName, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	return OpenKey(pszKeyName, true, hBaseKey, pszMachineName);
}

	// Close the active key
void RegKey::CloseKey()
{
	if(hTheKey_)
		RegCloseKey(hTheKey_);

	hTheKey_ = NULL;

	if(bRemote_) // Need to close remote connection ?
	{
		RegCloseKey(hBaseKey_);
		hBaseKey_ = NULL;
	}

	bRemote_ = false;

	if(pszComputerName_ != NULL)
	{
		delete [] pszComputerName_;
		pszComputerName_ = NULL;
	}
}

/*lint -e774 */
bool RegKey::RecursiveDelete(RegKey* pTheCallingClass, HKEY hTheKey, LPCTSTR pszKeyName)
{
	HKEY hChildHandle = NULL;
	LPTSTR pszTempKeyName = NULL;

		// Open the child
	long lRetValue = RegOpenKeyEx(hTheKey, pszKeyName, NULL, KEY_ALL_ACCESS, &hChildHandle);
	if(lRetValue != ERROR_SUCCESS)
	{
		pTheCallingClass->iLastErrorCode_ = GetLastError();
		return false;
	}

	pszTempKeyName = new TCHAR[_MAX_PATH];
	if(pszTempKeyName == NULL)
	{
		pTheCallingClass->iLastErrorCode_ = GetLastError();
		return false;
	}

		// Get the child's key name
	lRetValue = RegEnumKey(hChildHandle, 0, pszTempKeyName, _MAX_PATH);
	while(lRetValue != ERROR_NO_MORE_ITEMS)
	{
		RecursiveDelete(pTheCallingClass, hChildHandle, pszTempKeyName);
		lRetValue = RegEnumKey(hChildHandle, 0, pszTempKeyName, _MAX_PATH);
	}

	delete [] pszTempKeyName;
	pszTempKeyName = NULL;

	RegCloseKey(hChildHandle);

	lRetValue = RegDeleteKey(hTheKey, pszKeyName); 
	if(lRetValue != ERROR_SUCCESS)
	{
		pTheCallingClass->iLastErrorCode_ = GetLastError();
		return false;
	}

	return true;
}
/*lint +e774 */

	// Deletes a key and all values of that key
bool RegKey::DeleteKey(LPCTSTR pszKeyName)
{
	if(pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

	bool bRetValue = true;

		// You cannot delete a key if given a full path e.g. "A\\B"
		// We have to go back up a level to "A" and then delete

		// Take a copy of the keyName
	TCHAR* pszCopy = _tcsdup(pszKeyName);
	TCHAR* pBackSlash = _tcsrchr(pszCopy, _T('\\'));

	if(pBackSlash == NULL) // Not found
	{
			// No path, so specified key is just a subkey of active key
		bRetValue = RecursiveDelete(this, hTheKey_, pszKeyName);
	}
	else // Path specified
	{
		LPTSTR pszChildKeyName = pBackSlash + 1;
		*(pBackSlash) = _T('\0'); // Null terminate the parent string

		LPTSTR pszParentKey = (TCHAR*)pszCopy;
		HKEY hTempKey;

		LONG retValue = RegOpenKeyEx(hTheKey_, pszParentKey, NULL, KEY_ALL_ACCESS, &hTempKey);
		if(retValue == ERROR_SUCCESS)
		{
			bRetValue = RecursiveDelete(this, hTempKey, pszChildKeyName);
			RegCloseKey(hTempKey);
		}
		else
		{
			free(pszCopy);
			pszCopy = NULL;

			iLastErrorCode_ = GetLastError();
			return false;
		}
	}

	free(pszCopy);
	pszCopy = NULL;

	if(!bRetValue)
		return false;

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

bool RegKey::EnumerateKeys(LPTSTR pszSubkeyName, const DWORD dwIndex)
{
	if(pszSubkeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

		// Allocate buffers and zero them
	TCHAR subkeyNameBuffer[2048] = {'\0'};
	TCHAR classNameBuffer[2048] = {'\0'};

	DWORD sizeOfSubkeyName = sizeof(subkeyNameBuffer) - 1;
	DWORD sizeOfClassName = sizeof(classNameBuffer) - 1;

	LONG lRetValue = RegEnumKeyEx(hTheKey_, dwIndex, subkeyNameBuffer 
			, &sizeOfSubkeyName, NULL, classNameBuffer, &sizeOfClassName, &obLastWriteTime_);

	if(lRetValue == ERROR_NO_MORE_ITEMS)
	{
		iLastErrorCode_ = ERROR_NO_MORE_ITEMS;
		_tcscpy(pszSubkeyName, subkeyNameBuffer);
		return false;
	}

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	_tcscpy(pszSubkeyName, subkeyNameBuffer);

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Flushes the active key ( Write to hard disk )
bool RegKey::Flush()
{
	if(hTheKey_ == NULL)
		return true;

	if(RegFlushKey(hTheKey_) != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Connect to a remote computer's registry
	// Note: WinNT won't allow you to connect to these hives via RegConnectRegistry
bool RegKey::ConnectRemote(HKEY hKeyToOpen, LPCTSTR pszComputerName)
{
	if(pszComputerName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	LONG lRetValue = ERROR_SUCCESS; 

		// Try to connect using the remote key
	lRetValue = RegConnectRegistry((TCHAR *)pszComputerName, hKeyToOpen, &hBaseKey_);
	if(lRetValue == ERROR_SUCCESS)
	{
		bRemote_ = true;
		pszComputerName_ = new TCHAR[MAX_COMPUTERNAME_LENGTH + 1];
		memset(pszComputerName_, 0, (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(TCHAR));
		_tcsncpy(pszComputerName_, pszComputerName, MAX_COMPUTERNAME_LENGTH);
	}
	else
	{
		bRemote_ = false;
		pszComputerName_ = NULL;
		iLastErrorCode_ = GetLastError();

		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	//////////////////////////
	// Various Value Functions

	// Retrieves the size and type of a value for the active key
bool RegKey::QueryValue(LPCTSTR pszValueName, DWORD& dwValueLength, DWORD& dwValueType)
{
	if(pszValueName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

	LONG lRetValue = RegQueryValueEx(hTheKey_, pszValueName, NULL, &dwValueType, NULL, &dwValueLength);
	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Deletes a value from the currently open active key
bool RegKey::DeleteValue(LPCTSTR pszValueName)
{
	if(pszValueName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

	if(RegDeleteValue(hTheKey_, pszValueName) != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

		// Get all the values for the active key, returns XFC_NO_MOREDATA when no more items
bool RegKey::EnumerateValues(LPTSTR pszValueName, LPBYTE lpValue, DWORD& dwValueSize, DWORD& dwValueType, const DWORD dwIndex)
{
	if(pszValueName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

	TCHAR tmpName[2048] = {'\0'};

	DWORD dwTmpNameSize = sizeof(tmpName);

	LONG lRetValue = RegEnumValue(hTheKey_, dwIndex, tmpName, &dwTmpNameSize, NULL, &dwValueType, lpValue, &dwValueSize);
	if(lRetValue == ERROR_NO_MORE_ITEMS)
	{
		_tcscpy(pszValueName, tmpName);
		iLastErrorCode_ = ERROR_NO_MORE_ITEMS;
		return false;
	}

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	_tcscpy(pszValueName, tmpName);

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Get information on active key
bool RegKey::QueryKey(DWORD& dwNumSubKeys, DWORD& dwMaxSubKeyName, DWORD& dwNumValues, DWORD& dwMaxValueName, DWORD& dwMaxValueDataSize, FILETIME& lastWriteTime)
{
	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

		// Not interested in the class name or security in this version, so leave as NULL
	LONG lRetValue = RegQueryInfoKey(hTheKey_, NULL, NULL, NULL
                                , &dwNumSubKeys, &dwMaxSubKeyName, NULL, &dwNumValues, &dwMaxValueName
								, &dwMaxValueDataSize, NULL, &lastWriteTime);

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	///////////
	// SetValue

	// Sets a value for the active key, creates a new value if it doesn't exist
bool RegKey::IntSetValue(LPCTSTR pszValueName, const BYTE* pValue, DWORD dwValueLength, DWORD dwValueType)
{
	if(pszValueName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

	if(RegSetValueEx(hTheKey_, pszValueName, NULL, dwValueType, pValue, dwValueLength) != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Sets a DWORD value for the active key
bool RegKey::SetValue(LPCTSTR pszValueName, DWORD dwValue)
{
	return IntSetValue(pszValueName, (BYTE*)&dwValue, sizeof(DWORD), REG_DWORD);
}

	// Sets a STRING value for the active key
bool RegKey::SetValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwValueLength)
{
	return IntSetValue(pszValueName, (BYTE*)pszValue, dwValueLength, REG_SZ);
}

bool RegKey::SetValueEx(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwValueLength)
{
	return IntSetValue(pszValueName, (BYTE*)pszValue, dwValueLength, REG_EXPAND_SZ);
}

	// Sets a BINARY value for the active key
bool RegKey::SetValue(LPCTSTR pszValueName, const BYTE* pValue, DWORD dwValueLength)
{
	return IntSetValue(pszValueName, pValue, dwValueLength, REG_BINARY);
}

	///////////
	// GetValue

	// Gets a value from the active key
bool RegKey::IntGetValue(LPCTSTR pszValueName, BYTE& pValue, DWORD& dwValueLength)
{
	if(pszValueName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(hTheKey_ == NULL)
	{
		iLastErrorCode_ = ERROR_INVALID_HANDLE;
		return false;
	}

	DWORD dwType = 0;

	LONG lRetValue = RegQueryValueEx(hTheKey_, pszValueName, NULL, &dwType, (LPBYTE)&pValue, &dwValueLength);
	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Gets a DWORD value for the active key
bool RegKey::GetValue(LPCTSTR pszValueName, DWORD& dwValue)
{
	DWORD dwValueLen = sizeof(DWORD);

	if(!IntGetValue(pszValueName, (BYTE&)dwValue, dwValueLen))
		return false;

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Gets a STRING value for the active key
bool RegKey::GetValue(LPCTSTR pszValueName, LPTSTR pszValue, DWORD& dwValueLength)
{
	TCHAR* tmpBuffer = new TCHAR[dwValueLength + 1];
	memset(tmpBuffer, 0, dwValueLength * sizeof(TCHAR));

	if(!IntGetValue(pszValueName, (BYTE&)*tmpBuffer, dwValueLength))
	{
		delete [] tmpBuffer;
		tmpBuffer = NULL;
		return false;
	}

	_tcsncpy(pszValue, tmpBuffer, dwValueLength);
	delete [] tmpBuffer;
	tmpBuffer = NULL;

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Gets a BINARY value for the active key
bool RegKey::GetValue(LPCTSTR pszValueName, BYTE& pValue, DWORD& dwValueLength)
{
	BYTE* tmpBuffer = new BYTE[dwValueLength + 1];
	memset(tmpBuffer, 0, dwValueLength * sizeof(TCHAR));

	if(!IntGetValue(pszValueName, (BYTE&)*tmpBuffer, dwValueLength))
	{
		delete [] tmpBuffer;
		tmpBuffer = NULL;
		return false;
	}

	memcpy(&pValue, tmpBuffer, dwValueLength);
	delete [] tmpBuffer;
	tmpBuffer = NULL;

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	//////////////////////////
	// Configuration functions

	// Saves a registry tree into the specified file/path from the specified key position
bool RegKey::SaveRegistry(LPCTSTR pszFileName, LPCTSTR pszKeyName, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszFileName == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remote

		// Open the key
	if(!OpenKey(pszKeyName, false, hBaseKey, pszMachineName))
		return false;

	LONG lRetValue = RegSaveKey(hTheKey_, pszFileName, NULL);

	if(lRetValue == ERROR_ALREADY_EXISTS || lRetValue == ERROR_REGISTRY_IO_FAILED) // Win NT / Win 95
	{
		iLastErrorCode_ = ERROR_ALREADY_EXISTS;
		return false;
	}

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Restores a saved registry tree from the specified file to the specified key position
bool RegKey::RestoreRegistry(LPCTSTR pszFileName, LPCTSTR pszKeyName, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszFileName == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remote

		// Open the key
	if(!OpenKey(pszKeyName, true, hBaseKey, pszMachineName))
		return false;

	LONG lRetValue = RegRestoreKey(hTheKey_, pszFileName, REG_OPTION_NON_VOLATILE);
	if(lRetValue == ERROR_CALL_NOT_IMPLEMENTED) // NT ONLY
	{
		iLastErrorCode_ = ERROR_CALL_NOT_IMPLEMENTED;
		return false;
	}

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Notify of a change in the specified registry key/hive
bool RegKey::NotifyChange(LPCTSTR pszKeyName, DWORD dwNotifyfilter, bool bWatchSubKeys /* = false */, HANDLE hEvent /* = NULL */, HKEY hBaseKey /* = HKEY_CURRENT_USER */)
{
	if(pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	if(!OpenKey(pszKeyName, false, hBaseKey, NULL))
		return false;

	LONG lRetValue = ERROR_SUCCESS;

	if(hEvent == NULL)
		lRetValue = RegNotifyChangeKeyValue(hTheKey_, bWatchSubKeys, dwNotifyfilter, hEvent, FALSE);
	else
		lRetValue = RegNotifyChangeKeyValue(hTheKey_, bWatchSubKeys, dwNotifyfilter, hEvent, TRUE);

	if(lRetValue == ERROR_CALL_NOT_IMPLEMENTED) // NT ONLY
	{
		iLastErrorCode_ = ERROR_CALL_NOT_IMPLEMENTED;
		return false;
	}

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	/////////////////////
	// Shortcut functions
		// These functions perform an open automatically, and close if necessary
		// Saves having to do an Open(), Set(), Close() sequence.

DWORD RegKey::GetSizeOfValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	DWORD dwCount = 0;
	if(OpenKey(pszKeyName, false, hBaseKey, pszMachineName))
	{
		DWORD dwType = 0;
		DWORD dwValueLength = 0;

		LONG lRetValue = RegQueryValueEx(hTheKey_, pszValueName, NULL, &dwType, NULL, &dwValueLength);
		if(lRetValue == ERROR_SUCCESS || lRetValue == ERROR_MORE_DATA)
			dwCount = dwValueLength;

		CloseKey(); // Close it as we have finnished
	}

	return dwCount;
}

	// Opens/Creates a key, sets a value within the key and makes it the active key if active = true, else closes the key
bool RegKey::SetKeyValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, DWORD dwValue
	, bool bCreateIfNoExist /* = false */, bool bActive /* = false */
	, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remote

		// Open / create the key
	if(!OpenKey(pszKeyName, bCreateIfNoExist, hBaseKey, pszMachineName))
		return false;

	if(!SetValue(pszValueName, dwValue))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

bool RegKey::SetKeyValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwValueLength
	, bool bCreateIfNoExist /* = false */, bool bActive /* = false */
	, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pszValue == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}
	
	CloseKey(); // Close current active key and base key if remote

		// Open / create the key
	if(!OpenKey(pszKeyName, bCreateIfNoExist, hBaseKey, pszMachineName))
		return false;

	if(!SetValue(pszValueName, pszValue, dwValueLength))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Set an expanded String Value
bool RegKey::SetKeyValueEx(LPCTSTR pszKeyName, LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwValueLength
	, bool bCreateIfNoExist /* = false */, bool bActive /* = false */
	, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pszValue == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}
	
	CloseKey(); // Close current active key and base key if remote

		// Open / create the key
	if(!OpenKey(pszKeyName, bCreateIfNoExist, hBaseKey, pszMachineName))
		return false;

	if(!SetValueEx(pszValueName, pszValue, dwValueLength))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

bool RegKey::SetKeyValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, const BYTE* pValue, DWORD dwValueLength
	, bool bCreateIfNoExist /* = false */, bool bActive /* = false */
	, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pValue == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;		
		return false;
	}
	
	CloseKey(); // Close current active key and base key if remote

		// Open / create the key
	if(!OpenKey(pszKeyName, bCreateIfNoExist, hBaseKey, pszMachineName))
		return false;

	if(!SetValue(pszValueName, (BYTE*)pValue, dwValueLength))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Opens a key and retrieves A value
	// Make it the active key if active = true, else close the key
bool RegKey::GetKeyValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, DWORD& dwValue
	, bool bActive /* = false */, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remote

		// Open the key
	if(!OpenKey(pszKeyName, false, hBaseKey, pszMachineName))
		return false;

	if(!GetValue(pszValueName, dwValue))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

bool RegKey::GetKeyValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, LPTSTR pszValue, DWORD dwValueLength
	, bool bActive /* = false */, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pszValue == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}
	
	CloseKey(); // Close current active key and base key if remote

		// Open the key
	if(!OpenKey(pszKeyName, false, hBaseKey, pszMachineName))
		return false;

	if(!GetValue(pszValueName, pszValue, dwValueLength))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

/*lint -e774 */
bool RegKey::GetKeyValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, BYTE& pValue, DWORD dwValueLength
	, bool bActive /* = false */, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if((pszKeyName == NULL) || (pszValueName == NULL) || (&pValue == NULL))
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remote

		// Open the key
	if(!OpenKey(pszKeyName, false, hBaseKey, pszMachineName))
		return false;

	if(!GetValue(pszValueName, pValue, dwValueLength))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}
/*lint +e774 */

	// Opens a key, deletes a value from the key and makes key active if required
bool RegKey::DeleteKeyValue(LPCTSTR pszKeyName, LPCTSTR pszValueName, bool bActive /* = false */, HKEY hBaseKey /* = HKEY_CURRENT_USER */, LPCTSTR pszMachineName /* = NULL */)
{
	if(pszValueName == NULL || pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remote

		// Open the key
	if(!OpenKey(pszKeyName, false, hBaseKey, pszMachineName))
		return false;

	if(!DeleteValue(pszValueName))
	{
		if(!bActive)
			CloseKey();
		return false;
	}

	if(!bActive)
		CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Move a key, it's subkeys and all values
bool RegKey::MoveKey(LPCTSTR pszSourceKey, LPCTSTR pszDestKey, HKEY hBaseKey /* = HKEY_CURRENT_USER */)
{
	if(pszSourceKey == NULL || pszDestKey == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	HKEY hSource = NULL;
	HKEY hDest = NULL;

		// Open the source key
	LONG lRetValue = RegOpenKeyEx(hBaseKey, pszSourceKey, NULL, KEY_ALL_ACCESS, &hSource);

	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

		// Open/Create the destination key
	DWORD dwDisp; // Disposition

	lRetValue = RegCreateKeyEx(hBaseKey, pszDestKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hDest, &dwDisp);
	if(lRetValue != ERROR_SUCCESS)
	{
		iLastErrorCode_ = GetLastError();
		return false;
	}

		// We have opened and created all appropriate keys
		// Enumerate all values in hSource, and recreate in hDest
	TCHAR szValueName[_MAX_PATH];
	DWORD dwValueBuffer = _MAX_PATH;
	DWORD dwIndex = 0;
	DWORD dwValueType;
	DWORD dwValueLength = 0;
	bool bContinue = true;

		// Deal with the values first
	while(bContinue)
	{
		dwValueBuffer = _MAX_PATH;
		dwValueLength = 1;

		if(RegEnumValue(hSource, dwIndex, szValueName, &dwValueBuffer, NULL, &dwValueType, NULL, &dwValueLength) == ERROR_SUCCESS)
		{
			LPBYTE pValue = (LPBYTE) new TCHAR[dwValueLength + 1]; // Allocate memory for the data

			if(pValue)
			{
				DWORD dwRealDataLen = dwValueLength + 1;

				if(RegQueryValueEx(hSource, szValueName, NULL, NULL, pValue, &dwRealDataLen) == ERROR_SUCCESS)
				{
					if(RegSetValueEx(hDest, szValueName, NULL, dwValueType, pValue, dwValueLength) != ERROR_SUCCESS)
					{
						delete [] pValue;
						pValue = NULL;

						iLastErrorCode_ = GetLastError();
						return false;
					}
				}
				else
				{
					delete [] pValue;
					pValue = NULL;

					iLastErrorCode_ = GetLastError();
					return false;
				}

				delete [] pValue;
				pValue = NULL;

				dwIndex++;
			}
		}
		else
			bContinue = false;
	}

		// Enumerate all subkeys in hSource, and recreate in hDest
	bContinue = true;
	dwIndex = 0;

	while(bContinue)
	{
		if(RegEnumKey(hSource, dwIndex, szValueName, _MAX_PATH) == ERROR_SUCCESS)
		{
			TCHAR szSourceKey[_MAX_PATH] = {'\0'};
			TCHAR szDestKey[_MAX_PATH] = {'\0'};

			_tcscpy(szSourceKey, pszSourceKey);
			_tcscpy(szDestKey, pszDestKey);

			_tcscat(szSourceKey, _T("\\"));
			_tcscat(szSourceKey, szValueName);

			_tcscat(szDestKey, _T("\\"));
			_tcscat(szDestKey, szValueName);

			if(!MoveKey(szSourceKey, szDestKey, hBaseKey))
				dwIndex++;
		}
		else
			bContinue = false;
	}

		// Now delete the original key and it's values and subkeys
	RegCloseKey(hSource);
	RegCloseKey(hDest);
	QuickDeleteKey(pszSourceKey, hBaseKey);

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}

	// Delete a Key
bool RegKey::QuickDeleteKey(LPCTSTR pszKeyName, HKEY hBaseKey /* = HKEY_CURRENT_USER */)
{
	if(pszKeyName == NULL)
	{
		iLastErrorCode_ = ERROR_BAD_ARGUMENTS;
		return false;
	}

	CloseKey(); // Close current active key and base key if remote

	TCHAR* pBackSlash;
	bool bRetValue = true;

		// You cannot delete a key if given a full path e.g. "A\\B"
		// We have to go back up a level to "A" and then delete

		// Take a copy of the keyName
	TCHAR* pszCopy = _tcsdup(pszKeyName);

	pBackSlash = _tcsrchr(pszCopy, _T('\\'));
	if(pBackSlash == NULL) // Not found
	{
			// No path, so specified key is just a subkey of active key
		bRetValue = RecursiveDelete(this, hBaseKey, pszKeyName);
	}
	else // Path specified
	{
		LPTSTR pszChildKeyName = pBackSlash + 1;
		*(pBackSlash) = _T('\0'); // Null terminate the parent string

		LPTSTR pszParentKey = (TCHAR*)pszCopy;
		HKEY hTempKey;

		LONG retValue = RegOpenKeyEx(hBaseKey, pszParentKey, NULL, KEY_ALL_ACCESS, &hTempKey);

		if(retValue == ERROR_SUCCESS)
		{
			bRetValue = RecursiveDelete(this, hTempKey, pszChildKeyName);
			RegCloseKey(hTempKey);
		}
		else
		{
			free(pszCopy);
			pszCopy = NULL;

			iLastErrorCode_ = GetLastError();
			return false;
		}
	}

	free(pszCopy);

	if(!bRetValue)
		return false;

	CloseKey(); // Close current active key and base key if remote

	iLastErrorCode_ = ERROR_SUCCESS;
	return true;
}
/*lint +e534 +e730 */

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Elekta Limited
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions