KCoreAddons

kprocesslist_win.cpp
1 /*
2  This file is part of the KDE Frameworks
3 
4  SPDX-FileCopyrightText: 2011 Nokia Corporation and/or its subsidiary(-ies).
5  SPDX-FileCopyrightText: 2019 David Hallas <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.1-only WITH Qt-LGPL-exception-1.1 OR LicenseRef-Qt-Commercial
8 */
9 
10 #include "kprocesslist.h"
11 
12 #include <QLibrary>
13 #include <algorithm>
14 
15 // Enable Win API of XP SP1 and later
16 #ifdef Q_OS_WIN
17 #if !defined(_WIN32_WINNT)
18 #define _WIN32_WINNT 0x0502
19 #endif
20 #include <qt_windows.h>
21 #if !defined(PROCESS_SUSPEND_RESUME) // Check flag for MinGW
22 #define PROCESS_SUSPEND_RESUME (0x0800)
23 #endif // PROCESS_SUSPEND_RESUME
24 #endif // Q_OS_WIN
25 
26 #include <psapi.h>
27 #include <tlhelp32.h>
28 
29 using namespace KProcessList;
30 
31 // Resolve QueryFullProcessImageNameW out of kernel32.dll due
32 // to incomplete MinGW import libs and it not being present
33 // on Windows XP.
34 static inline BOOL queryFullProcessImageName(HANDLE h, DWORD flags, LPWSTR buffer, DWORD *size)
35 {
36  // Resolve required symbols from the kernel32.dll
37  typedef BOOL(WINAPI * QueryFullProcessImageNameWProtoType)(HANDLE, DWORD, LPWSTR, PDWORD);
38  static QueryFullProcessImageNameWProtoType queryFullProcessImageNameW = 0;
39  if (!queryFullProcessImageNameW) {
40  QLibrary kernel32Lib(QLatin1String("kernel32.dll"), 0);
41  if (kernel32Lib.isLoaded() || kernel32Lib.load()) {
42  queryFullProcessImageNameW = (QueryFullProcessImageNameWProtoType)kernel32Lib.resolve("QueryFullProcessImageNameW");
43  }
44  }
45  if (!queryFullProcessImageNameW)
46  return FALSE;
47  // Read out process
48  return (*queryFullProcessImageNameW)(h, flags, buffer, size);
49 }
50 
51 struct ProcessInfo {
52  QString processOwner;
53 };
54 
55 static inline ProcessInfo winProcessInfo(DWORD processId)
56 {
57  ProcessInfo pi;
58  HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, TOKEN_READ, processId);
59  if (handle == INVALID_HANDLE_VALUE)
60  return pi;
61  HANDLE processTokenHandle = NULL;
62  if (!OpenProcessToken(handle, TOKEN_READ, &processTokenHandle) || !processTokenHandle)
63  return pi;
64 
65  DWORD size = 0;
66  GetTokenInformation(processTokenHandle, TokenUser, NULL, 0, &size);
67 
68  if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
69  QByteArray buf;
70  buf.resize(size);
71  PTOKEN_USER userToken = reinterpret_cast<PTOKEN_USER>(buf.data());
72  if (userToken && GetTokenInformation(processTokenHandle, TokenUser, userToken, size, &size)) {
73  SID_NAME_USE sidNameUse;
74  TCHAR user[MAX_PATH] = {0};
75  DWORD userNameLength = MAX_PATH;
76  TCHAR domain[MAX_PATH] = {0};
77  DWORD domainNameLength = MAX_PATH;
78 
79  if (LookupAccountSid(NULL, userToken->User.Sid, user, &userNameLength, domain, &domainNameLength, &sidNameUse))
80  pi.processOwner = QString::fromUtf16(reinterpret_cast<const ushort *>(user));
81  }
82  }
83 
84  CloseHandle(processTokenHandle);
85  CloseHandle(handle);
86  return pi;
87 }
88 
89 KProcessInfoList KProcessList::processInfoList()
90 {
92 
93  PROCESSENTRY32 pe;
94  pe.dwSize = sizeof(PROCESSENTRY32);
95  HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
96  if (snapshot == INVALID_HANDLE_VALUE)
97  return rc;
98 
99  for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
100  const ProcessInfo processInf = winProcessInfo(pe.th32ProcessID);
101  rc.push_back(KProcessInfo(pe.th32ProcessID, QString::fromUtf16(reinterpret_cast<ushort *>(pe.szExeFile)), processInf.processOwner));
102  }
103  CloseHandle(snapshot);
104  return rc;
105 }
106 
107 KProcessInfo KProcessList::processInfo(qint64 pid)
108 {
109  KProcessInfoList processInfoList = KProcessList::processInfoList();
110  auto testProcessIterator = std::find_if(processInfoList.begin(), processInfoList.end(), [pid](const KProcessList::KProcessInfo &info) {
111  return info.pid() == pid;
112  });
113  if (testProcessIterator != processInfoList.end()) {
114  return *testProcessIterator;
115  }
116  return KProcessInfo();
117 }
Contains information about a process.
Definition: kprocesslist.h:27
void push_back(const T &value)
void resize(int size)
QString fromUtf16(const ushort *unicode, int size)
typedef HANDLE
QList::iterator end()
char * data()
QList::iterator begin()
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu Apr 22 2021 23:02:15 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.