master
c 405 lines 14.7 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "win_system-info.h"
4 #include "database/rrdhost-system-info.h"
5 #include "libnetdata/os/windows-api/windows_api.h"
6
7 #ifdef OS_WINDOWS
8
9 static void netdata_windows_ip(struct rrdhost_system_info *systemInfo)
10 {
11 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_DEFAULT_INTERFACE_DETECTION", "WINAPI");
12
13 char *ptr = netdata_win_local_interface();
14 if (ptr)
15 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_DEFAULT_INTERFACE_NAME", ptr);
16
17 ptr = netdata_win_local_ip();
18 if (ptr)
19 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_DEFAULT_INTERFACE_IP", ptr);
20 }
21
22 // Hardware
23 static char *netdata_windows_arch(DWORD value)
24 {
25 switch (value) {
26 case 9:
27 return "x86_64";
28 case 5:
29 return "ARM";
30 case 12:
31 return "ARM64";
32 case 6:
33 return "Intel Intaniun-based";
34 case 0:
35 return "x86";
36 default:
37 return NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN;
38 }
39 }
40
41 static DWORD netdata_windows_cpu_frequency(HKEY lKey)
42 {
43 DWORD freq = 0;
44 long ret = netdata_registry_get_dword_from_open_key(&freq, lKey, "~MHz");
45 if (ret != ERROR_SUCCESS)
46 return freq;
47
48 freq *= 1000000;
49 return freq;
50 }
51
52 static void netdata_windows_cpu_from_system_info(struct rrdhost_system_info *systemInfo)
53 {
54 SYSTEM_INFO sysInfo;
55 GetSystemInfo(&sysInfo);
56
57 char cpuData[256];
58 (void)snprintf(cpuData, 255, "%d", sysInfo.dwNumberOfProcessors);
59 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_CPU_LOGICAL_CPU_COUNT", cpuData);
60
61 char *arch = netdata_windows_arch(sysInfo.wProcessorArchitecture);
62 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_ARCHITECTURE", arch);
63
64 (void)rrdhost_system_info_set_by_name(
65 systemInfo, "NETDATA_SYSTEM_VIRTUALIZATION", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
66
67 (void)rrdhost_system_info_set_by_name(
68 systemInfo, "NETDATA_SYSTEM_VIRT_DETECTION", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
69
70 (void)rrdhost_system_info_set_by_name(
71 systemInfo, "NETDATA_SYSTEM_CONTAINER", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
72
73 (void)rrdhost_system_info_set_by_name(
74 systemInfo, "NETDATA_SYSTEM_CONTAINER_DETECTION", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
75
76 }
77
78 static void netdata_windows_cpu_vendor_model(struct rrdhost_system_info *systemInfo,
79 HKEY lKey,
80 char *variable,
81 char *key)
82 {
83 char cpuData[256];
84 long ret = netdata_registry_get_string_from_open_key(cpuData, 255, lKey, key);
85 (void)rrdhost_system_info_set_by_name(systemInfo,
86 variable,
87 (ret == ERROR_SUCCESS) ? cpuData : NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN);
88 }
89
90 static void netdata_windows_cpu_from_registry(struct rrdhost_system_info *systemInfo)
91 {
92 HKEY lKey;
93 long ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
94 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
95 0,
96 KEY_READ,
97 &lKey);
98 if (ret != ERROR_SUCCESS)
99 return;
100
101 ULONGLONG cpuFreq = netdata_windows_cpu_frequency(lKey);
102 char cpuData[256];
103 if (cpuFreq)
104 (void)snprintf(cpuData, 255, "%lu", (unsigned long)cpuFreq);
105
106 (void)rrdhost_system_info_set_by_name(systemInfo,
107 "NETDATA_SYSTEM_CPU_FREQ",
108 (!cpuFreq) ? NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN : cpuData);
109
110 netdata_windows_cpu_vendor_model(systemInfo, lKey, "NETDATA_SYSTEM_CPU_VENDOR", "VendorIdentifier");
111 netdata_windows_cpu_vendor_model(systemInfo, lKey, "NETDATA_SYSTEM_CPU_MODEL", "ProcessorNameString");
112 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_CPU_DETECTION", NETDATA_WIN_DETECTION_METHOD);
113 }
114
115 static void netdata_windows_get_cpu(struct rrdhost_system_info *systemInfo)
116 {
117 netdata_windows_cpu_from_system_info(systemInfo);
118
119 netdata_windows_cpu_from_registry(systemInfo);
120 }
121
122 static void netdata_windows_get_mem(struct rrdhost_system_info *systemInfo)
123 {
124 ULONGLONG size;
125 char memSize[256];
126 // The amount of physically installed RAM, in kilobytes.
127 if (!GetPhysicallyInstalledSystemMemory(&size))
128 size = 0;
129 else
130 (void)snprintf(memSize, 255, "%llu", size * 1024); // to bytes
131
132 (void)rrdhost_system_info_set_by_name(systemInfo,
133 "NETDATA_SYSTEM_TOTAL_RAM",
134 (!size) ? NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN : memSize);
135 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_RAM_DETECTION", NETDATA_WIN_DETECTION_METHOD);
136 }
137
138 static ULONGLONG netdata_windows_get_disk_size(char *cVolume)
139 {
140 HANDLE disk = CreateFile(cVolume, GENERIC_READ, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
141 if (!disk)
142 return 0;
143
144 GET_LENGTH_INFORMATION length;
145 DWORD ret;
146
147 if (!DeviceIoControl(disk, IOCTL_DISK_GET_LENGTH_INFO, 0, 0, &length, sizeof(length), &ret, 0))
148 return 0;
149
150 CloseHandle(disk);
151
152 return length.Length.QuadPart;
153 }
154
155 static void netdata_windows_get_total_disk_size(struct rrdhost_system_info *systemInfo)
156 {
157 ULONGLONG total = 0;
158 char cVolume[8];
159 snprintf(cVolume, 7, "\\\\.\\C:");
160
161 DWORD lDrives = GetLogicalDrives();
162 if (!lDrives) {
163 return;
164 }
165
166 int i;
167 #define ND_POSSIBLE_VOLUMES 26
168 for (i = 0; i < ND_POSSIBLE_VOLUMES; i++) {
169 if (!(lDrives & 1 << i))
170 continue;
171
172 cVolume[4] = 'A' + i;
173 total += netdata_windows_get_disk_size(cVolume);
174 }
175
176 char diskSize[256];
177 (void)snprintf(diskSize, 255, "%llu", total);
178 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_TOTAL_DISK_SIZE", diskSize);
179 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_DISK_DETECTION", NETDATA_WIN_DETECTION_METHOD);
180 }
181
182 // Host
183 static DWORD netdata_windows_get_current_build()
184 {
185 char cBuild[64];
186 if (!netdata_registry_get_string(
187 cBuild, 63, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentBuild"))
188 return 0;
189
190 errno_clear();
191
192 DWORD version = strtol(cBuild, NULL, 10);
193 if (errno == ERANGE)
194 return 0;
195
196 return version;
197 }
198
199 static void netdata_windows_discover_os_version(char *os, size_t length, DWORD build)
200 {
201 char versionName[256];
202 if (!netdata_registry_get_string(versionName,
203 255,
204 HKEY_LOCAL_MACHINE,
205 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
206 "DisplayVersion"))
207 {
208 (void)snprintf(os, length, "Microsoft Windows");
209 return;
210 }
211
212 if (IsWindowsServer()) {
213 (void)snprintf(os, length, "Microsoft Windows Version %s", versionName);
214 return;
215 }
216
217 #define ND_WIN_VER_LENGTH 16
218 char version[ND_WIN_VER_LENGTH + 1];
219 if (IsWindows10OrGreater()) {
220 // https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information
221 (void)snprintf(version, ND_WIN_VER_LENGTH, (build < 22000) ? "10" : "11");
222 } else if (IsWindows8Point1OrGreater()) {
223 (void)snprintf(version, ND_WIN_VER_LENGTH, "8.1");
224 } else if (IsWindows8OrGreater()) {
225 (void)snprintf(version, ND_WIN_VER_LENGTH, "8");
226 } else if (IsWindows7SP1OrGreater()) {
227 (void)snprintf(version, ND_WIN_VER_LENGTH, "7 SP1");
228 } else if (IsWindows7OrGreater()) {
229 (void)snprintf(version, ND_WIN_VER_LENGTH, "7");
230 } else if (IsWindowsVistaSP2OrGreater()) {
231 (void)snprintf(version, ND_WIN_VER_LENGTH, "Vista SP2");
232 } else if (IsWindowsVistaSP1OrGreater()) {
233 (void)snprintf(version, ND_WIN_VER_LENGTH, "Vista SP1");
234 } else if (IsWindowsVistaOrGreater()) {
235 (void)snprintf(version, ND_WIN_VER_LENGTH, "Vista");
236 }
237 // We are not testing older, because it is not supported anymore by Microsoft
238
239 (void)snprintf(os, length, "Microsoft Windows Version %s, Build %d", version, build);
240 }
241
242 static void netdata_windows_os_kernel_version(char *out, DWORD length, DWORD build)
243 {
244 DWORD major, minor;
245 if (!netdata_registry_get_dword(&major,
246 HKEY_LOCAL_MACHINE,
247 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
248 "CurrentMajorVersionNumber"))
249 major = 0;
250
251 if (!netdata_registry_get_dword(&minor,
252 HKEY_LOCAL_MACHINE,
253 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
254 "CurrentMinorVersionNumber"))
255 minor = 0;
256
257 (void)snprintf(out, length, "Windows %u.%u.%u Build: %u", major, minor, build, build);
258 }
259
260 static char *netdata_windows_get_edition(void)
261 {
262 static char edition[256] = {0};
263
264 // Try to read EditionID first, which is more precise
265 if (netdata_registry_get_string(edition, sizeof(edition)-1, HKEY_LOCAL_MACHINE,
266 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
267 "EditionID")) {
268 return edition;
269 }
270
271 // If EditionID fails, try ProductName
272 if (netdata_registry_get_string(edition, sizeof(edition)-1, HKEY_LOCAL_MACHINE,
273 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
274 "ProductName")) {
275 return edition;
276 }
277
278 // Return unknown if both methods fail
279 return NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN;
280 }
281
282 static char *netdata_windows_get_os_id_like(DWORD build)
283 {
284 static char id_like[256];
285 char *edition = netdata_windows_get_edition();
286 const char *base_id = "";
287
288 if (IsWindowsServer()) {
289 // Windows Server versions based on build numbers
290 if (build >= 25000)
291 base_id = "Windows-Server-2025";
292 else if (build >= 20348)
293 base_id = "Windows-Server-2022";
294 else if (build >= 17763)
295 base_id = "Windows-Server-2019";
296 else if (build >= 14393)
297 base_id = "Windows-Server-2016";
298 else if (build >= 9600)
299 base_id = "Windows-Server-2012R2";
300 else if (build >= 9200)
301 base_id = "Windows-Server-2012";
302 else if (build >= 7601)
303 base_id = "Windows-Server-2008R2";
304 else
305 base_id = "Windows-Server";
306 } else {
307 // Windows client versions
308 if (build >= 22000)
309 base_id = "Windows-11";
310 else if (build >= 10240)
311 base_id = "Windows-10";
312 else if (build >= 9600)
313 base_id = "Windows-8.1";
314 else if (build >= 9200)
315 base_id = "Windows-8";
316 else if (build >= 7601)
317 base_id = "Windows-7";
318 else
319 base_id = "Windows";
320 }
321
322 // If we have a valid edition, append it to the ID_LIKE with a dash
323 if (strcmp(edition, NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN) != 0) {
324 snprintf(id_like, sizeof(id_like), "%s-%s", base_id, edition);
325 } else {
326 strcpy(id_like, base_id);
327 }
328
329 return id_like;
330 }
331
332 static void netdata_windows_host(struct rrdhost_system_info *systemInfo)
333 {
334 char osVersion[4096];
335 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_NAME", "Microsoft Windows");
336
337 DWORD build = netdata_windows_get_current_build();
338
339 netdata_windows_discover_os_version(osVersion, 4095, build);
340 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_ID", osVersion);
341
342 char *id_like = netdata_windows_get_os_id_like(build);
343 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_ID_LIKE", id_like);
344
345 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_VERSION", osVersion);
346 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_VERSION_ID", osVersion);
347
348 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_HOST_OS_DETECTION", NETDATA_WIN_DETECTION_METHOD);
349
350 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_KERNEL_NAME", "Windows");
351
352 netdata_windows_os_kernel_version(osVersion, 4095, build);
353 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_SYSTEM_KERNEL_VERSION", osVersion);
354
355 (void)rrdhost_system_info_set_by_name(
356 systemInfo, "NETDATA_HOST_IS_K8S_NODE", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_FALSE);
357 }
358
359 // Cloud
360 static void netdata_windows_cloud(struct rrdhost_system_info *systemInfo)
361 {
362 (void)rrdhost_system_info_set_by_name(
363 systemInfo, "NETDATA_INSTANCE_CLOUD_TYPE", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN);
364 (void)rrdhost_system_info_set_by_name(
365 systemInfo, "NETDATA_INSTANCE_CLOUD_INSTANCE_TYPE", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN);
366 (void)rrdhost_system_info_set_by_name(
367 systemInfo, "NETDATA_INSTANCE_CLOUD_INSTANCE_REGION", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_UNKNOWN);
368 }
369
370 // Container
371 static void netdata_windows_container(struct rrdhost_system_info *systemInfo)
372 {
373 (void)rrdhost_system_info_set_by_name(
374 systemInfo, "NETDATA_CONTAINER_OS_NAME", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
375 (void)rrdhost_system_info_set_by_name(
376 systemInfo, "NETDATA_CONTAINER_OS_ID", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
377 (void)rrdhost_system_info_set_by_name(
378 systemInfo, "NETDATA_CONTAINER_OS_ID_LIKE", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
379 (void)rrdhost_system_info_set_by_name(
380 systemInfo, "NETDATA_CONTAINER_OS_VERSION", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
381 (void)rrdhost_system_info_set_by_name(
382 systemInfo, "NETDATA_CONTAINER_OS_VERSION_ID", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
383 (void)rrdhost_system_info_set_by_name(
384 systemInfo, "NETDATA_CONTAINER_OS_DETECTION", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_NONE);
385 (void)rrdhost_system_info_set_by_name(
386 systemInfo, "NETDATA_CONTAINER_IS_OFFICIAL_IMAGE", NETDATA_DEFAULT_SYSTEM_INFO_VALUE_FALSE);
387 }
388
389 static void netdata_windows_install_type(struct rrdhost_system_info *systemInfo)
390 {
391 (void)rrdhost_system_info_set_by_name(systemInfo, "NETDATA_INSTALL_TYPE", "netdata-installer.exe");
392 }
393
394 void netdata_windows_get_system_info(struct rrdhost_system_info *systemInfo)
395 {
396 netdata_windows_cloud(systemInfo);
397 netdata_windows_container(systemInfo);
398 netdata_windows_host(systemInfo);
399 netdata_windows_get_cpu(systemInfo);
400 netdata_windows_get_mem(systemInfo);
401 netdata_windows_get_total_disk_size(systemInfo);
402 netdata_windows_install_type(systemInfo);
403 netdata_windows_ip(systemInfo);
404 }
405 #endif