aheinecke@256: #include "installwrapper.h" aheinecke@256: aheinecke@256: #include aheinecke@256: #include aheinecke@256: #include aheinecke@256: #include aheinecke@256: #include aheinecke@256: aheinecke@256: #include "logging.h" aheinecke@256: aheinecke@285: #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */ aheinecke@285: aheinecke@256: InstallWrapper::InstallWrapper(QObject* parent, aheinecke@256: const QString& path, const QStringList& instructions): aheinecke@256: QThread(parent), aheinecke@256: mCertListFile(path), aheinecke@256: mInstructions(instructions) aheinecke@256: { aheinecke@256: } aheinecke@256: aheinecke@256: QFileInfo getCinstProcInfo() { aheinecke@256: QFileInfo fi(QCoreApplication::applicationFilePath()); aheinecke@256: QDir myDir = fi.absoluteDir(); aheinecke@256: QString instProcName = "cinst"; aheinecke@256: if (!fi.suffix().isEmpty()) { aheinecke@256: instProcName += "." + fi.suffix(); aheinecke@256: } aheinecke@256: return QFileInfo(myDir.absoluteFilePath(instProcName)); aheinecke@256: } aheinecke@256: aheinecke@256: #ifdef WIN32 aheinecke@256: void InstallWrapper::run() aheinecke@256: { aheinecke@285: /* TODO: We need errorcodes here so that we can see if a user aheinecke@285: * cancled the UAC elevation */ aheinecke@256: QTemporaryFile instructionsFile; aheinecke@256: QFileInfo cinstProcInfo = getCinstProcInfo(); aheinecke@285: DWORD retval = 0; aheinecke@285: SHELLEXECUTEINFOW shExecInfo; aheinecke@285: memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); aheinecke@256: aheinecke@256: QString cinstFileName = QDir::toNativeSeparators( aheinecke@256: getCinstProcInfo().absoluteFilePath()); aheinecke@256: aheinecke@256: if (!cinstProcInfo.isExecutable()) { aheinecke@285: emit error(tr("Could not find certificate installation process.")); aheinecke@256: return; aheinecke@256: } aheinecke@256: aheinecke@256: instructionsFile.open(); aheinecke@256: aheinecke@256: foreach (const QString &b64data, mInstructions) { aheinecke@256: instructionsFile.write(b64data.toLatin1()); aheinecke@256: instructionsFile.write("\n"); aheinecke@256: } aheinecke@256: aheinecke@256: instructionsFile.close(); aheinecke@256: aheinecke@285: QString parameters = "\"list=" + mCertListFile + aheinecke@285: "\" \"instructions=" +instructionsFile.fileName() + "\""; aheinecke@256: aheinecke@285: shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); aheinecke@285: shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; aheinecke@285: shExecInfo.lpVerb = L"runas"; aheinecke@285: shExecInfo.lpFile = reinterpret_cast (cinstFileName.utf16()); aheinecke@285: shExecInfo.lpParameters = reinterpret_cast (parameters.utf16()); aheinecke@256: aheinecke@256: qDebug() << "Starting process " << cinstFileName <<" params: " << parameters; aheinecke@256: aheinecke@285: if (!ShellExecuteExW(&shExecInfo)) { aheinecke@256: char* errmsg = getLastErrorMsg(); aheinecke@256: QString qerrmsg = QString::fromUtf8(errmsg); aheinecke@256: free(errmsg); aheinecke@285: emit error(tr("Error executing process: %1").arg(qerrmsg)); aheinecke@285: return; aheinecke@256: } aheinecke@285: aheinecke@285: retval = WaitForSingleObject(shExecInfo.hProcess, INSTALL_TIMEOUT); aheinecke@285: aheinecke@285: if (retval != WAIT_OBJECT_0) { aheinecke@285: if (retval == WAIT_FAILED) { aheinecke@285: char* errmsg = getLastErrorMsg(); aheinecke@285: QString qerrmsg = QString::fromUtf8(errmsg); aheinecke@285: free(errmsg); aheinecke@285: emit error (tr("Error monitoring process: %1").arg(qerrmsg)); aheinecke@285: return; aheinecke@285: } else { aheinecke@285: emit error (tr("Certificate installation timed out.")); aheinecke@285: return; aheinecke@285: } aheinecke@285: } aheinecke@285: aheinecke@285: if (GetExitCodeProcess(shExecInfo.hProcess, &retval)) { aheinecke@285: if (retval == STILL_ACTIVE) { aheinecke@285: qDebug() << "Process still running, huh.."; aheinecke@285: } aheinecke@285: } else { aheinecke@285: char* errmsg = getLastErrorMsg(); aheinecke@285: QString qerrmsg = QString::fromUtf8(errmsg); aheinecke@285: free(errmsg); aheinecke@285: emit error (tr("Failed to check process status: %1").arg(qerrmsg)); aheinecke@285: } aheinecke@285: CloseHandle(shExecInfo.hProcess); aheinecke@285: aheinecke@285: if (retval != 0) { aheinecke@285: /* TODO make this nicer */ aheinecke@285: emit error (tr("The process failed with return code. %1").arg(retval)); aheinecke@285: } aheinecke@256: } aheinecke@256: #else aheinecke@256: void InstallWrapper::run() aheinecke@256: { aheinecke@256: } aheinecke@256: #endif