From 5e5c9c07291f6b09623d31c92b1fb61c4ede576e Mon Sep 17 00:00:00 2001 From: Sandro Jäckel Date: Thu, 22 Feb 2018 16:54:34 +0100 Subject: Applied clang-format on source --- src/main.cpp | 1052 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 506 insertions(+), 546 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 935b7404..bc1b4bc5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,60 +17,58 @@ You should have received a copy of the GNU General Public License along with Mod Organizer. If not, see . */ - #ifdef LEAK_CHECK_WITH_VLD -#include #include +#include #endif // LEAK_CHECK_WITH_VLD #define WIN32_LEAN_AND_MEAN -#include #include +#include -#include -#include -#include -#include "mainwindow.h" -#include -#include "modlist.h" -#include "profile.h" -#include "spawn.h" #include "executableslist.h" -#include "singleinstance.h" -#include "utility.h" #include "helper.h" +#include "instancemanager.h" #include "logbuffer.h" -#include "selectiondialog.h" +#include "mainwindow.h" #include "moapplication.h" -#include "tutorialmanager.h" -#include "nxmaccessmanager.h" -#include "instancemanager.h" +#include "modlist.h" #include "moshortcut.h" +#include "nxmaccessmanager.h" +#include "profile.h" +#include "selectiondialog.h" +#include "singleinstance.h" +#include "spawn.h" +#include "tutorialmanager.h" +#include "utility.h" +#include +#include +#include +#include #include -#include #include +#include #include -#include -#include -#include +#include #include +#include +#include #include -#include -#include -#include -#include +#include #include -#include +#include +#include +#include #include +#include +#include #include -#include #include -#include -#include -#include #include +#include +#include #include @@ -81,629 +79,591 @@ along with Mod Organizer. If not, see . #include #include - -#pragma comment(linker, "/manifestDependency:\"name='dlls' processorArchitecture='x86' version='1.0.0.0' type='win32' \"") - +#pragma comment(linker, \ + "/manifestDependency:\"name='dlls' processorArchitecture='x86' version='1.0.0.0' type='win32' \"") using namespace MOBase; using namespace MOShared; -bool createAndMakeWritable(const std::wstring &subPath) { - QString const dataPath = qApp->property("dataPath").toString(); - QString fullPath = dataPath + "/" + QString::fromStdWString(subPath); - - if (!QDir(fullPath).exists() && !QDir().mkdir(fullPath)) { - QMessageBox::critical(nullptr, QObject::tr("Error"), - QObject::tr("Failed to create \"%1\". Your user " - "account probably lacks permission.") - .arg(fullPath)); - return false; - } else { - return true; - } +bool createAndMakeWritable(const std::wstring& subPath) { + QString const dataPath = qApp->property("dataPath").toString(); + QString fullPath = dataPath + "/" + QString::fromStdWString(subPath); + + if (!QDir(fullPath).exists() && !QDir().mkdir(fullPath)) { + QMessageBox::critical(nullptr, QObject::tr("Error"), + QObject::tr("Failed to create \"%1\". Your user " + "account probably lacks permission.") + .arg(fullPath)); + return false; + } else { + return true; + } } -bool bootstrap() -{ - // remove the temporary backup directory in case we're restarting after an update - QString backupDirectory = qApp->applicationDirPath() + "/update_backup"; - if (QDir(backupDirectory).exists()) { - shellDelete(QStringList(backupDirectory)); - } +bool bootstrap() { + // remove the temporary backup directory in case we're restarting after an update + QString backupDirectory = qApp->applicationDirPath() + "/update_backup"; + if (QDir(backupDirectory).exists()) { + shellDelete(QStringList(backupDirectory)); + } - // cycle logfile - removeOldFiles(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::logPath()), - "usvfs*.log", 5, QDir::Name); + // cycle logfile + removeOldFiles(qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::logPath()), + "usvfs*.log", 5, QDir::Name); - if (!createAndMakeWritable(AppConfig::logPath())) { - return false; - } + if (!createAndMakeWritable(AppConfig::logPath())) { + return false; + } - return true; + return true; } LPTOP_LEVEL_EXCEPTION_FILTER prevUnhandledExceptionFilter = nullptr; -static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs) -{ - const std::wstring& dumpPath = OrganizerCore::crashDumpsPath(); - int dumpRes = - CreateMiniDump(exceptionPtrs, OrganizerCore::getGlobalCrashDumpsType(), dumpPath.c_str()); - if (!dumpRes) - qCritical("ModOrganizer has crashed, crash dump created."); - else - qCritical("ModOrganizer has crashed, CreateMiniDump failed (%d, error %lu).", dumpRes, GetLastError()); - - if (prevUnhandledExceptionFilter) - return prevUnhandledExceptionFilter(exceptionPtrs); - else - return EXCEPTION_CONTINUE_SEARCH; +static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* exceptionPtrs) { + const std::wstring& dumpPath = OrganizerCore::crashDumpsPath(); + int dumpRes = CreateMiniDump(exceptionPtrs, OrganizerCore::getGlobalCrashDumpsType(), dumpPath.c_str()); + if (!dumpRes) + qCritical("ModOrganizer has crashed, crash dump created."); + else + qCritical("ModOrganizer has crashed, CreateMiniDump failed (%d, error %lu).", dumpRes, GetLastError()); + + if (prevUnhandledExceptionFilter) + return prevUnhandledExceptionFilter(exceptionPtrs); + else + return EXCEPTION_CONTINUE_SEARCH; } // Parses the first parseArgCount arguments of the current process command line and returns // them in parsedArgs, the rest of the command line is returned untouched. -LPCWSTR UntouchedCommandLineArguments(int parseArgCount, std::vector& parsedArgs) -{ - LPCWSTR cmd = GetCommandLineW(); - LPCWSTR arg = nullptr; // to skip executable name - for (; parseArgCount >= 0 && *cmd; ++cmd) - { - if (*cmd == '"') { - int escaped = 0; - for (++cmd; *cmd && (*cmd != '"' || escaped % 2 != 0); ++cmd) - escaped = *cmd == '\\' ? escaped + 1 : 0; - } - if (*cmd == ' ') { - if (arg) - if (cmd-1 > arg && *arg == '"' && *(cmd-1) == '"') - parsedArgs.push_back(std::wstring(arg+1, cmd-1)); - else - parsedArgs.push_back(std::wstring(arg, cmd)); - arg = cmd + 1; - --parseArgCount; +LPCWSTR UntouchedCommandLineArguments(int parseArgCount, std::vector& parsedArgs) { + LPCWSTR cmd = GetCommandLineW(); + LPCWSTR arg = nullptr; // to skip executable name + for (; parseArgCount >= 0 && *cmd; ++cmd) { + if (*cmd == '"') { + int escaped = 0; + for (++cmd; *cmd && (*cmd != '"' || escaped % 2 != 0); ++cmd) + escaped = *cmd == '\\' ? escaped + 1 : 0; + } + if (*cmd == ' ') { + if (arg) + if (cmd - 1 > arg && *arg == '"' && *(cmd - 1) == '"') + parsedArgs.push_back(std::wstring(arg + 1, cmd - 1)); + else + parsedArgs.push_back(std::wstring(arg, cmd)); + arg = cmd + 1; + --parseArgCount; + } } - } - return cmd; + return cmd; } static int SpawnWaitProcess(LPCWSTR workingDirectory, LPCWSTR commandLine) { - PROCESS_INFORMATION pi{ 0 }; - STARTUPINFO si{ 0 }; - si.cb = sizeof(si); - std::wstring commandLineCopy = commandLine; - - if (!CreateProcessW(NULL, &commandLineCopy[0], NULL, NULL, FALSE, 0, NULL, workingDirectory, &si, &pi)) { - // A bit of a problem where to log the error message here, at least this way you can get the message - // using a either DebugView or a live debugger: - std::wostringstream ost; - ost << L"CreateProcess failed: " << commandLine << ", " << GetLastError(); - OutputDebugStringW(ost.str().c_str()); - return -1; - } - - WaitForSingleObject(pi.hProcess, INFINITE); - - DWORD exitCode = (DWORD)-1; - ::GetExitCodeProcess(pi.hProcess, &exitCode); - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - return static_cast(exitCode); -} + PROCESS_INFORMATION pi{0}; + STARTUPINFO si{0}; + si.cb = sizeof(si); + std::wstring commandLineCopy = commandLine; + + if (!CreateProcessW(NULL, &commandLineCopy[0], NULL, NULL, FALSE, 0, NULL, workingDirectory, &si, &pi)) { + // A bit of a problem where to log the error message here, at least this way you can get the message + // using a either DebugView or a live debugger: + std::wostringstream ost; + ost << L"CreateProcess failed: " << commandLine << ", " << GetLastError(); + OutputDebugStringW(ost.str().c_str()); + return -1; + } -static DWORD WaitForProcess() { + WaitForSingleObject(pi.hProcess, INFINITE); + DWORD exitCode = (DWORD)-1; + ::GetExitCodeProcess(pi.hProcess, &exitCode); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return static_cast(exitCode); } -static bool HaveWriteAccess(const std::wstring &path) -{ - bool writable = false; - - const static SECURITY_INFORMATION requestedFileInformation = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; - - DWORD length = 0; - if (!::GetFileSecurityW(path.c_str(), requestedFileInformation, nullptr, 0UL, &length) - && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { - std::string tempBuffer; - tempBuffer.reserve(length); - PSECURITY_DESCRIPTOR security = (PSECURITY_DESCRIPTOR)tempBuffer.data(); - if (security - && ::GetFileSecurity(path.c_str(), requestedFileInformation, security, length, &length)) { - HANDLE token = nullptr; - const static DWORD tokenDesiredAccess = TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ; - if (!::OpenThreadToken(::GetCurrentThread(), tokenDesiredAccess, TRUE, &token)) { - if (!::OpenProcessToken(::GetCurrentProcess(), tokenDesiredAccess, &token)) { - throw std::runtime_error("Unable to get any thread or process token"); +static DWORD WaitForProcess() {} + +static bool HaveWriteAccess(const std::wstring& path) { + bool writable = false; + + const static SECURITY_INFORMATION requestedFileInformation = + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; + + DWORD length = 0; + if (!::GetFileSecurityW(path.c_str(), requestedFileInformation, nullptr, 0UL, &length) && + (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { + std::string tempBuffer; + tempBuffer.reserve(length); + PSECURITY_DESCRIPTOR security = (PSECURITY_DESCRIPTOR)tempBuffer.data(); + if (security && ::GetFileSecurity(path.c_str(), requestedFileInformation, security, length, &length)) { + HANDLE token = nullptr; + const static DWORD tokenDesiredAccess = + TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ; + if (!::OpenThreadToken(::GetCurrentThread(), tokenDesiredAccess, TRUE, &token)) { + if (!::OpenProcessToken(::GetCurrentProcess(), tokenDesiredAccess, &token)) { + throw std::runtime_error("Unable to get any thread or process token"); + } + } + + HANDLE impersonatedToken = nullptr; + if (::DuplicateToken(token, SecurityImpersonation, &impersonatedToken)) { + GENERIC_MAPPING mapping = {0xFFFFFFFF}; + mapping.GenericRead = FILE_GENERIC_READ; + mapping.GenericWrite = FILE_GENERIC_WRITE; + mapping.GenericExecute = FILE_GENERIC_EXECUTE; + mapping.GenericAll = FILE_ALL_ACCESS; + + DWORD genericAccessRights = FILE_GENERIC_WRITE; + ::MapGenericMask(&genericAccessRights, &mapping); + + PRIVILEGE_SET privileges = {0}; + DWORD grantedAccess = 0; + DWORD privilegesLength = sizeof(privileges); + BOOL result = 0; + if (::AccessCheck(security, impersonatedToken, genericAccessRights, &mapping, &privileges, + &privilegesLength, &grantedAccess, &result)) { + writable = result != 0; + } + ::CloseHandle(impersonatedToken); + } + + ::CloseHandle(token); } - } - - HANDLE impersonatedToken = nullptr; - if (::DuplicateToken(token, SecurityImpersonation, &impersonatedToken)) { - GENERIC_MAPPING mapping = { 0xFFFFFFFF }; - mapping.GenericRead = FILE_GENERIC_READ; - mapping.GenericWrite = FILE_GENERIC_WRITE; - mapping.GenericExecute = FILE_GENERIC_EXECUTE; - mapping.GenericAll = FILE_ALL_ACCESS; - - DWORD genericAccessRights = FILE_GENERIC_WRITE; - ::MapGenericMask(&genericAccessRights, &mapping); - - PRIVILEGE_SET privileges = { 0 }; - DWORD grantedAccess = 0; - DWORD privilegesLength = sizeof(privileges); - BOOL result = 0; - if (::AccessCheck(security, impersonatedToken, genericAccessRights, &mapping, &privileges, &privilegesLength, &grantedAccess, &result)) { - writable = result != 0; - } - ::CloseHandle(impersonatedToken); - } - - ::CloseHandle(token); } - } - return writable; + return writable; } - -QString determineProfile(QStringList &arguments, const QSettings &settings) -{ - QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray()); - { // see if there is a profile on the command line - int profileIndex = arguments.indexOf("-p", 1); - if ((profileIndex != -1) && (profileIndex < arguments.size() - 1)) { - qDebug("profile overwritten on command line"); - selectedProfileName = arguments.at(profileIndex + 1); +QString determineProfile(QStringList& arguments, const QSettings& settings) { + QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray()); + { // see if there is a profile on the command line + int profileIndex = arguments.indexOf("-p", 1); + if ((profileIndex != -1) && (profileIndex < arguments.size() - 1)) { + qDebug("profile overwritten on command line"); + selectedProfileName = arguments.at(profileIndex + 1); + } + arguments.removeAt(profileIndex); + arguments.removeAt(profileIndex); + } + if (selectedProfileName.isEmpty()) { + qDebug("no configured profile"); + selectedProfileName = "Default"; + } else { + qDebug("configured profile: %s", qPrintable(selectedProfileName)); } - arguments.removeAt(profileIndex); - arguments.removeAt(profileIndex); - } - if (selectedProfileName.isEmpty()) { - qDebug("no configured profile"); - selectedProfileName = "Default"; - } else { - qDebug("configured profile: %s", qPrintable(selectedProfileName)); - } - - return selectedProfileName; + + return selectedProfileName; } -MOBase::IPluginGame *selectGame(QSettings &settings, QDir const &gamePath, MOBase::IPluginGame *game) -{ - settings.setValue("gameName", game->gameName()); - //Sadly, hookdll needs gamePath in order to run. So following code block is - //commented out - /*if (gamePath == game->gameDirectory()) { +MOBase::IPluginGame* selectGame(QSettings& settings, QDir const& gamePath, MOBase::IPluginGame* game) { + settings.setValue("gameName", game->gameName()); + // Sadly, hookdll needs gamePath in order to run. So following code block is + // commented out + /*if (gamePath == game->gameDirectory()) { settings.remove("gamePath"); } else*/ { - QString gameDir = gamePath.absolutePath(); - game->setGamePath(gameDir); - settings.setValue("gamePath", QDir::toNativeSeparators(gameDir).toUtf8().constData()); - } - return game; //Woot + QString gameDir = gamePath.absolutePath(); + game->setGamePath(gameDir); + settings.setValue("gamePath", QDir::toNativeSeparators(gameDir).toUtf8().constData()); + } + return game; // Woot } - -MOBase::IPluginGame *determineCurrentGame(QString const &moPath, QSettings &settings, PluginContainer const &plugins) -{ - //Determine what game we are running where. Be very paranoid in case the - //user has done something odd. - //If the game name has been set up, use that. - QString gameName = settings.value("gameName", "").toString(); - if (!gameName.isEmpty()) { - MOBase::IPluginGame *game = plugins.managedGame(gameName); - if (game == nullptr) { - reportError(QObject::tr("Plugin to handle %1 no longer installed").arg(gameName)); - return nullptr; +MOBase::IPluginGame* determineCurrentGame(QString const& moPath, QSettings& settings, PluginContainer const& plugins) { + // Determine what game we are running where. Be very paranoid in case the + // user has done something odd. + // If the game name has been set up, use that. + QString gameName = settings.value("gameName", "").toString(); + if (!gameName.isEmpty()) { + MOBase::IPluginGame* game = plugins.managedGame(gameName); + if (game == nullptr) { + reportError(QObject::tr("Plugin to handle %1 no longer installed").arg(gameName)); + return nullptr; + } + QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray()); + if (gamePath == "") { + gamePath = game->gameDirectory().absolutePath(); + } + QDir gameDir(gamePath); + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } } + + // gameName wasn't set, or otherwise can't be found. Try looking through all + // the plugins using the gamePath QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray()); - if (gamePath == "") { - gamePath = game->gameDirectory().absolutePath(); - } - QDir gameDir(gamePath); - if (game->looksValid(gameDir)) { - return selectGame(settings, gameDir, game); + if (!gamePath.isEmpty()) { + QDir gameDir(gamePath); + // Look to see if one of the installed games binary file exists in the current + // game directory. + for (IPluginGame* const game : plugins.plugins()) { + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } + } } - } - - //gameName wasn't set, or otherwise can't be found. Try looking through all - //the plugins using the gamePath - QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray()); - if (!gamePath.isEmpty()) { - QDir gameDir(gamePath); - //Look to see if one of the installed games binary file exists in the current - //game directory. + + // The following code would try to determine the right game to mange but it would usually find the wrong one + // so it was commented out. + /* + //OK, we are in a new setup or existing info is useless. + //See if MO has been installed inside a game directory for (IPluginGame * const game : plugins.plugins()) { - if (game->looksValid(gameDir)) { - return selectGame(settings, gameDir, game); + if (game->isInstalled() && moPath.startsWith(game->gameDirectory().absolutePath())) { + //Found it. + return selectGame(settings, game->gameDirectory(), game); } } - } - - //The following code would try to determine the right game to mange but it would usually find the wrong one - //so it was commented out. - /* - //OK, we are in a new setup or existing info is useless. - //See if MO has been installed inside a game directory - for (IPluginGame * const game : plugins.plugins()) { - if (game->isInstalled() && moPath.startsWith(game->gameDirectory().absolutePath())) { - //Found it. - return selectGame(settings, game->gameDirectory(), game); - } - } - //Try walking up the directory tree to see if MO has been installed inside a game - { - QDir gameDir(moPath); - do { - //Look to see if one of the installed games binary file exists in the current - //directory. - for (IPluginGame * const game : plugins.plugins()) { - if (game->looksValid(gameDir)) { - return selectGame(settings, gameDir, game); + //Try walking up the directory tree to see if MO has been installed inside a game + { + QDir gameDir(moPath); + do { + //Look to see if one of the installed games binary file exists in the current + //directory. + for (IPluginGame * const game : plugins.plugins()) { + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } } - } - //OK, chop off the last directory and try again - } while (gameDir.cdUp()); - } - */ - - //Then try a selection dialogue. - if (!gamePath.isEmpty() || !gameName.isEmpty()) { - reportError(QObject::tr("Could not use configuration settings for game \"%1\", path \"%2\"."). - arg(gameName).arg(gamePath)); - } - - SelectionDialog selection(QObject::tr("Please select the game to manage"), nullptr, QSize(32, 32)); - - for (IPluginGame *game : plugins.plugins()) { - if (game->isInstalled()) { - QString path = game->gameDirectory().absolutePath(); - selection.addChoice(game->gameIcon(), game->gameName(), path, QVariant::fromValue(game)); + //OK, chop off the last directory and try again + } while (gameDir.cdUp()); } - } + */ - selection.addChoice(QString("Browse..."), QString(), QVariant::fromValue(static_cast(nullptr))); + // Then try a selection dialogue. + if (!gamePath.isEmpty() || !gameName.isEmpty()) { + reportError(QObject::tr("Could not use configuration settings for game \"%1\", path \"%2\".") + .arg(gameName) + .arg(gamePath)); + } + + SelectionDialog selection(QObject::tr("Please select the game to manage"), nullptr, QSize(32, 32)); - while (selection.exec() != QDialog::Rejected) { - IPluginGame * game = selection.getChoiceData().value(); - if (game != nullptr) { - return selectGame(settings, game->gameDirectory(), game); + for (IPluginGame* game : plugins.plugins()) { + if (game->isInstalled()) { + QString path = game->gameDirectory().absolutePath(); + selection.addChoice(game->gameIcon(), game->gameName(), path, QVariant::fromValue(game)); + } } - gamePath = QFileDialog::getExistingDirectory( - nullptr, QObject::tr("Please select the game to manage"), QString(), - QFileDialog::ShowDirsOnly); + selection.addChoice(QString("Browse..."), QString(), QVariant::fromValue(static_cast(nullptr))); - if (!gamePath.isEmpty()) { - QDir gameDir(gamePath); - for (IPluginGame * const game : plugins.plugins()) { - if (game->looksValid(gameDir)) { - return selectGame(settings, gameDir, game); + while (selection.exec() != QDialog::Rejected) { + IPluginGame* game = selection.getChoiceData().value(); + if (game != nullptr) { + return selectGame(settings, game->gameDirectory(), game); + } + + gamePath = QFileDialog::getExistingDirectory(nullptr, QObject::tr("Please select the game to manage"), + QString(), QFileDialog::ShowDirsOnly); + + if (!gamePath.isEmpty()) { + QDir gameDir(gamePath); + for (IPluginGame* const game : plugins.plugins()) { + if (game->looksValid(gameDir)) { + return selectGame(settings, gameDir, game); + } + } + reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain " + "the game binary and its launcher.") + .arg(gamePath)); } - } - reportError(QObject::tr("No game identified in \"%1\". The directory is required to contain " - "the game binary and its launcher.").arg(gamePath)); } - } - return nullptr; + return nullptr; } - // extend path to include dll directory so plugins don't need a manifest // (using AddDllDirectory would be an alternative to this but it seems fairly // complicated esp. // since it isn't easily accessible on Windows < 8 // SetDllDirectory replaces other search directories and this seems to // propagate to child processes) -void setupPath() -{ - static const int BUFSIZE = 4096; - - qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators( - QCoreApplication::applicationDirPath()))); - - boost::scoped_array oldPath(new TCHAR[BUFSIZE]); - DWORD offset = ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), BUFSIZE); - if (offset > BUFSIZE) { - oldPath.reset(new TCHAR[offset]); - ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), offset); - } - - std::wstring newPath(oldPath.get()); - newPath += L";"; - newPath += ToWString(QDir::toNativeSeparators( - QCoreApplication::applicationDirPath())) - .c_str(); - newPath += L"\\dlls"; - - ::SetEnvironmentVariableW(L"PATH", newPath.c_str()); +void setupPath() { + static const int BUFSIZE = 4096; + + qDebug("MO at: %s", qPrintable(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()))); + + boost::scoped_array oldPath(new TCHAR[BUFSIZE]); + DWORD offset = ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), BUFSIZE); + if (offset > BUFSIZE) { + oldPath.reset(new TCHAR[offset]); + ::GetEnvironmentVariable(TEXT("PATH"), oldPath.get(), offset); + } + + std::wstring newPath(oldPath.get()); + newPath += L";"; + newPath += ToWString(QDir::toNativeSeparators(QCoreApplication::applicationDirPath())).c_str(); + newPath += L"\\dlls"; + + ::SetEnvironmentVariableW(L"PATH", newPath.c_str()); } -static void preloadSsl() -{ - QString appPath = QDir::toNativeSeparators(QCoreApplication::applicationDirPath()); - if (GetModuleHandleA("libeay32.dll")) - qWarning("libeay32.dll already loaded?!"); - else { - QString libeay32 = appPath + "\\libeay32.dll"; - if (!QFile::exists(libeay32)) - qWarning("libeay32.dll not found: %s", qPrintable(libeay32)); - else if (!LoadLibraryW(libeay32.toStdWString().c_str())) - qWarning("failed to load: %s, %d", qPrintable(libeay32), GetLastError()); - } - if (GetModuleHandleA("ssleay32.dll")) - qWarning("ssleay32.dll already loaded?!"); - else { - QString ssleay32 = appPath + "\\ssleay32.dll"; - if (!QFile::exists(ssleay32)) - qWarning("ssleay32.dll not found: %s", qPrintable(ssleay32)); - else if (!LoadLibraryW(ssleay32.toStdWString().c_str())) - qWarning("failed to load: %s, %d", qPrintable(ssleay32), GetLastError()); - } +static void preloadSsl() { + QString appPath = QDir::toNativeSeparators(QCoreApplication::applicationDirPath()); + if (GetModuleHandleA("libeay32.dll")) + qWarning("libeay32.dll already loaded?!"); + else { + QString libeay32 = appPath + "\\libeay32.dll"; + if (!QFile::exists(libeay32)) + qWarning("libeay32.dll not found: %s", qPrintable(libeay32)); + else if (!LoadLibraryW(libeay32.toStdWString().c_str())) + qWarning("failed to load: %s, %d", qPrintable(libeay32), GetLastError()); + } + if (GetModuleHandleA("ssleay32.dll")) + qWarning("ssleay32.dll already loaded?!"); + else { + QString ssleay32 = appPath + "\\ssleay32.dll"; + if (!QFile::exists(ssleay32)) + qWarning("ssleay32.dll not found: %s", qPrintable(ssleay32)); + else if (!LoadLibraryW(ssleay32.toStdWString().c_str())) + qWarning("failed to load: %s, %d", qPrintable(ssleay32), GetLastError()); + } } -static QString getVersionDisplayString() -{ - VS_FIXEDFILEINFO version = GetFileVersion(ToWString(QApplication::applicationFilePath())); - return VersionInfo(version.dwFileVersionMS >> 16, - version.dwFileVersionMS & 0xFFFF, - version.dwFileVersionLS >> 16, - version.dwFileVersionLS & 0xFFFF).displayString(); +static QString getVersionDisplayString() { + VS_FIXEDFILEINFO version = GetFileVersion(ToWString(QApplication::applicationFilePath())); + return VersionInfo(version.dwFileVersionMS >> 16, version.dwFileVersionMS & 0xFFFF, version.dwFileVersionLS >> 16, + version.dwFileVersionLS & 0xFFFF) + .displayString(); } -int runApplication(MOApplication &application, SingleInstance &instance, - const QString &splashPath) -{ +int runApplication(MOApplication& application, SingleInstance& instance, const QString& splashPath) { - qDebug("Starting Mod Organizer version %s revision %s", qPrintable(getVersionDisplayString()), + qDebug("Starting Mod Organizer version %s revision %s", qPrintable(getVersionDisplayString()), #if defined(HGID) - HGID + HGID #elif defined(GITID) - GITID + GITID #else - "unknown" + "unknown" #endif - ); + ); #if !defined(QT_NO_SSL) - preloadSsl(); - qDebug("ssl support: %d", QSslSocket::supportsSsl()); + preloadSsl(); + qDebug("ssl support: %d", QSslSocket::supportsSsl()); #else - qDebug("non-ssl build"); + qDebug("non-ssl build"); #endif - QString dataPath = application.property("dataPath").toString(); - qDebug("data path: %s", qPrintable(dataPath)); - - if (!bootstrap()) { - reportError("failed to set up data paths"); - return 1; - } - - QStringList arguments = application.arguments(); - - try { - qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath()))); + QString dataPath = application.property("dataPath").toString(); + qDebug("data path: %s", qPrintable(dataPath)); - QSettings settings(dataPath + "/" - + QString::fromStdWString(AppConfig::iniFileName()), - QSettings::IniFormat); - - // global crashDumpType sits in OrganizerCore to make a bit less ugly to update it when the settings are changed during runtime - OrganizerCore::setGlobalCrashDumpsType(settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt()); - - qDebug("Loaded settings:"); - settings.beginGroup("Settings"); - for (auto k : settings.allKeys()) - if (!k.contains("username") && !k.contains("password")) - qDebug(" %s=%s", k.toUtf8().data(), settings.value(k).toString().toUtf8().data()); - settings.endGroup(); + if (!bootstrap()) { + reportError("failed to set up data paths"); + return 1; + } + QStringList arguments = application.arguments(); - qDebug("initializing core"); - OrganizerCore organizer(settings); - if (!organizer.bootstrap()) { - reportError("failed to set up data paths"); - return 1; - } - qDebug("initialize plugins"); - PluginContainer pluginContainer(&organizer); - pluginContainer.loadPlugins(); - - MOBase::IPluginGame *game = determineCurrentGame( - application.applicationDirPath(), settings, pluginContainer); - if (game == nullptr) { - return 1; - } - if (splashPath.startsWith(':')) { - // currently using MO splash, see if the plugin contains one - QString pluginSplash - = QString(":/%1/splash").arg(game->gameShortName()); - QImage image(pluginSplash); - if (!image.isNull()) { - image.save(dataPath + "/splash.png"); - } else { - qDebug("no plugin splash"); - } - } + try { + qDebug("Working directory: %s", qPrintable(QDir::toNativeSeparators(QDir::currentPath()))); + + QSettings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat); + + // global crashDumpType sits in OrganizerCore to make a bit less ugly to update it when the settings are changed + // during runtime + OrganizerCore::setGlobalCrashDumpsType( + settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt()); + + qDebug("Loaded settings:"); + settings.beginGroup("Settings"); + for (auto k : settings.allKeys()) + if (!k.contains("username") && !k.contains("password")) + qDebug(" %s=%s", k.toUtf8().data(), settings.value(k).toString().toUtf8().data()); + settings.endGroup(); + + qDebug("initializing core"); + OrganizerCore organizer(settings); + if (!organizer.bootstrap()) { + reportError("failed to set up data paths"); + return 1; + } + qDebug("initialize plugins"); + PluginContainer pluginContainer(&organizer); + pluginContainer.loadPlugins(); - organizer.setManagedGame(game); - organizer.createDefaultProfile(); - - if (!settings.contains("game_edition")) { - QStringList editions = game->gameVariants(); - if (editions.size() > 1) { - SelectionDialog selection( - QObject::tr("Please select the game edition you have (MO can't " - "start the game correctly if this is set " - "incorrectly!)"), - nullptr); - int index = 0; - for (const QString &edition : editions) { - selection.addChoice(edition, "", index++); + MOBase::IPluginGame* game = determineCurrentGame(application.applicationDirPath(), settings, pluginContainer); + if (game == nullptr) { + return 1; } - if (selection.exec() == QDialog::Rejected) { - return 1; - } else { - settings.setValue("game_edition", selection.getChoiceString()); + if (splashPath.startsWith(':')) { + // currently using MO splash, see if the plugin contains one + QString pluginSplash = QString(":/%1/splash").arg(game->gameShortName()); + QImage image(pluginSplash); + if (!image.isNull()) { + image.save(dataPath + "/splash.png"); + } else { + qDebug("no plugin splash"); + } } - } - } - game->setGameVariant(settings.value("game_edition").toString()); - - qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators( - game->gameDirectory().absolutePath()))); - - organizer.updateExecutablesList(settings); - QString selectedProfileName = determineProfile(arguments, settings); - organizer.setCurrentProfile(selectedProfileName); - - // if we have a command line parameter, it is either a nxm link or - // a binary to start - if (arguments.size() > 1) { - if (MOShortcut shortcut{ arguments.at(1) }) { - try { - organizer.runShortcut(shortcut); - return 0; - } catch (const std::exception &e) { - reportError( - QObject::tr("failed to start shortcut: %1").arg(e.what())); - return 1; + organizer.setManagedGame(game); + organizer.createDefaultProfile(); + + if (!settings.contains("game_edition")) { + QStringList editions = game->gameVariants(); + if (editions.size() > 1) { + SelectionDialog selection(QObject::tr("Please select the game edition you have (MO can't " + "start the game correctly if this is set " + "incorrectly!)"), + nullptr); + int index = 0; + for (const QString& edition : editions) { + selection.addChoice(edition, "", index++); + } + if (selection.exec() == QDialog::Rejected) { + return 1; + } else { + settings.setValue("game_edition", selection.getChoiceString()); + } + } } - } else if (OrganizerCore::isNxmLink(arguments.at(1))) { - qDebug("starting download from command line: %s", - qPrintable(arguments.at(1))); - organizer.externalMessage(arguments.at(1)); - } else { - QString exeName = arguments.at(1); - qDebug("starting %s from command line", qPrintable(exeName)); - arguments.removeFirst(); // remove application name (ModOrganizer.exe) - arguments.removeFirst(); // remove binary name - // pass the remaining parameters to the binary - try { - organizer.startApplication(exeName, arguments, QString(), QString()); - return 0; - } catch (const std::exception &e) { - reportError( - QObject::tr("failed to start application: %1").arg(e.what())); - return 1; + game->setGameVariant(settings.value("game_edition").toString()); + + qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(game->gameDirectory().absolutePath()))); + + organizer.updateExecutablesList(settings); + + QString selectedProfileName = determineProfile(arguments, settings); + organizer.setCurrentProfile(selectedProfileName); + + // if we have a command line parameter, it is either a nxm link or + // a binary to start + if (arguments.size() > 1) { + if (MOShortcut shortcut{arguments.at(1)}) { + try { + organizer.runShortcut(shortcut); + return 0; + } catch (const std::exception& e) { + reportError(QObject::tr("failed to start shortcut: %1").arg(e.what())); + return 1; + } + } else if (OrganizerCore::isNxmLink(arguments.at(1))) { + qDebug("starting download from command line: %s", qPrintable(arguments.at(1))); + organizer.externalMessage(arguments.at(1)); + } else { + QString exeName = arguments.at(1); + qDebug("starting %s from command line", qPrintable(exeName)); + arguments.removeFirst(); // remove application name (ModOrganizer.exe) + arguments.removeFirst(); // remove binary name + // pass the remaining parameters to the binary + try { + organizer.startApplication(exeName, arguments, QString(), QString()); + return 0; + } catch (const std::exception& e) { + reportError(QObject::tr("failed to start application: %1").arg(e.what())); + return 1; + } + } } - } - } - QPixmap pixmap(splashPath); - QSplashScreen splash(pixmap); - splash.show(); + QPixmap pixmap(splashPath); + QSplashScreen splash(pixmap); + splash.show(); - NexusInterface::instance()->getAccessManager()->startLoginCheck(); + NexusInterface::instance()->getAccessManager()->startLoginCheck(); - qDebug("initializing tutorials"); - TutorialManager::init( - qApp->applicationDirPath() + "/" - + QString::fromStdWString(AppConfig::tutorialsPath()) + "/", - &organizer); + qDebug("initializing tutorials"); + TutorialManager::init( + qApp->applicationDirPath() + "/" + QString::fromStdWString(AppConfig::tutorialsPath()) + "/", &organizer); - if (!application.setStyleFile(settings.value("Settings/style", "").toString())) { - // disable invalid stylesheet - settings.setValue("Settings/style", ""); - } + if (!application.setStyleFile(settings.value("Settings/style", "").toString())) { + // disable invalid stylesheet + settings.setValue("Settings/style", ""); + } - int res = 1; - { // scope to control lifetime of mainwindow - // set up main window and its data structures - MainWindow mainWindow(settings, organizer, pluginContainer); + int res = 1; + { // scope to control lifetime of mainwindow + // set up main window and its data structures + MainWindow mainWindow(settings, organizer, pluginContainer); - QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, - SLOT(setStyleFile(QString))); - QObject::connect(&instance, SIGNAL(messageSent(QString)), &organizer, - SLOT(externalMessage(QString))); + QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString))); + QObject::connect(&instance, SIGNAL(messageSent(QString)), &organizer, SLOT(externalMessage(QString))); - mainWindow.readSettings(); + mainWindow.readSettings(); - qDebug("displaying main window"); - mainWindow.show(); + qDebug("displaying main window"); + mainWindow.show(); - splash.finish(&mainWindow); - return application.exec(); + splash.finish(&mainWindow); + return application.exec(); + } + } catch (const std::exception& e) { + reportError(e.what()); + return 1; } - } catch (const std::exception &e) { - reportError(e.what()); - return 1; - } } +int main(int argc, char* argv[]) { + // Should allow for better scaling of ui with higher resolution displays + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); -int main(int argc, char *argv[]) -{ - //Should allow for better scaling of ui with higher resolution displays - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - - if (argc >= 4) { - std::vector arg; - auto args = UntouchedCommandLineArguments(2, arg); - if (arg[0] == L"launch") - return SpawnWaitProcess(arg[1].c_str(), args); - } - - MOApplication application(argc, argv); - QStringList arguments = application.arguments(); - - setupPath(); + if (argc >= 4) { + std::vector arg; + auto args = UntouchedCommandLineArguments(2, arg); + if (arg[0] == L"launch") + return SpawnWaitProcess(arg[1].c_str(), args); + } - bool forcePrimary = false; - if (arguments.contains("update")) { - arguments.removeAll("update"); - forcePrimary = true; - } + MOApplication application(argc, argv); + QStringList arguments = application.arguments(); - MOShortcut moshortcut{ arguments.size() > 1 ? arguments.at(1) : "" }; + setupPath(); - SingleInstance instance(forcePrimary); - if (!instance.primaryInstance()) { - if (moshortcut || - arguments.size() > 1 && OrganizerCore::isNxmLink(arguments.at(1))) - { - qDebug("not primary instance, sending shortcut/download message"); - instance.sendMessage(arguments.at(1)); - return 0; - } else if (arguments.size() == 1) { - QMessageBox::information( - nullptr, QObject::tr("Mod Organizer"), - QObject::tr("An instance of Mod Organizer is already running")); - return 0; + bool forcePrimary = false; + if (arguments.contains("update")) { + arguments.removeAll("update"); + forcePrimary = true; } - } // we continue for the primary instance OR if MO was called with parameters - do { - QString dataPath; + MOShortcut moshortcut{arguments.size() > 1 ? arguments.at(1) : ""}; + + SingleInstance instance(forcePrimary); + if (!instance.primaryInstance()) { + if (moshortcut || arguments.size() > 1 && OrganizerCore::isNxmLink(arguments.at(1))) { + qDebug("not primary instance, sending shortcut/download message"); + instance.sendMessage(arguments.at(1)); + return 0; + } else if (arguments.size() == 1) { + QMessageBox::information(nullptr, QObject::tr("Mod Organizer"), + QObject::tr("An instance of Mod Organizer is already running")); + return 0; + } + } // we continue for the primary instance OR if MO was called with parameters - try { - InstanceManager& instanceManager = InstanceManager::instance(); - if (moshortcut && moshortcut.hasInstance()) - instanceManager.overrideInstance(moshortcut.instance()); - dataPath = instanceManager.determineDataPath(); - } catch (const std::exception &e) { - if (strcmp(e.what(),"Canceled")) - QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"), e.what()); - return 1; - } - application.setProperty("dataPath", dataPath); + do { + QString dataPath; - // initialize dump collection only after "dataPath" since the crashes are stored under it - prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); + try { + InstanceManager& instanceManager = InstanceManager::instance(); + if (moshortcut && moshortcut.hasInstance()) + instanceManager.overrideInstance(moshortcut.instance()); + dataPath = instanceManager.determineDataPath(); + } catch (const std::exception& e) { + if (strcmp(e.what(), "Canceled")) + QMessageBox::critical(nullptr, QObject::tr("Failed to set up instance"), e.what()); + return 1; + } + application.setProperty("dataPath", dataPath); - LogBuffer::init(1000, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log"); + // initialize dump collection only after "dataPath" since the crashes are stored under it + prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); - QString splash = dataPath + "/splash.png"; - if (!QFile::exists(dataPath + "/splash.png")) { - splash = ":/MO/gui/splash"; - } + LogBuffer::init(1000, QtDebugMsg, qApp->property("dataPath").toString() + "/logs/mo_interface.log"); - int result = runApplication(application, instance, splash); - if (result != INT_MAX) { - return result; - } - argc = 1; - } while (true); + QString splash = dataPath + "/splash.png"; + if (!QFile::exists(dataPath + "/splash.png")) { + splash = ":/MO/gui/splash"; + } + + int result = runApplication(application, instance, splash); + if (result != INT_MAX) { + return result; + } + argc = 1; + } while (true); } -- cgit v1.3.1