summaryrefslogtreecommitdiff
path: root/src/spawn.cpp
diff options
context:
space:
mode:
authorTannin <Tannin@Serenity>2013-02-03 12:49:25 +0100
committerTannin <Tannin@Serenity>2013-02-03 12:49:25 +0100
commit981f8b3acf7e76f27c02f4ced80d55b424cc7497 (patch)
tree0f504d99d1e5fe197258febff3c147d0725abda4 /src/spawn.cpp
initial commit to mercurial repository.
Corresponds to MO version 0.12.6
Diffstat (limited to 'src/spawn.cpp')
-rw-r--r--src/spawn.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/spawn.cpp b/src/spawn.cpp
new file mode 100644
index 00000000..13e74f93
--- /dev/null
+++ b/src/spawn.cpp
@@ -0,0 +1,109 @@
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "spawn.h"
+#include "report.h"
+#include "utility.h"
+#include <gameinfo.h>
+#include <inject.h>
+#include <appconfig.h>
+#include <windows_error.h>
+#include <QApplication>
+
+
+bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, bool suspended, HANDLE& processHandle, HANDLE& threadHandle)
+{
+ STARTUPINFO si;
+ ::ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ int length = wcslen(binary) + wcslen(arguments) + 4;
+ wchar_t *commandLine = NULL;
+ 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(commandLine, length, L"\"%ls\"", binary);
+
+ }
+
+ PROCESS_INFORMATION pi;
+ BOOL success = ::CreateProcess(NULL,
+ commandLine,
+ NULL, NULL, // no special process or thread attributes
+ FALSE, // don't inherit handle
+ suspended ? CREATE_SUSPENDED : 0, // create suspended so I have time to inject the DLL
+ NULL, // same environment as parent
+ currentDirectory, // current directory
+ &si, &pi // startup and process information
+ );
+
+ delete [] commandLine;
+
+ if (!success) {
+ throw windows_error("failed to start process");
+ }
+
+ processHandle = pi.hProcess;
+ threadHandle = pi.hThread;
+ return true;
+}
+
+
+HANDLE startBinary(const QFileInfo &binary, const QString &arguments, const QString& profileName, int logLevel, const QDir &currentDirectory, bool hooked)
+{
+ 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(), hooked, processHandle, threadHandle)) {
+ reportError(QObject::tr("failed to spawn \"%1\"").arg(binary.fileName()));
+ return INVALID_HANDLE_VALUE;
+ }
+ } catch (const windows_error &e) {
+ reportError(QObject::tr("failed to spawn \"%1\": %2").arg(binary.fileName()).arg(e.what()));
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (hooked) {
+ try {
+ QFileInfo dllInfo(QApplication::applicationDirPath() + "/" + ToQString(AppConfig::hookDLLName()));
+ if (!dllInfo.exists()) {
+ reportError(QObject::tr("\"%1\" doesn't exist").arg(dllInfo.fileName()));
+ return INVALID_HANDLE_VALUE;
+ }
+ injectDLL(processHandle, threadHandle,
+ QDir::toNativeSeparators(dllInfo.canonicalFilePath()).toLocal8Bit().constData(),
+ ToWString(profileName).c_str(), logLevel);
+ } catch (const windows_error& e) {
+ reportError(QObject::tr("failed to inject dll into \"%1\": %2").arg(binary.fileName()).arg(e.what()));
+ ::TerminateProcess(processHandle, 1);
+ return INVALID_HANDLE_VALUE;
+ }
+#ifdef _DEBUG
+ reportError("ready?");
+#endif // DEBUG
+ if (::ResumeThread(threadHandle) == (DWORD)-1) {
+ reportError(QObject::tr("failed to run \"%1\"").arg(binary.fileName()));
+ return INVALID_HANDLE_VALUE;
+ }
+ }
+ return processHandle;
+}