From 633ef81972139f3c082429ada10ffb27d9f07898 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 27 Sep 2019 17:07:04 -0400 Subject: moved checks to sanitychecks.cpp added check for blocked files, only logs --- src/sanitychecks.cpp | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/sanitychecks.cpp (limited to 'src/sanitychecks.cpp') diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp new file mode 100644 index 00000000..5f9705b8 --- /dev/null +++ b/src/sanitychecks.cpp @@ -0,0 +1,174 @@ +#include "env.h" +#include "envmodule.h" +#include + +using namespace MOBase; + +enum class SecurityZone +{ + NoZone = -1, + MyComputer = 0, + Intranet = 1, + Trusted = 2, + Internet = 3, + Untrusted = 4, +}; + +QString toString(SecurityZone z) +{ + switch (z) + { + case SecurityZone::NoZone: return "NoZone"; + case SecurityZone::MyComputer: return "MyComputer"; + case SecurityZone::Intranet: return "Intranet"; + case SecurityZone::Trusted: return "Trusted"; + case SecurityZone::Internet: return "Internet"; + case SecurityZone::Untrusted: return "Untrusted"; + default: return QString("unknown (%1)").arg(static_cast(z)); + } +} + +bool isZoneBlocked(SecurityZone z) +{ + return (z == SecurityZone::Internet || z == SecurityZone::Untrusted); +} + +bool isFileBlocked(const QFileInfo& fi) +{ + const QString ads = "Zone.Identifier"; + const auto key = "ZoneTransfer/ZoneId"; + + const auto path = fi.absoluteFilePath(); + const auto adsPath = path + ":" + ads; + + QFile f(adsPath); + if (!f.exists()) { + return false; + } + + log::debug("file '{}' has an ADS for {}", path, adsPath); + + QSettings qs(adsPath, QSettings::IniFormat); + + if (!qs.contains(key)) { + log::debug("but key '{}' is not found", key); + return false; + } + + const auto v = qs.value(key); + if (v.isNull()) { + log::debug("but key '{}' is null", key); + return false; + } + + bool ok = false; + const auto z = static_cast(v.toInt(&ok)); + + if (!ok) { + log::debug( + "but key '{}' is not an int (value is '{}')", + key, v); + + return false; + } + + if (!isZoneBlocked(z)) { + log::debug( + "but zone id is {}, {}, which is fine", + static_cast(z), toString(z)); + + return false; + } + + log::warn( + "file '{}' is blocked (zone id is {}, {})", + path, static_cast(z), toString(z)); + + return true; +} + +void checkBlockedFiles(const QDir& dir) +{ + if (!dir.exists()) { + log::error( + "while checking for blocked files, directory '{}' not found", + dir.absolutePath()); + + return; + } + + const auto files = dir.entryInfoList({"*.dll", "*.exe"}, QDir::Files); + if (files.empty()) { + log::error( + "while checking for blocked files, directory '{}' is empty", + dir.absolutePath()); + + return; + } + + for (auto&& fi : files) { + isFileBlocked(fi); + } +} + +void checkBlocked() +{ + const QString appDir = QCoreApplication::applicationDirPath(); + + const QDir dirs[] = { + appDir, + appDir + "/dlls", + appDir + "/loot", + appDir + "/NCC", + appDir + "/platforms", + appDir + "/plugins" + }; + + for (const auto& d : dirs) { + checkBlockedFiles(d); + } +} + +void checkMissingFiles() +{ + // files that are likely to be eaten + static const QStringList files({ + "helper.exe", "nxmhandler.exe", + "usvfs_proxy_x64.exe", "usvfs_proxy_x86.exe", + "usvfs_x64.dll", "usvfs_x86.dll" + }); + + const auto dir = QCoreApplication::applicationDirPath(); + + for (const auto& name : files) { + const QFileInfo file(dir + QDir::separator() + name); + if (!file.exists()) { + log::warn( + "'{}' seems to be missing, an antivirus may have deleted it", + file.absoluteFilePath()); + } + } +} + +void checkNahimic(const env::Environment& e) +{ + for (auto&& m : e.loadedModules()) { + const QFileInfo file(m.path()); + + if (file.fileName().compare("NahimicOSD.dll", Qt::CaseInsensitive) == 0) { + log::warn( + "NahimicOSD.dll is loaded. Nahimic is known to cause issues with " + "Mod Organizer, such as freezing or blank windows. Consider " + "uninstalling it."); + + break; + } + } +} + +void sanityChecks(const env::Environment& e) +{ + checkBlocked(); + checkMissingFiles(); + checkNahimic(e); +} -- cgit v1.3.1 From 1dc39621998457ab09765520f6cce4e266eaa8db Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 5 Oct 2019 07:03:41 -0400 Subject: changed some of blocked files logging --- src/sanitychecks.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'src/sanitychecks.cpp') diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index 5f9705b8..185b1f9c 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -14,7 +14,7 @@ enum class SecurityZone Untrusted = 4, }; -QString toString(SecurityZone z) +QString toCodeName(SecurityZone z) { switch (z) { @@ -24,10 +24,17 @@ QString toString(SecurityZone z) case SecurityZone::Trusted: return "Trusted"; case SecurityZone::Internet: return "Internet"; case SecurityZone::Untrusted: return "Untrusted"; - default: return QString("unknown (%1)").arg(static_cast(z)); + default: return "Unknown"; } } +QString toString(SecurityZone z) +{ + return QString("%1 (%2)") + .arg(toCodeName(z)) + .arg(static_cast(z)); +} + bool isZoneBlocked(SecurityZone z) { return (z == SecurityZone::Internet || z == SecurityZone::Untrusted); @@ -46,18 +53,18 @@ bool isFileBlocked(const QFileInfo& fi) return false; } - log::debug("file '{}' has an ADS for {}", path, adsPath); + log::debug("'{}' has an ADS for {}", path, adsPath); - QSettings qs(adsPath, QSettings::IniFormat); + const QSettings qs(adsPath, QSettings::IniFormat); if (!qs.contains(key)) { - log::debug("but key '{}' is not found", key); + log::debug("'{}': key '{}' not found", adsPath, key); return false; } const auto v = qs.value(key); if (v.isNull()) { - log::debug("but key '{}' is null", key); + log::debug("'{}': key '{}' is null", adsPath, key); return false; } @@ -65,25 +72,16 @@ bool isFileBlocked(const QFileInfo& fi) const auto z = static_cast(v.toInt(&ok)); if (!ok) { - log::debug( - "but key '{}' is not an int (value is '{}')", - key, v); - + log::debug("'{}': key '{}' is not an int (value is '{}')", adsPath, key, v); return false; } if (!isZoneBlocked(z)) { - log::debug( - "but zone id is {}, {}, which is fine", - static_cast(z), toString(z)); - + log::debug("'{}': zone id is {}, which is fine", adsPath, toString(z)); return false; } - log::warn( - "file '{}' is blocked (zone id is {}, {})", - path, static_cast(z), toString(z)); - + log::warn("'{}': file is blocked (zone id is {})", path, toString(z)); return true; } @@ -141,7 +139,8 @@ void checkMissingFiles() const auto dir = QCoreApplication::applicationDirPath(); for (const auto& name : files) { - const QFileInfo file(dir + QDir::separator() + name); + const QFileInfo file(dir + "/" + name); + if (!file.exists()) { log::warn( "'{}' seems to be missing, an antivirus may have deleted it", @@ -168,6 +167,8 @@ void checkNahimic(const env::Environment& e) void sanityChecks(const env::Environment& e) { + log::debug("running sanity checks"); + checkBlocked(); checkMissingFiles(); checkNahimic(e); -- cgit v1.3.1 From 1467cb9955776c0e7738a93eb338321aabfda456 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 5 Oct 2019 08:11:12 -0400 Subject: sanity checks: comments, more debug logging --- src/sanitychecks.cpp | 131 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 106 insertions(+), 25 deletions(-) (limited to 'src/sanitychecks.cpp') diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index 185b1f9c..3b4185a7 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -24,7 +24,7 @@ QString toCodeName(SecurityZone z) case SecurityZone::Trusted: return "Trusted"; case SecurityZone::Internet: return "Internet"; case SecurityZone::Untrusted: return "Untrusted"; - default: return "Unknown"; + default: return "Unknown zone"; } } @@ -35,21 +35,42 @@ QString toString(SecurityZone z) .arg(static_cast(z)); } +// whether the given zone is considered blocked +// bool isZoneBlocked(SecurityZone z) { - return (z == SecurityZone::Internet || z == SecurityZone::Untrusted); + switch (z) + { + case SecurityZone::Internet: + case SecurityZone::Untrusted: + return true; + + case SecurityZone::NoZone: + case SecurityZone::MyComputer: + case SecurityZone::Intranet: + case SecurityZone::Trusted: + default: + return false; + } } +// whether the given file is blocked +// bool isFileBlocked(const QFileInfo& fi) { + // name of the alternate data stream containing the zone identifier ini const QString ads = "Zone.Identifier"; + + // key in the ini const auto key = "ZoneTransfer/ZoneId"; + // the path to the ADS is always `filename:Zone.Identifier` const auto path = fi.absoluteFilePath(); const auto adsPath = path + ":" + ads; QFile f(adsPath); if (!f.exists()) { + // no ADS for this file return false; } @@ -57,17 +78,20 @@ bool isFileBlocked(const QFileInfo& fi) const QSettings qs(adsPath, QSettings::IniFormat); + // looking for key if (!qs.contains(key)) { log::debug("'{}': key '{}' not found", adsPath, key); return false; } + // getting value const auto v = qs.value(key); if (v.isNull()) { log::debug("'{}': key '{}' is null", adsPath, key); return false; } + // should be an int bool ok = false; const auto z = static_cast(v.toInt(&ok)); @@ -77,57 +101,79 @@ bool isFileBlocked(const QFileInfo& fi) } if (!isZoneBlocked(z)) { + // that zone is not a blocked zone log::debug("'{}': zone id is {}, which is fine", adsPath, toString(z)); return false; } - log::warn("'{}': file is blocked (zone id is {})", path, toString(z)); + // file is blocked + log::warn("'{}': file is blocked, zone id is {}", path, toString(z)); return true; } -void checkBlockedFiles(const QDir& dir) +int checkBlockedFiles(const QDir& dir) { + // executables file types + const QStringList FileTypes = {"*.dll", "*.exe"}; + if (!dir.exists()) { + // shouldn't happen log::error( "while checking for blocked files, directory '{}' not found", dir.absolutePath()); - return; + return 1; } - const auto files = dir.entryInfoList({"*.dll", "*.exe"}, QDir::Files); + const auto files = dir.entryInfoList(FileTypes, QDir::Files); if (files.empty()) { + // shouldn't happen log::error( "while checking for blocked files, directory '{}' is empty", dir.absolutePath()); - return; + return 1; } + int n = 0; + + // checking each file in this directory for (auto&& fi : files) { - isFileBlocked(fi); + if (isFileBlocked(fi)) { + ++n; + } } + + return n; } -void checkBlocked() +int checkBlocked() { + // directories that contain executables; these need to be explicit because + // portable instances might add billions of files in MO's directory + const QString dirs[] = { + ".", + "/dlls", + "/loot", + "/NCC", + "/platforms", + "/plugins" + }; + + log::debug(" . blocked files"); const QString appDir = QCoreApplication::applicationDirPath(); - const QDir dirs[] = { - appDir, - appDir + "/dlls", - appDir + "/loot", - appDir + "/NCC", - appDir + "/platforms", - appDir + "/plugins" - }; + int n = 0; for (const auto& d : dirs) { - checkBlockedFiles(d); + const auto path = QDir(appDir + "/" + d).canonicalPath(); + n += checkBlockedFiles(path); } + + return n; } -void checkMissingFiles() +int checkMissingFiles() { // files that are likely to be eaten static const QStringList files({ @@ -136,8 +182,11 @@ void checkMissingFiles() "usvfs_x64.dll", "usvfs_x86.dll" }); + log::debug(" . missing files"); const auto dir = QCoreApplication::applicationDirPath(); + int n = 0; + for (const auto& name : files) { const QFileInfo file(dir + "/" + name); @@ -145,12 +194,23 @@ void checkMissingFiles() log::warn( "'{}' seems to be missing, an antivirus may have deleted it", file.absoluteFilePath()); + + ++n; } } + + return n; } -void checkNahimic(const env::Environment& e) +bool checkNahimic(const env::Environment& e) { + // Nahimic seems to interfere mostly with dialogs, like the mod info dialog: + // it renders dialogs fully white and makes it impossible to interact with + // them + // + // NahimicOSD.dll is usually loaded on startup, but there has been some + // reports where it got loaded later, so this check is not entirely accurate + for (auto&& m : e.loadedModules()) { const QFileInfo file(m.path()); @@ -160,16 +220,37 @@ void checkNahimic(const env::Environment& e) "Mod Organizer, such as freezing or blank windows. Consider " "uninstalling it."); - break; + return true; } } + + return false; +} + +int checkIncompatibilities(const env::Environment& e) +{ + log::debug(" . incompatibilities"); + + int n = 0; + + if (checkNahimic(e)) { + ++n; + } + + return n; } void sanityChecks(const env::Environment& e) { - log::debug("running sanity checks"); + log::debug("running sanity checks..."); + + int n = 0; + + n += checkBlocked(); + n += checkMissingFiles(); + n += checkIncompatibilities(e); - checkBlocked(); - checkMissingFiles(); - checkNahimic(e); + log::debug( + "sanity checks done, {}", + (n > 0 ? "problems were found" : "everything looks okay")); } -- cgit v1.3.1 From c3068ce50ab6e25e21452c2ea2f83086ddf555d5 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Tue, 26 Nov 2019 08:39:22 -0500 Subject: added rivatuner to sanity checks now also checks modules loaded after startup fixed crash on w7 when checking some modules --- src/env.cpp | 44 ++++++++++++++++++++++++++++++-------------- src/env.h | 11 ++++++++--- src/main.cpp | 4 +++- src/sanitychecks.cpp | 37 ++++++++++++++++++++++--------------- 4 files changed, 63 insertions(+), 33 deletions(-) (limited to 'src/sanitychecks.cpp') diff --git a/src/env.cpp b/src/env.cpp index 51631607..f9507dc1 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -56,8 +56,8 @@ Console::~Console() } -ModuleNotification::ModuleNotification(std::function f) - : m_cookie(nullptr), m_f(std::move(f)) +ModuleNotification::ModuleNotification(QObject* o, std::function f) + : m_cookie(nullptr), m_object(o), m_f(std::move(f)) { } @@ -97,10 +97,26 @@ void ModuleNotification::setCookie(void* c) m_cookie = c; } -void ModuleNotification::fire(const Module& m) +void ModuleNotification::fire(QString path, std::size_t fileSize) { + if (m_loaded.contains(path)) { + // don't notify if it's been loaded before + } + + m_loaded.insert(path); + + // constructing a Module will query the version info of the file, which seems + // to generate an access violation for at least plugin_python.dll on Windows 7 + // + // it's not clear what the problem is, but making sure this is deferred until + // _after_ the dll is loaded seems to fix it + // + // so this queues the callback in the main thread + if (m_f) { - m_f(m); + QMetaObject::invokeMethod(m_object, [path, fileSize, f=m_f] { + f(Module(path, fileSize)); + }, Qt::QueuedConnection); } } @@ -196,7 +212,7 @@ QString Environment::timezone() const } std::unique_ptr Environment::onModuleLoaded( - std::function f) + QObject* o, std::function f) { typedef struct _UNICODE_STRING { USHORT Length; @@ -263,19 +279,19 @@ std::unique_ptr Environment::onModuleLoaded( } - auto context = std::make_unique(f); + auto context = std::make_unique(o, f); void* cookie = nullptr; auto OnDllLoaded = [](ULONG reason, const PLDR_DLL_NOTIFICATION_DATA data, void* context) { if (reason == LDR_DLL_NOTIFICATION_REASON_LOADED) { - const Module m( - QString::fromWCharArray( - data->Loaded.FullDllName->Buffer, - data->Loaded.FullDllName->Length / sizeof(wchar_t)), - data->Loaded.SizeOfImage); - - if (context) { - static_cast(context)->fire(m); + if (data && data->Loaded.FullDllName) { + if (context) { + static_cast(context)->fire( + QString::fromWCharArray( + data->Loaded.FullDllName->Buffer, + data->Loaded.FullDllName->Length / sizeof(wchar_t)), + data->Loaded.SizeOfImage); + } } } }; diff --git a/src/env.h b/src/env.h index 946cb13b..dc0fd864 100644 --- a/src/env.h +++ b/src/env.h @@ -122,7 +122,7 @@ private: class ModuleNotification { public: - ModuleNotification(std::function f); + ModuleNotification(QObject* o, std::function f); ~ModuleNotification(); ModuleNotification(const ModuleNotification&) = delete; @@ -132,10 +132,12 @@ public: ModuleNotification& operator=(ModuleNotification&&) = default; void setCookie(void* c); - void fire(const Module& m); + void fire(QString path, std::size_t fileSize); private: void* m_cookie; + QObject* m_object; + std::set m_loaded; std::function m_f; }; @@ -172,8 +174,11 @@ public: // QString timezone() const; + // will call `f` on the same thread `o` is running on every time a module + // is loaded in the process + // std::unique_ptr onModuleLoaded( - std::function f); + QObject* o, std::function f); // logs the environment // diff --git a/src/main.cpp b/src/main.cpp index 6e112479..3cccf365 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -93,6 +93,7 @@ using namespace MOShared; void sanityChecks(const env::Environment& env); +int checkIncompatibleModule(const env::Module& m); bool createAndMakeWritable(const std::wstring &subPath) { QString const dataPath = qApp->property("dataPath").toString(); @@ -547,8 +548,9 @@ int runApplication(MOApplication &application, SingleInstance &instance, settings.dump(); sanityChecks(env); - const auto moduleNotification = env.onModuleLoaded([](auto&& m) { + const auto moduleNotification = env.onModuleLoaded(qApp, [](auto&& m) { log::debug("loaded module {}", m.toString()); + checkIncompatibleModule(m); }); log::debug("initializing core"); diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index 3b4185a7..495795f2 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -202,29 +202,36 @@ int checkMissingFiles() return n; } -bool checkNahimic(const env::Environment& e) +int checkIncompatibleModule(const env::Module& m) { - // Nahimic seems to interfere mostly with dialogs, like the mod info dialog: - // it renders dialogs fully white and makes it impossible to interact with - // them + // these dlls seems to interfere mostly with dialogs, like the mod info + // dialog: it renders dialogs fully white and makes it impossible to interact + // with them // - // NahimicOSD.dll is usually loaded on startup, but there has been some - // reports where it got loaded later, so this check is not entirely accurate + // the dlls is usually loaded on startup, but there has been some reports + // where it got loaded later, so this is also called every time a new module + // is loaded into this process - for (auto&& m : e.loadedModules()) { - const QFileInfo file(m.path()); + static const std::map names = { + {"NahimicOSD.dll", "Nahimic"}, + {"RTSSHooks64.dll", "RivaTuner Statistics Server"} + }; + + const QFileInfo file(m.path()); + int n = 0; - if (file.fileName().compare("NahimicOSD.dll", Qt::CaseInsensitive) == 0) { + for (auto&& p : names) { + if (file.fileName().compare(p.first, Qt::CaseInsensitive) == 0) { log::warn( - "NahimicOSD.dll is loaded. Nahimic is known to cause issues with " + "{} is loaded. This program is known to cause issues with " "Mod Organizer, such as freezing or blank windows. Consider " - "uninstalling it."); + "uninstalling it. ({})", p.second, file.absoluteFilePath()); - return true; + ++n; } } - return false; + return n; } int checkIncompatibilities(const env::Environment& e) @@ -233,8 +240,8 @@ int checkIncompatibilities(const env::Environment& e) int n = 0; - if (checkNahimic(e)) { - ++n; + for (auto&& m : e.loadedModules()) { + n += checkIncompatibleModule(m); } return n; -- cgit v1.3.1 From cde6137ca586239b36da59d46d7a1d3e55ed43ce Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Tue, 26 Nov 2019 08:59:15 -0500 Subject: added loot to missing files check --- src/sanitychecks.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/sanitychecks.cpp') diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index 495795f2..ef57a503 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -177,9 +177,14 @@ int checkMissingFiles() { // files that are likely to be eaten static const QStringList files({ - "helper.exe", "nxmhandler.exe", - "usvfs_proxy_x64.exe", "usvfs_proxy_x86.exe", - "usvfs_x64.dll", "usvfs_x86.dll" + "helper.exe", + "nxmhandler.exe", + "usvfs_proxy_x64.exe", + "usvfs_proxy_x86.exe", + "usvfs_x64.dll", + "usvfs_x86.dll", + "loot/loot.dll", + "loot/lootcli.exe" }); log::debug(" . missing files"); -- cgit v1.3.1 From 05759c4abcae0e54c7c6fb3aac43b55ed490b6f4 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 27 Nov 2019 16:03:42 -0500 Subject: added checks on startup for directories in program files --- src/main.cpp | 3 ++ src/sanitychecks.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) (limited to 'src/sanitychecks.cpp') diff --git a/src/main.cpp b/src/main.cpp index 3cccf365..1f6c57d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -94,6 +94,7 @@ using namespace MOShared; void sanityChecks(const env::Environment& env); int checkIncompatibleModule(const env::Module& m); +int checkPathsForSanity(MOBase::IPluginGame& game, const Settings& s); bool createAndMakeWritable(const std::wstring &subPath) { QString const dataPath = qApp->property("dataPath").toString(); @@ -593,6 +594,8 @@ int runApplication(MOApplication &application, SingleInstance &instance, return 1; } + checkPathsForSanity(*game, settings); + if (splashPath.startsWith(':')) { // currently using MO splash, see if the plugin contains one QString pluginSplash diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index ef57a503..a767e8f9 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -1,6 +1,9 @@ #include "env.h" #include "envmodule.h" +#include "settings.h" +#include #include +#include using namespace MOBase; @@ -252,6 +255,83 @@ int checkIncompatibilities(const env::Environment& e) return n; } +std::vector> getSystemDirectories() +{ + // folder ids and display names for logging + const std::vector> systemFolderIDs = { + {FOLDERID_ProgramFiles, "Program Files"}, + {FOLDERID_ProgramFilesX86, "Program Files"} + }; + + std::vector> systemDirs; + + for (auto&& p : systemFolderIDs) { + try + { + const auto dir = MOBase::getKnownFolder(p.first); + + auto path = QDir::toNativeSeparators(dir.absolutePath()).toLower(); + if (!path.endsWith("\\")) { + path += "\\"; + } + + systemDirs.push_back({path, p.second}); + } + catch(std::exception&) + { + // ignore + } + } + + return systemDirs; +} + +int checkProtected(const QDir& d, const QString& what) +{ + static const auto systemDirs = getSystemDirectories(); + + const auto path = QDir::toNativeSeparators(d.absolutePath()).toLower(); + + log::debug(" . {}: {}", what, path); + + for (auto&& sd : systemDirs) { + if (path.startsWith(sd.first)) { + log::warn( + "{} is in {}; this may cause issues because it's a protected " + "system folder", + what, sd.second); + + log::debug("path '{}' starts with '{}'", path, sd.first); + + return 1; + } + } + + return 0; +} + +int checkPathsForSanity(IPluginGame& game, const Settings& s) +{ + log::debug("checking paths"); + + int n = 0; + + n += checkProtected(game.gameDirectory(), "the game"); + n += checkProtected(QApplication::applicationDirPath(), "Mod Organizer"); + + if (checkProtected(s.paths().base(), "the instance base directory")) { + ++n; + } else { + n += checkProtected(s.paths().downloads(), "the downloads directory"); + n += checkProtected(s.paths().mods(), "the mods directory"); + n += checkProtected(s.paths().cache(), "the cache directory"); + n += checkProtected(s.paths().profiles(), "the profiles directory"); + n += checkProtected(s.paths().overwrite(), "the overwrite directory"); + } + + return n; +} + void sanityChecks(const env::Environment& e) { log::debug("running sanity checks..."); -- cgit v1.3.1 From d47fc5c973b5b17289c4915e911c4412956361ea Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 27 Nov 2019 16:37:58 -0500 Subject: allow relative paths for binaries in the executables settings added SSAudioOSD.dll to checks --- src/editexecutablesdialog.cpp | 2 +- src/executableslist.cpp | 6 +++--- src/sanitychecks.cpp | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src/sanitychecks.cpp') diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 32b31357..1c804a7c 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -327,7 +327,7 @@ void EditExecutablesDialog::clearEdits() void EditExecutablesDialog::setEdits(const Executable& e) { ui->title->setText(e.title()); - ui->binary->setText(QDir::toNativeSeparators(e.binaryInfo().absoluteFilePath())); + ui->binary->setText(QDir::toNativeSeparators(e.binaryInfo().filePath())); ui->workingDirectory->setText(QDir::toNativeSeparators(e.workingDirectory())); ui->arguments->setText(e.arguments()); ui->overwriteSteamAppID->setChecked(!e.steamAppID().isEmpty()); diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 1be34b53..75f29e8f 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -120,7 +120,7 @@ void ExecutablesList::store(Settings& s) map["toolbar"] = item.isShownOnToolbar(); map["ownicon"] = item.usesOwnIcon(); map["hide"] = item.hide(); - map["binary"] = item.binaryInfo().absoluteFilePath(); + map["binary"] = item.binaryInfo().filePath(); map["arguments"] = item.arguments(); map["workingDirectory"] = item.workingDirectory(); map["steamAppID"] = item.steamAppID(); @@ -358,7 +358,7 @@ void ExecutablesList::dump() const " steam ID: {}\n" " directory: {}\n" " flags: {} ({})", - e.title(), e.binaryInfo().absoluteFilePath(), e.arguments(), + e.title(), e.binaryInfo().filePath(), e.arguments(), e.steamAppID(), e.workingDirectory(), flags.join("|"), e.flags()); } } @@ -374,7 +374,7 @@ Executable::Executable(const MOBase::ExecutableInfo& info, Flags flags) : m_binaryInfo(info.binary()), m_arguments(info.arguments().join(" ")), m_steamAppID(info.steamAppID()), - m_workingDirectory(info.workingDirectory().absolutePath()), + m_workingDirectory(info.workingDirectory().path()), m_flags(flags) { } diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index a767e8f9..330735ed 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -222,7 +222,8 @@ int checkIncompatibleModule(const env::Module& m) static const std::map names = { {"NahimicOSD.dll", "Nahimic"}, - {"RTSSHooks64.dll", "RivaTuner Statistics Server"} + {"RTSSHooks64.dll", "RivaTuner Statistics Server"}, + {"SSAudioOSD.dll", "SteelSeries Audio"} }; const QFileInfo file(m.path()); -- cgit v1.3.1 From c3c1183308dbe00a14b8cf5e3c58e92bd9edfaf6 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 12 Dec 2019 14:47:35 -0500 Subject: fixed alt colors in saves list for dark.qss translated some sanity checks warnings fixed filter list not refreshing selection correctly --- src/filterlist.cpp | 38 +++++++++++++++++++------------------- src/filterlist.h | 1 + src/organizer_en.ts | 17 +++++++++++++++++ src/sanitychecks.cpp | 21 ++++++++++++++------- src/stylesheets/dark.qss | 2 +- 5 files changed, 52 insertions(+), 27 deletions(-) (limited to 'src/sanitychecks.cpp') diff --git a/src/filterlist.cpp b/src/filterlist.cpp index 6a85bcaa..69aca4c5 100644 --- a/src/filterlist.cpp +++ b/src/filterlist.cpp @@ -275,10 +275,7 @@ void FilterList::addSpecialCriteria(int type) void FilterList::refresh() { - QStringList selectedItems; - for (QTreeWidgetItem *item : ui->filters->selectedItems()) { - selectedItems.append(item->text(0)); - } + const auto oldSelection = selectedCriteria(); ui->filters->clear(); @@ -315,33 +312,30 @@ void FilterList::refresh() } addCategoryCriteria(nullptr, categoriesUsed, 0); - - for (const QString &item : selectedItems) { - QList matches = ui->filters->findItems( - item, Qt::MatchFixedString | Qt::MatchRecursive); - - if (matches.size() > 0) { - matches.at(0)->setSelected(true); - } - } + setSelection(oldSelection); } void FilterList::setSelection(const std::vector& criteria) { for (int i = 0; i < ui->filters->topLevelItemCount(); ++i) { - const auto* item = dynamic_cast( - ui->filters->topLevelItem(i)); - + auto* item = dynamic_cast(ui->filters->topLevelItem(i)); if (!item) { continue; } + bool found = false; + for (auto&& c : criteria) { if (item->type() == c.type && item->id() == c.id) { - ui->filters->setCurrentItem(ui->filters->topLevelItem(i)); + item->setState(c.inverse ? CriteriaItem::Inverted : CriteriaItem::Active); + found = true; break; } } + + if (!found) { + item->setState(CriteriaItem::Inactive); + } } } @@ -378,7 +372,7 @@ bool FilterList::cycleItem(QTreeWidgetItem* item, int direction) return true; } -void FilterList::checkCriteria() +std::vector FilterList::selectedCriteria() const { std::vector criteria; @@ -395,7 +389,12 @@ void FilterList::checkCriteria() } } - emit criteriaChanged(criteria); + return criteria; +} + +void FilterList::checkCriteria() +{ + emit criteriaChanged(selectedCriteria()); } void FilterList::editCategories() @@ -404,6 +403,7 @@ void FilterList::editCategories() if (dialog.exec() == QDialog::Accepted) { dialog.commitChanges(); + refresh(); } } diff --git a/src/filterlist.h b/src/filterlist.h index 72cbe8bf..b0ebc9a4 100644 --- a/src/filterlist.h +++ b/src/filterlist.h @@ -39,6 +39,7 @@ private: void editCategories(); void checkCriteria(); + std::vector selectedCriteria() const; bool cycleItem(QTreeWidgetItem* item, int direction); QTreeWidgetItem* addCriteriaItem( diff --git a/src/organizer_en.ts b/src/organizer_en.ts index 95854200..6101c8e7 100644 --- a/src/organizer_en.ts +++ b/src/organizer_en.ts @@ -6754,6 +6754,23 @@ You can restart Mod Organizer as administrator and try launching the program aga Exit Now + + + '%1': file is blocked (%2) + '%1': file is blocked ('%2') + + + + + '%1' seems to be missing, an antivirus may have deleted it + + + + + %1 is loaded. This program is known to cause issues with Mod Organizer, such as freezing or blank windows. Consider uninstalling it. + %1 is loaded. This program is known to cause issues with Mod Organizer, such as freezing or blank windows. Consider uninstalling it. (%2) + + QueryOverwriteDialog diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index 330735ed..bdf762d9 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -110,7 +110,11 @@ bool isFileBlocked(const QFileInfo& fi) } // file is blocked - log::warn("'{}': file is blocked, zone id is {}", path, toString(z)); + log::warn("{}", QObject::tr( + "'%1': file is blocked (%2)") + .arg(path) + .arg(toString(z))); + return true; } @@ -199,9 +203,9 @@ int checkMissingFiles() const QFileInfo file(dir + "/" + name); if (!file.exists()) { - log::warn( - "'{}' seems to be missing, an antivirus may have deleted it", - file.absoluteFilePath()); + log::warn("{}", QObject::tr( + "'%1' seems to be missing, an antivirus may have deleted it") + .arg(file.absoluteFilePath())); ++n; } @@ -231,10 +235,13 @@ int checkIncompatibleModule(const env::Module& m) for (auto&& p : names) { if (file.fileName().compare(p.first, Qt::CaseInsensitive) == 0) { - log::warn( - "{} is loaded. This program is known to cause issues with " + log::warn("{}", QObject::tr( + "%1 is loaded. This program is known to cause issues with " "Mod Organizer, such as freezing or blank windows. Consider " - "uninstalling it. ({})", p.second, file.absoluteFilePath()); + "uninstalling it.") + .arg(p.second)); + + log::warn("{}", file.absoluteFilePath()); ++n; } diff --git a/src/stylesheets/dark.qss b/src/stylesheets/dark.qss index 9d11109d..91f808bc 100644 --- a/src/stylesheets/dark.qss +++ b/src/stylesheets/dark.qss @@ -349,7 +349,7 @@ QToolButton:hover padding-bottom: 2px; } -QTreeView +QTreeView, QListView { color: #E9E6E4; background-color: #3F4041; -- cgit v1.3.1 From 26158687a8a6d3f9eef38a8004f242cf8046268c Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 12 Dec 2019 14:51:42 -0500 Subject: added SS3DevProps.dll to checks --- src/organizer_en.ts | 2 +- src/sanitychecks.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/sanitychecks.cpp') diff --git a/src/organizer_en.ts b/src/organizer_en.ts index 6101c8e7..593e4457 100644 --- a/src/organizer_en.ts +++ b/src/organizer_en.ts @@ -6766,7 +6766,7 @@ You can restart Mod Organizer as administrator and try launching the program aga - + %1 is loaded. This program is known to cause issues with Mod Organizer, such as freezing or blank windows. Consider uninstalling it. %1 is loaded. This program is known to cause issues with Mod Organizer, such as freezing or blank windows. Consider uninstalling it. (%2) diff --git a/src/sanitychecks.cpp b/src/sanitychecks.cpp index bdf762d9..6da42e79 100644 --- a/src/sanitychecks.cpp +++ b/src/sanitychecks.cpp @@ -227,7 +227,8 @@ int checkIncompatibleModule(const env::Module& m) static const std::map names = { {"NahimicOSD.dll", "Nahimic"}, {"RTSSHooks64.dll", "RivaTuner Statistics Server"}, - {"SSAudioOSD.dll", "SteelSeries Audio"} + {"SSAudioOSD.dll", "SteelSeries Audio"}, + {"SS3DevProps.dll", "Sonic Suite 3"} }; const QFileInfo file(m.path()); -- cgit v1.3.1