bool RegGetStartupScriptKeys()

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;
    }