host/AzureRecoveryLib/win32/RegistryUtil.cpp (994 lines of code) (raw):
/*
+------------------------------------------------------------------------------------+
Copyright(c) Microsoft Corp. 2015
+------------------------------------------------------------------------------------+
File : RegistryUtil.cpp
Description : Registry utility functions.
History : 1-6-2015 (Venu Sivanadham) - Created
+------------------------------------------------------------------------------------+
*/
#include "RegistryUtil.h"
#include "WmiRecordProcessors.h"
#include "../common/utils.h"
#include "../common/Trace.h"
#include "../Status.h"
#include <sstream>
#include <list>
#include <atlbase.h>
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/lexical_cast.hpp>
namespace AzureRecovery
{
/*
Method : LoadRegistryHive
Description : Loads the given registry file 'hivePath, and assigns the the hiveName
to access its contents using registy APIs.
Parameters : [in] hivePath: regstry hive file path
[in] hiveName: key name for the registry hive that beeing loaded.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG LoadRegistryHive(const std::string& hivePath, const std::string& hiveName)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!hivePath.empty());
BOOST_ASSERT(!hiveName.empty());
LONG lRegRet = ERROR_SUCCESS;
do
{
//
// Verify that there is no hive already loaded with hiveName. If loaded then uload it.
//
HKEY hKeyHive = NULL;
lRegRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, hiveName.c_str(), 0, KEY_ALL_ACCESS, &hKeyHive);
if (ERROR_SUCCESS == lRegRet)
{
CloseHandle(hKeyHive); hKeyHive = NULL;
lRegRet = RegUnLoadKey(HKEY_LOCAL_MACHINE, hiveName.c_str());
if (ERROR_SUCCESS != lRegRet)
{
TRACE_ERROR("Could not unload existing registry hive %s. Error %lu\n",
hiveName.c_str(),
lRegRet);
break;
}
}
//
// Load the registry hive
//
TRACE_INFO("Loading the Hive %s in registry\n", hiveName.c_str());
lRegRet = RegLoadKey(HKEY_LOCAL_MACHINE, hiveName.c_str(), hivePath.c_str());
if (ERROR_SUCCESS != lRegRet)
{
TRACE_ERROR("Could not load the registry hive %s from the path %s. Error %lu\n",
hiveName.c_str(),
hivePath.c_str(),
lRegRet);
SetLastErrorMsg("Loading registry hive %s failed with error %lu.",
hivePath.c_str(),
lRegRet);
// Check if the hive path is valid and accessible, if not
// then the volume might not be accessible or does not have valid OS installation.
if (!FileExists(hivePath))
{
SetRecoveryErrorCode(E_RECOVERY_VOL_UNEXPECTED_FORMAT);
}
break;
}
} while (false);
TRACE_FUNC_END;
return lRegRet;
}
/*
Method : UnloadRegistryHive
Description : Unloads the registry hive which is attached with the hiveName.
Parameters : [in] hiveName: Uloading registry hive name.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG UnloadRegistryHive(const std::string& hiveName)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!hiveName.empty());
LONG lRegRet = RegUnLoadKey(HKEY_LOCAL_MACHINE, hiveName.c_str());
if (ERROR_SUCCESS != lRegRet) // TODO: consider the file not found return code aslo as success
{
TRACE_ERROR("Could not uload the registry hive %s. RegUnLoadKey error %lu\n",
hiveName.c_str(),
lRegRet);
}
TRACE_FUNC_END;
return lRegRet;
}
/*
Method : RegGetStringValue
Description : Reads the string value data
Parameters : [in] hKey : Valied registry hey handle
[in] valueName : Name of the string registry value
[out] valueData : Filled with the string value data.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetStringValue(HKEY hKey, const std::string& valueName, std::string& valueData)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
BOOST_ASSERT(NULL != hKey);
DWORD ccData = MAX_PATH + 1;
TCHAR* pcData = NULL;
CRegKey key;
key.Attach(hKey);
do
{
pcData = (TCHAR*)malloc(ccData * sizeof(TCHAR));
if (NULL == pcData)
{
lRetStatus = ERROR_OUTOFMEMORY;
TRACE_ERROR("Out of memory\n");
break;
}
SecureZeroMemory(pcData, ccData * sizeof(TCHAR));
lRetStatus = key.QueryStringValue(valueName.c_str(), pcData, &ccData);
if (ERROR_MORE_DATA == lRetStatus)
{
free(pcData);
pcData = (TCHAR*)malloc(ccData * sizeof(TCHAR));
if (NULL == pcData)
{
lRetStatus = ERROR_OUTOFMEMORY;
TRACE_ERROR("Out of memory\n");
break;
}
SecureZeroMemory(pcData, ccData * sizeof(TCHAR));
lRetStatus = key.QueryStringValue(valueName.c_str(), pcData, &ccData);
}
if (ERROR_SUCCESS == lRetStatus)
valueData = pcData;
} while (false);
if (pcData) free(pcData);
// Calling Detach to avoid closing hKey handle by CRegKey class destuctor.
key.Detach();
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegSetStringValues
Description : Sets the list of string values under the registry key hKey
Parameters : [in] hKey : Valid registry key handle
[in] value_map: Map of string value->data entries.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegSetStringValues(HKEY hKey, std::map<std::string, std::string>& value_map)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
BOOST_ASSERT(NULL != hKey);
if (value_map.empty())
return lRetStatus;
CRegKey regKey;
regKey.Attach(hKey);
do
{
auto iterMap = value_map.begin();
for (; iterMap != value_map.end(); iterMap++)
{
if (iterMap->first.empty())
continue;
lRetStatus = regKey.SetStringValue(iterMap->first.c_str(), iterMap->second.c_str());
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("RegSetStringValue error for %s = %s. Error code %ld\n",
iterMap->first.c_str(),
iterMap->second.c_str(),
lRetStatus );
break;
}
}
} while (false);
regKey.Detach();
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegSetDWORDValues
Description : Sets list of dword values under the regisry key hKey
Parameters : [in] hKey : Valid registry key handle
[in] value_map: Map of value-name->dword entries.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegSetDWORDValues(HKEY hKey, std::map<std::string, DWORD>& value_map)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
BOOST_ASSERT(NULL != hKey);
if (value_map.empty())
return lRetStatus;
CRegKey regKey;
regKey.Attach(hKey);
do
{
auto iterMap = value_map.begin();
for (; iterMap != value_map.end(); iterMap++)
{
if (iterMap->first.empty())
continue;
lRetStatus = regKey.SetDWORDValue(iterMap->first.c_str(), iterMap->second);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("RegSetDWORDValue error for %s = %lu. Error code %ld\n",
iterMap->first.c_str(),
iterMap->second,
lRetStatus);
break;
}
}
} while (false);
regKey.Detach();
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegGetSubKeys
Description : Retries list of sub-keys under given base registry key
Parameters : [in] hBaseKey : Valid registry key handle
[out] subkeys : Filled with list of subkeys under the base key
[in, optional] keyContrains: a patterns that matches the sub-key names.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetSubKeys(HKEY hBaseKey, std::vector<std::string>& subKeys, const std::string& keyContains)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
BOOST_ASSERT(NULL != hBaseKey);
do {
TCHAR achClass[MAX_PATH] = { 0 }; // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys = 0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time
// Get the sub-key count.
lRetStatus = RegQueryInfoKey(
hBaseKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime); // last write time
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("RegQueryInfoKey failed with error %ld\n", lRetStatus);
break;
}
// Enumerate the subkeys
if (cSubKeys)
{
for (DWORD iSubKey = 0; iSubKey < cSubKeys; iSubKey++)
{
TCHAR achKey[MAX_PATH] = { 0 };
DWORD cbName = MAX_PATH;
lRetStatus = RegEnumKeyEx(hBaseKey, iSubKey,
achKey,
&cbName,
NULL,
NULL,
NULL,
&ftLastWriteTime);
if (lRetStatus == ERROR_SUCCESS)
{
if (keyContains.empty() ||
std::string(achKey).find(keyContains) != std::string::npos
)
subKeys.push_back(achKey);
else
TRACE_INFO("Skipping key [%s] as it does not contain the pattern %s\n",
achKey,
keyContains.c_str());
}
else
{
TRACE_ERROR("RegEnumKeyEx failed with error %ld\n", lRetStatus);
}
}
}
else
{
TRACE_WARNING("No subkeys found under the base key\n");
}
} while (false);
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegGetControlSets
Description : Retrieves the list of control sets under a give system hive
Parameters : [in] SystemHiveName: Name of the system hive from where the control sets should retrieve.
[in] controlSetPreference: Preferred Control Set
[out] controlSets : Filled with list of control set names.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetControlSets(
const std::string& SystemHiveName,
std::vector<std::string>& controlSets,
const std::string& controlSetPreference)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!SystemHiveName.empty());
LONG retStatus = ERROR_SUCCESS;
HKEY hKeySysHive = NULL;
controlSets.clear();
do
{
retStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SystemHiveName.c_str(), 0, KEY_READ, &hKeySysHive);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not open the reg key %s. RegOpenKeyEx error %ld\n",
SystemHiveName.c_str(),
retStatus);
break;
}
DWORD preferredControlSet = 0;
std::stringstream controlSetNum;
std::string controlSetkeyContains = "ControlSet";
if (boost::equals(controlSetPreference, std::string(RegistryConstants::VALUE_NAME_LASTKNOWNGOOD)))
{
retStatus = RegGetLastKnownGoodControlSetValue(RegistryConstants::VM_SYSTEM_HIVE_NAME, preferredControlSet);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not get last known good control set value.");
}
}
else if (boost::equals(controlSetPreference, std::string(RegistryConstants::VALUE_NAME_CURRENT)))
{
retStatus = RegGetCurrentControlSetValue(RegistryConstants::VM_SYSTEM_HIVE_NAME, preferredControlSet);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not get current control set value.");
}
}
if (retStatus == ERROR_SUCCESS &&
!controlSetPreference.empty())
{
controlSetNum << RegistryConstants::CONTROL_SET_PREFIX
<< std::setfill('0')
<< std::setw(3)
<< preferredControlSet;
controlSetkeyContains = controlSetNum.str();
TRACE_INFO("%s ControlSet is %s\n", controlSetPreference.c_str(), controlSetkeyContains.c_str());
}
retStatus = RegGetSubKeys(hKeySysHive, controlSets, controlSetkeyContains);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not get ControlSet subkeys under %s\n",
SystemHiveName.c_str());
break;
}
if (controlSets.empty())
{
TRACE_ERROR("No ControlSet subkeys found under the reg key %s.\n",
SystemHiveName.c_str());
retStatus = ERROR_FILE_NOT_FOUND;
break;
}
} while (false);
if (hKeySysHive) RegCloseKey(hKeySysHive);
TRACE_FUNC_END;
return retStatus;
}
/*
Method : RegUpdateSystemHiveDWORDValue
Description : Updates the DWORD registry value with given value, and creates a backup registry value for existing key.
Parameters : [in] systemHive: Name of the system hive under which the entry will be updated.
[in] controlSet: Name of the control set under systemHive.
[in] relativeKeyPath: relative key path
[in] valueName: Registry DWORD value name that need to update
[out] dwOldValue: Old DWORD value data of valueName.On failure or if key does not exist then the value is unchanged.
[in] dwNewValue: New DWORD value data to be updated.
[in, options] ignoreIfNotFound: if true, then retrun code will not be failure if specified relativepath key not found.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegUpdateSystemHiveDWORDValue(const std::string& systemHive,
const std::string& controlSet,
const std::string& relativeKeyPath,
const std::string& valueName,
DWORD & dwOldValue,
DWORD dwNewValue,
bool igonreIfNotFound)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!systemHive.empty());
BOOST_ASSERT(!controlSet.empty());
BOOST_ASSERT(!relativeKeyPath.empty());
BOOST_ASSERT(!valueName.empty());
LONG retStatus = ERROR_SUCCESS;
std::string keyPath = systemHive +
DIRECOTRY_SEPERATOR +
controlSet +
(boost::starts_with(relativeKeyPath, DIRECOTRY_SEPERATOR) ? "" : DIRECOTRY_SEPERATOR) +
relativeKeyPath;
do{
TRACE_INFO("Registry path %s\n", keyPath.c_str());
CRegKey svcKey;
retStatus = svcKey.Open(HKEY_LOCAL_MACHINE, keyPath.c_str(), KEY_ALL_ACCESS);
if (ERROR_SUCCESS != retStatus)
{
//
// If ignoreIfNotFound is set to true then ignore the ERROR_FILE_NOT_FOUND error for Open call
//
if (ERROR_FILE_NOT_FOUND == retStatus &&
igonreIfNotFound)
{
TRACE_WARNING("Registry entry %s not found\n", keyPath.c_str());
retStatus = ERROR_SUCCESS;
break;
}
TRACE_ERROR("Could not open the registry key. Error %ld\n", retStatus);
break;
}
//
// Get the existing DWORD value
//
retStatus = svcKey.QueryDWORDValue(valueName.c_str(), dwOldValue);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not query the DWORD value %s under %s. Error %ld\n",
valueName.c_str(),
keyPath.c_str(),
retStatus);
break;
}
//
// If the existing DWORD value and New DWORD values are same then no action is needed
//
if (dwOldValue == dwNewValue)
{
TRACE_INFO("Existing DWORD value is same as New DWORD value. Nothing to change.\n");
break;
}
//
// Update new value now
//
retStatus = svcKey.SetDWORDValue(valueName.c_str(), dwNewValue);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not change the DWORD value %s to %lu. Error %ld\n",
valueName.c_str(),
dwNewValue,
retStatus);
break;
}
TRACE_INFO("The DWORD registry value changed from %lu to %lu successfuly under %s.\n",
dwOldValue,
dwNewValue,
keyPath.c_str());
} while (false);
TRACE_FUNC_END;
return retStatus;
}
/*
Method : RegUpdateSystemHiveDWORDValue
Description : Updates the DWORD registry value with given value, and creates a backup registry value for existing key.
Parameters : [in] systemHive: Name of the system hive under which the entry will be updated.
[in] controlSet: Name of the control set under systemHive.
[in] relativeKeyPath: relative key path
[in] valueName: Registry DWORD value name that need to update
[out] dwOldValue: Old DWORD value data of valueName.On failure or if key does not exist then the value is unchanged.
[in] dwNewValue: New DWORD value data to be updated.
[in, options] ignoreIfNotFound: if true, then retrun code will not be failure if specified relativepath key not found.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegAddOrUpdateSystemHiveDWORDValue(const std::string& systemHive,
const std::string& controlSet,
const std::string& relativeKeyPath,
const std::string& valueName,
DWORD & dwOldValue,
DWORD dwNewValue,
bool igonreIfNotFound)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!systemHive.empty());
BOOST_ASSERT(!controlSet.empty());
BOOST_ASSERT(!relativeKeyPath.empty());
BOOST_ASSERT(!valueName.empty());
LONG retStatus = ERROR_SUCCESS;
std::string keyPath = systemHive +
DIRECOTRY_SEPERATOR +
controlSet +
(boost::starts_with(relativeKeyPath, DIRECOTRY_SEPERATOR) ? "" : DIRECOTRY_SEPERATOR) +
relativeKeyPath;
do {
TRACE_INFO("Registry path %s\n", keyPath.c_str());
CRegKey svcKey;
retStatus = svcKey.Open(HKEY_LOCAL_MACHINE, keyPath.c_str(), KEY_ALL_ACCESS);
if (ERROR_SUCCESS != retStatus)
{
//
// If ignoreIfNotFound is set to true then ignore the ERROR_FILE_NOT_FOUND error for Open call
//
if (ERROR_FILE_NOT_FOUND == retStatus &&
igonreIfNotFound)
{
TRACE_WARNING("Registry entry %s not found\n", keyPath.c_str());
retStatus = ERROR_SUCCESS;
break;
}
TRACE_ERROR("Could not open the registry key. Error %ld\n", retStatus);
break;
}
//
// Get the existing DWORD value
//
retStatus = svcKey.QueryDWORDValue(valueName.c_str(), dwOldValue);
if (ERROR_SUCCESS != retStatus)
{
TRACE_WARNING("Could not query the DWORD value %s under %s. Error %ld\n",
valueName.c_str(),
keyPath.c_str(),
retStatus);
}
else if (dwOldValue == dwNewValue)
{
TRACE_INFO("Existing DWORD value is same as New DWORD value. Nothing to change.\n");
break;
}
//
//Add or Update Value.
//
retStatus = svcKey.SetDWORDValue(valueName.c_str(), dwNewValue);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not change the DWORD value %s to %lu. Error %ld\n",
valueName.c_str(),
dwNewValue,
retStatus);
break;
}
TRACE_INFO("The DWORD registry value updated successfuly to %lu under %s.\n",
dwNewValue,
keyPath.c_str());
} while (false);
TRACE_FUNC_END;
return retStatus;
}
/*
Method : RegGetSystemHiveDWORDValue
Description : Gets the DWORD registry value with given value-name.
Parameters : [in] systemHive: Name of the system hive.
[in] controlSet: Name of the control set under systemHive.
[in] relativeKeyPath: relative key path
[in] valueName: Registry DWORD value name that need to retrieve
[out] dwValue: DWORD value data of valueName. On failure or if key does not exist then the value is unchanged.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetSystemHiveDWORDValue(const std::string& systemHive,
const std::string& controlSet,
const std::string& relativeKeyPath,
const std::string& valueName,
DWORD & dwValue)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!systemHive.empty());
BOOST_ASSERT(!controlSet.empty());
BOOST_ASSERT(!relativeKeyPath.empty());
BOOST_ASSERT(!valueName.empty());
LONG retStatus = ERROR_SUCCESS;
std::string keyPath = systemHive +
DIRECOTRY_SEPERATOR +
controlSet +
(boost::starts_with(relativeKeyPath, DIRECOTRY_SEPERATOR) ? "" : DIRECOTRY_SEPERATOR) +
relativeKeyPath;
do{
TRACE_INFO("Registry path %s\n", keyPath.c_str());
CRegKey svcKey;
retStatus = svcKey.Open(HKEY_LOCAL_MACHINE, keyPath.c_str(), KEY_ALL_ACCESS);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not open the registry key. Error %ld\n", retStatus);
break;
}
//
// Get the existing DWORD value
//
retStatus = svcKey.QueryDWORDValue(valueName.c_str(), dwValue);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not query the DWORD value %s under %s. Error %ld\n",
valueName.c_str(),
keyPath.c_str(),
retStatus);
break;
}
TRACE_INFO("The DWORD registry value is %lu.\n", dwValue);
} while (false);
TRACE_FUNC_END;
return retStatus;
}
/*
Method : RegKeyExists
Description : Verifies does the keyPath exists.
Parameters : [in] hKeyParent: parent key, for example: HKEY_LOCAL_MACHINE
[in] keyPath: Relative key path from the parent key.
Return code : true -> if key exists.
false -> if key does not exists.
exception will be thrown if a failure happens on accessing specified registry key.
*/
bool RegKeyExists(HKEY hKeyParent, const std::string& keyPath)
{
TRACE_FUNC_BEGIN;
bool bExist = false;
BOOST_ASSERT(!keyPath.empty());
BOOST_ASSERT(hKeyParent != NULL);
TRACE_INFO("Opening %s key.\n", keyPath.c_str());
CRegKey regKey;
LONG lRet = regKey.Open(hKeyParent, keyPath.c_str(), KEY_READ);
bExist = VERIFY_REG_STATUS(lRet, "Registry Key open failure");
TRACE_FUNC_END;
return bExist;
}
/*
Method : RegChangeServiceStartType
Description : Sets the service related registry entries to reflect its start type as dwSvcStartType under
the specified control set.
Parameters : [in] systemHive: Name of the system hive undewhich the service start type will be updated.
[in] controlSet: Name of the control set under systemHive.
[in] serviceName: Name of the service
[in] dwSvcStartType: Dword value indicating a valid service start type
[out] oldDwSvcStartType: set with last service start type dword value.
[in, options] ignoreIfNotFound: if true, then retrun code will not be failure if specified service
related service entries not found.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegChangeServiceStartType( const std::string& systemHive,
const std::string& controlSet,
const std::string& serviceName,
DWORD dwSvcStartType,
DWORD &oldDwSvcStartType,
bool ignoreIfNotFound)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!systemHive.empty());
BOOST_ASSERT(!controlSet.empty());
BOOST_ASSERT(!serviceName.empty());
LONG retStatus = ERROR_SUCCESS;
std::string svcPath = systemHive +
DIRECOTRY_SEPERATOR +
controlSet +
RegistryConstants::SERVICES +
serviceName;
do{
TRACE_INFO("Service registry path %s\n", svcPath.c_str());
CRegKey svcKey;
retStatus = svcKey.Open(HKEY_LOCAL_MACHINE, svcPath.c_str(), KEY_ALL_ACCESS);
if (ERROR_SUCCESS != retStatus)
{
//
// If ignoreIfNotFound is set to true then ignore the ERROR_FILE_NOT_FOUND error for Open call
//
if (ERROR_FILE_NOT_FOUND == retStatus &&
ignoreIfNotFound)
{
TRACE_WARNING("Registry entry not found for the service: %s\n", svcPath.c_str());
retStatus = ERROR_SUCCESS;
break;
}
TRACE_ERROR("Could not open the service registry key. Error %ld\n", retStatus);
break;
}
//
// Get the existing DWORD value
//
retStatus = svcKey.QueryDWORDValue(RegistryConstants::SERVICE_START_VALUE_NAME, oldDwSvcStartType);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not query the Start DWORD value for the service. Error %ld\n", retStatus);
break;
}
//
// Set the new Start DWORD value if its different than existing value.
//
if (oldDwSvcStartType == dwSvcStartType)
{
TRACE_INFO("The current service Start type value is same as the requested start type.\
Nothing to change.\n");
break;
}
retStatus = svcKey.SetDWORDValue(RegistryConstants::SERVICE_START_VALUE_NAME, dwSvcStartType);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not change the Start DWORD value for the service. Error %ld\n", retStatus);
break;
}
TRACE_INFO("The Service Start type value changed from %lu to %lu successfuly.\n",
oldDwSvcStartType,
dwSvcStartType );
} while (false);
TRACE_FUNC_END;
return retStatus;
}
/*
Method : RegSetServiceStartType
Description : Sets the list if services start types to specified values in all control sets under
the given systemHive.
Parameters : [in] systemHive: Name of the system hive
[in] serviceStarTypes: List of service name -> service start type dword values
[in, opt] ignoreIfNotFound: Ignore if the registry entries of a service is not found.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegSetServiceStartType(const std::string& systemHive,
const std::map<std::string, DWORD> serviceStartTypes,
bool ignoreIfNotFound
)
{
TRACE_FUNC_BEGIN;
BOOST_ASSERT(!systemHive.empty());
LONG lRetStatus = ERROR_SUCCESS;
std::stringstream ssError;
do{
if (serviceStartTypes.empty())
{
TRACE_INFO("Empty service list. Nothing to do.\n");
break;
}
std::vector<std::string> contolSets;
lRetStatus = RegGetControlSets(systemHive, contolSets);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not get ControlSets from Source VM system hive.\n");
break;
}
std::map<std::string, DWORD>::const_iterator iterSvc = serviceStartTypes.begin();
for (;
iterSvc != serviceStartTypes.end();
iterSvc++)
{
TRACE("Changing service start type for : %s\n", iterSvc->first.c_str());
for (size_t iCtrlSet = 0; iCtrlSet < contolSets.size(); iCtrlSet++)
{
DWORD dwOldSvcStartType = 0;
lRetStatus = RegChangeServiceStartType(systemHive,
contolSets[iCtrlSet],
iterSvc->first,
iterSvc->second,
dwOldSvcStartType,
ignoreIfNotFound);
if (ERROR_SUCCESS != lRetStatus)
{
ssError.str("");
ssError << "Could not set the service start type on controlset " <<
contolSets[iCtrlSet] << "error: " << lRetStatus << std::endl;
TRACE_WARNING(ssError.str().c_str());
}
}
}
} while (false);
TRACE_FUNC_END;
return ERROR_SUCCESS;
}
/*
Method : RegGetAgentInstallPath
Description : Reads the Source-Agent install path from its registry entries under the
specified software registry hive.
Parameters : [in] SoftwareHive: Name of the sotware hive
[out] agentInstallPath: Filled with agent install path on success
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetAgentInstallPath(const std::string& SoftwareHive, std::string& agentInstallPath)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
BOOST_ASSERT(!SoftwareHive.empty());
do
{
CRegKey svSystemsKey;
std::string strSvSystemsKey = SoftwareHive + RegistryConstants::INMAGE_INSTALL_PATH_X32;
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, strSvSystemsKey.c_str(), KEY_READ);
if (ERROR_FILE_NOT_FOUND == lRetStatus)
{
// Try 64bit path
strSvSystemsKey = SoftwareHive + RegistryConstants::INMAGE_INSTALL_PATH_X64;
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, strSvSystemsKey.c_str(), KEY_READ);
}
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not open registry key %s. Error %ld\n", strSvSystemsKey.c_str(), lRetStatus);
break;
}
lRetStatus = RegGetStringValue(svSystemsKey, RegistryConstants::VALUE_INMAGE_INSTALL_DIR, agentInstallPath);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not read %s value under the key %s. Error %ld\n",
RegistryConstants::VALUE_INMAGE_INSTALL_DIR,
strSvSystemsKey.c_str(),
lRetStatus);
break;
}
} while (false);
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegGetOSCurrentVersion
Description : Reads the windows OS version information from software registry hive.
Parameters : [in] SoftwareHive: Name of the software hive
[out] osVersion: filled with string representation of OS version info.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetOSCurrentVersion(const std::string& SoftwareHive, std::string& osVersion)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
do{
std::string strCurrVerPath = SoftwareHive + RegistryConstants::WIN_CURRENT_VERSION_KEY;
CRegKey winCurrVerkey;
lRetStatus = winCurrVerkey.Open(HKEY_LOCAL_MACHINE, strCurrVerPath.c_str(), KEY_READ);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not open registry key %s. Error %ld\n",
strCurrVerPath.c_str(),
lRetStatus);
break;
}
lRetStatus = RegGetStringValue(winCurrVerkey, RegistryConstants::VALUE_CURRENT_VERSION, osVersion);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not read %s value under the key %s. Error %ld\n",
RegistryConstants::VALUE_CURRENT_VERSION,
strCurrVerPath.c_str(),
lRetStatus);
break;
}
} while (false);
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegAddBootUpScript
Description : Adds the required registry values to setup boot up script.
Parameters : [in] BootupScriptRegKeyPath : Path of the bootup script registry key.
[in] Script : Script command
[in] ScriptParams : Script command parameters
[in] SrcSystemVolName : Source system volume name
[in] osVersion : OS version information
[in] IsPowerShellScript : Is the bootup script is a powershell script.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegAddBootUpScript(const std::string& BootupScriptRegKeyPath,
const std::string& Script,
const std::string& ScriptParams,
const std::string& SrcSystemVolName,
const OSVersion& osVersion,
bool IsPowerShellScript)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
BOOST_ASSERT(!BootupScriptRegKeyPath.empty());
BOOST_ASSERT(!Script.empty());
do
{
CRegKey bootupScriptKey;
//
// Set script and its parameters under BootupScriptRegKeyPath key
//
lRetStatus = bootupScriptKey.Create( HKEY_LOCAL_MACHINE,
BootupScriptRegKeyPath.c_str(),
0,
REG_OPTION_NON_VOLATILE );
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not create reg key %s. Error %ld\n",
BootupScriptRegKeyPath.c_str(),
lRetStatus );
break;
}
std::map<std::string, std::string> mapStringValues;
mapStringValues[RegistryConstants::VALUE_NAME_SOM_ID] = "Local";
mapStringValues[RegistryConstants::VALUE_NAME_GPO_ID] = "LocalGPO";
mapStringValues[RegistryConstants::VALUE_NAME_GPONAME] = "Local Group Policy";
mapStringValues[RegistryConstants::VALUE_NAME_DISAPLAYNAME] = "Local Group Policy";
mapStringValues[RegistryConstants::VALUE_NAME_FILESYSPATH] = SrcSystemVolName +
std::string("Windows\\System32\\GroupPolicy\\Machine");
lRetStatus = RegSetStringValues(bootupScriptKey, mapStringValues);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not set all string values under the registry key %s.\n",
BootupScriptRegKeyPath.c_str());
break;
}
if (osVersion >= OSVersion(6, 1))
{
//
// Below key is required if the OS version is greater than or equla to 6.1
// (Windows Server 2008 R2)
//
std::map<std::string, DWORD> mapDWordValues;
mapDWordValues[RegistryConstants::VALUE_NAME_SCRIPT_ORDER] = 1;
lRetStatus = RegSetDWORDValues(bootupScriptKey, mapDWordValues);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not set all DWORD values under the registry key %s.\n",
BootupScriptRegKeyPath.c_str());
break;
}
}
bootupScriptKey.Flush();
bootupScriptKey.Close();
mapStringValues.clear();
//
// Set script and its parameters under BootupScriptRegKeyPath\0 subkey
//
std::string BootupScriptRegKeySubPath = BootupScriptRegKeyPath + "\\0";
lRetStatus = bootupScriptKey.Create(HKEY_LOCAL_MACHINE,
BootupScriptRegKeySubPath.c_str(),
0,
REG_OPTION_NON_VOLATILE);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not create reg key %s. Error %ld\n",
BootupScriptRegKeySubPath.c_str(),
lRetStatus);
break;
}
mapStringValues[RegistryConstants::VALUE_NAME_SCRIPT] = Script;
mapStringValues[RegistryConstants::VALUE_NAME_SCRIPT_PARAMS] = ScriptParams;
lRetStatus = RegSetStringValues(bootupScriptKey, mapStringValues);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not set all string values under the registry key %s.\n",
BootupScriptRegKeyPath.c_str());
break;
}
if (osVersion >= OSVersion(6,1))
{
//
// Below key is required if the OS version is greater than or equla to 6.1
// (Windows Server 2008 R2)
//
std::map<std::string, DWORD> mapDWordValues;
mapDWordValues[RegistryConstants::VALUE_NAME_IS_POWERSHELL] = IsPowerShellScript ? 1 : 0;
lRetStatus = RegSetDWORDValues(bootupScriptKey, mapDWordValues);
if (ERROR_SUCCESS != lRetStatus)
{
TRACE_ERROR("Could not set all DWORD values under the registry key %s.\n",
BootupScriptRegKeySubPath.c_str());
break;
}
}
bootupScriptKey.Flush();
} while (false);
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegGetSVSystemDWORDValue
Description : Wrapper function to get DWORD value under "SV Systems" registry key.
Parameters : [in] valueName : Name of the registry value.
[in, out] valueData : Filled with DWORD value of valueName.
[in, Optional] relativeKeyPath : Relative key path under "SV Systems" key. Empty string
indicate that the valueName needs to update directly under "SV Systems" key.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetSVSystemDWORDValue(const std::string& valueName,
DWORD& valueData,
const std::string& relativeKeyPath)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
std::stringstream errorStream;
do
{
CRegKey svSystemsKey;
std::string svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X32)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
if (ERROR_FILE_NOT_FOUND == lRetStatus)
{
svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X64)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
}
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not open " << svSystemsPath
<< ". Error " << lRetStatus;
break;
}
lRetStatus = svSystemsKey.QueryDWORDValue(valueName.c_str(), valueData);
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not get "
<< valueName
<< " value under the key " << svSystemsPath
<< ". Error " << lRetStatus;
}
} while (false);
if (ERROR_SUCCESS != lRetStatus)
{
SetLastErrorMsg(errorStream.str());
TRACE_ERROR("%s\n", errorStream.str().c_str());
}
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegSetSVSystemDWORDValue
Description : Wrapper function to set DWORD value under "SV Systems" registry key.
Parameters : [in] valueName : Name of the registry value.
[in] valueData : Data to be set to the registry value.
[in, Optional] relativeKeyPath : Relative key path under "SV Systems" key. Empty string
indicate that the valueName needs to update directly under "SV Systems" key.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegSetSVSystemDWORDValue(const std::string& valueName,
DWORD valueData,
const std::string& relativeKeyPath)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
std::stringstream errorStream;
do
{
CRegKey svSystemsKey;
std::string svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X32)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
if (ERROR_FILE_NOT_FOUND == lRetStatus)
{
svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X64)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
}
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not open " << svSystemsPath
<< ". Error " << lRetStatus;
break;
}
lRetStatus = svSystemsKey.SetDWORDValue(valueName.c_str(), valueData);
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not set "
<< valueName << " = " << valueData
<< " value under the key " << svSystemsPath
<< ". Error " << lRetStatus;
}
} while (false);
if (ERROR_SUCCESS != lRetStatus)
{
SetLastErrorMsg(errorStream.str());
TRACE_ERROR("%s\n", errorStream.str().c_str());
}
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegSetSVSystemStringValue
Description : Wrapper function to set String/MultiString value under "SV Systems" registry key.
Parameters : [in] valueName : Name of the registry value.
[in] valueData : Data to be set to the registry value.
[in, Optional] isMultiString : Pass true if the registry value is multustring, othewise false
[in, Optional] relativeKeyPath : Relative key path under "SV Systems" key. Empty string
indicate that the valueName needs to update directly under "SV Systems" key.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegSetSVSystemStringValue(const std::string& valueName,
const std::string& valueData,
bool isMultiString,
const std::string& relativeKeyPath)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
std::stringstream errorStream;
do
{
CRegKey svSystemsKey;
std::string svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X32)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
if (ERROR_FILE_NOT_FOUND == lRetStatus)
{
svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X64)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
}
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not open " << svSystemsPath
<< ". Error " << lRetStatus;
break;
}
lRetStatus = isMultiString ?
svSystemsKey.SetMultiStringValue(valueName.c_str(), valueData.c_str()) :
svSystemsKey.SetStringValue(valueName.c_str(), valueData.c_str() );
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not set "
<< valueName << " = " << valueData
<< " value under the key " << svSystemsPath
<< ". Error " << lRetStatus;
}
} while (false);
if (ERROR_SUCCESS != lRetStatus)
{
SetLastErrorMsg(errorStream.str());
TRACE_ERROR("%s\n", errorStream.str().c_str());
}
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegGetSVSystemStringValue
Description : Wrapper function to Get String value under "SV Systems" registry key.
Parameters : [in] valueName : Name of the registry value.
[out] valueData : Registry value data will be filled in it on success.
[in, Optional] relativeKeyPath : Relative key path under "SV Systems" key. Empty string
indicate that the valueName needs to update directly under "SV Systems" key.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetSVSystemStringValue(const std::string& valueName,
std::string& valueData,
const std::string& relativeKeyPath)
{
TRACE_FUNC_BEGIN;
LONG lRetStatus = ERROR_SUCCESS;
std::stringstream errorStream;
do
{
CRegKey svSystemsKey;
std::string svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X32)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
if (ERROR_FILE_NOT_FOUND == lRetStatus)
{
svSystemsPath = RegistryConstants::VM_SOFTWARE_HIVE_NAME
+ std::string(RegistryConstants::INMAGE_SV_SYSTEMS_X64)
+ (relativeKeyPath.empty() ? "" : relativeKeyPath);
lRetStatus = svSystemsKey.Open(HKEY_LOCAL_MACHINE, svSystemsPath.c_str());
}
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not open " << svSystemsPath
<< ". Error " << lRetStatus;
break;
}
lRetStatus = RegGetStringValue(svSystemsKey.m_hKey,valueName,valueData);
if (ERROR_SUCCESS != lRetStatus)
{
errorStream << "Could not get "
<< valueName
<< " value under the key " << svSystemsPath
<< ". Error " << lRetStatus;
}
} while (false);
if (ERROR_SUCCESS != lRetStatus)
{
SetLastErrorMsg(errorStream.str());
TRACE_ERROR("%s\n", errorStream.str().c_str());
}
TRACE_FUNC_END;
return lRetStatus;
}
/*
Method : RegGetCurrentControlSetValue
Description : Gets the current control.
Parameters : [in] systemHiveName : Name of the system hive.
[out] dwValue : Filled with current controlset number.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetCurrentControlSetValue(const std::string& systemHiveName, DWORD & dwValue)
{
LONG retStatus = ERROR_SUCCESS;
std::string keyPath = systemHiveName +
DIRECOTRY_SEPERATOR + RegistryConstants::SYSTEM_SELECT_KEY;
do{
TRACE_INFO("Registry path %s\n", keyPath.c_str());
CRegKey selectKey;
retStatus = selectKey.Open(HKEY_LOCAL_MACHINE, keyPath.c_str(), KEY_READ);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not open the registry key %s. Error %ld\n", keyPath.c_str(), retStatus);
break;
}
//
// Get the existing DWORD value
//
retStatus = selectKey.QueryDWORDValue(RegistryConstants::VALUE_NAME_CURRENT, dwValue);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not query the Current DWORD value under %s. Error %ld\n",
keyPath.c_str(),
retStatus);
break;
}
TRACE_INFO("The Current Control set is %lu.\n", dwValue);
} while (false);
TRACE_FUNC_END;
return retStatus;
}
/*
Method : RegGetLastKnownGoodControlSetValue
Description : Gets the LastKnownGood control number.
Parameters : [in] systemHiveName : Name of the system hive.
[out] dwValue : Filled with current controlset number.
Return code : ERROR_SUCCESS -> on success
win32 error -> on failure.
*/
LONG RegGetLastKnownGoodControlSetValue(const std::string& systemHiveName, DWORD & dwValue)
{
LONG retStatus = ERROR_SUCCESS;
std::string keyPath = systemHiveName +
DIRECOTRY_SEPERATOR + RegistryConstants::SYSTEM_SELECT_KEY;
do {
TRACE_INFO("Registry path %s\n", keyPath.c_str());
CRegKey selectKey;
retStatus = selectKey.Open(HKEY_LOCAL_MACHINE, keyPath.c_str(), KEY_READ);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not open the registry key %s. Error %ld\n", keyPath.c_str(), retStatus);
break;
}
//
// Get the existing DWORD value
//
retStatus = selectKey.QueryDWORDValue(RegistryConstants::VALUE_NAME_LASTKNOWNGOOD, dwValue);
if (ERROR_SUCCESS != retStatus)
{
TRACE_ERROR("Could not query the last known good DWORD value under %s. Error %ld\n",
keyPath.c_str(),
retStatus);
break;
}
TRACE_INFO("The last known good set is %lu.\n", dwValue);
} while (false);
TRACE_FUNC_END;
return retStatus;
}
}