reliably kill dbus-daemon and kdeconnect-daemon using WinAPIs

This commit is contained in:
Piyush Aggarwal 2020-10-23 11:25:36 +05:30
parent 28b7ad0a5d
commit 06d81412b6
3 changed files with 99 additions and 4 deletions

View file

@ -16,6 +16,14 @@
#include <KStatusNotifierItem>
#endif
#ifdef Q_OS_WIN
#include <QUrl>
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;

View file

@ -7,8 +7,15 @@
#include <QFile>
#include <QIcon>
#include <QStandardPaths>
#include <QDebug>
#include <iostream>
#include <Windows.h>
#include <tlhelp32.h>
#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;
}

View file

@ -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
};