diff --git a/indicator/indicatorhelper.h b/indicator/indicatorhelper.h index e6bdd1599..c40d09841 100644 --- a/indicator/indicatorhelper.h +++ b/indicator/indicatorhelper.h @@ -16,6 +16,14 @@ #include #endif +#ifdef Q_OS_WIN +#include + namespace processes { + const QString dbus_daemon = QStringLiteral("dbus-daemon.exe"); + const QString kdeconnect_daemon = QStringLiteral("kdeconnectd.exe"); + }; +#endif + class IndicatorHelper { public: @@ -35,6 +43,16 @@ public: void systrayIconHook(KStatusNotifierItem &systray); #endif +#ifdef Q_OS_WIN + /** + * Terminate processes of KDE Connect like kdeconnectd.exe and dbus-daemon.exe + * + * @return True if termination was successful, false otherwise + */ + + bool terminateProcess(const QString &processName, const QUrl &indicatorUrl) const; +#endif + private: #ifdef Q_OS_MAC QSplashScreen *m_splashScreen; diff --git a/indicator/indicatorhelper_win.cpp b/indicator/indicatorhelper_win.cpp index dee6cf95e..0591c4862 100644 --- a/indicator/indicatorhelper_win.cpp +++ b/indicator/indicatorhelper_win.cpp @@ -7,8 +7,15 @@ #include #include #include +#include + +#include + +#include +#include #include "indicatorhelper.h" +#include "indicator_debug.h" IndicatorHelper::IndicatorHelper() {} IndicatorHelper::~IndicatorHelper() {} @@ -21,7 +28,7 @@ void IndicatorHelper::iconPathHook() {} int IndicatorHelper::daemonHook(QProcess &kdeconnectd) { - kdeconnectd.start(QStringLiteral("kdeconnectd.exe")); + kdeconnectd.start(processes::kdeconnect_daemon); return 0; } @@ -36,3 +43,65 @@ void IndicatorHelper::systrayIconHook(KStatusNotifierItem &systray) Q_UNUSED(systray); } #endif + + +bool IndicatorHelper::terminateProcess(const QString &processName, const QUrl &indicatorUrl) const +{ + HANDLE hProcessSnap; + HANDLE hProcess; + + hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + qCWarning(KDECONNECT_INDICATOR) << "Failed to get snapshot of processes."; + return FALSE; + } + + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + + if (!Process32First(hProcessSnap, &pe32)) { + qCWarning(KDECONNECT_INDICATOR) << "Failed to get handle for the first process."; + CloseHandle(hProcessSnap); + return FALSE; + } + + do + { + if (QString::fromWCharArray(pe32.szExeFile) == processName) { + hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); + + if (hProcess == NULL) { + qCWarning(KDECONNECT_INDICATOR) << "Failed to get handle for the process:" << processName; + return FALSE; + } else { + const DWORD processPathSize = 4096; + CHAR processPathString[processPathSize]; + + BOOL gotProcessPath = QueryFullProcessImageNameA( + hProcess, + 0, + (LPSTR)processPathString, + (PDWORD) &processPathSize + ); + + if (gotProcessPath) { + const QUrl processUrl = QUrl::fromLocalFile(QString::fromStdString(processPathString)); // to replace \\ with / + if (indicatorUrl.isParentOf(processUrl)) { + BOOL terminateSuccess = TerminateProcess( + hProcess, + 0 + ); + if (!terminateSuccess) { + qCWarning(KDECONNECT_INDICATOR) << "Failed to terminate process:" << processName; + return FALSE; + } + } + } + } + } + } while (Process32Next(hProcessSnap, &pe32)); + + CloseHandle(hProcessSnap); + return TRUE; +} + diff --git a/indicator/main.cpp b/indicator/main.cpp index 8c5d67470..47b940d98 100644 --- a/indicator/main.cpp +++ b/indicator/main.cpp @@ -56,7 +56,7 @@ int main(int argc, char** argv) QMenu* menu = new QMenu; DaemonDbusInterface iface; - auto refreshMenu = [&iface, &model, &menu]() { + auto refreshMenu = [&iface, &model, &menu, &helper]() { menu->clear(); auto configure = menu->addAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure...")); QObject::connect(configure, &QAction::triggered, configure, [](){ @@ -83,9 +83,9 @@ int main(int argc, char** argv) pairMenu->addAction(i18n("Reject"), dev, &DeviceDbusInterface::rejectPairing); } } - -#if (defined Q_OS_MAC || defined Q_OS_WIN) // Add quit menu +#if defined Q_OS_MAC + menu->addAction(i18n("Quit"), [](){ auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect.daemon"), QStringLiteral("/MainApplication"), @@ -98,6 +98,14 @@ int main(int argc, char** argv) QStringLiteral("quit")); DBusHelper::sessionBus().call(message, QDBus::NoBlock); // Close our indicator }); +#elif defined Q_OS_WIN + + menu->addAction(i18n("Quit"), [&helper](){ + const QUrl indicatorUrl = QUrl::fromLocalFile(qApp->applicationDirPath()); + helper.terminateProcess(processes::dbus_daemon, indicatorUrl); + helper.terminateProcess(processes::kdeconnect_daemon, indicatorUrl); + qApp->quit(); + }); #endif };