# HG changeset patch # User Andre Heinecke # Date 1397494700 0 # Node ID dc4efb0a70cb6500983fb0f263ef78806412fe9b # Parent d10d9bc2e84f51dafeef5175dd83b790d04bac9b Add Linux support diff -r d10d9bc2e84f -r dc4efb0a70cb ui/installwrapper.cpp --- a/ui/installwrapper.cpp Mon Apr 14 16:57:41 2014 +0000 +++ b/ui/installwrapper.cpp Mon Apr 14 16:58:20 2014 +0000 @@ -1,6 +1,7 @@ #include "installwrapper.h" #include +#include #include #include #include @@ -11,10 +12,10 @@ #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */ InstallWrapper::InstallWrapper(QObject* parent, - const QString& path, const QStringList& instructions): + const QString& path, const QStringList& choices): QThread(parent), mCertListFile(path), - mInstructions(instructions) + mChoices(choices) { } @@ -28,16 +29,32 @@ return QFileInfo(myDir.absoluteFilePath(instProcName)); } -#ifdef WIN32 +bool InstallWrapper::writeChoices(QTemporaryFile* choicesFile) const +{ + if (!choicesFile->open()) { + return false; + } + + foreach (const QString &b64data, mChoices) { + if (!choicesFile->write(b64data.toLatin1())) { + return false; + } + if (!choicesFile->write("\n")) { + return false; + } + } + + choicesFile->close(); + + return true; +} + void InstallWrapper::run() { /* TODO: We need errorcodes here so that we can see if a user * cancled the UAC elevation */ - QTemporaryFile instructionsFile; + QTemporaryFile choicesFile; QFileInfo cinstProcInfo = getCinstProcInfo(); - DWORD retval = 0; - SHELLEXECUTEINFOW shExecInfo; - memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); QString cinstFileName = QDir::toNativeSeparators( getCinstProcInfo().absoluteFilePath()); @@ -47,17 +64,26 @@ return; } - instructionsFile.open(); - - foreach (const QString &b64data, mInstructions) { - instructionsFile.write(b64data.toLatin1()); - instructionsFile.write("\n"); + if (!writeChoices(&choicesFile)) { + emit error(tr("Failed to write temporary file.")); + return; } - instructionsFile.close(); + QString parameters = "\"list=" + mCertListFile + + "\" \"choices=" + choicesFile.fileName() + "\""; - QString parameters = "\"list=" + mCertListFile + - "\" \"instructions=" +instructionsFile.fileName() + "\""; +#ifdef WIN32 + /* QProcess on Windows uses CreateProcess but we have to + * use the runas shell command to get the UAC prompt if necessary. + * So we have to handle the process ourself. Starting with + * shell execute also means that we can not have stdout and stderr + * redirection. This is the reason we use command line parameters + * and not a pipe for communication. In debug mode the installer + * also makes use of output debug string. */ + DWORD retval = 0; + SHELLEXECUTEINFOW shExecInfo; + + memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; @@ -106,9 +132,35 @@ /* TODO make this nicer */ emit error (tr("The process failed with return code. %1").arg(retval)); } + return; +#else /* WIN32 */ + QProcess installerProcess; + installerProcess.setProgram(cinstProcInfo.absoluteFilePath()); + installerProcess.waitForStarted(); + if (installerProcess.state() == QProcess::NotRunning) { + emit error (tr("Failed to start installer process.")); + return; + } + + installerProcess.waitForFinished(); + + if (installerProcess.exitStatus() == QProcess::CrashExit) { + /* Woops */ + qWarning() << "Installer process crashed"; + } else if (installerProcess.exitStatus() != QProcess::NormalExit) { + /* Can not Happen. there are only those two values but maybe + * qt changed.. */ + qWarning() << "Exit status neither normal nor crash."; + return; + } + + if (installerProcess.exitCode() == 0) { + qDebug() << "output: " << installerProcess.readAllStandardOutput(); + } else { + /* TODO handle errors defined by errorcodes.h */ + qDebug() << "Installer Process returned: " << installerProcess.exitCode(); + qDebug() << "output: " << installerProcess.readAllStandardOutput(); + return; + } +#endif } -#else -void InstallWrapper::run() -{ -} -#endif diff -r d10d9bc2e84f -r dc4efb0a70cb ui/installwrapper.h --- a/ui/installwrapper.h Mon Apr 14 16:57:41 2014 +0000 +++ b/ui/installwrapper.h Mon Apr 14 16:58:20 2014 +0000 @@ -1,14 +1,24 @@ #ifndef UI_INSTALLWRAPPER_H #define UI_INSTALLWRAPPER_H +#include #include #include +#include #include #include "certificate.h" /** @file installwrapper.h * @brief Wrapper around the call to the updated process */ +/** @brief Get the FileInfo for the installation process. + * + * This points to the file where the installation process is + * supposed to be. + * + * @returns A FileInfo with the path of the installation process.*/ +QFileInfo getCinstProcInfo(); + /** @brief wrapper around installer process * * This wrapper is mostly needed because QProcess executes @@ -36,14 +46,22 @@ * * @param[in] parent the parent object. * @param[in] listFileName the absolute path to the certificatelist. - * @param[in] instructions a list of instructions to execute. + * @param[in] choices a list of R: / I: lines to execute. */ InstallWrapper(QObject* parent, const QString& path, const QStringList& instructions); private: + /**@brief write the choices made into a temporary file + * + * @param[in] choicesFile the temporary file to write. + * + * @returns true on success. false on error. + */ + bool writeChoices(QTemporaryFile* choicesFile) const; + const QString mCertListFile; - const QStringList mInstructions; + const QStringList mChoices; protected: void run();