diff options
author | Liang Qi <liang.qi@qt.io> | 2016-04-27 09:18:05 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-04-27 09:18:05 +0200 |
commit | 23a36fd2bfcdb57849deaa1e10e6e3f7b1156ed8 (patch) | |
tree | b527c7e3ba4a831b542b0bccfb6a5a748a8a4fd9 /src/corelib/io/qprocess_win.cpp | |
parent | c003a18ee332abf2387172eb0856a176a32a6c8f (diff) | |
parent | 072f5b513e486e884ea7fa4a1cac9aedf3846374 (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.cpp | 40 |
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; |