comparison ui/installwrapper.cpp @ 364:dc4efb0a70cb

Add Linux support
author Andre Heinecke <aheinecke@intevation.de>
date Mon, 14 Apr 2014 16:58:20 +0000
parents f23e0ccd5d14
children 72487438a180
comparison
equal deleted inserted replaced
363:d10d9bc2e84f 364:dc4efb0a70cb
1 #include "installwrapper.h" 1 #include "installwrapper.h"
2 2
3 #include <QFileInfo> 3 #include <QFileInfo>
4 #include <QProcess>
4 #include <QTemporaryFile> 5 #include <QTemporaryFile>
5 #include <QApplication> 6 #include <QApplication>
6 #include <QDir> 7 #include <QDir>
7 #include <QDebug> 8 #include <QDebug>
8 9
9 #include "logging.h" 10 #include "logging.h"
10 11
11 #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */ 12 #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */
12 13
13 InstallWrapper::InstallWrapper(QObject* parent, 14 InstallWrapper::InstallWrapper(QObject* parent,
14 const QString& path, const QStringList& instructions): 15 const QString& path, const QStringList& choices):
15 QThread(parent), 16 QThread(parent),
16 mCertListFile(path), 17 mCertListFile(path),
17 mInstructions(instructions) 18 mChoices(choices)
18 { 19 {
19 } 20 }
20 21
21 QFileInfo getCinstProcInfo() { 22 QFileInfo getCinstProcInfo() {
22 QFileInfo fi(QCoreApplication::applicationFilePath()); 23 QFileInfo fi(QCoreApplication::applicationFilePath());
26 instProcName += "." + fi.suffix(); 27 instProcName += "." + fi.suffix();
27 } 28 }
28 return QFileInfo(myDir.absoluteFilePath(instProcName)); 29 return QFileInfo(myDir.absoluteFilePath(instProcName));
29 } 30 }
30 31
31 #ifdef WIN32 32 bool InstallWrapper::writeChoices(QTemporaryFile* choicesFile) const
33 {
34 if (!choicesFile->open()) {
35 return false;
36 }
37
38 foreach (const QString &b64data, mChoices) {
39 if (!choicesFile->write(b64data.toLatin1())) {
40 return false;
41 }
42 if (!choicesFile->write("\n")) {
43 return false;
44 }
45 }
46
47 choicesFile->close();
48
49 return true;
50 }
51
32 void InstallWrapper::run() 52 void InstallWrapper::run()
33 { 53 {
34 /* TODO: We need errorcodes here so that we can see if a user 54 /* TODO: We need errorcodes here so that we can see if a user
35 * cancled the UAC elevation */ 55 * cancled the UAC elevation */
36 QTemporaryFile instructionsFile; 56 QTemporaryFile choicesFile;
37 QFileInfo cinstProcInfo = getCinstProcInfo(); 57 QFileInfo cinstProcInfo = getCinstProcInfo();
38 DWORD retval = 0;
39 SHELLEXECUTEINFOW shExecInfo;
40 memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW));
41 58
42 QString cinstFileName = QDir::toNativeSeparators( 59 QString cinstFileName = QDir::toNativeSeparators(
43 getCinstProcInfo().absoluteFilePath()); 60 getCinstProcInfo().absoluteFilePath());
44 61
45 if (!cinstProcInfo.isExecutable()) { 62 if (!cinstProcInfo.isExecutable()) {
46 emit error(tr("Could not find certificate installation process.")); 63 emit error(tr("Could not find certificate installation process."));
47 return; 64 return;
48 } 65 }
49 66
50 instructionsFile.open(); 67 if (!writeChoices(&choicesFile)) {
51 68 emit error(tr("Failed to write temporary file."));
52 foreach (const QString &b64data, mInstructions) { 69 return;
53 instructionsFile.write(b64data.toLatin1());
54 instructionsFile.write("\n");
55 } 70 }
56 71
57 instructionsFile.close(); 72 QString parameters = "\"list=" + mCertListFile +
73 "\" \"choices=" + choicesFile.fileName() + "\"";
58 74
59 QString parameters = "\"list=" + mCertListFile + 75 #ifdef WIN32
60 "\" \"instructions=" +instructionsFile.fileName() + "\""; 76 /* QProcess on Windows uses CreateProcess but we have to
77 * use the runas shell command to get the UAC prompt if necessary.
78 * So we have to handle the process ourself. Starting with
79 * shell execute also means that we can not have stdout and stderr
80 * redirection. This is the reason we use command line parameters
81 * and not a pipe for communication. In debug mode the installer
82 * also makes use of output debug string. */
83 DWORD retval = 0;
84 SHELLEXECUTEINFOW shExecInfo;
85
86 memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW));
61 87
62 shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); 88 shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
63 shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; 89 shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
64 shExecInfo.lpVerb = L"runas"; 90 shExecInfo.lpVerb = L"runas";
65 shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (cinstFileName.utf16()); 91 shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (cinstFileName.utf16());
104 130
105 if (retval != 0) { 131 if (retval != 0) {
106 /* TODO make this nicer */ 132 /* TODO make this nicer */
107 emit error (tr("The process failed with return code. %1").arg(retval)); 133 emit error (tr("The process failed with return code. %1").arg(retval));
108 } 134 }
135 return;
136 #else /* WIN32 */
137 QProcess installerProcess;
138 installerProcess.setProgram(cinstProcInfo.absoluteFilePath());
139 installerProcess.waitForStarted();
140 if (installerProcess.state() == QProcess::NotRunning) {
141 emit error (tr("Failed to start installer process."));
142 return;
143 }
144
145 installerProcess.waitForFinished();
146
147 if (installerProcess.exitStatus() == QProcess::CrashExit) {
148 /* Woops */
149 qWarning() << "Installer process crashed";
150 } else if (installerProcess.exitStatus() != QProcess::NormalExit) {
151 /* Can not Happen. there are only those two values but maybe
152 * qt changed.. */
153 qWarning() << "Exit status neither normal nor crash.";
154 return;
155 }
156
157 if (installerProcess.exitCode() == 0) {
158 qDebug() << "output: " << installerProcess.readAllStandardOutput();
159 } else {
160 /* TODO handle errors defined by errorcodes.h */
161 qDebug() << "Installer Process returned: " << installerProcess.exitCode();
162 qDebug() << "output: " << installerProcess.readAllStandardOutput();
163 return;
164 }
165 #endif
109 } 166 }
110 #else
111 void InstallWrapper::run()
112 {
113 }
114 #endif

http://wald.intevation.org/projects/trustbridge/