summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-09-12 02:45:03 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2019-09-12 02:45:03 -0400
commitac6bc5fd01e115d523de65a02e46b2cde1188d37 (patch)
tree6849ce32e1f869b3fc39d01e26e06607104297bf
parentbf3d7527801bcba16ba01735efd3d5acc052f485 (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()
-rw-r--r--src/env.cpp105
-rw-r--r--src/env.h5
-rw-r--r--src/envmodule.cpp81
-rw-r--r--src/envmodule.h24
-rw-r--r--src/spawn.cpp62
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();
}
}
}
diff --git a/src/env.h b/src/env.h
index 46095ca3..6222c86b 100644
--- a/src/env.h
+++ b/src/env.h
@@ -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;
}