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