changeset 256:84ae353688e0

Add installwrapper class to handle process communication
author Andre Heinecke <aheinecke@intevation.de>
date Tue, 01 Apr 2014 10:52:06 +0000
parents c82dab1824be
children 06089ba2614a
files ui/installwrapper.cpp ui/installwrapper.h
diffstat 2 files changed, 153 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/installwrapper.cpp	Tue Apr 01 10:52:06 2014 +0000
@@ -0,0 +1,87 @@
+#include "installwrapper.h"
+
+#include <QFileInfo>
+#include <QTemporaryFile>
+#include <QApplication>
+#include <QDir>
+#include <QDebug>
+
+#include "logging.h"
+
+InstallWrapper::InstallWrapper(QObject* parent,
+        const QString& path, const QStringList& instructions):
+    QThread(parent),
+    mCertListFile(path),
+    mInstructions(instructions)
+{
+}
+
+QFileInfo getCinstProcInfo() {
+    QFileInfo fi(QCoreApplication::applicationFilePath());
+    QDir myDir = fi.absoluteDir();
+    QString instProcName = "cinst";
+    if (!fi.suffix().isEmpty()) {
+        instProcName += "." + fi.suffix();
+    }
+    return QFileInfo(myDir.absoluteFilePath(instProcName));
+}
+
+#ifdef WIN32
+extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
+
+void InstallWrapper::run()
+{
+    QTemporaryFile instructionsFile;
+    QFileInfo cinstProcInfo = getCinstProcInfo();
+
+    QString cinstFileName = QDir::toNativeSeparators(
+            getCinstProcInfo().absoluteFilePath());
+
+    if (!cinstProcInfo.isExecutable()) {
+        emit error (tr("Could not find certificate installation process."));
+        return;
+    }
+
+    instructionsFile.open();
+
+    qt_ntfs_permission_lookup++;
+    if (instructionsFile.permissions() ^ (
+                QFileDevice::ReadUser |
+                QFileDevice::WriteUser |
+                QFileDevice::ReadOwner |
+                QFileDevice::WriteOwner)) {
+        emit error (tr("Invalid permissions on temporary file."));
+    }
+
+    foreach (const QString &b64data, mInstructions) {
+       instructionsFile.write(b64data.toLatin1());
+       instructionsFile.write("\n");
+    }
+
+    instructionsFile.close();
+
+    QString parameters = "\"" + mCertListFile + "\" \"" +instructionsFile.fileName() + "\"";
+
+    memset (&mExecInfo, 0, sizeof(SHELLEXECUTEINFOW));
+    mExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
+    mExecInfo.fMask = SEE_MASK_FLAG_NO_UI |
+                      SEE_MASK_NOASYNC;
+    mExecInfo.lpVerb = L"runas";
+    mExecInfo.lpFile = reinterpret_cast<LPCWSTR> (cinstFileName.utf16());
+    mExecInfo.lpParameters =  reinterpret_cast<LPCWSTR> (parameters.utf16());
+
+    qDebug() << "Starting process " << cinstFileName <<" params: " << parameters;
+
+    if (!ShellExecuteExW(&mExecInfo)) {
+        char* errmsg = getLastErrorMsg();
+        QString qerrmsg = QString::fromUtf8(errmsg);
+        free(errmsg);
+        emit(tr("Error executing process: %1").arg(qerrmsg));
+    }
+    qt_ntfs_permission_lookup--;
+}
+#else
+void InstallWrapper::run()
+{
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/installwrapper.h	Tue Apr 01 10:52:06 2014 +0000
@@ -0,0 +1,66 @@
+#ifndef UI_INSTALLWRAPPER_H
+#define UI_INSTALLWRAPPER_H
+
+#include <QString>
+#include <QStringList>
+#include <QProcess>
+#include <QThread>
+
+#include "certificate.h"
+/** @file installwrapper.h
+ * @brief Wrapper around the call to the updated process */
+
+ /** @brief wrapper around installer process
+  *
+  * This wrapper is mostly needed because QProcess executes
+  * a process on Windows directly with CreateProcess and
+  * thus can not be used to elevate the Process.
+  *
+  * On Windows this class uses ShellExecuteExW to control
+  * the child process. On Linux systems QProcess is used.
+  *
+  * It subclasses QThread so the installation can be done
+  * asynchronusly. */
+class InstallWrapper : public QThread
+{
+    Q_OBJECT
+
+public:
+    /**
+     * @brief Construct an installwrapper for a certificateList
+     *
+     * The install wrapper will start the cinst process to execute
+     * the specified instructions with the provided certificatelist.
+     *
+     * The cinst executable is expected to be in the same directory
+     * as the current application.
+     *
+     * @param[in] parent the parent object.
+     * @param[in] listFileName the absolute path to the certificatelist.
+     * @param[in] instructions a list of instructions to execute.
+     */
+    InstallWrapper(QObject* parent, const QString& path,
+                   const QStringList& instructions);
+
+private:
+    const QString mCertListFile;
+    const QStringList mInstructions;
+#ifdef WIN32
+    SHELLEXECUTEINFOW mExecInfo;
+#else
+    QProcess cinstProc;
+#endif
+
+protected:
+    void run();
+
+Q_SIGNALS:
+    /**
+     * @brief An error happened
+     *
+     * @param[out] message: A localized message to show. Can be empty.
+     */
+    void error(const QString &message);
+};
+
+#endif // UI_INSTALLWRAPPER_H

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