KontactInterface

processes.cpp
Go to the documentation of this file.
1/**
2 * This file is part of the kpimutils library.
3 *
4 * SPDX-FileCopyrightText: 2008 Jarosław Staniek <staniek@kde.org>
5 * SPDX-FileCopyrightText: 2012 Andre Heinecke <aheinecke@intevation.de>
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9/**
10 @file
11 This file is part of the KDEPIM Utilities library and provides
12 static methods for process handling (Windows only at this time).
13
14 @author Jarosław Staniek <staniek@kde.org>
15*/
16
17// krazy:excludeall=captruefalse,null
18
19#include "processes.h"
20using namespace KontactInterface;
21
22#ifdef Q_OS_WIN
23
24// windows.h needs to come first
25// clang-format off
26#include <windows.h>
27#include <psapi.h>
28#include <signal.h>
29#include <tlhelp32.h>
30// clang-format on
31
32#include "kontactinterface_debug.h"
33#include <QCoreApplication>
34
35// Copy from kdelibs/kinit/kinit_win.cpp
36PSID copySid(PSID from)
37{
38 if (!from) {
39 return 0;
40 }
41
42 int sidLength = GetLengthSid(from);
43 PSID to = (PSID)malloc(sidLength);
44 CopySid(sidLength, to, from);
45 return to;
46}
47
48// Copy from kdelibs/kinit/kinit_win.cpp
49static PSID getProcessOwner(HANDLE hProcess)
50{
51 HANDLE hToken = NULL;
52 PSID sid;
53
54 OpenProcessToken(hProcess, TOKEN_READ, &hToken);
55 if (hToken) {
56 DWORD size;
57 PTOKEN_USER userStruct;
58
59 // check how much space is needed
60 GetTokenInformation(hToken, TokenUser, NULL, 0, &size);
61 if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
62 userStruct = reinterpret_cast<PTOKEN_USER>(new BYTE[size]);
63 GetTokenInformation(hToken, TokenUser, userStruct, size, &size);
64
65 sid = copySid(userStruct->User.Sid);
66 CloseHandle(hToken);
67 delete[] userStruct;
68 return sid;
69 }
70 }
71 return 0;
72}
73
74// Copy from kdelibs/kinit/kinit_win.cpp
75static HANDLE getProcessHandle(int processID)
76{
77 return OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, false, processID);
78}
79
80void KontactInterface::getProcessesIdForName(const QString &processName, QList<int> &pids)
81{
82 HANDLE h;
83 PROCESSENTRY32 pe32;
84
85 h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
86 if (h == INVALID_HANDLE_VALUE) {
87 return;
88 }
89
90 pe32.dwSize = sizeof(PROCESSENTRY32); // Necessary according to MSDN
91 if (!Process32First(h, &pe32)) {
92 return;
93 }
94
95 pids.clear();
96
97 do {
98 if (QString::fromWCharArray(pe32.szExeFile) == processName) {
99 PSID user_sid = getProcessOwner(GetCurrentProcess());
100 if (user_sid) {
101 // Also check that we are the Owner of that process
102 HANDLE hProcess = getProcessHandle(pe32.th32ProcessID);
103 if (!hProcess) {
104 continue;
105 }
106
107 PSID sid = getProcessOwner(hProcess);
108 PSID userSid = getProcessOwner(GetCurrentProcess());
109 if (!sid || userSid && !EqualSid(userSid, sid)) {
110 free(sid);
111 continue;
112 }
113 }
114 pids.append((int)pe32.th32ProcessID);
115 qCDebug(KONTACTINTERFACE_LOG) << "found PID: " << (int)pe32.th32ProcessID;
116 }
117 } while (Process32Next(h, &pe32));
118 CloseHandle(h);
119}
120
121struct EnumWindowsStruct {
122 EnumWindowsStruct()
123 : windowId(0)
124 {
125 }
126 int pid;
127 HWND windowId;
128};
129
130BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
131{
132 if (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) {
133 DWORD pidwin;
134
135 GetWindowThreadProcessId(hwnd, &pidwin);
136 if (pidwin == ((EnumWindowsStruct *)lParam)->pid) {
137 ((EnumWindowsStruct *)lParam)->windowId = hwnd;
138 return FALSE;
139 }
140 }
141 return TRUE;
142}
143
144void KontactInterface::activateWindowForProcess(const QString &executableName)
145{
146 QList<int> pids;
147 KontactInterface::getProcessesIdForName(executableName, pids);
149 int foundPid = 0;
150 for (int pid : std::as_const(pids)) {
151 if (myPid != pid) {
152 qCDebug(KONTACTINTERFACE_LOG) << "activateWindowForProcess(): PID to activate:" << pid;
153 foundPid = pid;
154 break;
155 }
156 }
157 if (foundPid == 0) {
158 return;
159 }
160 EnumWindowsStruct winStruct;
161 winStruct.pid = foundPid;
162 EnumWindows(EnumWindowsProc, (LPARAM)&winStruct);
163 if (winStruct.windowId == 0) {
164 return;
165 }
166 SetForegroundWindow(winStruct.windowId);
167}
168
169#endif // Q_OS_WIN
This file is part of the kpimutils library.
qint64 applicationPid()
void append(QList< T > &&value)
void clear()
QString fromWCharArray(const wchar_t *string, qsizetype size)
typedef HANDLE
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:19:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.