summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@nokia.com>2011-12-08 11:04:24 +0100
committerQt by Nokia <qt-info@nokia.com>2012-01-06 14:44:41 +0100
commitd0bb97c327612eea76ba61070c5d93d0fb06360b (patch)
treebcf31c73d4ef36132c880f4e1501d5d4076daadf /src
parent156d160c56a802c8b477a1a975853eda2f8eff61 (diff)
split qprocess_win.cpp into Windows and WinCE parts
Change-Id: I7f2cf2c42dd24ca162238e6dc6408ac39dfcd790 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/io.pri7
-rw-r--r--src/corelib/io/qprocess_win.cpp83
-rw-r--r--src/corelib/io/qprocess_wince.cpp330
3 files changed, 345 insertions, 75 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index d7eb7109a1..1d31e5d794 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -72,7 +72,6 @@ SOURCES += \
win32 {
SOURCES += io/qsettings_win.cpp
- SOURCES += io/qprocess_win.cpp
SOURCES += io/qfsfileengine_win.cpp
SOURCES += io/qfilesystemwatcher_win.cpp
@@ -84,6 +83,12 @@ win32 {
SOURCES += io/qfilesystemengine_win.cpp
SOURCES += io/qfilesystemiterator_win.cpp
SOURCES += io/qstandardpaths_win.cpp
+
+ wince* {
+ SOURCES += io/qprocess_wince.cpp
+ } else {
+ SOURCES += io/qprocess_win.cpp
+ }
} else:unix|integrity {
SOURCES += \
io/qfsfileengine_unix.cpp \
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 410f153447..fd5f078ff0 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -72,7 +72,6 @@ static void qt_create_pipe(Q_PIPE *pipe, bool in)
// read handles to avoid non-closable handles (this is done by the
// DuplicateHandle() call).
-#if !defined(Q_OS_WINCE)
SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE };
HANDLE tmpHandle;
@@ -91,10 +90,6 @@ static void qt_create_pipe(Q_PIPE *pipe, bool in)
}
CloseHandle(tmpHandle);
-#else
- Q_UNUSED(pipe);
- Q_UNUSED(in);
-#endif
}
/*
@@ -277,7 +272,6 @@ static QString qt_create_commandline(const QString &program, const QStringList &
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
-#if !defined(Q_OS_WINCE)
// Calls to setenv() affect the low-level environment as well.
// This is not the case the other way round.
if (wchar_t *envStrings = GetEnvironmentStringsW()) {
@@ -293,11 +287,9 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment()
}
FreeEnvironmentStringsW(envStrings);
}
-#endif
return env;
}
-#if !defined(Q_OS_WINCE)
static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash &environment)
{
QByteArray envlist;
@@ -357,7 +349,6 @@ static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash &
}
return envlist;
}
-#endif
void QProcessPrivate::startProcess()
{
@@ -381,14 +372,10 @@ void QProcessPrivate::startProcess()
!createChannel(stderrChannel))
return;
-#if defined(Q_OS_WINCE)
- QString args = qt_create_commandline(QString(), arguments);
-#else
QString args = qt_create_commandline(program, arguments);
QByteArray envlist;
if (environment.d.constData())
envlist = qt_create_environment(environment.d.constData()->hash);
-#endif
if (!nativeArguments.isEmpty()) {
if (!args.isEmpty())
args += QLatin1Char(' ');
@@ -402,15 +389,6 @@ void QProcessPrivate::startProcess()
qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes");
#endif
-#if defined(Q_OS_WINCE)
- QString fullPathProgram = program;
- if (!QDir::isAbsolutePath(fullPathProgram))
- fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath();
- fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
- success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
- (wchar_t*)args.utf16(),
- 0, 0, false, 0, 0, 0, 0, pid);
-#else
DWORD dwCreationFlags = CREATE_NO_WINDOW;
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
@@ -443,7 +421,6 @@ void QProcessPrivate::startProcess()
CloseHandle(stderrChannel.pipe[1]);
stderrChannel.pipe[1] = INVALID_Q_PIPE;
}
-#endif // Q_OS_WINCE
if (!success) {
cleanup();
@@ -484,7 +461,6 @@ qint64 QProcessPrivate::bytesAvailableFromStdout() const
return 0;
DWORD bytesAvail = 0;
-#if !defined(Q_OS_WINCE)
PeekNamedPipe(stdoutChannel.pipe[0], 0, 0, 0, &bytesAvail, 0);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
@@ -501,7 +477,6 @@ qint64 QProcessPrivate::bytesAvailableFromStdout() const
}
bytesAvail = 0;
}
-#endif
return bytesAvail;
}
@@ -511,7 +486,6 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const
return 0;
DWORD bytesAvail = 0;
-#if !defined(Q_OS_WINCE)
PeekNamedPipe(stderrChannel.pipe[0], 0, 0, 0, &bytesAvail, 0);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
@@ -528,7 +502,6 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const
}
bytesAvail = 0;
}
-#endif
return bytesAvail;
}
@@ -596,13 +569,6 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
{
Q_Q(QProcess);
-#if defined(Q_OS_WINCE)
- processError = QProcess::ReadError;
- q->setErrorString(QProcess::tr("Error reading from process"));
- emit q->error(processError);
- return false;
-#endif
-
QIncrementalSleepTimer timer(msecs);
forever {
@@ -646,13 +612,6 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
{
Q_Q(QProcess);
-#if defined(Q_OS_WINCE)
- processError = QProcess::ReadError;
- q->setErrorString(QProcess::tr("Error reading from process"));
- emit q->error(processError);
- return false;
-#endif
-
QIncrementalSleepTimer timer(msecs);
forever {
@@ -786,13 +745,6 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
{
Q_Q(QProcess);
-#if defined(Q_OS_WINCE)
- processError = QProcess::WriteError;
- q->setErrorString(QProcess::tr("Error writing to process"));
- emit q->error(processError);
- return -1;
-#endif
-
if (!pipeWriter) {
pipeWriter = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
pipeWriter->start();
@@ -832,36 +784,19 @@ void QProcessPrivate::_q_notified()
bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
{
-#if defined(Q_OS_WINCE)
- Q_UNUSED(workingDir);
- QString args = qt_create_commandline(QString(), arguments);
-#else
QString args = qt_create_commandline(program, arguments);
-#endif
-
bool success = false;
-
PROCESS_INFORMATION pinfo;
-#if defined(Q_OS_WINCE)
- QString fullPathProgram = program;
- if (!QDir::isAbsolutePath(fullPathProgram))
- fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/')));
- fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
- success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
- (wchar_t*)args.utf16(),
- 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo);
-#else
- STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- (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, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
- workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(),
- &startupInfo, &pinfo);
-#endif // Q_OS_WINCE
+ STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ (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, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
+ workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(),
+ &startupInfo, &pinfo);
if (success) {
CloseHandle(pinfo.hThread);
diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp
new file mode 100644
index 0000000000..16a34469e7
--- /dev/null
+++ b/src/corelib/io/qprocess_wince.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qprocess.h"
+#include "qprocess_p.h"
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qwineventnotifier.h>
+#include <qdebug.h>
+
+#ifndef QT_NO_PROCESS
+
+QT_BEGIN_NAMESPACE
+
+//#define QPROCESS_DEBUG
+
+void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
+{
+ Q_UNUSED(pipe);
+}
+
+static QString qt_create_commandline(const QString &program, const QStringList &arguments)
+{
+ 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('\\'));
+
+ // add the prgram as the first arg ... it works better
+ args = programName + QLatin1Char(' ');
+ }
+
+ for (int i=0; i<arguments.size(); ++i) {
+ QString tmp = arguments.at(i);
+ // Quotes are escaped and their preceding backslashes are doubled.
+ tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\""));
+ if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\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('\\'))
+ --i;
+ tmp.insert(i, QLatin1Char('"'));
+ tmp.prepend(QLatin1Char('"'));
+ }
+ args += QLatin1Char(' ') + tmp;
+ }
+ return args;
+}
+
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ QProcessEnvironment env;
+ return env;
+}
+
+void QProcessPrivate::startProcess()
+{
+ Q_Q(QProcess);
+
+ bool success = false;
+
+ if (pid) {
+ CloseHandle(pid->hThread);
+ CloseHandle(pid->hProcess);
+ delete pid;
+ pid = 0;
+ }
+ pid = new PROCESS_INFORMATION;
+ memset(pid, 0, sizeof(PROCESS_INFORMATION));
+
+ q->setProcessState(QProcess::Starting);
+
+ QString args = qt_create_commandline(QString(), arguments);
+ if (!nativeArguments.isEmpty()) {
+ if (!args.isEmpty())
+ args += QLatin1Char(' ');
+ args += nativeArguments;
+ }
+
+#if defined QPROCESS_DEBUG
+ qDebug("Creating process");
+ qDebug(" program : [%s]", program.toLatin1().constData());
+ qDebug(" args : %s", args.toLatin1().constData());
+ qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes");
+#endif
+
+ QString fullPathProgram = program;
+ if (!QDir::isAbsolutePath(fullPathProgram))
+ fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath();
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
+ (wchar_t*)args.utf16(),
+ 0, 0, false, 0, 0, 0, 0, pid);
+
+ if (!success) {
+ cleanup();
+ processError = QProcess::FailedToStart;
+ emit q->error(processError);
+ q->setProcessState(QProcess::NotRunning);
+ return;
+ }
+
+ q->setProcessState(QProcess::Running);
+ // User can call kill()/terminate() from the stateChanged() slot
+ // so check before proceeding
+ if (!pid)
+ return;
+
+ if (threadData->eventDispatcher) {
+ processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q);
+ QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied()));
+ processFinishedNotifier->setEnabled(true);
+ }
+
+ // give the process a chance to start ...
+ Sleep(SLEEPMIN * 2);
+ _q_startupNotification();
+}
+
+bool QProcessPrivate::processStarted()
+{
+ return processState == QProcess::Running;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStdout() const
+{
+ return 0;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStderr() const
+{
+ return 0;
+}
+
+qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
+{
+ return -1;
+}
+
+qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
+{
+ return -1;
+}
+
+static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId)
+{
+ DWORD currentProcId = 0;
+ GetWindowThreadProcessId(hwnd, &currentProcId);
+ if (currentProcId == (DWORD)procId)
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+
+ return TRUE;
+}
+
+void QProcessPrivate::terminateProcess()
+{
+ if (pid) {
+ EnumWindows(qt_terminateApp, (LPARAM)pid->dwProcessId);
+ PostThreadMessage(pid->dwThreadId, WM_CLOSE, 0, 0);
+ }
+}
+
+void QProcessPrivate::killProcess()
+{
+ if (pid)
+ TerminateProcess(pid->hProcess, 0xf291);
+}
+
+bool QProcessPrivate::waitForStarted(int)
+{
+ Q_Q(QProcess);
+
+ if (processStarted())
+ return true;
+
+ if (processError == QProcess::FailedToStart)
+ return false;
+
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+bool QProcessPrivate::waitForReadyRead(int msecs)
+{
+ return false;
+}
+
+bool QProcessPrivate::waitForBytesWritten(int msecs)
+{
+ return false;
+}
+
+bool QProcessPrivate::waitForFinished(int msecs)
+{
+ Q_Q(QProcess);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
+#endif
+
+ QIncrementalSleepTimer timer(msecs);
+
+ forever {
+ if (!pid)
+ return true;
+
+ if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
+ _q_processDied();
+ return true;
+ }
+
+ if (timer.hasTimedOut())
+ break;
+ }
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+void QProcessPrivate::findExitCode()
+{
+ DWORD theExitCode;
+ if (GetExitCodeProcess(pid->hProcess, &theExitCode)) {
+ exitCode = theExitCode;
+ //### for now we assume a crash if exit code is less than -1 or the magic number
+ crashed = (exitCode == 0xf291 || (int)exitCode < 0);
+ }
+}
+
+void QProcessPrivate::flushPipeWriter()
+{
+}
+
+qint64 QProcessPrivate::pipeWriterBytesToWrite() const
+{
+ return 0;
+}
+
+qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+ return -1;
+}
+
+bool QProcessPrivate::waitForWrite(int msecs)
+{
+ Q_UNUSED(msecs);
+ return false;
+}
+
+void QProcessPrivate::_q_notified()
+{
+}
+
+bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
+{
+ Q_UNUSED(workingDir);
+ QString args = qt_create_commandline(QString(), arguments);
+
+ bool success = false;
+
+ PROCESS_INFORMATION pinfo;
+
+ QString fullPathProgram = program;
+ if (!QDir::isAbsolutePath(fullPathProgram))
+ fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/')));
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
+ (wchar_t*)args.utf16(),
+ 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo);
+
+ if (success) {
+ CloseHandle(pinfo.hThread);
+ CloseHandle(pinfo.hProcess);
+ if (pid)
+ *pid = pinfo.dwProcessId;
+ }
+
+ return success;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PROCESS