Improve error handling on Windows Launcher

This commit is contained in:
luiscuenca 2019-07-02 15:22:00 -07:00
parent a3ec365f6c
commit b877d20219
No known key found for this signature in database
GPG key ID: 2387ECD129A6961D
8 changed files with 234 additions and 104 deletions

View file

@ -21,6 +21,7 @@
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View file

@ -32,19 +32,31 @@ CLauncherApp theApp;
// CLauncherApp initialization // CLauncherApp initialization
BOOL CLauncherApp::InitInstance() { BOOL CLauncherApp::InitInstance() {
int iNumOfArgs;
LPWSTR* pArgs = CommandLineToArgvW(GetCommandLine(), &iNumOfArgs);
bool isUninstalling = false;
bool isRestarting = false;
if (iNumOfArgs > 1) {
if (CString(pArgs[1]).Compare(_T("--uninstall")) == 0) {
isUninstalling = true;
} else if (CString(pArgs[1]).Compare(_T("--restart")) == 0) {
isRestarting = true;
}
}
if (!isRestarting) {
// don't launch if already running // don't launch if already running
CreateMutex(NULL, TRUE, _T("HQ_Launcher_Mutex")); CreateMutex(NULL, TRUE, _T("HQ_Launcher_Mutex"));
if (GetLastError() == ERROR_ALREADY_EXISTS) { if (GetLastError() == ERROR_ALREADY_EXISTS) {
return FALSE; return FALSE;
} }
int iNumOfArgs; }
LPWSTR* pArgs = CommandLineToArgvW(GetCommandLine(), &iNumOfArgs);
if (iNumOfArgs > 1 && CString(pArgs[1]).Compare(_T("--uninstall")) == 0) { if (isUninstalling) {
_manager.uninstall(); _manager.uninstall();
} else { } else {
_manager.init(); _manager.init();
} }
if (!_manager.installLauncher()) { if (!_manager.hasFailed() && !_manager.installLauncher()) {
return FALSE; return FALSE;
} }
installFont(IDR_FONT_REGULAR); installFont(IDR_FONT_REGULAR);

View file

@ -207,6 +207,10 @@ void CLauncherDlg::startProcess() {
default: default:
break; break;
} }
if (error != LauncherUtils::DeleteDirError::NoErrorDeleting) {
theApp._manager.saveErrorLog();
theApp._manager.setFailed(true);
}
}); });
} }
@ -230,7 +234,15 @@ afx_msg void CLauncherDlg::OnTermsClicked() {
} }
afx_msg void CLauncherDlg::OnNextClicked() { afx_msg void CLauncherDlg::OnNextClicked() {
if (_drawStep != DrawStep::DrawChoose) { if (_drawStep == DrawStep::DrawChoose) {
CString displayName;
m_username.GetWindowTextW(displayName);
theApp._manager.setDisplayName(displayName);
theApp._manager.addToLog(_T("Setting display name: " + displayName));
startProcess();
} else if (_drawStep == DrawStep::DrawError) {
theApp._manager.restartLauncher();
} else {
CString token; CString token;
CString username, password, orgname; CString username, password, orgname;
m_orgname.GetWindowTextW(orgname); m_orgname.GetWindowTextW(orgname);
@ -261,12 +273,6 @@ afx_msg void CLauncherDlg::OnNextClicked() {
setDrawDialog(DrawStep::DrawLoginErrorOrg); setDrawDialog(DrawStep::DrawLoginErrorOrg);
} }
} }
} else {
CString displayName;
m_username.GetWindowTextW(displayName);
theApp._manager.setDisplayName(displayName);
theApp._manager.addToLog(_T("Setting display name: " + displayName));
startProcess();
} }
} }
@ -318,7 +324,6 @@ void CLauncherDlg::drawVoxel(CHwndRenderTarget* pRenderTarget) {
pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
} }
void CLauncherDlg::showWindows(std::vector<CStatic*> windows, bool show) { void CLauncherDlg::showWindows(std::vector<CStatic*> windows, bool show) {
for (auto window : windows) { for (auto window : windows) {
window->ShowWindow(show ? SW_SHOW : SW_HIDE); window->ShowWindow(show ? SW_SHOW : SW_HIDE);
@ -342,7 +347,7 @@ void CLauncherDlg::prepareLogin(DrawStep step) {
m_password.ShowWindow(SW_SHOW); m_password.ShowWindow(SW_SHOW);
CString actionText = step == DrawStep::DrawLoginLogin ? _T("Please log in") : _T("Uh-oh, we have a problem"); CString actionText = step == DrawStep::DrawLoginLogin ? _T("Please log in") : _T("Uh-oh, we have a problem");
CString messageText = step == DrawStep::DrawLoginLogin ? _T("Be sure you've uploaded your Avatar before signing in.") : CString messageText = step == DrawStep::DrawLoginLogin ? _T("Be sure you've uploaded your Avatar before signing in.") :
step == DrawStep::DrawLoginErrorCred ? _T("There is a problem with your credentials\n please try again.") : _T("There is a problem with your Organization name\n please try again."); step == DrawStep::DrawLoginErrorCred ? _T("There is a problem with your credentials.\n Please try again.") : _T("There is a problem with your Organization name.\n Please try again.");
m_action_label->SetWindowTextW(actionText); m_action_label->SetWindowTextW(actionText);
m_message_label->SetWindowTextW(messageText); m_message_label->SetWindowTextW(messageText);
m_action_label->ShowWindow(SW_SHOW); m_action_label->ShowWindow(SW_SHOW);
@ -354,7 +359,6 @@ void CLauncherDlg::prepareLogin(DrawStep step) {
} }
void CLauncherDlg::prepareChoose() { void CLauncherDlg::prepareChoose() {
m_orgname.ShowWindow(SW_HIDE); m_orgname.ShowWindow(SW_HIDE);
m_username.SetWindowTextW(_T("")); m_username.SetWindowTextW(_T(""));
@ -371,14 +375,7 @@ void CLauncherDlg::prepareChoose() {
m_terms_link.ShowWindow(SW_SHOW); m_terms_link.ShowWindow(SW_SHOW);
m_terms->SetWindowTextW(_T("By signing in, you agree to the High Fidelity")); m_terms->SetWindowTextW(_T("By signing in, you agree to the High Fidelity"));
m_terms_link.SetWindowTextW(_T("Terms of Service")); m_terms_link.SetWindowTextW(_T("Terms of Service"));
CRect rec; setVerticalElement(&m_btnNext, -35, 0, false);
m_btnNext.GetWindowRect(&rec);
ScreenToClient(&rec);
if (rec.top > 281) {
rec.bottom -= 35;
rec.top -= 35;
m_btnNext.MoveWindow(rec, FALSE);
}
m_btnNext.ShowWindow(SW_SHOW); m_btnNext.ShowWindow(SW_SHOW);
} }
@ -401,6 +398,7 @@ void CLauncherDlg::prepareProcess(DrawStep step) {
m_voxel->ShowWindow(SW_SHOW); m_voxel->ShowWindow(SW_SHOW);
CString actionText = _T(""); CString actionText = _T("");
CString messageText = _T(""); CString messageText = _T("");
switch (step) { switch (step) {
case DrawStep::DrawProcessSetup: case DrawStep::DrawProcessSetup:
actionText = _T("We're building your virtual HQ"); actionText = _T("We're building your virtual HQ");
@ -422,6 +420,15 @@ void CLauncherDlg::prepareProcess(DrawStep step) {
actionText = _T("Uninstalling..."); actionText = _T("Uninstalling...");
messageText = _T("It'll take one sec."); messageText = _T("It'll take one sec.");
break; break;
case DrawStep::DrawError:
actionText = _T("Uh oh.");
messageText = _T("We seem to have a problem.\nPlease restart HQ.");
setVerticalElement(m_message2_label, 0, 5, false);
setVerticalElement(&m_btnNext, 10);
m_btnNext.ShowWindow(SW_SHOW);
break;
default:
break;
} }
m_action2_label->SetWindowTextW(actionText); m_action2_label->SetWindowTextW(actionText);
m_message2_label->SetWindowTextW(messageText); m_message2_label->SetWindowTextW(messageText);
@ -429,9 +436,6 @@ void CLauncherDlg::prepareProcess(DrawStep step) {
m_message2_label->ShowWindow(SW_SHOW); m_message2_label->ShowWindow(SW_SHOW);
} }
void CLauncherDlg::prepareError() {
}
BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) { BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) {
// Set default values for message // Set default values for message
BOOL isText = TRUE; BOOL isText = TRUE;
@ -523,6 +527,8 @@ void CLauncherDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
btnName += _drawStep == DrawStep::DrawLoginLogin ? _T("NEXT") : _T("LOG IN"); btnName += _drawStep == DrawStep::DrawLoginLogin ? _T("NEXT") : _T("LOG IN");
int xpan = -20; int xpan = -20;
defrect = CRect(rect.left - xpan, rect.top, rect.right + xpan, rect.bottom); defrect = CRect(rect.left - xpan, rect.top, rect.right + xpan, rect.bottom);
} else if (_drawStep == DrawStep::DrawError) {
btnName += _T("RESTART");
} else { } else {
btnName += _T("TRY AGAIN"); btnName += _T("TRY AGAIN");
} }
@ -594,6 +600,12 @@ BOOL CLauncherDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
const int CONSOLE_MAX_SHUTDOWN_TRY_COUNT = 10; const int CONSOLE_MAX_SHUTDOWN_TRY_COUNT = 10;
const int CONSOLE_DELTATIME_BETWEEN_TRYS = 10; const int CONSOLE_DELTATIME_BETWEEN_TRYS = 10;
if (theApp._manager.hasFailed() && _drawStep != DrawStep::DrawError) {
theApp._manager.saveErrorLog();
prepareProcess(DrawStep::DrawError);
setDrawDialog(DrawStep::DrawError, false);
}
if (_drawStep != DrawStep::DrawError) {
if (_drawStep == DrawStep::DrawProcessSetup || if (_drawStep == DrawStep::DrawProcessSetup ||
_drawStep == DrawStep::DrawProcessUpdate || _drawStep == DrawStep::DrawProcessUpdate ||
_drawStep == DrawStep::DrawProcessUninstall) { _drawStep == DrawStep::DrawProcessUninstall) {
@ -605,11 +617,13 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
if (theApp._manager.needsUninstall()) { if (theApp._manager.needsUninstall()) {
theApp._manager.addToLog(_T("Waiting to uninstall")); theApp._manager.addToLog(_T("Waiting to uninstall"));
setDrawDialog(DrawStep::DrawProcessUninstall); setDrawDialog(DrawStep::DrawProcessUninstall);
} else { }
else {
theApp._manager.addToLog(_T("Start splash screen")); theApp._manager.addToLog(_T("Start splash screen"));
setDrawDialog(DrawStep::DrawLogo); setDrawDialog(DrawStep::DrawLogo);
} }
} else if (_splashStep > 100) { }
else if (_splashStep > 100) {
_showSplash = false; _showSplash = false;
if (theApp._manager.shouldShutDown()) { if (theApp._manager.shouldShutDown()) {
if (_applicationWND != NULL) { if (_applicationWND != NULL) {
@ -619,12 +633,21 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
if (LauncherUtils::IsProcessRunning(L"interface.exe")) { if (LauncherUtils::IsProcessRunning(L"interface.exe")) {
exit(0); exit(0);
} }
} else if (theApp._manager.needsUpdate()) { }
else if (theApp._manager.needsUpdate()) {
startProcess(); startProcess();
} else if (theApp._manager.needsUninstall()) { }
theApp._manager.uninstallApplication(); else if (theApp._manager.needsUninstall()) {
if (theApp._manager.uninstallApplication()) {
theApp._manager.addToLog(_T("HQ uninstalled successfully."));
exit(0); exit(0);
} else { }
else {
theApp._manager.addToLog(_T("HQ failed to uninstall."));
theApp._manager.setFailed(true);
}
}
else {
theApp._manager.addToLog(_T("Starting login")); theApp._manager.addToLog(_T("Starting login"));
setDrawDialog(DrawStep::DrawLoginLogin); setDrawDialog(DrawStep::DrawLoginLogin);
} }
@ -639,6 +662,26 @@ void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) {
_applicationWND = theApp._manager.launchApplication(); _applicationWND = theApp._manager.launchApplication();
} }
} }
}
void CLauncherDlg::setVerticalElement(CWnd* element, int verticalOffset, int heightOffset, bool fromMainWindowBottom) {
CRect elementRec;
CRect windowRec;
if (element != NULL) {
element->GetWindowRect(&elementRec);
ScreenToClient(&elementRec);
int offset = verticalOffset;
if (fromMainWindowBottom) {
GetWindowRect(&windowRec);
ScreenToClient(&windowRec);
int currentDistance = windowRec.bottom - elementRec.bottom;
offset = currentDistance - verticalOffset;
}
elementRec.bottom = elementRec.bottom + offset + heightOffset;
elementRec.top = elementRec.top + offset;
element->MoveWindow(elementRec, FALSE);
}
}
void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) { void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) {
_drawStep = step; _drawStep = step;
@ -671,6 +714,7 @@ void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) {
m_pRenderTarget->EndDraw(); m_pRenderTarget->EndDraw();
RedrawWindow(); RedrawWindow();
break; break;
case DrawStep::DrawError:
case DrawStep::DrawProcessFinishHq: case DrawStep::DrawProcessFinishHq:
case DrawStep::DrawProcessFinishUpdate: case DrawStep::DrawProcessFinishUpdate:
case DrawStep::DrawProcessUpdate: case DrawStep::DrawProcessUpdate:

View file

@ -43,19 +43,18 @@ public:
void setDrawDialog(DrawStep step, BOOL isUpdate = FALSE); void setDrawDialog(DrawStep step, BOOL isUpdate = FALSE);
// Dialog Data // Dialog Data
#ifdef AFX_DESIGN_TIME #ifdef AFX_DESIGN_TIME
enum { IDD = IDD_LAUNCHER_DIALOG }; enum { IDD = IDD_LAUNCHER_DIALOG };
#endif #endif
// Implementation
protected: protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
void startProcess(); void startProcess();
void setCustomDialog(); void setCustomDialog();
// Implementation void setVerticalElement(CWnd* element, int verticalOffset, int heightOffset = 0, bool fromMainWindowBottom = true);
protected:
BOOL getHQInfo(const CString& orgname); BOOL getHQInfo(const CString& orgname);
DrawStep _drawStep { DrawStep::DrawLogo }; DrawStep _drawStep { DrawStep::DrawLogo };
@ -100,7 +99,6 @@ protected:
void prepareLogin(DrawStep step); void prepareLogin(DrawStep step);
void prepareProcess(DrawStep step); void prepareProcess(DrawStep step);
void prepareChoose(); void prepareChoose();
void prepareError();
void redrawBanner(const CEdit& edit, CStatic* banner); void redrawBanner(const CEdit& edit, CStatic* banner);

View file

@ -27,7 +27,8 @@ LauncherManager::~LauncherManager()
void LauncherManager::init() { void LauncherManager::init() {
initLog(); initLog();
addToLog(_T("Getting most recent build")); addToLog(_T("Getting most recent build"));
getMostRecentBuild(_latestApplicationURL, _latestVersion); LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion);
if (error == LauncherUtils::ResponseError::NoError) {
addToLog(_T("Latest version: ") + _latestVersion); addToLog(_T("Latest version: ") + _latestVersion);
CString currentVersion; CString currentVersion;
if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) { if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) {
@ -41,6 +42,13 @@ void LauncherManager::init() {
_shouldUpdate = TRUE; _shouldUpdate = TRUE;
} }
} }
} else {
_hasFailed = true;
CString msg;
msg.Format(_T("Getting most recent build has failed with error: %d"), error);
addToLog(msg);
}
} }
BOOL LauncherManager::initLog() { BOOL LauncherManager::initLog() {
@ -74,8 +82,19 @@ void LauncherManager::closeLog() {
} }
} }
void LauncherManager::saveErrorLog() {
CString logPath = _logFile.GetFilePath();
CString errorLogPath;
auto result = getAndCreatePaths(PathType::Launcher_Directory, errorLogPath);
if (result) {
CString filename;
errorLogPath += _T("log_error.txt");
closeLog();
CopyFile(logPath, errorLogPath, FALSE);
}
}
BOOL LauncherManager::installLauncher() { BOOL LauncherManager::installLauncher() {
addToLog(_T("Installing Launcher."));
CString appPath; CString appPath;
BOOL result = getAndCreatePaths(PathType::Running_Path, appPath); BOOL result = getAndCreatePaths(PathType::Running_Path, appPath);
if (!result) { if (!result) {
@ -93,13 +112,14 @@ BOOL LauncherManager::installLauncher() {
if (!_shouldUninstall) { if (!_shouldUninstall) {
// The installer is not running on the desired location and has to be installed // The installer is not running on the desired location and has to be installed
// Kill of running before self-copy // Kill of running before self-copy
addToLog(_T("Installing Launcher."));
if (LauncherUtils::IsProcessRunning(LAUNCHER_EXE_FILENAME)) { if (LauncherUtils::IsProcessRunning(LAUNCHER_EXE_FILENAME)) {
ShellExecute(NULL, NULL, L"taskkill", L"/F /T /IM " + LAUNCHER_EXE_FILENAME, NULL, SW_HIDE); ShellExecute(NULL, NULL, L"taskkill", L"/F /T /IM " + LAUNCHER_EXE_FILENAME, NULL, SW_HIDE);
} }
CopyFile(appPath, instalationPath, FALSE); CopyFile(appPath, instalationPath, FALSE);
} }
} else if (_shouldUninstall) { } else if (_shouldUninstall) {
addToLog(_T("Launching uninstall mode.")); addToLog(_T("Launching Uninstall mode."));
CString tempPath; CString tempPath;
if (getAndCreatePaths(PathType::Temp_Directory, tempPath)) { if (getAndCreatePaths(PathType::Temp_Directory, tempPath)) {
tempPath += _T("\\HQ_uninstaller_tmp.exe"); tempPath += _T("\\HQ_uninstaller_tmp.exe");
@ -111,6 +131,18 @@ BOOL LauncherManager::installLauncher() {
return TRUE; return TRUE;
} }
BOOL LauncherManager::restartLauncher() {
addToLog(_T("Restarting Launcher."));
CString installDirectory;
if (getAndCreatePaths(PathType::Launcher_Directory, installDirectory)) {
CString installPath = installDirectory + LAUNCHER_EXE_FILENAME;
LauncherUtils::launchApplication(installPath, _T(" --restart"));
exit(0);
}
addToLog(_T("Error restarting Launcher."));
return FALSE;
}
BOOL LauncherManager::createShortcuts() { BOOL LauncherManager::createShortcuts() {
CString desktopLnkPath; CString desktopLnkPath;
addToLog(_T("Creating shortcuts.")); addToLog(_T("Creating shortcuts."));
@ -395,8 +427,10 @@ BOOL LauncherManager::uninstallApplication() {
CString installDir; CString installDir;
getAndCreatePaths(PathType::Launcher_Directory, installDir); getAndCreatePaths(PathType::Launcher_Directory, installDir);
BOOL success = LauncherUtils::deleteFileOrDirectory(installDir); BOOL success = LauncherUtils::deleteFileOrDirectory(installDir);
success = success && (deleteShortcuts()); if (success) {
success = success && (deleteApplicationRegistryKeys()); deleteShortcuts();
deleteApplicationRegistryKeys();
}
return success; return success;
} }
@ -425,7 +459,12 @@ BOOL LauncherManager::extractApplication() {
getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installPath); getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installPath);
BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipApplication, LauncherUtils::cStringToStd(_applicationZipPath), BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipApplication, LauncherUtils::cStringToStd(_applicationZipPath),
LauncherUtils::cStringToStd(installPath), [&](int type, int size) { LauncherUtils::cStringToStd(installPath), [&](int type, int size) {
if (size > 0) {
onZipExtracted((ZipType)type, size); onZipExtracted((ZipType)type, size);
} else {
addToLog(_T("Error decompressing application zip file."));
_hasFailed = true;
}
}); });
if (success) { if (success) {
addToLog(_T("Created thread for unzipping application.")); addToLog(_T("Created thread for unzipping application."));
@ -452,7 +491,13 @@ BOOL LauncherManager::installContent() {
getAndCreatePaths(LauncherManager::PathType::Content_Directory, contentPath); getAndCreatePaths(LauncherManager::PathType::Content_Directory, contentPath);
BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipContent, contentZipFile, BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipContent, contentZipFile,
LauncherUtils::cStringToStd(contentPath), [&](int type, int size) { LauncherUtils::cStringToStd(contentPath), [&](int type, int size) {
if (size > 0) {
addToLog(_T("Content zip decompresed."));
onZipExtracted((ZipType)type, size); onZipExtracted((ZipType)type, size);
} else {
addToLog(_T("Error decompressing content zip file."));
_hasFailed = true;
}
}); });
if (success) { if (success) {
addToLog(_T("Created thread for unzipping content.")); addToLog(_T("Created thread for unzipping content."));
@ -469,8 +514,18 @@ BOOL LauncherManager::downloadFile(DownloadType type, const CString& url, CStrin
BOOL success = getAndCreatePaths(LauncherManager::PathType::Download_Directory, downloadDirectory); BOOL success = getAndCreatePaths(LauncherManager::PathType::Download_Directory, downloadDirectory);
outPath = downloadDirectory + fileName; outPath = downloadDirectory + fileName;
if (success) { if (success) {
if (!LauncherUtils::downloadFileOnThread(type, url, outPath, [&](int type) { addToLog(_T("Downloading: ") + url);
if (!LauncherUtils::downloadFileOnThread(type, url, outPath, [&](int type, bool error) {
if (!error) {
onFileDownloaded((DownloadType)type); onFileDownloaded((DownloadType)type);
} else {
if (type == DownloadType::DownloadApplication) {
addToLog(_T("Error downloading content."));
} else {
addToLog(_T("Error downloading application."));
}
_hasFailed = true;
}
})) { })) {
success = FALSE; success = FALSE;
} }

View file

@ -56,6 +56,7 @@ public:
BOOL initLog(); BOOL initLog();
BOOL addToLog(const CString& line); BOOL addToLog(const CString& line);
void closeLog(); void closeLog();
void saveErrorLog();
BOOL getAndCreatePaths(PathType type, CString& outPath); BOOL getAndCreatePaths(PathType type, CString& outPath);
BOOL getInstalledVersion(const CString& path, CString& version); BOOL getInstalledVersion(const CString& path, CString& version);
BOOL isApplicationInstalled(CString& version, CString& domain, BOOL isApplicationInstalled(CString& version, CString& domain,
@ -73,6 +74,7 @@ public:
HWND launchApplication(); HWND launchApplication();
BOOL uninstallApplication(); BOOL uninstallApplication();
BOOL installLauncher(); BOOL installLauncher();
BOOL restartLauncher();
// getters // getters
const CString& getContentURL() const { return _contentURL; } const CString& getContentURL() const { return _contentURL; }
@ -84,6 +86,8 @@ public:
BOOL needsUninstall() { return _shouldUninstall; } BOOL needsUninstall() { return _shouldUninstall; }
void setDisplayName(const CString& displayName) { _displayName = displayName; } void setDisplayName(const CString& displayName) { _displayName = displayName; }
bool isLoggedIn() { return _loggedIn; } bool isLoggedIn() { return _loggedIn; }
bool hasFailed() { return _hasFailed; }
void setFailed(bool hasFailed) { _hasFailed = hasFailed; }
const CString& getLatestInterfaceURL() const { return _latestApplicationURL; } const CString& getLatestInterfaceURL() const { return _latestApplicationURL; }
void uninstall() { _shouldUninstall = true; }; void uninstall() { _shouldUninstall = true; };
@ -106,6 +110,7 @@ private:
CString _applicationZipPath; CString _applicationZipPath;
CString _contentZipPath; CString _contentZipPath;
bool _loggedIn{ false }; bool _loggedIn{ false };
bool _hasFailed{ false };
BOOL _shouldUpdate{ FALSE }; BOOL _shouldUpdate{ FALSE };
BOOL _shouldUninstall{ FALSE }; BOOL _shouldUninstall{ FALSE };
BOOL _shouldShutdown{ FALSE }; BOOL _shouldShutdown{ FALSE };

View file

@ -258,38 +258,54 @@ uint64_t LauncherUtils::extractZip(const std::string& zipFile, const std::string
} }
int fileCount = (int)mz_zip_reader_get_num_files(&zip_archive); int fileCount = (int)mz_zip_reader_get_num_files(&zip_archive);
if (fileCount == 0) { {
theApp._manager.addToLog(_T("Zip archive has a file count of 0")); CString msg;
msg.Format(_T("Zip archive has a file count of %d"), fileCount);
theApp._manager.addToLog(msg);
}
if (fileCount == 0) {
mz_zip_reader_end(&zip_archive); mz_zip_reader_end(&zip_archive);
return 0; return 0;
} }
mz_zip_archive_file_stat file_stat; mz_zip_archive_file_stat file_stat;
if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) { if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) {
theApp._manager.addToLog(_T("Zip archive cannot be stat'd")); theApp._manager.addToLog(_T("Zip archive cannot be stat'd"));
mz_zip_reader_end(&zip_archive); mz_zip_reader_end(&zip_archive);
return 0; return 0;
} }
// Get root folder // Get root folder
CString lastDir = _T(""); CString lastDir = _T("");
uint64_t totalSize = 0; uint64_t totalSize = 0;
bool _shouldFail = false;
for (int i = 0; i < fileCount; i++) { for (int i = 0; i < fileCount; i++) {
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) continue; if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) continue;
std::string filename = file_stat.m_filename; std::string filename = file_stat.m_filename;
std::replace(filename.begin(), filename.end(), '/', '\\'); std::replace(filename.begin(), filename.end(), '/', '\\');
CString fullFilename = CString(path.c_str()) + "\\" + CString(filename.c_str()); CString fullFilename = CString(path.c_str()) + "\\" + CString(filename.c_str());
if (mz_zip_reader_is_file_a_directory(&zip_archive, i)) { if (mz_zip_reader_is_file_a_directory(&zip_archive, i)) {
if (SHCreateDirectoryEx(NULL, fullFilename, NULL) || ERROR_ALREADY_EXISTS == GetLastError()) { int error = SHCreateDirectoryEx(NULL, fullFilename, NULL);
break; if (error == ERROR_BAD_PATHNAME ||
} else { error == ERROR_FILENAME_EXCED_RANGE ||
continue; error == ERROR_PATH_NOT_FOUND ||
error == ERROR_CANCELLED) {
CString msg;
msg.Format(_T("Unzipping error: %d creating folder: %s"), error, fullFilename);
theApp._manager.addToLog(msg);
mz_zip_reader_end(&zip_archive);
return 0;
} }
continue;
} }
CT2A destFile(fullFilename); CT2A destFile(fullFilename);
if (mz_zip_reader_extract_to_file(&zip_archive, i, destFile, 0)) { if (mz_zip_reader_extract_to_file(&zip_archive, i, destFile, 0)) {
totalSize += (uint64_t)file_stat.m_uncomp_size; totalSize += (uint64_t)file_stat.m_uncomp_size;
files.emplace_back(destFile); files.emplace_back(destFile);
} else {
CString msg;
msg.Format(_T("Error unzipping the file: %s"), fullFilename);
theApp._manager.addToLog(msg);
_shouldFail = true;
} }
} }
@ -421,11 +437,10 @@ DWORD WINAPI LauncherUtils::unzipThread(LPVOID lpParameter) {
return 0; return 0;
} }
DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) {
{
DownloadThreadData& data = *((DownloadThreadData*)lpParameter); DownloadThreadData& data = *((DownloadThreadData*)lpParameter);
auto hr = URLDownloadToFile(0, data._url, data._file, 0, NULL); auto hr = URLDownloadToFile(0, data._url, data._file, 0, NULL);
data.callback(data._type); data.callback(data._type, hr != S_OK);
return 0; return 0;
} }
@ -457,7 +472,7 @@ BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, cons
return FALSE; return FALSE;
} }
BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file, std::function<void(int)> callback) { BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file, std::function<void(int, bool)> callback) {
DWORD myThreadID; DWORD myThreadID;
DownloadThreadData* downloadThreadData = new DownloadThreadData(); DownloadThreadData* downloadThreadData = new DownloadThreadData();
downloadThreadData->_type = type; downloadThreadData->_type = type;

View file

@ -41,10 +41,10 @@ public:
int _type; int _type;
CString _url; CString _url;
CString _file; CString _file;
std::function<void(int)> callback; std::function<void(int, bool)> callback;
// function(type) // function(type, errorType)
void setCallback(std::function<void(int)> fn) { void setCallback(std::function<void(int, bool)> fn) {
callback = std::bind(fn, std::placeholders::_1); callback = std::bind(fn, std::placeholders::_1, std::placeholders::_2);
} }
}; };
@ -82,7 +82,7 @@ public:
static uint64_t extractZip(const std::string& zipFile, const std::string& path, std::vector<std::string>& files); static uint64_t extractZip(const std::string& zipFile, const std::string& path, std::vector<std::string>& files);
static BOOL deleteRegistryKey(const CString& registryPath); static BOOL deleteRegistryKey(const CString& registryPath);
static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function<void(int, int)> callback); static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function<void(int, int)> callback);
static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, std::function<void(int)> callback); static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, std::function<void(int, bool)> callback);
static BOOL deleteDirectoriesOnThread(const CString& applicationDir, static BOOL deleteDirectoriesOnThread(const CString& applicationDir,
const CString& downloadsDir, const CString& downloadsDir,
std::function<void(int)> callback); std::function<void(int)> callback);