/*++ Copyright (c) 2001 Microsoft Corporation Module Name : reg.cxx Abstract: Class that modifies the registry Author: Christopher Achille (cachille) Project: Internet Services Setup Revision History: June 2001: Created --*/ #include "stdafx.h" #include "reg.hxx" #include "tstr.hxx" // constructor // CRegistry::CRegistry(): m_hKey(NULL) { } // destructor // CRegistry::~CRegistry() { CloseRegistry(); } // function: QueryKey // // Query our current registry key // HKEY CRegistry::QueryKey() { return m_hKey; } // function: OpenRegistry // // Open a registry handle // // Parameters: // szNodetoOpen - A string containing the node to open // szSubKey - The subkey that you need to open // dwAccess - Access that is needed // pKey - A pointer to a key that is returned // // Return // TRUE - Success // FALSE - Failure // BOOL CRegistry::OpenRegistry(LPTSTR szNodetoOpen, LPTSTR szSubKey, DWORD dwAccess) { HKEY hHandleValue = HKEY_LOCAL_MACHINE; if ( _tcsicmp( szNodetoOpen, _T("HKCR") ) == 0 ) { hHandleValue = HKEY_CLASSES_ROOT; } else if ( _tcsicmp( szNodetoOpen, _T("HKCC") ) == 0 ) { hHandleValue = HKEY_CURRENT_CONFIG; } else if ( _tcsicmp( szNodetoOpen, _T("HKCU") ) == 0 ) { hHandleValue = HKEY_CURRENT_USER; } else if ( _tcsicmp( szNodetoOpen, _T("HKLM") ) == 0 ) { hHandleValue = HKEY_LOCAL_MACHINE; } else if ( _tcsicmp( szNodetoOpen, _T("HKU") ) == 0 ) { hHandleValue = HKEY_USERS; } return OpenRegistry( hHandleValue, szSubKey, dwAccess ); } // function: OpenRegistry // // Open a registry handle // // Parameters: // hKey - Key to open from // szSubKey - The subkey that you need to open // dwAccess - Access that is needed // bCreateIfNotPresent - Should we create key if not existent? // // Return // TRUE - Success // FALSE - Failure // BOOL CRegistry::OpenRegistry(HKEY hKey, LPCTSTR szSubKey, DWORD dwAccess, BOOL bCreateIfNotPresent /*= FALSE*/ ) { DWORD dwRet; // Close just incase it was open before CloseRegistry(); dwRet = RegOpenKeyEx(hKey, szSubKey, 0, dwAccess, &m_hKey); if ( ( dwRet == ERROR_PATH_NOT_FOUND ) && ( bCreateIfNotPresent ) ) { // Try to create is dwRet = RegCreateKeyEx( hKey, szSubKey, 0, // Reserved NULL, REG_OPTION_NON_VOLATILE, dwAccess, NULL, // SD &m_hKey, NULL ); } return ( dwRet == ERROR_SUCCESS ); } // function: CloseRegistry // void CRegistry::CloseRegistry() { if ( m_hKey ) { RegCloseKey( m_hKey ); m_hKey = NULL; } } // function: ReadValue // // Parameters: // Value - The container for the Value // // Return: // TRUE - Successfully read // FALSE - Could not be read BOOL CRegistry::ReadValue(LPCTSTR szName, CRegValue &Value) { DWORD dwSize = 0; DWORD dwType; if ( RegQueryValueEx(m_hKey, szName, NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS) { // We could not request the size return FALSE; } if ( !Value.m_buffData.Resize( dwSize ) ) { // Could not expland value size return FALSE; } Value.m_dwSize = dwSize; if ( RegQueryValueEx(m_hKey, szName, NULL, &Value.m_dwType, (LPBYTE) Value.m_buffData.QueryPtr() , &dwSize) != ERROR_SUCCESS) { // Could not retrieve value return FALSE; } return TRUE; } // funtion : ReadValueString // // Read a string in from the registry. If it is not string, then fail // // Parameters: // szName - The name of the registry key // strValue - The value of the registry value // // Return: // TRUE - Successfully read // FALSE - Could not be read, or it is not a string value BOOL CRegistry::ReadValueString(LPCTSTR szName, TSTR *strValue) { DWORD dwSize = 0; DWORD dwType; if ( RegQueryValueEx(m_hKey, szName, NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS) { // We could not request the size return FALSE; } if ( dwType != REG_SZ ) { // It is not a string return FALSE; } if ( !strValue->Resize( dwSize ) ) { // Could not expland the string return FALSE; } if ( RegQueryValueEx(m_hKey, szName, NULL, &dwType, (LPBYTE) strValue->QueryStr() , &dwSize) != ERROR_SUCCESS) { // Could not retrieve value return FALSE; } return TRUE; } // function: SetValue // // Parameters: // szName - Name of Value // Value - The container for the Value // // Return: // TRUE - Successfully written // FALSE - Could not be written BOOL CRegistry::SetValue(LPCTSTR szName, CRegValue &Value) { DWORD dwSize = 0; if ( RegSetValueEx(m_hKey, szName, NULL, Value.m_dwType, (LPBYTE) Value.m_buffData.QueryPtr(), Value.m_dwSize ) != ERROR_SUCCESS) { // Failed to write value return FALSE; } return TRUE; } // function: DeleteValue // // Parameters: // szName - Name of item to remove // BOOL CRegistry::DeleteValue(LPCTSTR szName) { return ( RegDeleteValue( m_hKey, szName ) == ERROR_SUCCESS ); } // function: DeleteAllValues // // Delete all of the values inside a key // // Parameters: // BOOL CRegistry::DeleteAllValues() { TSTR strValueName; DWORD dwRet = ERROR_SUCCESS; DWORD dwValueNameSize; if ( !strValueName.Resize( MAX_PATH ) ) { return FALSE; } while ( dwRet == ERROR_SUCCESS ) { dwValueNameSize = strValueName.QuerySize(); dwRet = RegEnumValue( m_hKey, 0, // Always delete first item strValueName.QueryStr(), // Buffer &dwValueNameSize, // Buffer Size NULL, // Reserverd NULL, // Type NULL, // Data 0); // Size of Data Buffer if ( dwRet == ERROR_SUCCESS ) { dwRet = RegDeleteValue( m_hKey, strValueName.QueryStr() ); } } return ( ( dwRet == ERROR_SUCCESS ) || ( dwRet == ERROR_NO_MORE_ITEMS ) ); } // function: DeleteKey // // Delete a key, and possible recursively delete the keys within it // // Parameters: // szKeyName - The name of the key to delete // bDeleteSubKeys - Should we delete all subkeys? // dwDepth - The depth that we are in, in our recursive calls // BOOL CRegistry::DeleteKey(LPTSTR szKeyName, BOOL bDeleteSubKeys, DWORD dwDepth ) { CRegistry CurrentKey; TSTR strSubKeyName; DWORD dwSubKeySize; DWORD dwErr = ERROR_SUCCESS; FILETIME ft; if ( dwDepth >= REGKEY_RECURSION_MAXDEPTH ) { // For security reasons, and stack space, lets put a limit on the depth return FALSE; } if ( !strSubKeyName.Resize( MAX_PATH ) ) { return FALSE; } if ( bDeleteSubKeys ) { if ( !CurrentKey.OpenRegistry( m_hKey, szKeyName, KEY_ALL_ACCESS ) ) { return FALSE; } while ( dwErr == ERROR_SUCCESS ) { dwSubKeySize = strSubKeyName.QuerySize(); // Always look at the first key, since after you delete the first key, // the second will automatically become the first, and so on // WARNING: Watch the return paths for DeleteKey, because if it returns // a true without deleting the key, we will loop forever... dwErr = RegEnumKeyEx( CurrentKey.QueryKey(), 0, strSubKeyName.QueryStr(), &dwSubKeySize, NULL, NULL, 0, &ft ); // Not call this function, to recursively delete the key // that we have found if ( dwErr == ERROR_SUCCESS ) { if ( !CurrentKey.DeleteKey( strSubKeyName.QueryStr(), TRUE, dwDepth + 1 ) ) { dwErr = ERROR_ACCESS_DENIED; } } } // This should be treated as success, we hit the end of the list if ( dwErr == ERROR_NO_MORE_ITEMS ) { dwErr = ERROR_SUCCESS; } // If we had not problem so far and we are deleting recurisively, // delete all the values in this key if ( dwErr == ERROR_SUCCESS ) { if (!CurrentKey.DeleteAllValues() ) { dwErr = ERROR_ACCESS_DENIED; } } CurrentKey.CloseRegistry(); } // If we had not problem so far, delete the key itself if ( dwErr == ERROR_SUCCESS ) { dwErr = RegDeleteKey( m_hKey, strSubKeyName.QueryStr() ); } return ( dwErr == ERROR_SUCCESS ); } // function: Verify Parameters // // Verify that the parameters are correct // BOOL CRegistry_MoveValue::VerifyParameters(CItemList &ciParams) { if ( ciParams.GetNumberOfItems() == 6 ) { return TRUE; } return FALSE; } // function: DoInternalWork // // Move a registry value // // Parameters: // ciList - Parameters for function // 0 - Source location (HKLM/HKCU/...) // 1 - Source Path (/Software/Microsoft/...) // 2 - Source Name // 3 - Target location // 4 - Target Path // 5 - Target Name // BOOL CRegistry_MoveValue::DoInternalWork(CItemList &ciList) { CRegistry RegSource; CRegistry RegTarget; CRegValue Value; BOOL bRet = TRUE; BOOL bSameLocation = TRUE; if ( !RegSource.OpenRegistry(ciList.GetItem(0), ciList.GetItem(1), KEY_READ | KEY_WRITE) ) { // We could not open this node in the registry return FALSE; } if ( ( _tcsicmp( ciList.GetItem(0), ciList.GetItem(3) ) != 0 ) || ( _tcsicmp( ciList.GetItem(1), ciList.GetItem(4) ) != 0 ) ) { // Since the read and write are not both located at the same node, open the // write node also. if ( !RegTarget.OpenRegistry(ciList.GetItem(3), ciList.GetItem(4), KEY_READ |KEY_WRITE ) ) { // We could not open the node needed for write in the registry return FALSE; } bSameLocation = FALSE; } // See if the target already has a value, if it does, then we do not need to move the old value if ( bSameLocation ) bRet = !RegSource.ReadValue( ciList.GetItem(5), Value ); else bRet = !RegTarget.ReadValue( ciList.GetItem(5), Value ); if ( bRet ) { // Try to read old value bRet = RegSource.ReadValue( ciList.GetItem(2), Value ); } if ( bRet ) { // Try to Set the new value if ( bSameLocation ) bRet = RegSource.SetValue( ciList.GetItem(5), Value ); else bRet = RegTarget.SetValue( ciList.GetItem(5), Value ); } if ( bRet ) { // Remove old value, since we have successfully copied it bRet = RegSource.DeleteValue( ciList.GetItem(2) ); } return bRet; } // function: GetMethodName // LPTSTR CRegistry_MoveValue::GetMethodName() { return _T("Registry_MoveValue"); } // function: Verify Parameters // // Verify that the parameters are correct // BOOL CRegistry_DeleteKey::VerifyParameters(CItemList &ciParams) { // 3 parameters are for Root,Path,Name of Key // 4th parameter can be the if you want it recursively deleted if ( ( ciParams.GetNumberOfItems() == 3 ) || ( ( ciParams.GetNumberOfItems() == 4 ) && ( ciParams.IsNumber(3) ) ) ) { return TRUE; } return FALSE; } // function: DoInternalWork // // Delete a registry key // // Parameters: // ciList - Parameters for function // 0 - Source location (HKLM/HKCU/...) // 1 - Source Path (/Software/Microsoft/...) // 2 - Source Name // 3 - Recursively delete keys? (optional) // BOOL CRegistry_DeleteKey::DoInternalWork(CItemList &ciList) { CRegistry Reg; BOOL bRet = TRUE; if ( !Reg.OpenRegistry(ciList.GetItem(0), ciList.GetItem(1), KEY_ALL_ACCESS ) ) { // We could not open this node in the registry return FALSE; } bRet = Reg.DeleteKey( ciList.GetItem(2), // Name of specific key to delete ciList.GetNumberOfItems() == 4 ? ciList.GetNumber(3) != 0 : TRUE); // Delete recursively Reg.CloseRegistry( ); return bRet; } // function: GetMethodName // LPTSTR CRegistry_DeleteKey::GetMethodName() { return _T("Registry_DeleteKey"); } // SetDword // // Set the value to a DWORD // BOOL CRegValue::SetDword( DWORD dwNewValue ) { if ( !m_buffData.Resize( sizeof( DWORD ) ) ) { return FALSE; } m_dwSize = sizeof( DWORD ); m_dwType = REG_DWORD; *( (LPDWORD) m_buffData.QueryPtr() ) = dwNewValue; return TRUE; } // GetDword // // Retrieve the DWORD Value from the class // BOOL CRegValue::GetDword( LPDWORD pdwValue ) { if ( m_dwType != REG_DWORD ) { // This is not a DWORD return FALSE; } *pdwValue = *( (LPDWORD) m_buffData.QueryPtr() ); return TRUE; }