in host/AzureRecoveryLib/win32/RecoveryHelpers.cpp [2472:2618]
bool RegGetStartupScriptKeys(const OSVersion& winVer,
std::string& key1, std::string& key2,
DWORD& scriptNumber,
std::stringstream& errorSteam)
{
TRACE_FUNC_BEGIN;
bool bSuccess = true;
std::string strBootScriptKey1Prefix, strBootScriptKey2Prefix;
strBootScriptKey1Prefix = RegistryConstants::VM_SOFTWARE_HIVE_NAME + (
winVer > OSVersion(5, 2) ? // 5.2 --> Windows Server 2003
std::string(RegistryConstants::BOOTUP_SCRIPT_KEY1_2K8ABOVE) :
std::string(RegistryConstants::BOOTUP_SCRIPT_KEY1_2K8BELOW));
strBootScriptKey2Prefix = RegistryConstants::VM_SOFTWARE_HIVE_NAME +
std::string(RegistryConstants::BOOTUP_SCRIPT_KEY2);
try
{
//
// Check startup script number under sv-systems key, if not found then look for next available number.
// If the startup script number found under sv-systems key then verify the script name under startup script number key
// is matching with failover boot-up script name. If it is not matching then the script number might be stale and invalid
// and go for next available script number, if it is matching then reuse the same script number.
//
LONG lReturn = RegGetSVSystemDWORDValue(RegistryConstants::VALUE_NAME_BOOTUP_SCRIPT_ORDER_NUMBER, scriptNumber);
if (VERIFY_REG_STATUS(lReturn, "Could not read startup script order number"))
{
TRACE_INFO("Starup script number %lu found under SV-Systems key.\n", scriptNumber);
std::stringstream scriptKey1, scriptKey2;
scriptKey1 << strBootScriptKey1Prefix << scriptNumber;
scriptKey2 << strBootScriptKey2Prefix << scriptNumber;
std::string scriptNameFromKey1, scriptNameFromKey2;
if (RegKeyExists(HKEY_LOCAL_MACHINE, scriptKey1.str()))
{
CRegKey startupScriptKey;
lReturn = startupScriptKey.Open(HKEY_LOCAL_MACHINE, (scriptKey1.str() + "\\0").c_str());
if (VERIFY_REG_STATUS(lReturn, "Error opening " + scriptKey1.str()) &&
VERIFY_REG_STATUS(RegGetStringValue(startupScriptKey.m_hKey,
RegistryConstants::VALUE_NAME_SCRIPT, scriptNameFromKey1),
"Error accessing registry value Script under " + scriptKey1.str()))
{
TRACE_INFO("Script Name under %s key is %s\n",
scriptKey1.str().c_str(),
scriptNameFromKey1.c_str());
}
}
if (RegKeyExists(HKEY_LOCAL_MACHINE, scriptKey2.str()))
{
CRegKey startupScriptKey;
lReturn = startupScriptKey.Open(HKEY_LOCAL_MACHINE, (scriptKey2.str() + "\\0").c_str());
if (VERIFY_REG_STATUS(lReturn, "Error opening " + scriptKey2.str()) &&
VERIFY_REG_STATUS(RegGetStringValue(startupScriptKey.m_hKey,
RegistryConstants::VALUE_NAME_SCRIPT, scriptNameFromKey2),
"Error accessing registry value Script under " + scriptKey2.str()))
{
TRACE_INFO("Script Name under %s key is %s\n",
scriptKey2.str().c_str(),
scriptNameFromKey2.c_str());
}
}
if ((scriptNameFromKey1.empty() || boost::iends_with(scriptNameFromKey1, STARTUP_EXE_NAME)) &&
(scriptNameFromKey2.empty() || boost::iends_with(scriptNameFromKey2, STARTUP_EXE_NAME)))
{
TRACE_INFO("Reusing the existing startup script number %lu.\n", scriptNumber);
key1 = scriptKey1.str();
key2 = scriptKey2.str();
TRACE_FUNC_END;
return bSuccess;
}
else if (boost::iends_with(scriptNameFromKey1, STARTUP_EXE_NAME))
{
// One of the key is with STARTUP_EXE_NAME and other is with different name so clear the script value which has STARTUP_EXE_NAME.
CRegKey startupScriptKey;
lReturn = startupScriptKey.Open(HKEY_LOCAL_MACHINE, (scriptKey1.str() + "\\0").c_str());
VERIFY_REG_STATUS(lReturn, "Error clearing miss configured startup script key");
VERIFY_REG_STATUS(startupScriptKey.SetStringValue(RegistryConstants::VALUE_NAME_SCRIPT, ""),
"Error clearing miss configured startup script name");
TRACE_INFO("%s is miss configured. Finding out next available number.\n", scriptKey1.str().c_str());
}
else if (boost::iends_with(scriptNameFromKey2, STARTUP_EXE_NAME))
{
// One of the key is with STARTUP_EXE_NAME and other is with different name so clear the script value which has STARTUP_EXE_NAME.
CRegKey startupScriptKey;
lReturn = startupScriptKey.Open(HKEY_LOCAL_MACHINE, (scriptKey2.str() + "\\0").c_str());
VERIFY_REG_STATUS(lReturn, "Error clearing miss configured startup script key");
VERIFY_REG_STATUS(startupScriptKey.SetStringValue(RegistryConstants::VALUE_NAME_SCRIPT, ""),
"Error clearing miss configured startup script name");
TRACE_INFO("%s is miss configured. Finding out next available number.\n", scriptKey2.str().c_str());
}
else
{
TRACE_INFO("This number seems to be stale entry under SV-Systems key. Finding out next available number.\n");
}
}
//
// If script number is not found under SV-Systems then findout next available number.
//
bool bNextAvailableKeyFound = false;
for (int scriptOrderNum = 0;
scriptOrderNum < RegistryConstants::MAX_STARTUP_SCRIPT_SEARCH_LIMIT;
scriptOrderNum++)
{
std::stringstream scriptKey1, scriptKey2;
scriptKey1 << strBootScriptKey1Prefix << scriptOrderNum;
scriptKey2 << strBootScriptKey2Prefix << scriptOrderNum;
if (!RegKeyExists(HKEY_LOCAL_MACHINE, scriptKey1.str()) &&
!RegKeyExists(HKEY_LOCAL_MACHINE, scriptKey2.str()))
{
TRACE_INFO("Available next script order number is %d\n", scriptOrderNum);
key1 = scriptKey1.str();
key2 = scriptKey2.str();
scriptNumber = scriptOrderNum;
bNextAvailableKeyFound = true;
break;
}
}
if (!bNextAvailableKeyFound)
THROW_RECVRY_EXCEPTION("Reached max lookup limit for determining next available script order number.\n");
}
catch (const std::exception& exp)
{
errorSteam << "Could not determine the startup script order number." << std::endl
<< "Error details: " << exp.what();
bSuccess = false;
}
TRACE_FUNC_END;
return bSuccess;
}