stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
sys_info.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023-2024 Amebis
4*/
5
6#pragma once
7
8#include "assert.hpp"
9#include "compat.hpp"
10#include "string.hpp"
11#include "system.hpp"
12#if defined(_WIN32)
13#include "windows.h"
14#include <stdlib.h>
15#include <tchar.h>
16#else
17#include <sys/utsname.h>
18#endif
19#include <map>
20#include <memory>
21
22#if defined(__GNUC__)
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-Wexit-time-destructors"
25#endif
26
27namespace stdex
28{
32 enum class platform_id : uint16_t {
33#ifdef _WIN32
34 unknown = IMAGE_FILE_MACHINE_UNKNOWN,
35 i386 = IMAGE_FILE_MACHINE_I386,
36 x86_64 = IMAGE_FILE_MACHINE_AMD64,
37 arm = IMAGE_FILE_MACHINE_ARMNT,
38 aarch64 = IMAGE_FILE_MACHINE_ARM64,
39#else
40 unknown = 0,
41 i386 = 0x014c,
42 x86_64 = 0x8664,
43 arm = 0x01c4,
44 aarch64 = 0xaa64,
45#endif
46 };
47
55 inline platform_id platform_from_name(_In_z_ const char* name)
56 {
57 struct platform_less {
58 bool operator()(_In_z_ const char* a, _In_z_ const char* b) const
59 {
60 return stricmp(a, b) < 0;
61 }
62 };
63 static const std::map<const char*, platform_id, platform_less> platforms = {
64 { "aarch64", platform_id::aarch64 },
65 { "arm", platform_id::arm },
66 { "i386", platform_id::i386 },
67 { "x86_64", platform_id::x86_64 },
68 };
69 if (auto el = platforms.find(name); el != platforms.end())
70 return el->second;
71 return platform_id::unknown;
72 }
73
77 inline const struct sys_info_t
78 {
82#if _M_IX86 || __i386__
83 static constexpr platform_id process_platform = platform_id::i386;
84#elif _M_X64 /* _M_ARM64EC is introducing as x64 */ || __x86_64__
85 static constexpr platform_id process_platform = platform_id::x86_64;
86#elif _M_ARM || __arm__
87 static constexpr platform_id process_platform = platform_id::arm;
88#elif _M_ARM64 || __aarch64__
89 static constexpr platform_id process_platform = platform_id::aarch64;
90#else
91 #error Unknown platform
92#endif
93
97 platform_id os_platform;
98
99#ifdef _WIN32
103 bool wow64;
104#endif
105
110
114 bool admin;
115
120
121 sys_info_t() :
122 os_platform(platform_id::unknown),
123#ifdef _WIN32
124 wow64(false),
125#endif
127 admin(false),
128 elevated(false)
129 {
130#ifdef _WIN32
131 HMODULE kernel32_handle;
132 kernel32_handle = LoadLibrary(_T("kernel32.dll"));
133 stdex_assert(kernel32_handle);
134 BOOL(WINAPI * IsWow64Process2)(HANDLE hProcess, USHORT * pProcessMachine, USHORT * pNativeMachine);
135 *reinterpret_cast<FARPROC*>(&IsWow64Process2) = GetProcAddress(kernel32_handle, "IsWow64Process2");
136 HANDLE process = GetCurrentProcess();
137 USHORT process_machine;
138#ifndef _WIN64
139 BOOL Wow64Process;
140#endif
141 if (IsWow64Process2 && IsWow64Process2(process, &process_machine, reinterpret_cast<USHORT*>(&os_platform))) {
142 wow64 = process_machine != IMAGE_FILE_MACHINE_UNKNOWN;
143 }
144#ifdef _WIN64
145 else {
146 os_platform = process_platform;
147 wow64 = false;
148 }
149#else
150 else if (IsWow64Process(process, &Wow64Process)) {
151 if (Wow64Process) {
152 os_platform = platform_id::x86_64;
153 wow64 = true;
154 }
155 else {
156 os_platform = process_platform;
157 wow64 = false;
158 }
159 }
160#endif
161 FreeLibrary(kernel32_handle);
162#else
163 memset(&m_utsn, 0, sizeof(m_utsn));
164 if (uname(&m_utsn) != -1)
165 os_platform = platform_from_name(m_utsn.machine);
166#endif
167
168#ifdef _WIN32
169 HWINSTA hWinSta = GetProcessWindowStation();
170 if (hWinSta) {
171 TCHAR sName[MAX_PATH];
172 if (GetUserObjectInformation(hWinSta, UOI_NAME, sName, sizeof(sName), NULL)) {
173 sName[_countof(sName) - 1] = 0;
174 // Only "WinSta0" is interactive (Source: KB171890)
175 interactive_process = _tcsicmp(sName, _T("WinSta0")) == 0;
176 }
177 }
178#else
179 // TODO: Research interactive process vs service/agent/daemon on this platform.
180#endif
181
182#if defined(_WIN32)
183 {
184 HANDLE token_h;
185 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_h)) {
186 sys_object token(token_h);
187
188 TOKEN_ELEVATION elevation;
189 DWORD size = sizeof(TOKEN_ELEVATION);
190 if (GetTokenInformation(token_h, TokenElevation, &elevation, sizeof(elevation), &size))
191 elevated = elevation.TokenIsElevated;
192
193 GetTokenInformation(token.get(), TokenGroups, NULL, 0, &size);
194 std::unique_ptr<TOKEN_GROUPS> groups((TOKEN_GROUPS*)new uint8_t[size]);
195 if (GetTokenInformation(token.get(), TokenGroups, (LPVOID)groups.get(), size, &size)) {
196 SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
197 PSID sid_admins_h = NULL;
198 if (AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid_admins_h)) {
199 struct SID_delete { void operator()(_In_ PSID p) const { FreeSid(p); } };
200 std::unique_ptr<void, SID_delete> sid_admins(sid_admins_h);
201 for (DWORD i = 0; i < groups->GroupCount; ++i)
202 if (EqualSid(sid_admins.get(), groups->Groups[i].Sid)) {
203 admin = true;
204 break;
205 }
206 }
207 }
208 }
209 }
210#elif defined(__APPLE__)
211 {
212 gid_t gids[NGROUPS_MAX];
213 for (int i = 0, n = getgroups(NGROUPS_MAX, gids); i < n; ++i) {
214 struct group* group = getgrgid(gids[i]);
215 if (!group) continue;
216 if (strcmp(group->gr_name, "admin") == 0) {
217 admin = true;
218 break;
219 }
220 }
221 }
222
223 elevated = geteuid() == 0;
224#else
225 // TODO: Set admin.
226 elevated = geteuid() == 0;
227#endif
228 }
229
233 static bool is_screen_reader()
234 {
235#ifdef _WIN32
236 BOOL b;
237 return SystemParametersInfo(SPI_GETSCREENREADER, 0, &b, 0) && b;
238#else
239 return false;
240#endif
241 }
242
243 protected:
244#ifndef _WIN32
245 struct utsname m_utsn;
246#endif
247 } sys_info;
248}
249
250#if defined(__GNUC__)
251#pragma GCC diagnostic pop
252#endif
Operating system object base class.
Definition system.hpp:142
T get() const noexcept
Returns object handle.
Definition system.hpp:199
System information.
Definition sys_info.hpp:78
bool admin
Is member of local group Administrators (Windows) or member of group wheel/sudoers (others)?
Definition sys_info.hpp:114
bool elevated
Is elevated process (Windows) or running as root (others)?
Definition sys_info.hpp:119
platform_id os_platform
The platform this process was compiled for.
Definition sys_info.hpp:97
static bool is_screen_reader()
Is screen reader currently active?
Definition sys_info.hpp:233
bool interactive_process
Is interactive process?
Definition sys_info.hpp:109