Warning, file /frameworks/kinit/src/kwrapper/kwrapper_win.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2007 Ralf Habacker <ralf.habacker@freenet.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 /* 0009 kde application starter 0010 - allows starting kde application without any additional path settings [1] 0011 - supports multiple root installation which is often used by packagers 0012 (adds bin/lib directories from KDEDIRS environment to PATH environment) 0013 - designed to start kde application from windows start menu entries 0014 - support for reading KDEDIRS setting from flat file 0015 (located in <path-of-kwrapper.exe>/../../kdedirs.cache) 0016 - planned: automatic KDEDIRS detection support 0017 0018 [1] recent kde cmake buildsystem on win32 installs shared libraries 0019 into lib instead of bin. This requires to have the lib directory 0020 in the PATH environment variable too (required for all paths in KDEDIRS) 0021 0022 TODO: There is an prelimary concept of setting KDEDIRS environment variable 0023 from a cache file located on a well known path relative from the requested 0024 application. 0025 The recent implementation expects a file name 'kdedirs.cache' two level 0026 above this executable which will be <ProgramFiles> in case kwrapper5 lives 0027 in <Programfiles>/kde5/bin. 0028 This works not in any case especially when running application inside the 0029 build directory. 0030 0031 */ 0032 0033 #include <stdio.h> 0034 #include <assert.h> 0035 #include <stdlib.h> 0036 #include <process.h> 0037 #include <windows.h> 0038 0039 #include <QString> 0040 #include <QProcess> 0041 #include <QtDebug> 0042 #include <QFileInfo> 0043 #include <QCoreApplication> 0044 #include <QList> 0045 0046 bool verbose = 0; 0047 0048 int main(int argc, char **argv) 0049 { 0050 QCoreApplication app(argc, argv); 0051 0052 QStringList envPath; /// paths for using in environment of started process 0053 QStringList searchPath; /// paths for using to find executable 0054 QString exeToStart; 0055 QString myAppName = QStringLiteral("kwrapper5:"); 0056 QStringList exeParams; 0057 int firstParam = 1; 0058 0059 if (QCoreApplication::arguments().size() == 1) { 0060 qDebug() << myAppName << "no application given"; 0061 return 1; 0062 } 0063 0064 if (QCoreApplication::arguments().at(1) == QStringLiteral("--verbose")) { 0065 verbose = 1; 0066 firstParam = 2; 0067 } 0068 0069 exeToStart = QCoreApplication::arguments().at(firstParam); 0070 0071 for (int i = firstParam + 1; i < QCoreApplication::arguments().size(); i++) { 0072 exeParams << QCoreApplication::arguments().at(i); 0073 } 0074 0075 QString path = QString::fromLocal8Bit(qgetenv("PATH")).toLower() 0076 .replace(QLatin1Char('\\'), QLatin1Char('/')); 0077 0078 /** add paths from PATH environment 0079 - all to client path environment 0080 - paths not ending with lib to application search path 0081 */ 0082 const auto lst = path.split(QLatin1Char(';')); 0083 for (const QString &a : lst) { 0084 if (!envPath.contains(a)) { 0085 envPath << a; 0086 } 0087 if (!a.endsWith(QLatin1String("/lib")) && !a.endsWith(QLatin1String("/lib/")) && !searchPath.contains(a)) { 0088 searchPath << a; 0089 } 0090 } 0091 0092 // add current install path 0093 path = QCoreApplication::applicationDirPath().toLower().replace(QLatin1Char('\\'), QLatin1Char('/')); 0094 if (!envPath.contains(path)) { 0095 envPath << path; 0096 } 0097 0098 // detect directory where kdedirs.cache lives 0099 // this is not complete, KDEDIRS path should be used as base too 0100 QFileInfo fi(path + QStringLiteral("/../..")); 0101 QString rootPath = fi.canonicalPath(); 0102 0103 if (verbose) { 0104 qDebug() << "try to find kdedirs.cache in" << rootPath; 0105 } 0106 0107 // add current lib path to client path environment 0108 path = path.replace(QStringLiteral("bin"), QStringLiteral("lib")); 0109 if (!envPath.contains(path)) { 0110 envPath << path; 0111 } 0112 0113 /** 0114 add bin and lib paths from KDEDIRS 0115 - bin/lib to client path environment 0116 - bin to application search path 0117 */ 0118 path = QString::fromLocal8Bit(qgetenv("KDEDIRS")).toLower().replace(QLatin1Char('\\'), QLatin1Char('/')); 0119 QStringList kdedirs; 0120 0121 if (!path.isEmpty()) { 0122 kdedirs = path.split(QLatin1Char(';')); 0123 } 0124 0125 bool changedKDEDIRS = 0; 0126 // setup kdedirs if not present 0127 if (kdedirs.size() == 0) { 0128 QStringList kdedirsCacheList; 0129 #ifdef Q_CC_MSVC 0130 kdedirsCacheList << rootPath + QStringLiteral("/kdedirs.cache.msvc"); 0131 #endif 0132 kdedirsCacheList << rootPath + QStringLiteral("/kdedirs.cache"); 0133 0134 bool found = false; 0135 for (const QString &kdedirsCachePath : std::as_const(kdedirsCacheList)) { 0136 QFile f(kdedirsCachePath); 0137 if (f.exists()) { 0138 f.open(QIODevice::ReadOnly); 0139 QByteArray data = f.readAll(); 0140 f.close(); 0141 kdedirs = QString::fromLocal8Bit(data).split(QLatin1Char(';')); 0142 if (verbose) { 0143 qDebug() << "load kdedirs cache from " << kdedirsCachePath << "values=" << kdedirs; 0144 } 0145 found = true; 0146 break; 0147 } 0148 } 0149 if (!found) { 0150 /* 0151 f.open(QIODevice::WriteOnly); 0152 // search all paths one level above for a directory share/apps 0153 // write entries into a cache 0154 f.write(kdedirs.join(";").toLatin1()); 0155 f.close(); 0156 */ 0157 } 0158 changedKDEDIRS = 1; 0159 } 0160 if (verbose) { 0161 qDebug() << "found KDEDIRS\n\t" << kdedirs.join(QStringLiteral("\n\t")); 0162 } 0163 0164 for (const QString &a : std::as_const(kdedirs)) { 0165 if (!envPath.contains(a + QStringLiteral("/bin"))) { 0166 envPath << a + QStringLiteral("/bin"); 0167 } 0168 if (!envPath.contains(a + QStringLiteral("/lib"))) { 0169 envPath << a + QStringLiteral("/lib"); 0170 } 0171 if (!searchPath.contains(a + QStringLiteral("/bin"))) { 0172 searchPath << a + QStringLiteral("/bin"); 0173 } 0174 } 0175 0176 // find executable 0177 WCHAR _appName[MAX_PATH + 1]; 0178 0179 if (verbose) { 0180 qDebug() << "search " << exeToStart << "in"; 0181 } 0182 0183 bool found = false; 0184 for (const QString &a : std::as_const(searchPath)) { 0185 if (verbose) { 0186 qDebug() << "\t" << a; 0187 } 0188 #ifndef _WIN32_WCE 0189 if (SearchPathW((LPCWSTR)a.utf16(), (LPCWSTR)exeToStart.utf16(), 0190 L".exe", MAX_PATH + 1, (LPWSTR)_appName, NULL)) { 0191 found = true; 0192 break; 0193 } 0194 #else 0195 if (QFile::exists(a + "/" + exeToStart + ".exe")) { 0196 found = true; 0197 break; 0198 } 0199 #endif 0200 } 0201 QString appName = QString::fromUtf16((unsigned short *)_appName); 0202 0203 if (!found) { 0204 qWarning() << myAppName << "application not found"; 0205 return 3; 0206 } 0207 0208 if (verbose) { 0209 qDebug() << "run" << exeToStart << "with params" << exeParams 0210 << "and PATH environment\n\t" << envPath.join(QStringLiteral("\n\t")); 0211 } 0212 0213 // setup client process environment 0214 QStringList env = QProcess::systemEnvironment(); 0215 env.replaceInStrings(QRegExp(QStringLiteral("^PATH=(.*)"), Qt::CaseInsensitive), 0216 QLatin1String("PATH=") + envPath.join(QLatin1Char(';'))); 0217 if (changedKDEDIRS) { 0218 env << QStringLiteral("KDEDIRS=") + kdedirs.join(QLatin1Char(';')); 0219 } 0220 0221 QProcess *process = new QProcess; 0222 process->setEnvironment(env); 0223 process->start(appName, exeParams); 0224 if (process->state() == QProcess::NotRunning) { 0225 qWarning() << myAppName << "process not running"; 0226 return 4; 0227 } 0228 process->waitForStarted(); 0229 0230 return 0; 0231 }