Ejemplo n.º 1
0
//////////////////////////////////////////////////////////
//
// ValidateGTAPath
//
// Check GTA path looks good
//
//////////////////////////////////////////////////////////
void ValidateGTAPath( void )
{
    // Get path to GTA
    ePathResult iResult = DiscoverGTAPath( true );
    if ( iResult == GAME_PATH_MISSING ) {
        DisplayErrorMessageBox ( _("Registry entries are missing. Please reinstall Multi Theft Auto: San Andreas."), _E("CL12"), "reg-entries-missing" );
        return ExitProcess( EXIT_ERROR );
    }
    else if ( iResult == GAME_PATH_UNICODE_CHARS ) {
        DisplayErrorMessageBox ( _("The path to your installation of GTA: San Andreas contains unsupported (unicode) characters. Please move your Grand Theft Auto: San Andreas installation to a compatible path that contains only standard ASCII characters and reinstall Multi Theft Auto: San Andreas."), _E("CL13") );
        return ExitProcess( EXIT_ERROR );
    }
    else if ( iResult == GAME_PATH_STEAM ) {
        DisplayErrorMessageBox ( _("It appears you have a Steam version of GTA:SA, which is currently incompatible with MTASA.  You are now being redirected to a page where you can find information to resolve this issue."), _E("CL14") );
        BrowseToSolution ( "downgrade-steam" );
        return ExitProcess( EXIT_ERROR );
    }

    SString strGTAPath = GetGTAPath();

    // We can now set this
    SetCurrentDirectory ( strGTAPath );

    const SString strMTASAPath = GetMTASAPath ();
    if ( strGTAPath.Contains ( ";" ) || strMTASAPath.Contains ( ";" ) )
    {
        DisplayErrorMessageBox (_( "The path to your installation of 'MTA:SA' or 'GTA: San Andreas'\n"
                                   "contains a ';' (semicolon).\n\n"
                                   " If you experience problems when running MTA:SA,\n"
                                   " move your installation(s) to a path that does not contain a semicolon." ), _E("CL15"), "path-semicolon" );
    }
}
Ejemplo n.º 2
0
//////////////////////////////////////////////////////////
//
// CheckOnRestartCommand
//
// Changes current directory if required
//
//////////////////////////////////////////////////////////
SString CheckOnRestartCommand ( void )
{
    const SString strMTASAPath = GetMTASAPath ();

    SetCurrentDirectory ( strMTASAPath );
    SetDllDirectory( strMTASAPath );

    SString strOperation, strFile, strParameters, strDirectory, strShowCmd;
    if ( GetOnRestartCommand ( strOperation, strFile, strParameters, strDirectory, strShowCmd ) )
    {
        if ( strOperation == "files" || strOperation == "silent" )
        {
            //
            // Update
            //

            // Make temp path name and go there
            SString strArchivePath, strArchiveName;
            strFile.Split ( "\\", &strArchivePath, &strArchiveName, -1 );

            SString strTempPath = MakeUniquePath ( strArchivePath + "\\_" + strArchiveName + "_tmp_" );

            if ( !MkDir ( strTempPath ) )
                return "FileError1";

            if ( !SetCurrentDirectory ( strTempPath ) )
                return "FileError2";

            // Start progress bar
            if ( !strParameters.Contains( "hideprogress" ) )
               StartPseudoProgress( g_hInstance, "MTA: San Andreas", _("Extracting files...") );

            // Try to extract the files
            if ( !ExtractFiles ( strFile ) )
            {
                // If extract failed and update file is an exe, try to run it
                if ( ExtractExtension ( strFile ).CompareI ( "exe" ) )
                    ShellExecuteBlocking ( "open", strFile, "-s" );
            }

            // Stop progress bar
            StopPseudoProgress();

            // If a new "Multi Theft Auto.exe" exists, let that complete the install
            if ( FileExists ( MTA_EXE_NAME_RELEASE ) )
                return "install from far " + strOperation + " " + strParameters;

            // Otherwise use the current exe to install
            return "install from near " + strOperation + " " + strParameters;
        }
        else
        {
            AddReportLog ( 5052, SString ( "CheckOnRestartCommand: Unknown restart command %s", strOperation.c_str () ) );
        }
    }
    return "no update";
}
Ejemplo n.º 3
0
//////////////////////////////////////////////////////////
//
// CheckDataFiles
//
// Basic check for some essential files
//
//////////////////////////////////////////////////////////
void CheckDataFiles( void )
{
    const SString strMTASAPath = GetMTASAPath();
    const SString strGTAPath = GetGTAPath();

    const char* dataFilesFiles [] = { "MTA\\cgui\\images\\background_logo.png"
                                     ,"MTA\\cgui\\images\\radarset\\up.png"
                                     ,"MTA\\cgui\\images\\busy_spinner.png"
                                     ,"MTA\\cgui\\images\\rect_edge.png"
                                     ,"MTA\\D3DX9_42.dll"
                                     ,"MTA\\D3DCompiler_42.dll"
                                     ,"MTA\\bass.dll"
                                     ,"MTA\\bass_fx.dll"
                                     ,"MTA\\tags.dll"
                                     ,"MTA\\sa.dat"
                                     ,"MTA\\XInput9_1_0_mta.dll"
                                     ,"MTA\\vea.dll"};

    for ( uint i = 0 ; i < NUMELMS( dataFilesFiles ) ; i++ )
    {
        if ( !FileExists ( PathJoin( strMTASAPath, dataFilesFiles [ i ] ) ) )
        {
            DisplayErrorMessageBox ( _("Load failed. Please ensure that the latest data files have been installed correctly."), _E("CL16"), "mta-datafiles-missing" );
            return ExitProcess( EXIT_ERROR );
        }
    }

    if ( FileSize ( PathJoin( strMTASAPath, "MTA", "bass.dll" ) ) != 0x0001A440 )
    {
        DisplayErrorMessageBox ( _("Load failed. Please ensure that the latest data files have been installed correctly."), _E("CL17"), "mta-datafiles-missing" );
        return ExitProcess( EXIT_ERROR );
    }

    // Check for client file
    if ( !FileExists ( PathJoin( strMTASAPath, CHECK_DM_CLIENT_NAME ) ) )
    {
        DisplayErrorMessageBox ( SString(_("Load failed. Please ensure that %s is installed correctly."),CHECK_DM_CLIENT_NAME), _E("CL18"), "client-missing" );
        return ExitProcess( EXIT_ERROR );
    }

    // Make sure the gta executable exists
    if ( !FileExists( PathJoin( strGTAPath, MTA_GTAEXE_NAME ) ) )
    {
        DisplayErrorMessageBox ( SString ( _("Load failed. Could not find gta_sa.exe in %s."), strGTAPath.c_str () ), _E("CL20"), "gta_sa-missing" );
        return ExitProcess( EXIT_ERROR );
    }

    // Make sure important dll's do not exist in the wrong place
    const char* dllCheckList[] = { "xmll.dll", "cgui.dll", "netc.dll", "libcurl.dll", "pthread.dll" };
    for ( int i = 0 ; i < NUMELMS ( dllCheckList ); i++ )
    {
        if ( FileExists( PathJoin( strGTAPath, dllCheckList[i] ) ) )
        {
            DisplayErrorMessageBox ( SString ( _("Load failed. %s exists in the GTA directory. Please delete before continuing."), dllCheckList[i] ), _E("CL21"), "file-clash" );
            return ExitProcess( EXIT_ERROR );
        }    
    }

    // Check main exe has the correct name
    if ( GetLaunchFilename().CompareI( MTA_EXE_NAME ) == false )
    {
        SString strMessage( _("Main file has an incorrect name (%s)"), *GetLaunchFilename() );
        int iResponse = MessageBoxUTF8 ( NULL, strMessage, _("Error")+_E("CL33"), MB_RETRYCANCEL | MB_ICONERROR | MB_TOPMOST  );
        ReleaseSingleInstanceMutex ();
        if ( iResponse == IDRETRY )
            ShellExecuteNonBlocking( "open", PathJoin ( strMTASAPath, MTA_EXE_NAME ) );            
        return ExitProcess( EXIT_ERROR );
    }

    // Check for possible virus file changing activities
    if ( !VerifyEmbeddedSignature( PathJoin( strMTASAPath, MTA_EXE_NAME ) ) )
    {
        SString strMessage( _("Main file is unsigned. Possible virus activity.\n\nSee online help if MTA does not work correctly.") );
        #if MTASA_VERSION_BUILD > 0 && defined(MTA_DM_CONNECT_TO_PUBLIC) && !defined(MTA_DEBUG)
            DisplayErrorMessageBox( strMessage, _E("CL29"), "maybe-virus1" );
        #endif
    }

    struct {
        const char* szMd5;
        const char* szFilename;
    } integrityCheckList[] = { { "9586E7BE6AE8016932038932D1417241", "bass.dll", },
                               { "B2E49F0C22C8B7D92D615F942BA19353", "bass_aac.dll", },
                               { "569C60F8397C34034E685A303B7404C0", "bass_ac3.dll", },
                               { "0E44BCAC0E940DB2BFB13448E96E4B29", "bass_fx.dll", },
                               { "50AF8A7D49E83A723ED0F70FB682DCFB", "bassflac.dll", },
                               { "BEBA64522AA8265751187E38D1FC0653", "bassmidi.dll", },
                               { "99F4F38007D347CEED482B7C04FDD122", "bassmix.dll", },
                               { "7B52BE6D702AA590DB57A0E135F81C45", "basswma.dll", }, 
                               { "38D7679D3B8B6D7F16A0AA9BF2A60043", "tags.dll", },
                               { "309D860FC8137E5FE9E7056C33B4B8BE", "vea.dll", },
                               { "0602F672BA595716E64EC4040E6DE376", "vog.dll", },
                               { "B37D7DF4A1430DB65AD3EA84801F9EC3", "vvo.dll", },
                               { "47FF3EE45DE53528F1AFD9F5982DF8C7", "vvof.dll", },
                               { "ADFB6D7B61E301761C700652B6FE7CCD", "XInput9_1_0_mta.dll", }, };
    for ( int i = 0 ; i < NUMELMS ( integrityCheckList ); i++ )
    {
        SString strMd5 = CMD5Hasher::CalculateHexString( PathJoin( strMTASAPath, "mta", integrityCheckList[i].szFilename ) );
        if ( !strMd5.CompareI( integrityCheckList[i].szMd5 ) )
        {
            DisplayErrorMessageBox( _("Data files modified. Possible virus activity.\n\nSee online help if MTA does not work correctly."), _E("CL30"), "maybe-virus2" );
            break;
        }    
    }

    // Check for asi files
    {
        bool bFoundInGTADir = !FindFiles( PathJoin( strGTAPath, "*.asi" ), true, false ).empty();
        bool bFoundInMTADir = !FindFiles( PathJoin( strMTASAPath, "mta", "*.asi" ), true, false ).empty();
        if ( bFoundInGTADir || bFoundInMTADir )
        {
            DisplayErrorMessageBox (_( ".asi files are in the 'MTA:SA' or 'GTA: San Andreas' installation directory.\n\n"
                                       "Remove these .asi files if you experience problems with MTA:SA." ), _E("CL28"), "asi-files" );
        }
    }

    // Warning if d3d9.dll exists in the GTA install directory
    if ( FileExists( PathJoin ( strGTAPath, "d3d9.dll" ) ) )
    {
        ShowD3dDllDialog ( g_hInstance, PathJoin ( strGTAPath, "d3d9.dll" ) );
        HideD3dDllDialog ();
    }

    // Remove old log files saved in the wrong place
    SString strMtaDir = PathJoin( strMTASAPath, "mta" );
    if ( strGTAPath.CompareI( strMtaDir ) == false )
    {
        FileDelete( PathJoin( strGTAPath, "CEGUI.log" ) );
        FileDelete( PathJoin( strGTAPath, "logfile.txt" ) );
        FileDelete( PathJoin( strGTAPath, "shutdown.log" ) );
    }
}
Ejemplo n.º 4
0
//////////////////////////////////////////////////////////
//
// InitLocalization
//
// Start localization thingmy
//
//////////////////////////////////////////////////////////
void InitLocalization( bool bNoFail )
{
    static bool bDone = false;
    if ( bDone )
        return;

    // Check for and load core.dll for localization
    // Use launch relative path so core.dll can get updated
    SString strCoreDLL = PathJoin( GetLaunchPath(), "mta", MTA_DLL_NAME );
    if ( !FileExists ( strCoreDLL ) )
    {
        if ( !bNoFail )
            return;
        DisplayErrorMessageBox ( ("Load failed.  Please ensure that "
                            "the file core.dll is in the modules "
                            "directory within the MTA root directory."), _E("CL23"), "core-missing" ); // Core.dll missing

        return ExitProcess( EXIT_ERROR );
    }

    // Use registry setting of mta path for dlls, as they will not be present in update files
    const SString strMTASAPath = GetMTASAPath ();
    SetDllDirectory( PathJoin( strMTASAPath, "mta" ) );

    // See if xinput is loadable (XInput9_1_0.dll is core.dll dependency)
    HMODULE hXInputModule = LoadLibrary( "XInput9_1_0.dll" );
    if ( hXInputModule )
        FreeLibrary( hXInputModule );
    else
    {
        // If not, do hack to use dll supplied with MTA
        SString strDest = PathJoin( strMTASAPath, "mta", "XInput9_1_0.dll" );
        if ( !FileExists( strDest ) )
        {
            SString strSrc = PathJoin( strMTASAPath, "mta", "XInput9_1_0_mta.dll" );       
            FileCopy( strSrc, strDest );
        }
    }

    // Check if the core can be loaded - failure may mean msvcr90.dll or d3dx9_40.dll etc is not installed
    HMODULE hCoreModule = LoadLibrary( strCoreDLL );
    if ( hCoreModule == NULL )
    {
        if ( !bNoFail )
            return;
        DisplayErrorMessageBox ( ("Loading core failed.  Please ensure that \n"
                            "Microsoft Visual C++ 2008 SP1 Redistributable Package (x86) \n"
                            "and the latest DirectX is correctly installed."), _E("CL24"), "vc-redist-missing" );  // Core.dll load failed.  Ensure VC++ Redists and DX are installed
        return ExitProcess( EXIT_ERROR );
    }

    // Grab our locale from the registry if possible, if not Windows
    SString strLocale = GetApplicationSetting ( "locale" );
    if ( strLocale.empty() )
    {
        setlocale(LC_ALL, "");
        char* szLocale = setlocale(LC_ALL, NULL);
        strLocale = szLocale;
    }

    typedef CLocalizationInterface* (__cdecl *FUNC_CREATELOCALIZATIONFROMENVIRONMENT)(SString strLocale);
    FUNC_CREATELOCALIZATIONFROMENVIRONMENT pFunc = (FUNC_CREATELOCALIZATIONFROMENVIRONMENT)GetProcAddress ( hCoreModule, "L10n_CreateLocalization" );
    CLocalizationInterface* pLocalization = pFunc(strLocale);
    if ( pLocalization == NULL )
    {
        if ( !bNoFail )
            return;

        DisplayErrorMessageBox ( ("Loading core failed.  Please ensure that \n"
                            "Microsoft Visual C++ 2008 SP1 Redistributable Package (x86) \n"
                            "and the latest DirectX is correctly installed."), _E("CL26"), "vc-redist-missing" );  // Core.dll load failed.  Ensure VC++ Redists and DX are installed
        FreeLibrary ( hCoreModule );
        return ExitProcess( EXIT_ERROR );
    }

    SAFE_DELETE( g_pLocalization );
    g_pLocalization = pLocalization;
    bDone = true;

#ifdef MTA_DEBUG
    TestDialogs();
#endif
}
Ejemplo n.º 5
0
//////////////////////////////////////////////////////////
//
// HandleDuplicateLaunching
//
// Handle duplicate launching, or running from mtasa:// URI ?
//
//////////////////////////////////////////////////////////
void HandleDuplicateLaunching( void )
{
    LPSTR lpCmdLine = GetCommandLine();

    int iRecheckTimeLimit = 2000;
    while ( ! CreateSingleInstanceMutex () )
    {
        if ( strcmp ( lpCmdLine, "" ) != 0 )
        {
            HWND hwMTAWindow = FindWindow( NULL, "MTA: San Andreas" );
#ifdef MTA_DEBUG
            if( hwMTAWindow == NULL )
                hwMTAWindow = FindWindow( NULL, "MTA: San Andreas [DEBUG]" );
#endif
            if( hwMTAWindow != NULL )
            {
                LPWSTR szCommandLine = GetCommandLineW ();
                int numArgs;
                LPWSTR* aCommandLineArgs = CommandLineToArgvW ( szCommandLine, &numArgs );
                for ( int i = 0; i < numArgs; ++i )
                {
                    if ( StrCmpW ( aCommandLineArgs[i], L"-c" ) == 0 && numArgs > i )
                    {
                        WString wideConnectInfo = aCommandLineArgs[i + 1];
                        SString strConnectInfo = ToUTF8 ( wideConnectInfo );

                        COPYDATASTRUCT cdStruct;
                        cdStruct.cbData = strConnectInfo.length () + 1;
                        cdStruct.lpData = const_cast<char *> ( strConnectInfo.c_str () );
                        cdStruct.dwData = URI_CONNECT;

                        SendMessage( hwMTAWindow, WM_COPYDATA, NULL, (LPARAM)&cdStruct );
                        break;
                    }
                }

                
            }
            else
            {
                if ( iRecheckTimeLimit > 0 )
                {
                    // Sleep a little bit and check the mutex again
                    Sleep ( 500 );
                    iRecheckTimeLimit -= 500;
                    continue;
                }
                SString strMessage;
                strMessage += _(    "Trouble restarting MTA:SA\n\n"
                                    "If the problem persists, open Task Manager and\n"
                                    "stop the 'gta_sa.exe' and 'Multi Theft Auto.exe' processes\n\n\n"
                                    "Try to launch MTA:SA again?" );
                if ( MessageBoxUTF8( 0, strMessage, _("Error")+_E("CL04"), MB_ICONWARNING | MB_YESNO | MB_TOPMOST  ) == IDYES ) // Trouble restarting MTA:SA
                {
                    TerminateGTAIfRunning ();
                    TerminateOtherMTAIfRunning ();
                    ShellExecuteNonBlocking( "open", PathJoin ( GetMTASAPath (), MTA_EXE_NAME ), lpCmdLine );
                }
                return ExitProcess( EXIT_ERROR );
            }
        }
        else
        {
            if ( !IsGTARunning () && !IsOtherMTARunning () )
            {
                MessageBoxUTF8 ( 0, _("Another instance of MTA is already running.\n\nIf this problem persists, please restart your computer"), _("Error")+_E("CL05"), MB_ICONERROR | MB_TOPMOST  );
            }
            else
            if ( MessageBoxUTF8( 0, _("Another instance of MTA is already running.\n\nDo you want to terminate it?"), _("Error")+_E("CL06"), MB_ICONQUESTION | MB_YESNO | MB_TOPMOST  ) == IDYES )
            {
                TerminateGTAIfRunning ();
                TerminateOtherMTAIfRunning ();
                ShellExecuteNonBlocking( "open", PathJoin ( GetMTASAPath (), MTA_EXE_NAME ), lpCmdLine );
            }
        }
        return ExitProcess( EXIT_ERROR );
    }
}
Ejemplo n.º 6
0
///////////////////////////////////////////////////////////////
//
// DoInstallFiles
//
// Copy directory tree at current dirctory to GetMTASAPath ()
//
///////////////////////////////////////////////////////////////
bool DoInstallFiles ( void )
{
    SString strCurrentDir = PathConform ( GetSystemCurrentDirectory () );

    const SString strMTASAPath = PathConform ( GetMTASAPath () );

    SString path1, path2;
    strCurrentDir.Split ( "\\", &path1, &path2, -1 );

    SString strDestRoot = strMTASAPath;
    SString strSrcRoot = strCurrentDir;
    SString strBakRoot = MakeUniquePath ( strCurrentDir + "_bak_" );

    // Clean backup dir
    if ( !MkDir ( strBakRoot ) )
    {
        AddReportLog ( 5020, SString ( "InstallFiles: Couldn't make dir '%s'", strBakRoot.c_str () ) );
        return false;
    }

    // Get list of files to install
    std::vector < SFileItem > itemList;
    {
        std::vector < SString > fileList;
        FindFilesRecursive ( PathJoin ( strCurrentDir, "*" ), fileList );
        for ( unsigned int i = 0 ; i < fileList.size () ; i++ )
        {
            SFileItem item;
            item.strSrcPathFilename = PathConform ( fileList[i] );
            item.strDestPathFilename = PathConform ( fileList[i].Replace ( strSrcRoot, strDestRoot ) );
            item.strBackupPathFilename = PathConform ( fileList[i].Replace ( strSrcRoot, strBakRoot ) );
            itemList.push_back ( item );
        }
    }

    // See if any files to be updated are running.
    // If so, terminate them
    for ( unsigned int i = 0 ; i < itemList.size () ; i++ )
    {
        SString strFile = itemList[i].strDestPathFilename;
        if ( strFile.EndsWithI( ".exe" ) )
            TerminateProcessFromPathFilename ( strFile );
    }

    // Copy current(old) files into backup location
    for ( unsigned int i = 0 ; i < itemList.size () ; i++ )
    {
        const SFileItem& item = itemList[i];
        if ( !FileCopy ( item.strDestPathFilename, item.strBackupPathFilename ) )
        {
            if ( FileExists ( item.strDestPathFilename ) )
            {
                AddReportLog ( 5021, SString ( "InstallFiles: Couldn't backup '%s' to '%s'", *item.strDestPathFilename, *item.strBackupPathFilename ) );
                return false;
            }
            AddReportLog ( 4023, SString ( "InstallFiles: Couldn't backup '%s' as it does not exist", *item.strDestPathFilename ) );
        }
    }

    // Try copy new files
    bool bOk = true;
    std::vector < SFileItem > fileListSuccess;
    for (  unsigned int i = 0 ; i < itemList.size () ; i++ )
    {
        const SFileItem& item = itemList[i];
        if ( !FileCopy ( item.strSrcPathFilename, item.strDestPathFilename ) )
        {
            // If copy failed, check if we really need to copy the file
            if ( GenerateSha256HexStringFromFile( item.strSrcPathFilename ) != GenerateSha256HexStringFromFile( item.strDestPathFilename ) )
            {
                AddReportLog ( 5022, SString ( "InstallFiles: Couldn't copy '%s' to '%s'", *item.strSrcPathFilename, *item.strDestPathFilename ) );
                bOk = false;
                break;
            }
        }
        fileListSuccess.push_back ( item );
    }

    // If fail, copy back old files
    if ( !bOk )
    {
        bool bPossibleDisaster = false;
        for ( unsigned int i = 0 ; i < fileListSuccess.size () ; i++ )
        {
            const SFileItem& item = fileListSuccess[i];
            int iRetryCount = 3;
            while ( true )
            {
                if ( FileCopy ( item.strBackupPathFilename, item.strDestPathFilename ) )
                    break;

                // If copy failed, check if we really need to copy the file
                if ( GenerateSha256HexStringFromFile( item.strBackupPathFilename ) != GenerateSha256HexStringFromFile( item.strDestPathFilename ) )
                    break;

                if ( !--iRetryCount )
                {
                    AddReportLog ( 5023, SString ( "InstallFiles: Possible disaster restoring '%s' to '%s'", *item.strBackupPathFilename, *item.strDestPathFilename ) );
                    bPossibleDisaster = true;
                    break;
                }
            }
        }

        //if ( bPossibleDisaster )
        //    MessageBox ( NULL, _("Installation may be corrupt. Please redownload from www.mtasa.com"), _("Error"), MB_OK | MB_ICONERROR );
        //else 
        //    MessageBox ( NULL, _("Could not update due to file conflicts."), _("Error"), MB_OK | MB_ICONERROR );
    }

    // Launch MTA_EXE_NAME
    return bOk;
}
Ejemplo n.º 7
0
//////////////////////////////////////////////////////////
//
// CInstallManager::GetLauncherPathFilename
//
// Get path to launch exe
//
//////////////////////////////////////////////////////////
SString CInstallManager::GetLauncherPathFilename ( void )
{
    SString strLocation = m_pSequencer->GetVariable ( INSTALL_LOCATION );
    SString strResult = PathJoin ( strLocation == "far" ? GetSystemCurrentDirectory () : GetMTASAPath (), MTA_EXE_NAME );
    AddReportLog ( 1062, SString ( "GetLauncherPathFilename %s", *strResult ) );
    return strResult;
}
Ejemplo n.º 8
0
//////////////////////////////////////////////////////////
//
// CInstallManager::Continue
//
// Process next step
//
//////////////////////////////////////////////////////////
SString CInstallManager::Continue ( void )
{
    // Initial report line
    DWORD dwProcessId = GetCurrentProcessId();
    SString GotPathFrom = ( m_pSequencer->GetVariable ( INSTALL_LOCATION ) == "far" ) ? "registry" : "module location";
    AddReportLog ( 1041, SString ( "* Launch * pid:%d '%s' MTASAPath set from %s '%s'", dwProcessId, GetMTASAModuleFileName ().c_str (), GotPathFrom.c_str (), GetMTASAPath ().c_str () ) );

    // Run sequencer
    for ( int i = 0 ; !m_pSequencer->AtEnd () && i < 1000 ; i++ )
        m_pSequencer->ProcessNextLine ();

    // Remove unwanted files
    CleanDownloadCache ();

    // Extract command line launch args
    SString strCommandLineOut;
    for ( int i = 0 ; i < m_pSequencer->GetVariableInt ( "_argc" ) ; i++ )
        strCommandLineOut += m_pSequencer->GetVariable ( SString ( "_arg_%d", i ) ) + " ";

    AddReportLog ( 1060, SString ( "CInstallManager::Continue - return %s", *strCommandLineOut ) );
    return *strCommandLineOut.TrimEnd ( " " );
}