summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qprocess_win.cpp
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-04-27 09:18:05 +0200
committerLiang Qi <liang.qi@qt.io>2016-04-27 09:18:05 +0200
commit23a36fd2bfcdb57849deaa1e10e6e3f7b1156ed8 (patch)
treeb527c7e3ba4a831b542b0bccfb6a5a748a8a4fd9 /src/corelib/io/qprocess_win.cpp
parentc003a18ee332abf2387172eb0856a176a32a6c8f (diff)
parent072f5b513e486e884ea7fa4a1cac9aedf3846374 (diff)
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts: src/corelib/io/qprocess_win.cpp src/widgets/itemviews/qheaderview.cpp Change-Id: I0a59ade9cd6e91f770fdf298a7d72a41e79fd761
Diffstat (limited to 'src/corelib/io/qprocess_win.cpp')
-rw-r--r--src/corelib/io/qprocess_win.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 5d8b567c8c..ed540f9e5b 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>
@@ -817,8 +818,45 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
return stdinChannel.writer->write(data, maxlen);
}
+// 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 +876,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;