From b877d2021938bf02a582617f2211b0d2ab160cec Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 2 Jul 2019 15:22:00 -0700 Subject: [PATCH] Improve error handling on Windows Launcher --- launchers/win32/Launcher.rc | 3 +- launchers/win32/LauncherApp.cpp | 26 +++-- launchers/win32/LauncherDlg.cpp | 154 ++++++++++++++++++---------- launchers/win32/LauncherDlg.h | 8 +- launchers/win32/LauncherManager.cpp | 95 +++++++++++++---- launchers/win32/LauncherManager.h | 5 + launchers/win32/LauncherUtils.cpp | 37 +++++-- launchers/win32/LauncherUtils.h | 10 +- 8 files changed, 234 insertions(+), 104 deletions(-) diff --git a/launchers/win32/Launcher.rc b/launchers/win32/Launcher.rc index 4d9e0ffcd6..f0288fa795 100644 --- a/launchers/win32/Launcher.rc +++ b/launchers/win32/Launcher.rc @@ -21,6 +21,7 @@ #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -103,7 +104,7 @@ BEGIN CTEXT "",IDC_MESSAGE2_LABEL,35,172,239,15,NOT WS_VISIBLE CTEXT "",IDC_ACTION2_LABEL,15,147,278,25,NOT WS_VISIBLE RTEXT "",IDC_TERMS,15,172,180,15,NOT WS_VISIBLE - CONTROL "",IDC_TERMS_LINK,"Button", BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15 + CONTROL "",IDC_TERMS_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,197,172,80,15 CTEXT "",IDC_TROUBLE,65,203,174,15,NOT WS_VISIBLE CONTROL "NEXT",IDC_BUTTON_NEXT,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,107,158,94,16 CONTROL "Having Trouble?",IDC_TROUBLE_LINK,"Button",BS_OWNERDRAW | BS_FLAT | NOT WS_VISIBLE | WS_TABSTOP,126,203,56,11 diff --git a/launchers/win32/LauncherApp.cpp b/launchers/win32/LauncherApp.cpp index 4ed20fea13..244d618fcb 100644 --- a/launchers/win32/LauncherApp.cpp +++ b/launchers/win32/LauncherApp.cpp @@ -32,19 +32,31 @@ CLauncherApp theApp; // CLauncherApp initialization BOOL CLauncherApp::InitInstance() { - // don't launch if already running - CreateMutex(NULL, TRUE, _T("HQ_Launcher_Mutex")); - if (GetLastError() == ERROR_ALREADY_EXISTS) { - return FALSE; - } int iNumOfArgs; LPWSTR* pArgs = CommandLineToArgvW(GetCommandLine(), &iNumOfArgs); - if (iNumOfArgs > 1 && CString(pArgs[1]).Compare(_T("--uninstall")) == 0) { + 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 + CreateMutex(NULL, TRUE, _T("HQ_Launcher_Mutex")); + if (GetLastError() == ERROR_ALREADY_EXISTS) { + return FALSE; + } + } + + if (isUninstalling) { _manager.uninstall(); } else { _manager.init(); } - if (!_manager.installLauncher()) { + if (!_manager.hasFailed() && !_manager.installLauncher()) { return FALSE; } installFont(IDR_FONT_REGULAR); diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index a4fe9e494b..9f3382998f 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -207,6 +207,10 @@ void CLauncherDlg::startProcess() { default: 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() { - 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 username, password, orgname; m_orgname.GetWindowTextW(orgname); @@ -261,12 +273,6 @@ afx_msg void CLauncherDlg::OnNextClicked() { 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()); } - void CLauncherDlg::showWindows(std::vector windows, bool show) { for (auto window : windows) { window->ShowWindow(show ? SW_SHOW : SW_HIDE); @@ -342,7 +347,7 @@ void CLauncherDlg::prepareLogin(DrawStep step) { m_password.ShowWindow(SW_SHOW); 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.") : - 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_message_label->SetWindowTextW(messageText); m_action_label->ShowWindow(SW_SHOW); @@ -354,7 +359,6 @@ void CLauncherDlg::prepareLogin(DrawStep step) { } - void CLauncherDlg::prepareChoose() { m_orgname.ShowWindow(SW_HIDE); m_username.SetWindowTextW(_T("")); @@ -371,14 +375,7 @@ void CLauncherDlg::prepareChoose() { m_terms_link.ShowWindow(SW_SHOW); m_terms->SetWindowTextW(_T("By signing in, you agree to the High Fidelity")); m_terms_link.SetWindowTextW(_T("Terms of Service")); - CRect rec; - m_btnNext.GetWindowRect(&rec); - ScreenToClient(&rec); - if (rec.top > 281) { - rec.bottom -= 35; - rec.top -= 35; - m_btnNext.MoveWindow(rec, FALSE); - } + setVerticalElement(&m_btnNext, -35, 0, false); m_btnNext.ShowWindow(SW_SHOW); } @@ -401,6 +398,7 @@ void CLauncherDlg::prepareProcess(DrawStep step) { m_voxel->ShowWindow(SW_SHOW); CString actionText = _T(""); CString messageText = _T(""); + switch (step) { case DrawStep::DrawProcessSetup: actionText = _T("We're building your virtual HQ"); @@ -422,6 +420,15 @@ void CLauncherDlg::prepareProcess(DrawStep step) { actionText = _T("Uninstalling..."); messageText = _T("It'll take one sec."); 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_message2_label->SetWindowTextW(messageText); @@ -429,9 +436,6 @@ void CLauncherDlg::prepareProcess(DrawStep step) { m_message2_label->ShowWindow(SW_SHOW); } -void CLauncherDlg::prepareError() { -} - BOOL CLauncherDlg::getTextFormat(int resID, TextFormat& formatOut) { // Set default values for message BOOL isText = TRUE; @@ -523,6 +527,8 @@ void CLauncherDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) btnName += _drawStep == DrawStep::DrawLoginLogin ? _T("NEXT") : _T("LOG IN"); int xpan = -20; defrect = CRect(rect.left - xpan, rect.top, rect.right + xpan, rect.bottom); + } else if (_drawStep == DrawStep::DrawError) { + btnName += _T("RESTART"); } else { btnName += _T("TRY AGAIN"); } @@ -594,49 +600,86 @@ BOOL CLauncherDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) void CLauncherDlg::OnTimer(UINT_PTR nIDEvent) { const int CONSOLE_MAX_SHUTDOWN_TRY_COUNT = 10; const int CONSOLE_DELTATIME_BETWEEN_TRYS = 10; - if (_drawStep == DrawStep::DrawProcessSetup || - _drawStep == DrawStep::DrawProcessUpdate || - _drawStep == DrawStep::DrawProcessUninstall) { - // Refresh - setDrawDialog(_drawStep, true); + if (theApp._manager.hasFailed() && _drawStep != DrawStep::DrawError) { + theApp._manager.saveErrorLog(); + prepareProcess(DrawStep::DrawError); + setDrawDialog(DrawStep::DrawError, false); } - if (_showSplash) { - if (_splashStep == 0){ - if (theApp._manager.needsUninstall()) { - theApp._manager.addToLog(_T("Waiting to uninstall")); - setDrawDialog(DrawStep::DrawProcessUninstall); - } else { - theApp._manager.addToLog(_T("Start splash screen")); - setDrawDialog(DrawStep::DrawLogo); + if (_drawStep != DrawStep::DrawError) { + if (_drawStep == DrawStep::DrawProcessSetup || + _drawStep == DrawStep::DrawProcessUpdate || + _drawStep == DrawStep::DrawProcessUninstall) { + // Refresh + setDrawDialog(_drawStep, true); + } + if (_showSplash) { + if (_splashStep == 0) { + if (theApp._manager.needsUninstall()) { + theApp._manager.addToLog(_T("Waiting to uninstall")); + setDrawDialog(DrawStep::DrawProcessUninstall); + } + else { + theApp._manager.addToLog(_T("Start splash screen")); + setDrawDialog(DrawStep::DrawLogo); + } } - } else if (_splashStep > 100) { - _showSplash = false; - if (theApp._manager.shouldShutDown()) { - if (_applicationWND != NULL) { - ::SetForegroundWindow(_applicationWND); - ::SetActiveWindow(_applicationWND); + else if (_splashStep > 100) { + _showSplash = false; + if (theApp._manager.shouldShutDown()) { + if (_applicationWND != NULL) { + ::SetForegroundWindow(_applicationWND); + ::SetActiveWindow(_applicationWND); + } + if (LauncherUtils::IsProcessRunning(L"interface.exe")) { + exit(0); + } } - if (LauncherUtils::IsProcessRunning(L"interface.exe")) { - exit(0); + else if (theApp._manager.needsUpdate()) { + startProcess(); } - } else if (theApp._manager.needsUpdate()) { - 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); + } + else { + theApp._manager.addToLog(_T("HQ failed to uninstall.")); + theApp._manager.setFailed(true); + } + } + else { + theApp._manager.addToLog(_T("Starting login")); + setDrawDialog(DrawStep::DrawLoginLogin); + } + } + _splashStep++; + } else if (theApp._manager.shouldShutDown()) { + if (LauncherUtils::IsProcessRunning(L"interface.exe")) { exit(0); - } else { - theApp._manager.addToLog(_T("Starting login")); - setDrawDialog(DrawStep::DrawLoginLogin); } } - _splashStep++; - } else if (theApp._manager.shouldShutDown()) { - if (LauncherUtils::IsProcessRunning(L"interface.exe")) { - exit(0); + if (theApp._manager.shouldLaunch()) { + _applicationWND = theApp._manager.launchApplication(); } } - if (theApp._manager.shouldLaunch()) { - _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); } } @@ -671,6 +714,7 @@ void CLauncherDlg::setDrawDialog(DrawStep step, BOOL isUpdate) { m_pRenderTarget->EndDraw(); RedrawWindow(); break; + case DrawStep::DrawError: case DrawStep::DrawProcessFinishHq: case DrawStep::DrawProcessFinishUpdate: case DrawStep::DrawProcessUpdate: diff --git a/launchers/win32/LauncherDlg.h b/launchers/win32/LauncherDlg.h index 6357c2a5b0..9d34fe5503 100644 --- a/launchers/win32/LauncherDlg.h +++ b/launchers/win32/LauncherDlg.h @@ -43,19 +43,18 @@ public: void setDrawDialog(DrawStep step, BOOL isUpdate = FALSE); - // Dialog Data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_LAUNCHER_DIALOG }; #endif - protected: +// Implementation +protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support void startProcess(); void setCustomDialog(); -// Implementation -protected: + void setVerticalElement(CWnd* element, int verticalOffset, int heightOffset = 0, bool fromMainWindowBottom = true); BOOL getHQInfo(const CString& orgname); DrawStep _drawStep { DrawStep::DrawLogo }; @@ -100,7 +99,6 @@ protected: void prepareLogin(DrawStep step); void prepareProcess(DrawStep step); void prepareChoose(); - void prepareError(); void redrawBanner(const CEdit& edit, CStatic* banner); diff --git a/launchers/win32/LauncherManager.cpp b/launchers/win32/LauncherManager.cpp index 47c84f1124..2916f614cb 100644 --- a/launchers/win32/LauncherManager.cpp +++ b/launchers/win32/LauncherManager.cpp @@ -27,20 +27,28 @@ LauncherManager::~LauncherManager() void LauncherManager::init() { initLog(); addToLog(_T("Getting most recent build")); - getMostRecentBuild(_latestApplicationURL, _latestVersion); - addToLog(_T("Latest version: ") + _latestVersion); - CString currentVersion; - if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) { - addToLog(_T("Installed version: ") + currentVersion); - if (_latestVersion.Compare(currentVersion) == 0) { - addToLog(_T("Already running most recent build. Launching interface.exe")); - _shouldLaunch = TRUE; - _shouldShutdown = TRUE; - } else { - addToLog(_T("New build found. Updating")); - _shouldUpdate = TRUE; + LauncherUtils::ResponseError error = getMostRecentBuild(_latestApplicationURL, _latestVersion); + if (error == LauncherUtils::ResponseError::NoError) { + addToLog(_T("Latest version: ") + _latestVersion); + CString currentVersion; + if (isApplicationInstalled(currentVersion, _domainURL, _contentURL, _loggedIn) && _loggedIn) { + addToLog(_T("Installed version: ") + currentVersion); + if (_latestVersion.Compare(currentVersion) == 0) { + addToLog(_T("Already running most recent build. Launching interface.exe")); + _shouldLaunch = TRUE; + _shouldShutdown = TRUE; + } else { + addToLog(_T("New build found. Updating")); + _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() { @@ -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() { - addToLog(_T("Installing Launcher.")); CString appPath; BOOL result = getAndCreatePaths(PathType::Running_Path, appPath); if (!result) { @@ -93,13 +112,14 @@ BOOL LauncherManager::installLauncher() { if (!_shouldUninstall) { // The installer is not running on the desired location and has to be installed // Kill of running before self-copy + addToLog(_T("Installing Launcher.")); if (LauncherUtils::IsProcessRunning(LAUNCHER_EXE_FILENAME)) { ShellExecute(NULL, NULL, L"taskkill", L"/F /T /IM " + LAUNCHER_EXE_FILENAME, NULL, SW_HIDE); } CopyFile(appPath, instalationPath, FALSE); } } else if (_shouldUninstall) { - addToLog(_T("Launching uninstall mode.")); + addToLog(_T("Launching Uninstall mode.")); CString tempPath; if (getAndCreatePaths(PathType::Temp_Directory, tempPath)) { tempPath += _T("\\HQ_uninstaller_tmp.exe"); @@ -111,6 +131,18 @@ BOOL LauncherManager::installLauncher() { 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() { CString desktopLnkPath; addToLog(_T("Creating shortcuts.")); @@ -395,8 +427,10 @@ BOOL LauncherManager::uninstallApplication() { CString installDir; getAndCreatePaths(PathType::Launcher_Directory, installDir); BOOL success = LauncherUtils::deleteFileOrDirectory(installDir); - success = success && (deleteShortcuts()); - success = success && (deleteApplicationRegistryKeys()); + if (success) { + deleteShortcuts(); + deleteApplicationRegistryKeys(); + } return success; } @@ -425,7 +459,12 @@ BOOL LauncherManager::extractApplication() { getAndCreatePaths(LauncherManager::PathType::Interface_Directory, installPath); BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipApplication, LauncherUtils::cStringToStd(_applicationZipPath), LauncherUtils::cStringToStd(installPath), [&](int type, int size) { - onZipExtracted((ZipType)type, size); + if (size > 0) { + onZipExtracted((ZipType)type, size); + } else { + addToLog(_T("Error decompressing application zip file.")); + _hasFailed = true; + } }); if (success) { addToLog(_T("Created thread for unzipping application.")); @@ -452,7 +491,13 @@ BOOL LauncherManager::installContent() { getAndCreatePaths(LauncherManager::PathType::Content_Directory, contentPath); BOOL success = LauncherUtils::unzipFileOnThread(ZipType::ZipContent, contentZipFile, LauncherUtils::cStringToStd(contentPath), [&](int type, int size) { - onZipExtracted((ZipType)type, size); + if (size > 0) { + addToLog(_T("Content zip decompresed.")); + onZipExtracted((ZipType)type, size); + } else { + addToLog(_T("Error decompressing content zip file.")); + _hasFailed = true; + } }); if (success) { 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); outPath = downloadDirectory + fileName; if (success) { - if (!LauncherUtils::downloadFileOnThread(type, url, outPath, [&](int type) { - onFileDownloaded((DownloadType)type); + addToLog(_T("Downloading: ") + url); + if (!LauncherUtils::downloadFileOnThread(type, url, outPath, [&](int type, bool error) { + if (!error) { + onFileDownloaded((DownloadType)type); + } else { + if (type == DownloadType::DownloadApplication) { + addToLog(_T("Error downloading content.")); + } else { + addToLog(_T("Error downloading application.")); + } + _hasFailed = true; + } })) { success = FALSE; } diff --git a/launchers/win32/LauncherManager.h b/launchers/win32/LauncherManager.h index 6fa7efeeda..e1b1557faf 100644 --- a/launchers/win32/LauncherManager.h +++ b/launchers/win32/LauncherManager.h @@ -56,6 +56,7 @@ public: BOOL initLog(); BOOL addToLog(const CString& line); void closeLog(); + void saveErrorLog(); BOOL getAndCreatePaths(PathType type, CString& outPath); BOOL getInstalledVersion(const CString& path, CString& version); BOOL isApplicationInstalled(CString& version, CString& domain, @@ -73,6 +74,7 @@ public: HWND launchApplication(); BOOL uninstallApplication(); BOOL installLauncher(); + BOOL restartLauncher(); // getters const CString& getContentURL() const { return _contentURL; } @@ -84,6 +86,8 @@ public: BOOL needsUninstall() { return _shouldUninstall; } void setDisplayName(const CString& displayName) { _displayName = displayName; } bool isLoggedIn() { return _loggedIn; } + bool hasFailed() { return _hasFailed; } + void setFailed(bool hasFailed) { _hasFailed = hasFailed; } const CString& getLatestInterfaceURL() const { return _latestApplicationURL; } void uninstall() { _shouldUninstall = true; }; @@ -106,6 +110,7 @@ private: CString _applicationZipPath; CString _contentZipPath; bool _loggedIn{ false }; + bool _hasFailed{ false }; BOOL _shouldUpdate{ FALSE }; BOOL _shouldUninstall{ FALSE }; BOOL _shouldShutdown{ FALSE }; diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index 3ffbd37c58..9365dd52a1 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -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); - 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); return 0; } mz_zip_archive_file_stat file_stat; if (!mz_zip_reader_file_stat(&zip_archive, 0, &file_stat)) { theApp._manager.addToLog(_T("Zip archive cannot be stat'd")); - mz_zip_reader_end(&zip_archive); return 0; } // Get root folder CString lastDir = _T(""); uint64_t totalSize = 0; + bool _shouldFail = false; for (int i = 0; i < fileCount; i++) { if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) continue; std::string filename = file_stat.m_filename; std::replace(filename.begin(), filename.end(), '/', '\\'); CString fullFilename = CString(path.c_str()) + "\\" + CString(filename.c_str()); if (mz_zip_reader_is_file_a_directory(&zip_archive, i)) { - if (SHCreateDirectoryEx(NULL, fullFilename, NULL) || ERROR_ALREADY_EXISTS == GetLastError()) { - break; - } else { - continue; + int error = SHCreateDirectoryEx(NULL, fullFilename, NULL); + if (error == ERROR_BAD_PATHNAME || + error == ERROR_FILENAME_EXCED_RANGE || + 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); if (mz_zip_reader_extract_to_file(&zip_archive, i, destFile, 0)) { totalSize += (uint64_t)file_stat.m_uncomp_size; 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; } -DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) -{ +DWORD WINAPI LauncherUtils::downloadThread(LPVOID lpParameter) { DownloadThreadData& data = *((DownloadThreadData*)lpParameter); auto hr = URLDownloadToFile(0, data._url, data._file, 0, NULL); - data.callback(data._type); + data.callback(data._type, hr != S_OK); return 0; } @@ -457,7 +472,7 @@ BOOL LauncherUtils::unzipFileOnThread(int type, const std::string& zipFile, cons return FALSE; } -BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file, std::function callback) { +BOOL LauncherUtils::downloadFileOnThread(int type, const CString& url, const CString& file, std::function callback) { DWORD myThreadID; DownloadThreadData* downloadThreadData = new DownloadThreadData(); downloadThreadData->_type = type; diff --git a/launchers/win32/LauncherUtils.h b/launchers/win32/LauncherUtils.h index a1cc553128..a6f124e18d 100644 --- a/launchers/win32/LauncherUtils.h +++ b/launchers/win32/LauncherUtils.h @@ -41,10 +41,10 @@ public: int _type; CString _url; CString _file; - std::function callback; - // function(type) - void setCallback(std::function fn) { - callback = std::bind(fn, std::placeholders::_1); + std::function callback; + // function(type, errorType) + void setCallback(std::function fn) { + 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& files); static BOOL deleteRegistryKey(const CString& registryPath); static BOOL unzipFileOnThread(int type, const std::string& zipFile, const std::string& path, std::function callback); - static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, std::function callback); + static BOOL downloadFileOnThread(int type, const CString& url, const CString& file, std::function callback); static BOOL deleteDirectoriesOnThread(const CString& applicationDir, const CString& downloadsDir, std::function callback);