summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qprocess_win.cpp
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-05-12 07:31:50 +0200
committerLiang Qi <liang.qi@qt.io>2016-05-12 08:33:08 +0200
commit990969655c5fb4d03682e96df9b12101f5ee9815 (patch)
treeb8fb5c50285105c8bc5a938fb50f93ff9f24889d /src/corelib/io/qprocess_win.cpp
parenta213011a53f12f101d08a04afc8fdacd2d54a232 (diff)
parente64b2234e829cc47872225debcf80d6c06db18f0 (diff)
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts: config_help.txt configure src/corelib/io/qprocess_wince.cpp src/plugins/platforms/windows/qwindowstheme.cpp src/plugins/platforms/xcb/qxcbbackingstore.cpp tests/auto/corelib/tools/qtimezone/BLACKLIST tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp Change-Id: I26644d1cb3b78412c8ff285e2a55bea1bd641c01
Diffstat (limited to 'src/corelib/io/qprocess_win.cpp')
-rw-r--r--src/corelib/io/qprocess_win.cpp50
1 files changed, 48 insertions, 2 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 5d8b567c8c..96b39efe3a 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -49,6 +49,7 @@
#include <qfileinfo.h>
#include <qregexp.h>
#include <qwineventnotifier.h>
+#include <private/qsystemlibrary_p.h>
#include <private/qthread_p.h>
#include <qdebug.h>
@@ -804,21 +805,64 @@ qint64 QProcessPrivate::pipeWriterBytesToWrite() const
return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0);
}
-qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
+bool QProcessPrivate::writeToStdin()
{
Q_Q(QProcess);
if (!stdinChannel.writer) {
stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
+ QObject::connect(stdinChannel.writer, &QWindowsPipeWriter::bytesWritten,
+ q, &QProcess::bytesWritten);
QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite,
this, &QProcessPrivate::_q_canWrite);
+ } else {
+ if (stdinChannel.writer->isWriteOperationActive())
+ return true;
}
- return stdinChannel.writer->write(data, maxlen);
+ stdinChannel.writer->write(writeBuffer.read());
+ return true;
+}
+
+// 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 &workingDir, qint64 *pid)
+{
+ typedef BOOL (WINAPI *ShellExecuteExType)(SHELLEXECUTEINFOW *);
+
+ static const ShellExecuteExType shellExecuteEx = // XP ServicePack 1 onwards.
+ reinterpret_cast<ShellExecuteExType>(QSystemLibrary::resolve(QLatin1String("shell32"),
+ "ShellExecuteExW"));
+ if (!shellExecuteEx)
+ return false;
+
+ const QString args = qt_create_commandline(QString(), arguments); // needs arguments only
+ SHELLEXECUTEINFOW shellExecuteExInfo;
+ memset(&shellExecuteExInfo, 0, sizeof(SHELLEXECUTEINFOW));
+ shellExecuteExInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
+ shellExecuteExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE | SEE_MASK_FLAG_NO_UI;
+ shellExecuteExInfo.lpVerb = L"runas";
+ const QString program = QDir::toNativeSeparators(programIn);
+ shellExecuteExInfo.lpFile = reinterpret_cast<LPCWSTR>(program.utf16());
+ if (!args.isEmpty())
+ shellExecuteExInfo.lpParameters = reinterpret_cast<LPCWSTR>(args.utf16());
+ if (!workingDir.isEmpty())
+ shellExecuteExInfo.lpDirectory = reinterpret_cast<LPCWSTR>(workingDir.utf16());
+ shellExecuteExInfo.nShow = SW_SHOWNORMAL;
+
+ if (!shellExecuteEx(&shellExecuteExInfo))
+ return false;
+ if (pid)
+ *pid = qint64(GetProcessId(shellExecuteExInfo.hProcess));
+ CloseHandle(shellExecuteExInfo.hProcess);
+ return true;
}
bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
{
+ static const DWORD errorElevationRequired = 740;
+
QString args = qt_create_commandline(program, arguments);
bool success = false;
PROCESS_INFORMATION pinfo;
@@ -838,6 +882,8 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
CloseHandle(pinfo.hProcess);
if (pid)
*pid = pinfo.dwProcessId;
+ } else if (GetLastError() == errorElevationRequired) {
+ success = startDetachedUacPrompt(program, arguments, workingDir, pid);
}
return success;