From d0bb97c327612eea76ba61070c5d93d0fb06360b Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 8 Dec 2011 11:04:24 +0100 Subject: split qprocess_win.cpp into Windows and WinCE parts Change-Id: I7f2cf2c42dd24ca162238e6dc6408ac39dfcd790 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/io.pri | 7 +- src/corelib/io/qprocess_win.cpp | 83 ++-------- src/corelib/io/qprocess_wince.cpp | 330 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 345 insertions(+), 75 deletions(-) create mode 100644 src/corelib/io/qprocess_wince.cpp (limited to 'src') 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 +#include +#include +#include +#include +#include + +#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 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, ¤tProcId); + 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 -- cgit v1.2.3