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