summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qprocess_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qprocess_win.cpp')
-rw-r--r--src/corelib/io/qprocess_win.cpp124
1 files changed, 55 insertions, 69 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index aaaccf4e0d..e64b133815 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QPROCESS_DEBUG
#include <qdebug.h>
@@ -64,6 +28,10 @@
QT_BEGIN_NAMESPACE
+constexpr UINT KillProcessExitCode = 0xf291;
+
+using namespace Qt::StringLiterals;
+
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
@@ -172,6 +140,7 @@ static bool qt_create_pipe(Q_PIPE *pipe, bool isInputPipe, BOOL defInheritFlag)
DWORD dwError = GetLastError();
if (dwError != ERROR_PIPE_BUSY || !--attempts) {
qErrnoWarning(dwError, "QProcess: CreateNamedPipe failed.");
+ SetLastError(dwError);
return false;
}
}
@@ -186,8 +155,10 @@ static bool qt_create_pipe(Q_PIPE *pipe, bool isInputPipe, BOOL defInheritFlag)
FILE_FLAG_OVERLAPPED,
NULL);
if (hClient == INVALID_HANDLE_VALUE) {
+ DWORD dwError = GetLastError();
qErrnoWarning("QProcess: CreateFile failed.");
CloseHandle(hServer);
+ SetLastError(dwError);
return false;
}
@@ -204,10 +175,12 @@ static bool qt_create_pipe(Q_PIPE *pipe, bool isInputPipe, BOOL defInheritFlag)
WaitForSingleObject(overlapped.hEvent, INFINITE);
break;
default:
+ dwError = GetLastError();
qErrnoWarning(dwError, "QProcess: ConnectNamedPipe failed.");
CloseHandle(overlapped.hEvent);
CloseHandle(hClient);
CloseHandle(hServer);
+ SetLastError(dwError);
return false;
}
}
@@ -233,8 +206,13 @@ bool QProcessPrivate::openChannel(Channel &channel)
switch (channel.type) {
case Channel::Normal: {
// we're piping this channel to our own process
- if (&channel == &stdinChannel)
- return qt_create_pipe(channel.pipe, true, FALSE);
+ if (&channel == &stdinChannel) {
+ if (!qt_create_pipe(channel.pipe, true, FALSE)) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
+ return false;
+ }
+ return true;
+ }
if (&channel == &stdoutChannel) {
if (!stdoutChannel.reader) {
@@ -247,8 +225,10 @@ bool QProcessPrivate::openChannel(Channel &channel)
q->connect(stderrChannel.reader, SIGNAL(readyRead()), SLOT(_q_canReadStandardError()));
}
}
- if (!qt_create_pipe(channel.pipe, false, FALSE))
+ if (!qt_create_pipe(channel.pipe, false, FALSE)) {
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
return false;
+ }
channel.reader->setHandle(channel.pipe[0]);
channel.reader->startAsyncRead();
@@ -297,7 +277,6 @@ bool QProcessPrivate::openChannel(Channel &channel)
setErrorAndEmit(QProcess::FailedToStart,
QProcess::tr("Could not open output redirection for writing"));
}
- cleanup();
return false;
}
case Channel::PipeSource: {
@@ -314,8 +293,10 @@ bool QProcessPrivate::openChannel(Channel &channel)
Q_ASSERT(source == &stdoutChannel);
Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink);
- if (!qt_create_pipe(source->pipe, /* in = */ false, TRUE)) // source is stdout
+ if (!qt_create_pipe(source->pipe, /* in = */ false, TRUE)) { // source is stdout
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
return false;
+ }
sink->pipe[0] = source->pipe[0];
source->pipe[0] = INVALID_Q_PIPE;
@@ -334,8 +315,10 @@ bool QProcessPrivate::openChannel(Channel &channel)
Q_ASSERT(sink == &stdinChannel);
Q_ASSERT(source->process == this && source->type == Channel::PipeSource);
- if (!qt_create_pipe(sink->pipe, /* in = */ true, TRUE)) // sink is stdin
+ if (!qt_create_pipe(sink->pipe, /* in = */ true, TRUE)) { // sink is stdin
+ setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
return false;
+ }
source->pipe[1] = sink->pipe[1];
sink->pipe[1] = INVALID_Q_PIPE;
@@ -391,44 +374,44 @@ static QString qt_create_commandline(const QString &program, const QStringList &
QString args;
if (!program.isEmpty()) {
QString programName = program;
- if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1Char(' ')))
- programName = QLatin1Char('\"') + programName + QLatin1Char('\"');
- programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ if (!programName.startsWith(u'\"') && !programName.endsWith(u'\"') && programName.contains(u' '))
+ programName = u'\"' + programName + u'\"';
+ programName.replace(u'/', u'\\');
// add the program as the first arg ... it works better
- args = programName + QLatin1Char(' ');
+ args = programName + u' ';
}
- for (int i=0; i<arguments.size(); ++i) {
+ for (qsizetype i = 0; i < arguments.size(); ++i) {
QString tmp = arguments.at(i);
// Quotes are escaped and their preceding backslashes are doubled.
- int index = tmp.indexOf(QLatin1Char('"'));
+ qsizetype index = tmp.indexOf(u'"');
while (index >= 0) {
// Escape quote
- tmp.insert(index++, QLatin1Char('\\'));
+ tmp.insert(index++, u'\\');
// Double preceding backslashes (ignoring the one we just inserted)
- for (int i = index - 2 ; i >= 0 && tmp.at(i) == QLatin1Char('\\') ; --i) {
- tmp.insert(i, QLatin1Char('\\'));
+ for (qsizetype i = index - 2 ; i >= 0 && tmp.at(i) == u'\\' ; --i) {
+ tmp.insert(i, u'\\');
index++;
}
- index = tmp.indexOf(QLatin1Char('"'), index + 1);
+ index = tmp.indexOf(u'"', index + 1);
}
- if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
+ if (tmp.isEmpty() || tmp.contains(u' ') || tmp.contains(u'\t')) {
// The argument must not end with a \ since this would be interpreted
// as escaping the quote -- rather put the \ behind the quote: e.g.
// rather use "foo"\ than "foo\"
- int i = tmp.length();
- while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\'))
+ qsizetype i = tmp.length();
+ while (i > 0 && tmp.at(i - 1) == u'\\')
--i;
- tmp.insert(i, QLatin1Char('"'));
- tmp.prepend(QLatin1Char('"'));
+ tmp.insert(i, u'"');
+ tmp.prepend(u'"');
}
- args += QLatin1Char(' ') + tmp;
+ args += u' ' + tmp;
}
if (!nativeArguments.isEmpty()) {
if (!args.isEmpty())
- args += QLatin1Char(' ');
+ args += u' ';
args += nativeArguments;
}
@@ -441,7 +424,7 @@ static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Map &e
QProcessEnvironmentPrivate::Map copy = environment;
// add PATH if necessary (for DLL loading)
- QProcessEnvironmentPrivate::Key pathKey(QLatin1String("PATH"));
+ QProcessEnvironmentPrivate::Key pathKey("PATH"_L1);
if (!copy.contains(pathKey)) {
QByteArray path = qgetenv("PATH");
if (!path.isEmpty())
@@ -449,7 +432,7 @@ static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Map &e
}
// add systemroot if needed
- QProcessEnvironmentPrivate::Key rootKey(QLatin1String("SystemRoot"));
+ QProcessEnvironmentPrivate::Key rootKey("SystemRoot"_L1);
if (!copy.contains(rootKey)) {
QByteArray systemRoot = qgetenv("SystemRoot");
if (!systemRoot.isEmpty())
@@ -555,9 +538,9 @@ void QProcessPrivate::startProcess()
q->setProcessState(QProcess::Starting);
if (!openChannels()) {
- QString errorString = QProcess::tr("Process failed to start: %1").arg(qt_error_string());
+ // openChannel sets the error string
+ Q_ASSERT(!errorString.isEmpty());
cleanup();
- setErrorAndEmit(QProcess::FailedToStart, errorString);
return;
}
@@ -666,7 +649,7 @@ void QProcessPrivate::terminateProcess()
void QProcessPrivate::killProcess()
{
if (pid)
- TerminateProcess(pid->hProcess, 0xf291);
+ TerminateProcess(pid->hProcess, KillProcessExitCode);
}
bool QProcessPrivate::waitForStarted(const QDeadlineTimer &)
@@ -816,8 +799,11 @@ void QProcessPrivate::findExitCode()
Q_ASSERT(pid);
if (GetExitCodeProcess(pid->hProcess, &theExitCode)) {
exitCode = theExitCode;
- crashed = (exitCode == 0xf291 // our magic number, see killProcess
- || (theExitCode >= 0x80000000 && theExitCode < 0xD0000000));
+ if (exitCode == KillProcessExitCode
+ || (theExitCode >= 0x80000000 && theExitCode < 0xD0000000))
+ exitStatus = QProcess::CrashExit;
+ else
+ exitStatus = QProcess::NormalExit;
}
}