From 57e65abf75f62bf07880e0a2f888eaf5f14f0871 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Wed, 27 Dec 2017 01:31:43 +0200 Subject: Clean up proxy spawning a process (cleaner args forwarding and QProcess had some problems even without arguments) --- src/main.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 11 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 99ff641a..5418abc2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -78,6 +78,7 @@ along with Mod Organizer. If not, see . #include #include +#include #include @@ -139,6 +140,60 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except return EXCEPTION_CONTINUE_SEARCH; } +// Parses the first parseArgCount arguments of the current process command line and returns +// them in parsedArgs, the rest of the command line is returned untouched. +LPCWSTR UntouchedCommandLineArguments(int parseArgCount, std::vector& parsedArgs) +{ + LPCWSTR cmd = GetCommandLineW(); + LPCWSTR arg = nullptr; // to skip executable name + for (; parseArgCount >= 0 && *cmd; ++cmd) + { + if (*cmd == '"') { + int escaped = 0; + for (++cmd; *cmd && (*cmd != '"' || escaped % 2 != 0); ++cmd) + escaped = *cmd == '\\' ? escaped + 1 : 0; + } + if (*cmd == ' ') { + if (arg) + if (cmd-1 > arg && *arg == '"' && *(cmd-1) == '"') + parsedArgs.push_back(std::wstring(arg+1, cmd-1)); + else + parsedArgs.push_back(std::wstring(arg, cmd)); + arg = cmd + 1; + --parseArgCount; + } + } + return cmd; +} + +static int SpawnWaitProcess(LPCWSTR workingDirectory, LPCWSTR commandLine) { + PROCESS_INFORMATION pi{ 0 }; + STARTUPINFO si{ 0 }; + si.cb = sizeof(si); + std::wstring commandLineCopy = commandLine; + + if (!CreateProcessW(NULL, &commandLineCopy[0], NULL, NULL, FALSE, 0, NULL, workingDirectory, &si, &pi)) { + // A bit of a problem where to log the error message here, at least this way you can get the message + // using a either DebugView or a live debugger: + std::wostringstream ost; + ost << L"CreateProcess failed: " << commandLine << ", " << GetLastError(); + OutputDebugStringW(ost.str().c_str()); + return -1; + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exitCode = (DWORD)-1; + ::GetExitCodeProcess(pi.hProcess, &exitCode); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return static_cast(exitCode); +} + +static DWORD WaitForProcess() { + +} + static bool HaveWriteAccess(const std::wstring &path) { bool writable = false; @@ -532,20 +587,16 @@ int runApplication(MOApplication &application, SingleInstance &instance, int main(int argc, char *argv[]) { + if (argc >= 4) { + std::vector arg; + auto args = UntouchedCommandLineArguments(2, arg); + if (arg[0] == L"launch") + return SpawnWaitProcess(arg[1].c_str(), args); + } + MOApplication application(argc, argv); QStringList arguments = application.arguments(); - if ((arguments.length() >= 4) && (arguments.at(1) == "launch")) { - // all we're supposed to do is launch another process - QProcess process; - process.setWorkingDirectory(QDir::fromNativeSeparators(arguments.at(2))); - process.setProgram(QDir::fromNativeSeparators(arguments.at(3))); - process.setArguments(arguments.mid(4)); - process.start(); - process.waitForFinished(-1); - return process.exitCode(); - } - setupPath(); #if !defined(QT_NO_SSL) -- cgit v1.3.1