view ui/installwrapper.cpp @ 363:d10d9bc2e84f

Update Windows api usage. Warning: To build on windows you need a shell32.dll with SHGetKnownFolder
author Andre Heinecke <aheinecke@intevation.de>
date Mon, 14 Apr 2014 16:57:41 +0000
parents f23e0ccd5d14
children dc4efb0a70cb
line wrap: on
line source
#include "installwrapper.h"

#include <QFileInfo>
#include <QTemporaryFile>
#include <QApplication>
#include <QDir>
#include <QDebug>

#include "logging.h"

#define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */

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
void InstallWrapper::run()
{
    /* TODO: We need errorcodes here so that we can see if a user
     * cancled the UAC elevation */
    QTemporaryFile instructionsFile;
    QFileInfo cinstProcInfo = getCinstProcInfo();
    DWORD retval = 0;
    SHELLEXECUTEINFOW shExecInfo;
    memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW));

    QString cinstFileName = QDir::toNativeSeparators(
            getCinstProcInfo().absoluteFilePath());

    if (!cinstProcInfo.isExecutable()) {
        emit error(tr("Could not find certificate installation process."));
        return;
    }

    instructionsFile.open();

    foreach (const QString &b64data, mInstructions) {
       instructionsFile.write(b64data.toLatin1());
       instructionsFile.write("\n");
    }

    instructionsFile.close();

    QString parameters = "\"list=" + mCertListFile + 
        "\" \"instructions=" +instructionsFile.fileName() + "\"";

    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
    shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    shExecInfo.lpVerb = L"runas";
    shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (cinstFileName.utf16());
    shExecInfo.lpParameters =  reinterpret_cast<LPCWSTR> (parameters.utf16());

    qDebug() << "Starting process " << cinstFileName <<" params: " << parameters;

    if (!ShellExecuteExW(&shExecInfo)) {
        char* errmsg = getLastErrorMsg();
        QString qerrmsg = QString::fromUtf8(errmsg);
        free(errmsg);
        emit error(tr("Error executing process: %1").arg(qerrmsg));
        return;
    }

    retval = WaitForSingleObject(shExecInfo.hProcess, INSTALL_TIMEOUT);

    if (retval != WAIT_OBJECT_0) {
        if (retval == WAIT_FAILED) {
            char* errmsg = getLastErrorMsg();
            QString qerrmsg = QString::fromUtf8(errmsg);
            free(errmsg);
            emit error (tr("Error monitoring process: %1").arg(qerrmsg));
            return;
        } else {
            emit error (tr("Certificate installation timed out."));
            return;
        }
    }

    if (GetExitCodeProcess(shExecInfo.hProcess, &retval)) {
        if (retval == STILL_ACTIVE) {
            qDebug() << "Process still running, huh..";
        }
    } else {
        char* errmsg = getLastErrorMsg();
        QString qerrmsg = QString::fromUtf8(errmsg);
        free(errmsg);
        emit error (tr("Failed to check process status: %1").arg(qerrmsg));
    }
    CloseHandle(shExecInfo.hProcess);

    if (retval != 0) {
        /* TODO make this nicer */
        emit error (tr("The process failed with return code. %1").arg(retval));
    }
}
#else
void InstallWrapper::run()
{
}
#endif

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