1 /*
2 * SPDX-FileCopyrightText: 2019 Weixuan XIAO <veyx.shaw@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5 */
6
7 #include <QFile>
8 #include <QIcon>
9 #include <QStandardPaths>
10 #include <QDebug>
11
12 #include <iostream>
13
14 #include <Windows.h>
15 #include <tlhelp32.h>
16
17 #include "indicatorhelper.h"
18 #include "indicator_debug.h"
19
IndicatorHelper(const QUrl & indicatorUrl)20 IndicatorHelper::IndicatorHelper(const QUrl& indicatorUrl)
21 : m_indicatorUrl(indicatorUrl) {}
22
~IndicatorHelper()23 IndicatorHelper::~IndicatorHelper() {
24 this->terminateProcess(processes::dbus_daemon, m_indicatorUrl);
25 this->terminateProcess(processes::kdeconnect_app, m_indicatorUrl);
26 this->terminateProcess(processes::kdeconnect_handler, m_indicatorUrl);
27 this->terminateProcess(processes::kdeconnect_settings, m_indicatorUrl);
28 this->terminateProcess(processes::kdeconnect_sms, m_indicatorUrl);
29 this->terminateProcess(processes::kdeconnect_daemon, m_indicatorUrl);
30 }
31
preInit()32 void IndicatorHelper::preInit() {}
33
postInit()34 void IndicatorHelper::postInit() {}
35
iconPathHook()36 void IndicatorHelper::iconPathHook() {}
37
daemonHook(QProcess & kdeconnectd)38 int IndicatorHelper::daemonHook(QProcess &kdeconnectd)
39 {
40 kdeconnectd.start(processes::kdeconnect_daemon);
41 return 0;
42 }
43
44 #ifdef QSYSTRAY
systrayIconHook(QSystemTrayIcon & systray)45 void IndicatorHelper::systrayIconHook(QSystemTrayIcon &systray)
46 {
47 systray.setIcon(QIcon::fromTheme(QStringLiteral("kdeconnect-tray")));
48 }
49 #else
systrayIconHook(KStatusNotifierItem & systray)50 void IndicatorHelper::systrayIconHook(KStatusNotifierItem &systray)
51 {
52 Q_UNUSED(systray);
53 }
54 #endif
55
56
terminateProcess(const QString & processName,const QUrl & indicatorUrl) const57 bool IndicatorHelper::terminateProcess(const QString &processName, const QUrl &indicatorUrl) const
58 {
59 HANDLE hProcessSnap;
60 HANDLE hProcess;
61
62 hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
63 if (hProcessSnap == INVALID_HANDLE_VALUE) {
64 qCWarning(KDECONNECT_INDICATOR) << "Failed to get snapshot of processes.";
65 return FALSE;
66 }
67
68 PROCESSENTRY32 pe32;
69 pe32.dwSize = sizeof(PROCESSENTRY32);
70
71 if (!Process32First(hProcessSnap, &pe32)) {
72 qCWarning(KDECONNECT_INDICATOR) << "Failed to get handle for the first process.";
73 CloseHandle(hProcessSnap);
74 return FALSE;
75 }
76
77 do
78 {
79 if (QString::fromWCharArray((wchar_t *)pe32.szExeFile) == processName) {
80 hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
81
82 if (hProcess == NULL) {
83 qCWarning(KDECONNECT_INDICATOR) << "Failed to get handle for the process:" << processName;
84 return FALSE;
85 } else {
86 const DWORD processPathSize = 4096;
87 CHAR processPathString[processPathSize];
88
89 BOOL gotProcessPath = QueryFullProcessImageNameA(
90 hProcess,
91 0,
92 (LPSTR)processPathString,
93 (PDWORD) &processPathSize
94 );
95
96 if (gotProcessPath) {
97 const QUrl processUrl = QUrl::fromLocalFile(QString::fromStdString(processPathString)); // to replace \\ with /
98 if (indicatorUrl.isParentOf(processUrl)) {
99 BOOL terminateSuccess = TerminateProcess(
100 hProcess,
101 0
102 );
103 if (!terminateSuccess) {
104 qCWarning(KDECONNECT_INDICATOR) << "Failed to terminate process:" << processName;
105 return FALSE;
106 }
107 }
108 }
109 }
110 }
111 } while (Process32Next(hProcessSnap, &pe32));
112
113 CloseHandle(hProcessSnap);
114 return TRUE;
115 }
116
117