diff options
Diffstat (limited to 'src/corelib/io/qprocess_win.cpp')
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 329d1842f0..fc4d3b225d 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -358,7 +358,8 @@ void QProcessPrivate::closeChannel(Channel *channel) destroyPipe(channel->pipe); } -static QString qt_create_commandline(const QString &program, const QStringList &arguments) +static QString qt_create_commandline(const QString &program, const QStringList &arguments, + const QString &nativeArguments) { QString args; if (!program.isEmpty()) { @@ -387,6 +388,13 @@ static QString qt_create_commandline(const QString &program, const QStringList & } args += QLatin1Char(' ') + tmp; } + + if (!nativeArguments.isEmpty()) { + if (!args.isEmpty()) + args += QLatin1Char(' '); + args += nativeArguments; + } + return args; } @@ -450,6 +458,16 @@ static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash & return envlist; } +bool QProcessPrivate::callCreateProcess(QProcess::CreateProcessArguments *cpargs) +{ + if (modifyCreateProcessArgs) + modifyCreateProcessArgs(cpargs); + return CreateProcess(cpargs->applicationName, cpargs->arguments, cpargs->processAttributes, + cpargs->threadAttributes, cpargs->inheritHandles, cpargs->flags, + cpargs->environment, cpargs->currentDirectory, cpargs->startupInfo, + cpargs->processInformation); +} + void QProcessPrivate::startProcess() { Q_Q(QProcess); @@ -472,15 +490,10 @@ void QProcessPrivate::startProcess() !openChannel(stderrChannel)) return; - QString args = qt_create_commandline(program, arguments); + const QString args = qt_create_commandline(program, arguments, nativeArguments); QByteArray envlist; if (environment.d.constData()) envlist = qt_create_environment(environment.d.constData()->hash); - if (!nativeArguments.isEmpty()) { - if (!args.isEmpty()) - args += QLatin1Char(' '); - args += nativeArguments; - } #if defined QPROCESS_DEBUG qDebug("Creating process"); @@ -507,18 +520,14 @@ void QProcessPrivate::startProcess() const QString nativeWorkingDirectory = QDir::toNativeSeparators(workingDirectory); QProcess::CreateProcessArguments cpargs = { - 0, (wchar_t*)args.utf16(), - 0, 0, TRUE, dwCreationFlags, - environment.isEmpty() ? 0 : envlist.data(), - nativeWorkingDirectory.isEmpty() ? Q_NULLPTR : (wchar_t*)nativeWorkingDirectory.utf16(), + nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())), + nullptr, nullptr, true, dwCreationFlags, + environment.isEmpty() ? nullptr : envlist.data(), + nativeWorkingDirectory.isEmpty() + ? nullptr : reinterpret_cast<const wchar_t *>(nativeWorkingDirectory.utf16()), &startupInfo, pid }; - if (modifyCreateProcessArgs) - modifyCreateProcessArgs(&cpargs); - success = CreateProcess(cpargs.applicationName, cpargs.arguments, cpargs.processAttributes, - cpargs.threadAttributes, cpargs.inheritHandles, cpargs.flags, - cpargs.environment, cpargs.currentDirectory, cpargs.startupInfo, - cpargs.processInformation); + success = callCreateProcess(&cpargs); QString errorString; if (!success) { @@ -826,6 +835,7 @@ bool QProcessPrivate::writeToStdin() // Use ShellExecuteEx() to trigger an UAC prompt when CreateProcess()fails // with ERROR_ELEVATION_REQUIRED. static bool startDetachedUacPrompt(const QString &programIn, const QStringList &arguments, + const QString &nativeArguments, const QString &workingDir, qint64 *pid) { typedef BOOL (WINAPI *ShellExecuteExType)(SHELLEXECUTEINFOW *); @@ -836,7 +846,8 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList & if (!shellExecuteEx) return false; - const QString args = qt_create_commandline(QString(), arguments); // needs arguments only + const QString args = qt_create_commandline(QString(), // needs arguments only + arguments, nativeArguments); SHELLEXECUTEINFOW shellExecuteExInfo; memset(&shellExecuteExInfo, 0, sizeof(SHELLEXECUTEINFOW)); shellExecuteExInfo.cbSize = sizeof(SHELLEXECUTEINFOW); @@ -859,14 +870,21 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList & return true; } -bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid) +bool QProcessPrivate::startDetached(qint64 *pid) { static const DWORD errorElevationRequired = 740; - QString args = qt_create_commandline(program, arguments); + QString args = qt_create_commandline(program, arguments, nativeArguments); bool success = false; PROCESS_INFORMATION pinfo; + void *envPtr = nullptr; + QByteArray envlist; + if (environment.d.constData()) { + envlist = qt_create_environment(environment.d.constData()->hash); + envPtr = envlist.data(); + } + DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW); dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, @@ -874,10 +892,14 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - success = CreateProcess(0, (wchar_t*)args.utf16(), - 0, 0, FALSE, dwCreationFlags, 0, - workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(), - &startupInfo, &pinfo); + QProcess::CreateProcessArguments cpargs = { + nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())), + nullptr, nullptr, false, dwCreationFlags, envPtr, + workingDirectory.isEmpty() + ? nullptr : reinterpret_cast<const wchar_t *>(workingDirectory.utf16()), + &startupInfo, &pinfo + }; + success = callCreateProcess(&cpargs); if (success) { CloseHandle(pinfo.hThread); @@ -885,7 +907,10 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a if (pid) *pid = pinfo.dwProcessId; } else if (GetLastError() == errorElevationRequired) { - success = startDetachedUacPrompt(program, arguments, workingDir, pid); + if (envPtr) + qWarning("QProcess: custom environment will be ignored for detached elevated process."); + success = startDetachedUacPrompt(program, arguments, nativeArguments, + workingDirectory, pid); } return success; |