mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 13:17:49 +00:00
321 lines
12 KiB
C++
321 lines
12 KiB
C++
#pragma once
|
|
|
|
#include "commonresourceconstants.h"
|
|
#include "Maindialog.h"
|
|
|
|
#include <boost/enable_shared_from_this.hpp>
|
|
#include <boost/scoped_ptr.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <boost/function.hpp>
|
|
#include "boost/thread.hpp"
|
|
#include <fstream>
|
|
#include <vector>
|
|
#include "FileSystem.h"
|
|
#include "format_string.h"
|
|
#include <atlsync.h>
|
|
#include "Progress.h"
|
|
#include "SharedHelpers.h"
|
|
#include "FileDeployer.h"
|
|
#include "ComModule.h"
|
|
#include "InfluxDbHelper.h"
|
|
|
|
class Bootstrapper : public boost::enable_shared_from_this<Bootstrapper>, public IInstallerSite
|
|
{
|
|
boost::condition_variable done;
|
|
boost::mutex mut;
|
|
|
|
CHandle latestProcess; // A shared file that contains the PID of the latest instance of this module
|
|
const DWORD mainThreadId;
|
|
|
|
int windowDelay;
|
|
int cancelDelay;
|
|
bool editMode;
|
|
bool service;
|
|
bool force;
|
|
bool fullCheck;
|
|
bool isUninstall;
|
|
bool isFailIfNotUpToDate;
|
|
bool debug;
|
|
bool windowed;
|
|
bool dontStartApp;
|
|
bool perUser;
|
|
bool adminInstallDetected;
|
|
bool userCancelled;
|
|
bool isNop;
|
|
bool requestedInstall; // indicates that the -install command line flag was used
|
|
bool performedNewInstall;
|
|
bool performedUpdateInstall;
|
|
bool performedBootstrapperUpdateAndQuit;
|
|
time_t startTime;
|
|
time_t userCancelledTime;
|
|
DWORD startTickCounter;
|
|
int stage;
|
|
std::vector<std::string> errors;
|
|
unsigned long reportStatGuid;
|
|
|
|
std::string moduleVersionNumber; // The version number of this module
|
|
|
|
bool silentMode;
|
|
// only used if silentMode is true, which means we don't show dialog at all
|
|
CEvent robloxReady;
|
|
// this mean that bootstrapper should not run anything except preDeploy
|
|
bool noRun;
|
|
bool waitOnStart;
|
|
|
|
virtual std::string Type() = 0;
|
|
virtual std::string BinaryType() { return ""; }
|
|
std::string baseHost;
|
|
std::string installHost; // HTTP host for getting installation components
|
|
std::string installVersion; // version string of latest installer
|
|
std::string browserTrackerId; // passed in from website
|
|
int exitCode;
|
|
|
|
//will be used to track all versions of this component to do proper clean up
|
|
std::list<std::string> prevVersions;
|
|
|
|
int influxdbLottery;
|
|
|
|
std::wstring prevVersionRegKey();
|
|
std::wstring prevVersionValueKey(int index);
|
|
void loadPrevVersions();
|
|
void storePrevVersions();
|
|
|
|
void postData(std::fstream &data);
|
|
void LogMACaddress();
|
|
|
|
void showWindowAfterDelay()
|
|
{
|
|
{
|
|
boost::unique_lock<boost::mutex> lock(mut);
|
|
if (done.timed_wait(lock, boost::get_system_time() + boost::posix_time::time_duration(0, 0, windowDelay)))
|
|
return;
|
|
}
|
|
|
|
LOG_ENTRY1("Bootstrapper::showWindowAfterDelay showing window, thread id = %d", ::GetCurrentThreadId());
|
|
if (!this->isSilentMode())
|
|
{
|
|
dialog->ShowWindow(CMainDialog::WindowTimeDelayShow);
|
|
}
|
|
}
|
|
|
|
void showCancelAfterDelay()
|
|
{
|
|
{
|
|
boost::unique_lock<boost::mutex> lock(mut);
|
|
if (done.timed_wait(lock, boost::get_system_time() + boost::posix_time::time_duration(0, 0, cancelDelay)))
|
|
return;
|
|
}
|
|
dialog->ShowCancelButton(CMainDialog::CancelTimeDelayShow);
|
|
}
|
|
|
|
|
|
void userCancel();
|
|
void checkCancel();
|
|
|
|
bool isIEUpToDate();
|
|
void checkIEPrerequisit();
|
|
void checkDirectXPrerequisit();
|
|
bool isDirectXUpToDate();
|
|
void checkOSPrerequisit();
|
|
void checkCPUPrerequisit();
|
|
|
|
void parseCmdLine();
|
|
void run();
|
|
void install();
|
|
void uninstall();
|
|
void uninstall(bool isPerUser);
|
|
|
|
bool checkBootstrapperVersion();
|
|
void shutdownRobloxApp(std::wstring appExeName);
|
|
void checkDiskSpace();
|
|
bool shutdownProgress(int& time, int pos, int max);
|
|
void deleteVersionFolder(std::string version);
|
|
|
|
void setLatestProcess();
|
|
bool isLatestProcess();
|
|
|
|
void deleteVersionsDirectoryContents();
|
|
void forceUninstallMFCStudio();
|
|
void forceMFCStudioCleanup();
|
|
|
|
// If size is set to 0, size will not be included in the log.
|
|
// Reporting eventually boils down to http requests, which will be made
|
|
// with normal strings (not unicode strings), so this method also uses
|
|
// normal strings to that the caller will consider and handle unicode as needed.
|
|
void reportDurationAndSizeEvent(const char* category, const char* result, DWORD duration, DWORD size);
|
|
void reportFinishingHelper(const char* category, const char* result);
|
|
|
|
void ReportToInfluxDbImpl(const std::string& json);
|
|
|
|
virtual bool EarlyInstall(bool isUninstall) { return false; }
|
|
|
|
protected:
|
|
|
|
HINSTANCE hInstance;
|
|
HWND launchedAppHwnd;
|
|
|
|
boost::scoped_ptr<CMainDialog> dialog;
|
|
boost::scoped_ptr<FileDeployer> deployer;
|
|
CRegKey classesKey;
|
|
|
|
//TODO move this into client part
|
|
std::wstring robloxAppArgs; // If empty, then don't launch RobloxApp.exe
|
|
|
|
InfluxDb influxDb;
|
|
|
|
Bootstrapper(HINSTANCE hInstance);
|
|
|
|
static void dummyProgress(int pos, int max) {}
|
|
static void createDirectory(const TCHAR* dir);
|
|
|
|
void setStage(int s) { stage = s; }
|
|
bool isPerUser() const { return perUser; }
|
|
bool isDontStartApp() { return dontStartApp; }
|
|
CMainDialog *Dialog() { return dialog.get(); }
|
|
void setInstallVersion(std::string version) { installVersion = version; }
|
|
|
|
std::wstring GetSelfName() const;
|
|
|
|
virtual void initialize();
|
|
virtual void createDialog() {} ;
|
|
|
|
// lets make sure that this guy will be 100% client only (RCC won't run this code)
|
|
virtual HRESULT SheduleRobloxUpdater() { return S_OK; };
|
|
virtual HRESULT UninstallRobloxUpdater() { return S_OK; };
|
|
// will load settings from server
|
|
virtual void LoadSettings() {}
|
|
virtual bool CanRunBgTask() { return true; }
|
|
|
|
virtual void SetupInfluxDb();
|
|
virtual std::string InfluxDbUrl() { return ""; }
|
|
virtual std::string InfluxDbDatabase() { return ""; }
|
|
virtual std::string InfluxDbUser() { return ""; }
|
|
virtual std::string InfluxDbPassword() { return ""; }
|
|
virtual int InfluxDbReportHundredthsPercentage() { return 0; }
|
|
virtual int InfluxDbInstallHundredthsPercentage() { return 0; }
|
|
void ReportToInfluxDb(int throttle, const std::string& json, bool blocking = false);
|
|
void ReportInstallMetricsToInfluxDb(bool isUpdate, const std::string& result, const std::string& message);
|
|
|
|
virtual void SetupGoogleAnalytics() {}
|
|
virtual bool ValidateInstalledExeVersion() { return false; }
|
|
virtual bool IsInstalledVersionUptodate() { return true; }
|
|
|
|
virtual bool IsPreDeployOn() { return false; }
|
|
virtual bool NeedPreDeployRun() { return false; }
|
|
virtual void RunPreDeploy() {}
|
|
virtual bool ForceNoDialogMode() { return false; }
|
|
virtual bool GetLogChromeProtocolFix() { return false; }
|
|
virtual bool GetUseNewVersionFetch() { return false; }
|
|
virtual bool GetUseDataDomain() { return true; }
|
|
virtual bool CreateEdgeRegistry() { return true; }
|
|
virtual bool DeleteEdgeRegistry() { return false; }
|
|
|
|
std::string fetchVersionGuid(std::string product);
|
|
virtual std::string fetchVersionGuidFromWeb(std::string product);
|
|
void writeAppSettings();
|
|
|
|
void CreateProcess(const TCHAR* module, const TCHAR* args, PROCESS_INFORMATION& pi);
|
|
void RegisterElevationPolicy(const TCHAR* appName, const TCHAR* appPath);
|
|
void RegisterUninstall(const TCHAR *productName);
|
|
void RegisterProtocolHandler(const std::wstring& protocolScheme, const std::wstring& exePath, const std::wstring& installKeyRegPath);
|
|
void UnregisterProtocolHandler(const std::wstring& protocolScheme);
|
|
bool isInstalled(std::wstring productKey);
|
|
void CreateShortcuts(bool forceDesktopIconCreation, const TCHAR *linkName, const TCHAR *exeName, const TCHAR *params);
|
|
void DeleteOldVersionsDirectories();
|
|
void DoDeployComponents(const std::vector<std::pair<std::wstring, std::wstring> > &files, bool isUpdating, bool commitData);
|
|
|
|
bool deleteDirectory(const std::wstring &refcstrRootDirectory, bool childrenOnly = false);
|
|
std::string queryInstalledInstallHost();
|
|
|
|
std::string queryInstalledVersion(const std::wstring& RegistryPath);
|
|
std::string queryInstalledVersion() { return queryInstalledVersion(GetRegistryPath()); }
|
|
|
|
std::wstring getInstalledBootstrapperPath(const std::wstring& RegistryPath);
|
|
std::wstring getInstalledBootstrapperPath() { return getInstalledBootstrapperPath(GetRegistryPath()); }
|
|
|
|
void deploySelf(bool commitData);
|
|
void message(const std::string& message);
|
|
|
|
void deleteLegacyShortcuts();
|
|
|
|
void validateAndFixChromeState();
|
|
|
|
HWND GetHwndFromPID(DWORD pid);
|
|
|
|
public:
|
|
simple_logger<wchar_t> logger;
|
|
|
|
virtual ~Bootstrapper(void);
|
|
|
|
static boost::shared_ptr<Bootstrapper> Create(HINSTANCE hInstance, Bootstrapper*(*newBootstrapper)(HINSTANCE));
|
|
static bool hasSse2();
|
|
|
|
virtual std::wstring programDirectory() const; // Local location for installing components to
|
|
std::wstring programDirectory(bool isPerUser) const; // Local location for installing components to
|
|
std::wstring baseProgramDirectory(bool isPerUser) const; //place where all installed versions are
|
|
bool hasReturnValue() const { return isFailIfNotUpToDate; }
|
|
bool hasLegacyStudioDesktopShortcut();
|
|
bool isSilentMode() const { return silentMode; }
|
|
bool isWindowed() const { return windowed; }
|
|
bool WaitForCompletion() { DWORD result = WaitForSingleObject(robloxReady, 30*60*1000); return (result == WAIT_TIMEOUT); }
|
|
int ExitCode() const { return exitCode; }
|
|
void cleanKey(const std::wstring regPathToDelete, CRegKey &hk);
|
|
std::string BrowserTrackerId() { return browserTrackerId; }
|
|
HWND getLaunchedAppHwnd() { return launchedAppHwnd; }
|
|
|
|
// IInstallerSite
|
|
virtual std::string BaseHost() { return baseHost; }
|
|
virtual std::string InstallHost() { return installHost; }
|
|
virtual std::string InstallVersion() { return installVersion; }
|
|
virtual simple_logger<wchar_t> &Logger() { return logger; }
|
|
virtual void progressBar(int pos, int max);
|
|
virtual void CheckCancel() { checkCancel(); }
|
|
virtual void Error(const std::exception& e) { error(e); }
|
|
virtual std::wstring ProgramDirectory() { return programDirectory(); }
|
|
virtual bool UseNewCdn() { return false; }
|
|
virtual bool ReplaceCdnTxt() { return false; }
|
|
|
|
void Close();
|
|
void postLogFile(bool uploadApp);
|
|
bool hasErrors() const { return errors.size()>0; }
|
|
bool hasLongUserCancel() const { return userCancelled && ((userCancelledTime - startTime) > 60); }
|
|
bool hasUserCancel() const { return userCancelled; }
|
|
bool stopRequested() const { return userCancelled || hasErrors(); }
|
|
void error(const std::exception& e);
|
|
|
|
DWORD GetElapsedTime();
|
|
void ReportElapsedEvent(bool startingGameClient);
|
|
virtual void RegisterEvent(const TCHAR *eventName) {};
|
|
virtual void FlushEvents() {};
|
|
// Returns true if we want to enhance remote event reporting with
|
|
// information needed to separate different bootstrapper use cases
|
|
// (e.g. to be able to separate installs vs plays vs check-if-up-to-date).
|
|
virtual bool PerModeLoggingEnabled() { return false; }
|
|
void ReportFinishing(const char* status);
|
|
|
|
virtual std::wstring GetRegistryPath() const = 0;
|
|
virtual std::wstring GetRegistrySubPath() const = 0;
|
|
virtual const wchar_t* GetVersionFileName() const = 0;
|
|
virtual const wchar_t* GetGuidName() const = 0;
|
|
virtual const wchar_t* GetStartAppMutexName() const = 0;
|
|
virtual const wchar_t* GetBootstrapperMutexName() const = 0;
|
|
virtual const wchar_t* GetFriendlyName() const = 0;
|
|
virtual const wchar_t* GetProtocolHandlerUrlScheme() const = 0;
|
|
|
|
virtual void DoInstallApp() {};
|
|
virtual void DoUninstallApp(CRegKey &hk) {}; //component specific uninstall actions
|
|
virtual std::wstring GetRobloxAppFileName() const { return std::wstring(_T("")); }
|
|
virtual std::wstring GetBootstrapperFileName() const { return std::wstring(_T("")); }
|
|
virtual std::wstring GetProductCodeKey() const { return std::wstring(_T("")); }
|
|
virtual void DeployComponents(bool isUpdating, bool commitData) {};
|
|
virtual void StartRobloxApp(bool fromInstall) {}
|
|
virtual bool IsPlayMode() { return false; }
|
|
virtual bool HasUnhideGuid() {return false; }
|
|
virtual bool ProcessProtocolHandlerArgs(const std::map<std::wstring, std::wstring>& args) { return false; }
|
|
virtual bool ProcessArg(wchar_t** args, int &pos, int count) { return false; }
|
|
|
|
};
|
|
|
|
int BootstrapperMain(HINSTANCE hInstance, int nCmdShow, Bootstrapper*(*newBootstrapper)(HINSTANCE));
|
|
|