summaryrefslogtreecommitdiff
path: root/src/spawn.cpp
diff options
context:
space:
mode:
authorBrian Munro <brian.alexander.munro@gmail.com>2018-02-22 18:02:02 +0200
committerGitHub <noreply@github.com>2018-02-22 18:02:02 +0200
commit28714f0eb800f2170acbf29dddce1582d20d6b8b (patch)
tree0684c123db375336e0e03f0240155a12e744db16 /src/spawn.cpp
parent0bcd752b2758bdb072b498ccc90905276be065e9 (diff)
parent5e5c9c07291f6b09623d31c92b1fb61c4ede576e (diff)
Merge pull request #236 from SuperSandro2000/new_vfs_library
Update reame.md
Diffstat (limited to 'src/spawn.cpp')
-rw-r--r--src/spawn.cpp226
1 files changed, 108 insertions, 118 deletions
diff --git a/src/spawn.cpp b/src/spawn.cpp
index ac8ccf30..f5b0bdb2 100644
--- a/src/spawn.cpp
+++ b/src/spawn.cpp
@@ -21,10 +21,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "report.h"
#include "utility.h"
-#include <report.h>
-#include <usvfs.h>
#include <Shellapi.h>
#include <appconfig.h>
+#include <report.h>
+#include <usvfs.h>
#include <windows_error.h>
#include <QApplication>
@@ -37,137 +37,127 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
using namespace MOShared;
-
static const int BUFSIZE = 4096;
-static bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory,
- bool suspended, bool hooked,
- HANDLE stdOut, HANDLE stdErr,
- HANDLE& processHandle, HANDLE& threadHandle)
-{
- BOOL inheritHandles = FALSE;
- STARTUPINFO si;
- ::ZeroMemory(&si, sizeof(si));
- if (stdOut != INVALID_HANDLE_VALUE) {
- si.hStdOutput = stdOut;
- inheritHandles = TRUE;
- si.dwFlags |= STARTF_USESTDHANDLES;
- }
- if (stdErr != INVALID_HANDLE_VALUE) {
- si.hStdError = stdErr;
- inheritHandles = TRUE;
- si.dwFlags |= STARTF_USESTDHANDLES;
- }
- si.cb = sizeof(si);
- size_t length = wcslen(binary) + wcslen(arguments) + 4;
- wchar_t *commandLine = nullptr;
- if (arguments[0] != L'\0') {
- commandLine = new wchar_t[length];
- _snwprintf(commandLine, length, L"\"%ls\" %ls", binary, arguments);
- } else {
- commandLine = new wchar_t[length];
- _snwprintf_s(commandLine, length, _TRUNCATE, L"\"%ls\"", binary);
- }
+static bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, bool suspended, bool hooked,
+ HANDLE stdOut, HANDLE stdErr, HANDLE& processHandle, HANDLE& threadHandle) {
+ BOOL inheritHandles = FALSE;
+ STARTUPINFO si;
+ ::ZeroMemory(&si, sizeof(si));
+ if (stdOut != INVALID_HANDLE_VALUE) {
+ si.hStdOutput = stdOut;
+ inheritHandles = TRUE;
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ }
+ if (stdErr != INVALID_HANDLE_VALUE) {
+ si.hStdError = stdErr;
+ inheritHandles = TRUE;
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ }
+ si.cb = sizeof(si);
+ size_t length = wcslen(binary) + wcslen(arguments) + 4;
+ wchar_t* commandLine = nullptr;
+ if (arguments[0] != L'\0') {
+ commandLine = new wchar_t[length];
+ _snwprintf(commandLine, length, L"\"%ls\" %ls", binary, arguments);
+ } else {
+ commandLine = new wchar_t[length];
+ _snwprintf_s(commandLine, length, _TRUNCATE, L"\"%ls\"", binary);
+ }
- QString moPath = QCoreApplication::applicationDirPath();
+ QString moPath = QCoreApplication::applicationDirPath();
- boost::scoped_array<TCHAR> 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);
- }
+ boost::scoped_array<TCHAR> 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);
+ }
- {
- boost::scoped_array<TCHAR> newPath(new TCHAR[offset + moPath.length() + 2]);
- _tcsncpy(newPath.get(), oldPath.get(), offset);
- newPath.get()[offset] = '\0';
- _tcsncat(newPath.get(), TEXT(";"), 1);
- _tcsncat(newPath.get(), ToWString(QDir::toNativeSeparators(moPath)).c_str(), moPath.length());
+ {
+ boost::scoped_array<TCHAR> newPath(new TCHAR[offset + moPath.length() + 2]);
+ _tcsncpy(newPath.get(), oldPath.get(), offset);
+ newPath.get()[offset] = '\0';
+ _tcsncat(newPath.get(), TEXT(";"), 1);
+ _tcsncat(newPath.get(), ToWString(QDir::toNativeSeparators(moPath)).c_str(), moPath.length());
- ::SetEnvironmentVariable(TEXT("PATH"), newPath.get());
- }
+ ::SetEnvironmentVariable(TEXT("PATH"), newPath.get());
+ }
- PROCESS_INFORMATION pi;
- BOOL success = FALSE;
- if (hooked) {
- success = ::CreateProcessHooked(nullptr,
- commandLine,
- nullptr, nullptr, // no special process or thread attributes
- inheritHandles, // inherit handles if we plan to use stdout or stderr reroute
- CREATE_BREAKAWAY_FROM_JOB,
- nullptr, // same environment as parent
- currentDirectory, // current directory
- &si, &pi // startup and process information
- );
- } else {
- success = ::CreateProcess(nullptr,
- commandLine,
- nullptr, nullptr, // no special process or thread attributes
- inheritHandles, // inherit handles if we plan to use stdout or stderr reroute
- CREATE_BREAKAWAY_FROM_JOB,
- nullptr, // same environment as parent
- currentDirectory, // current directory
- &si, &pi // startup and process information
- );
- }
+ PROCESS_INFORMATION pi;
+ BOOL success = FALSE;
+ if (hooked) {
+ success =
+ ::CreateProcessHooked(nullptr, commandLine, nullptr, nullptr, // no special process or thread attributes
+ inheritHandles, // inherit handles if we plan to use stdout or stderr reroute
+ CREATE_BREAKAWAY_FROM_JOB,
+ nullptr, // same environment as parent
+ currentDirectory, // current directory
+ &si, &pi // startup and process information
+ );
+ } else {
+ success = ::CreateProcess(nullptr, commandLine, nullptr, nullptr, // no special process or thread attributes
+ inheritHandles, // inherit handles if we plan to use stdout or stderr reroute
+ CREATE_BREAKAWAY_FROM_JOB,
+ nullptr, // same environment as parent
+ currentDirectory, // current directory
+ &si, &pi // startup and process information
+ );
+ }
- ::SetEnvironmentVariable(TEXT("PATH"), oldPath.get());
+ ::SetEnvironmentVariable(TEXT("PATH"), oldPath.get());
- delete [] commandLine;
+ delete[] commandLine;
- if (!success) {
- throw windows_error("failed to start process");
- }
+ if (!success) {
+ throw windows_error("failed to start process");
+ }
- processHandle = pi.hProcess;
- threadHandle = pi.hThread;
- return true;
+ processHandle = pi.hProcess;
+ threadHandle = pi.hThread;
+ return true;
}
+HANDLE startBinary(const QFileInfo& binary, const QString& arguments, const QDir& currentDirectory, bool hooked,
+ HANDLE stdOut, HANDLE stdErr) {
+ HANDLE processHandle, threadHandle;
+ std::wstring binaryName = ToWString(QDir::toNativeSeparators(binary.absoluteFilePath()));
+ std::wstring currentDirectoryName = ToWString(QDir::toNativeSeparators(currentDirectory.absolutePath()));
-HANDLE startBinary(const QFileInfo &binary,
- const QString &arguments,
- const QDir &currentDirectory,
- bool hooked,
- HANDLE stdOut,
- HANDLE stdErr)
-{
- HANDLE processHandle, threadHandle;
- std::wstring binaryName = ToWString(QDir::toNativeSeparators(binary.absoluteFilePath()));
- std::wstring currentDirectoryName = ToWString(QDir::toNativeSeparators(currentDirectory.absolutePath()));
-
- try {
- if (!spawn(binaryName.c_str(), ToWString(arguments).c_str(), currentDirectoryName.c_str(),
- true, hooked, stdOut, stdErr, processHandle, threadHandle)) {
- reportError(QObject::tr("failed to spawn \"%1\"").arg(binary.fileName()));
- return INVALID_HANDLE_VALUE;
- }
- } catch (const windows_error &e) {
- if (e.getErrorCode() == ERROR_ELEVATION_REQUIRED) {
- // TODO: check if this is really correct. Are all settings updated that the secondary instance may use?
+ try {
+ if (!spawn(binaryName.c_str(), ToWString(arguments).c_str(), currentDirectoryName.c_str(), true, hooked, stdOut,
+ stdErr, processHandle, threadHandle)) {
+ reportError(QObject::tr("failed to spawn \"%1\"").arg(binary.fileName()));
+ return INVALID_HANDLE_VALUE;
+ }
+ } catch (const windows_error& e) {
+ if (e.getErrorCode() == ERROR_ELEVATION_REQUIRED) {
+ // TODO: check if this is really correct. Are all settings updated that the secondary instance may use?
- if (QMessageBox::question(nullptr, QObject::tr("Elevation required"),
- QObject::tr("This process requires elevation to run.\n"
- "This is a potential security risk so I highly advice you to investigate if\n"
- "\"%1\"\n"
- "can be installed to work without elevation.\n\n"
- "Start elevated anyway? "
- "(you will be asked if you want to allow ModOrganizer.exe to make changes to the system)").arg(
- QDir::toNativeSeparators(binary.absoluteFilePath())),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- ::ShellExecuteW(nullptr, L"runas", ToWString(QCoreApplication::applicationFilePath()).c_str(),
- (std::wstring(L"\"") + binaryName + L"\" " + ToWString(arguments)).c_str(), currentDirectoryName.c_str(), SW_SHOWNORMAL);
- return INVALID_HANDLE_VALUE;
- } else {
- return INVALID_HANDLE_VALUE;
- }
- } else {
- reportError(QObject::tr("failed to spawn \"%1\": %2").arg(binary.fileName()).arg(e.what()));
- return INVALID_HANDLE_VALUE;
+ if (QMessageBox::question(
+ nullptr, QObject::tr("Elevation required"),
+ QObject::tr(
+ "This process requires elevation to run.\n"
+ "This is a potential security risk so I highly advice you to investigate if\n"
+ "\"%1\"\n"
+ "can be installed to work without elevation.\n\n"
+ "Start elevated anyway? "
+ "(you will be asked if you want to allow ModOrganizer.exe to make changes to the system)")
+ .arg(QDir::toNativeSeparators(binary.absoluteFilePath())),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ ::ShellExecuteW(nullptr, L"runas", ToWString(QCoreApplication::applicationFilePath()).c_str(),
+ (std::wstring(L"\"") + binaryName + L"\" " + ToWString(arguments)).c_str(),
+ currentDirectoryName.c_str(), SW_SHOWNORMAL);
+ return INVALID_HANDLE_VALUE;
+ } else {
+ return INVALID_HANDLE_VALUE;
+ }
+ } else {
+ reportError(QObject::tr("failed to spawn \"%1\": %2").arg(binary.fileName()).arg(e.what()));
+ return INVALID_HANDLE_VALUE;
+ }
}
- }
- ::CloseHandle(threadHandle);
- return processHandle;
+ ::CloseHandle(threadHandle);
+ return processHandle;
}