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