diff options
| author | isanae <14251494+isanae@users.noreply.github.com> | 2019-09-12 02:45:03 -0400 |
|---|---|---|
| committer | isanae <14251494+isanae@users.noreply.github.com> | 2019-09-12 02:45:03 -0400 |
| commit | ac6bc5fd01e115d523de65a02e46b2cde1188d37 (patch) | |
| tree | 6849ce32e1f869b3fc39d01e26e06607104297bf /src | |
| parent | bf3d7527801bcba16ba01735efd3d5acc052f485 (diff) | |
testForSteam() now uses env to get processes
moved processes from env.cpp to envmodule.cpp, merged what crash dumps did with what was in testForSteam()
Diffstat (limited to 'src')
| -rw-r--r-- | src/env.cpp | 105 | ||||
| -rw-r--r-- | src/env.h | 5 | ||||
| -rw-r--r-- | src/envmodule.cpp | 81 | ||||
| -rw-r--r-- | src/envmodule.h | 24 | ||||
| -rw-r--r-- | src/spawn.cpp | 62 |
5 files changed, 131 insertions, 146 deletions
diff --git a/src/env.cpp b/src/env.cpp index e2b85560..34f53294 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -72,6 +72,11 @@ const std::vector<Module>& Environment::loadedModules() const return m_modules; } +std::vector<Process> Environment::runningProcesses() const +{ + return getRunningProcesses(); +} + const WindowsInfo& Environment::windowsInfo() const { if (!m_windows) { @@ -166,18 +171,6 @@ void Environment::dumpDisks(const Settings& s) const } -struct Process -{ - std::wstring filename; - DWORD pid; - - Process(std::wstring f, DWORD id) - : filename(std::move(f)), pid(id) - { - } -}; - - // returns the filename of the given process or the current one // std::wstring processFilename(HANDLE process=INVALID_HANDLE_VALUE) @@ -233,84 +226,6 @@ std::wstring processFilename(HANDLE process=INVALID_HANDLE_VALUE) return {}; } -std::vector<DWORD> runningProcessesIds() -{ - // double the buffer size 10 times - const int MaxTries = 10; - - // initial size of 300 processes, unlikely to be more than that - std::size_t size = 300; - - for (int tries=0; tries<MaxTries; ++tries) { - auto ids = std::make_unique<DWORD[]>(size); - std::fill(ids.get(), ids.get() + size, 0); - - DWORD bytesGiven = static_cast<DWORD>(size * sizeof(ids[0])); - DWORD bytesWritten = 0; - - if (!EnumProcesses(ids.get(), bytesGiven, &bytesWritten)) - { - const auto e = GetLastError(); - - std::wcerr - << L"failed to enumerate processes, " - << formatSystemMessage(e) << L"\n"; - - return {}; - } - - if (bytesWritten == bytesGiven) { - // no way to distinguish between an exact fit and not enough space, - // just try again - size *= 2; - continue; - } - - const auto count = bytesWritten / sizeof(ids[0]); - return std::vector<DWORD>(ids.get(), ids.get() + count); - } - - std::cerr << L"too many processes to enumerate"; - return {}; -} - -std::vector<Process> runningProcesses() -{ - const auto pids = runningProcessesIds(); - std::vector<Process> v; - - for (const auto& pid : pids) { - if (pid == 0) { - // the idle process has pid 0 and seems to be picked up by EnumProcesses() - continue; - } - - HandlePtr h(OpenProcess( - PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid)); - - if (!h) { - const auto e = GetLastError(); - - if (e != ERROR_ACCESS_DENIED) { - // don't log access denied, will happen a lot for system processes, even - // when elevated - std::wcerr - << L"failed to open process " << pid << L", " - << formatSystemMessage(e) << L"\n"; - } - - continue; - } - - auto filename = processFilename(h.get()); - if (!filename.empty()) { - v.emplace_back(std::move(filename), pid); - } - } - - return v; -} - DWORD findOtherPid() { const std::wstring defaultName = L"ModOrganizer.exe"; @@ -322,7 +237,7 @@ DWORD findOtherPid() std::wclog << L"this process id is " << thisPid << L"\n"; // getting the filename for this process, assumes the other process has the - // smae one + // same one auto filename = processFilename(); if (filename.empty()) { std::wcerr @@ -335,15 +250,15 @@ DWORD findOtherPid() } // getting all running processes - const auto processes = runningProcesses(); + const auto processes = getRunningProcesses(); std::wclog << L"there are " << processes.size() << L" processes running\n"; // going through processes, trying to find one with the same name and a // different pid than this process has for (const auto& p : processes) { - if (p.filename == filename) { - if (p.pid != thisPid) { - return p.pid; + if (p.name() == filename) { + if (p.pid() != thisPid) { + return p.pid(); } } } @@ -7,6 +7,7 @@ namespace env { class Module; +class Process; class SecurityProduct; class WindowsInfo; class Metrics; @@ -129,6 +130,10 @@ public: // const std::vector<Module>& loadedModules() const; + // list of running processes; not cached + // + std::vector<Process> runningProcesses() const; + // information about the operating system // const WindowsInfo& windowsInfo() const; diff --git a/src/envmodule.cpp b/src/envmodule.cpp index 8cea414a..3f1f8912 100644 --- a/src/envmodule.cpp +++ b/src/envmodule.cpp @@ -320,6 +320,40 @@ QString Module::getMD5() const } +Process::Process(DWORD pid, QString name) + : m_pid(pid), m_name(std::move(name)) +{ +} + +DWORD Process::pid() const +{ + return m_pid; +} + +const QString& Process::name() const +{ + return m_name; +} + +// whether this process can be accessed; fails if the current process doesn't +// have the proper permissions +// +bool Process::canAccess() const +{ + HandlePtr h(OpenProcess( + PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, m_pid)); + + if (!h) { + const auto e = GetLastError(); + if (e == ERROR_ACCESS_DENIED) { + return false; + } + } + + return true; +} + + std::vector<Module> getLoadedModules() { HandlePtr snapshot(CreateToolhelp32Snapshot( @@ -373,4 +407,51 @@ std::vector<Module> getLoadedModules() return v; } + +std::vector<Process> getRunningProcesses() +{ + HandlePtr snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + + if (snapshot.get() == INVALID_HANDLE_VALUE) + { + const auto e = GetLastError(); + log::error("CreateToolhelp32Snapshot() failed, {}", formatSystemMessage(e)); + return {}; + } + + PROCESSENTRY32 entry = {}; + entry.dwSize = sizeof(entry); + + // first process, this shouldn't fail because there's at least one process + // running + if (!Process32First(snapshot.get(), &entry)) { + const auto e = GetLastError(); + log::error("Process32First() failed, {}", formatSystemMessage(e)); + return {}; + } + + std::vector<Process> v; + + for (;;) + { + v.push_back(Process( + entry.th32ProcessID, + QString::fromStdWString(entry.szExeFile))); + + // next process + if (!Process32Next(snapshot.get(), &entry)) + { + const auto e = GetLastError(); + + // no more processes is not an error + if (e != ERROR_NO_MORE_FILES) + log::error("Process32Next() failed, {}", formatSystemMessage(e)); + + break; + } + } + + return v; +} + } // namespace diff --git a/src/envmodule.h b/src/envmodule.h index 3f0f99ab..deb7520f 100644 --- a/src/envmodule.h +++ b/src/envmodule.h @@ -12,7 +12,7 @@ namespace env class Module { public: - explicit Module(QString path, std::size_t fileSize); + Module(QString path, std::size_t fileSize); // returns the module's path // @@ -96,6 +96,28 @@ private: }; +// represents one process +// +class Process +{ +public: + Process(DWORD pid, QString name); + + DWORD pid() const; + const QString& name() const; + + // whether this process can be accessed; fails if the current process doesn't + // have the proper permissions + // + bool canAccess() const; + +private: + DWORD m_pid; + QString m_name; +}; + + +std::vector<Process> getRunningProcesses(); std::vector<Module> getLoadedModules(); } // namespace env diff --git a/src/spawn.cpp b/src/spawn.cpp index a56df23a..604f9ffa 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -24,6 +24,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "env.h"
#include "envwindows.h"
#include "envsecurity.h"
+#include "envmodule.h"
#include "settings.h"
#include <errorcodes.h>
#include <report.h>
@@ -49,7 +50,6 @@ namespace spawn namespace
{
-
std::wstring pathEnv()
{
std::wstring s(4000, L' ');
@@ -249,6 +249,9 @@ void spawnFailed(const SpawnParameters& sp, DWORD code) "This error typically happens because an antivirus is preventing Mod "
"Organizer from starting programs. Add an exclusion for Mod Organizer's "
"installation folder in your antivirus and try again.");
+ } else if (code == ERROR_FILE_NOT_FOUND) {
+ content = QObject::tr("The file '%1' does not exist.")
+ .arg(QDir::toNativeSeparators(sp.binary.absoluteFilePath()));
} else {
content = QString::fromStdWString(formatSystemMessage(code));
}
@@ -337,10 +340,7 @@ void startBinaryAdmin(const SpawnParameters& sp) bool checkBinary(QWidget* parent, const SpawnParameters& sp)
{
if (!sp.binary.exists()) {
- reportError(
- QObject::tr("Executable not found: %1")
- .arg(sp.binary.absoluteFilePath()));
-
+ spawnFailed(sp, ERROR_FILE_NOT_FOUND);
return false;
}
@@ -349,61 +349,23 @@ bool checkBinary(QWidget* parent, const SpawnParameters& sp) bool testForSteam(bool *found, bool *access)
{
- HANDLE hProcessSnap;
- HANDLE hProcess;
- PROCESSENTRY32 pe32;
- DWORD lastError;
-
if (found == nullptr || access == nullptr) {
return false;
}
- // Take a snapshot of all processes in the system.
- hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (hProcessSnap == INVALID_HANDLE_VALUE) {
- lastError = GetLastError();
- log::error("unable to get snapshot of processes (error {})", lastError);
- return false;
- }
-
- // Retrieve information about the first process,
- // and exit if unsuccessful
- pe32.dwSize = sizeof(PROCESSENTRY32);
- if (!Process32First(hProcessSnap, &pe32)) {
- lastError = GetLastError();
- log::error("unable to get first process (error {})", lastError);
- CloseHandle(hProcessSnap);
- return false;
- }
-
+ const auto ps = env::Environment().runningProcesses();
*found = false;
- *access = true;
-
- // Now walk the snapshot of processes, and
- // display information about each process in turn
- do {
- if ((_tcsicmp(pe32.szExeFile, L"Steam.exe") == 0) ||
- (_tcsicmp(pe32.szExeFile, L"SteamService.exe") == 0)) {
+ for (const auto& p : ps) {
+ if ((p.name().compare("Steam.exe", Qt::CaseInsensitive) == 0) ||
+ (p.name().compare("SteamService.exe", Qt::CaseInsensitive) == 0))
+ {
*found = true;
-
- // Try to open the process to determine if MO has the proper access
- hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- FALSE, pe32.th32ProcessID);
- if (hProcess == NULL) {
- lastError = GetLastError();
- if (lastError == ERROR_ACCESS_DENIED) {
- *access = false;
- }
- } else {
- CloseHandle(hProcess);
- }
+ *access = p.canAccess();
break;
}
+ }
- } while(Process32Next(hProcessSnap, &pe32));
-
- CloseHandle(hProcessSnap);
return true;
}
|
