[SYSTEMINFO]
[reactos.git] / rosapps / applications / sysutils / systeminfo / systeminfo.c
1 /*
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16 /* Copyright (C) 2007, Dmitry Chapyshev <lentind@yandex.ru> */
17 /* Copyright (C) 2011, Rafal Harabien <rafalh1992@o2.pl> */
18
19 #include <wchar.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <windows.h>
24 #include <time.h>
25 #include <locale.h>
26 #include <lm.h>
27 #include <shlwapi.h>
28
29 #include "resource.h"
30
31 #define BUFFER_SIZE 32767
32
33 /* Load from resource and convert to OEM */
34 static
35 BOOL
36 GetOemStrings(UINT rcID, LPWSTR OutMsg)
37 {
38 if (LoadStringW(GetModuleHandle(NULL), rcID, OutMsg, BUFFER_SIZE))
39 return TRUE;
40
41 return FALSE;
42 }
43
44 /* Load data from registry */
45 static
46 unsigned
47 RegGetSZ(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPWSTR lpBuf, DWORD cchBuf)
48 {
49 DWORD dwBytes = cchBuf*sizeof(WCHAR), dwType;
50 unsigned cChars;
51
52 /* If SubKy is specified open it */
53 if (lpSubKey && RegOpenKeyExW(hKey,
54 lpSubKey,
55 0,
56 KEY_QUERY_VALUE,
57 &hKey) != ERROR_SUCCESS)
58 {
59 wprintf(L"Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
60 return 0;
61 }
62
63 if (RegQueryValueExW(hKey,
64 lpValueName,
65 NULL,
66 &dwType,
67 (LPBYTE)lpBuf,
68 &dwBytes) != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_MULTI_SZ))
69 {
70 wprintf(L"Warning! Cannot query %s. Last error: %lu, type: %lu.\n", lpValueName, GetLastError(), dwType);
71 dwBytes = 0;
72 }
73
74 /* Close key if we opened it */
75 if (lpSubKey)
76 RegCloseKey(hKey);
77
78 cChars = dwBytes/sizeof(WCHAR);
79
80 /* NULL-terminate string */
81 lpBuf[min(cchBuf-1, cChars)] = L'\0';
82
83 /* Don't count NULL characters */
84 while(cChars && !lpBuf[cChars-1])
85 --cChars;
86
87 return cChars;
88 }
89
90 static
91 BOOL
92 RegGetDWORD(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPDWORD lpData)
93 {
94 DWORD dwBytes = sizeof(*lpData), dwType;
95 BOOL bRet = TRUE;
96
97 /* If SubKy is specified open it */
98 if (lpSubKey && RegOpenKeyExW(hKey,
99 lpSubKey,
100 0,
101 KEY_QUERY_VALUE,
102 &hKey) != ERROR_SUCCESS)
103 {
104 wprintf(L"Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
105 return FALSE;
106 }
107
108 if (RegQueryValueExW(hKey,
109 lpValueName,
110 NULL,
111 &dwType,
112 (LPBYTE)lpData,
113 &dwBytes) != ERROR_SUCCESS || dwType != REG_DWORD)
114 {
115 wprintf(L"Warning! Cannot query %s. Last err: %lu, type: %lu\n", lpValueName, GetLastError(), dwType);
116 *lpData = 0;
117 bRet = FALSE;
118 }
119
120 /* Close key if we opened it */
121 if (lpSubKey)
122 RegCloseKey(hKey);
123
124 return bRet;
125 }
126
127 static
128 VOID
129 FormatBytes(LPWSTR lpBuf, unsigned cBytes)
130 {
131 WCHAR szMB[32];
132 NUMBERFMTW fmt;
133 unsigned i;
134
135 _itow(cBytes / (1024*1024), szMB, 10);
136
137 fmt.NumDigits = 0;
138 fmt.LeadingZero = 0;
139 fmt.Grouping = 3;
140 fmt.lpDecimalSep = L"";
141 fmt.lpThousandSep = L" ";
142 fmt.NegativeOrder = 0;
143
144 i = GetNumberFormatW(LOCALE_SYSTEM_DEFAULT, 0, szMB, &fmt, lpBuf, BUFFER_SIZE - 3);
145 if (i)
146 --i; /* don't count NULL character */
147 wcscpy(lpBuf + i, L" MB");
148 }
149
150 static
151 VOID
152 FormatDateTime(time_t Time, LPWSTR lpBuf)
153 {
154 unsigned i;
155 SYSTEMTIME SysTime;
156 const struct tm *lpTm;
157
158 lpTm = localtime(&Time);
159 SysTime.wYear = (WORD)(1900 + lpTm->tm_year);
160 SysTime.wMonth = (WORD)(1 + lpTm->tm_mon);
161 SysTime.wDayOfWeek = (WORD)lpTm->tm_wday;
162 SysTime.wDay = (WORD)lpTm->tm_mday;
163 SysTime.wHour = (WORD)lpTm->tm_hour;
164 SysTime.wMinute = (WORD)lpTm->tm_min;
165 SysTime.wSecond = (WORD)lpTm->tm_sec;
166 SysTime.wMilliseconds = 0;
167
168 /* Copy date first */
169 i = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf, BUFFER_SIZE - 2);
170 if (i)
171 --i; /* don't count NULL character */
172
173 /* Copy time now */
174 i += swprintf(lpBuf + i, L", ");
175 i += 2;
176 GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf + i, BUFFER_SIZE - i);
177 }
178
179 /* Show usage */
180 static
181 VOID
182 Usage(VOID)
183 {
184 WCHAR Buf[BUFFER_SIZE];
185
186 if(GetOemStrings(IDS_USAGE, Buf))
187 wprintf(L"%s", Buf);
188 }
189
190 static
191 VOID
192 PrintRow(UINT nTitleID, unsigned cxOffset, LPWSTR lpFormat, ...)
193 {
194 WCHAR Buf[BUFFER_SIZE];
195 va_list Args;
196 unsigned c;
197
198 if (nTitleID)
199 {
200 c = LoadStringW(GetModuleHandle(NULL), nTitleID, Buf, BUFFER_SIZE);
201 if (!c)
202 return;
203
204 wcscpy(Buf + c, L":");
205 } else
206 Buf[0] = L'\0';
207 wprintf(L"%-32s ", Buf);
208
209 va_start(Args, lpFormat);
210 vwprintf(lpFormat, Args);
211 va_end(Args);
212
213 wprintf(L"\n");
214 }
215
216 /* Print all system information */
217 VOID
218 AllSysInfo(VOID)
219 {
220 DWORD dwCharCount = BUFFER_SIZE, dwTimestamp;
221 OSVERSIONINFOW VersionInfo;
222 SYSTEM_INFO SysInfo;
223 WCHAR Buf[BUFFER_SIZE], Tmp[BUFFER_SIZE], Msg[BUFFER_SIZE], szSystemDir[MAX_PATH];
224 const WCHAR *lpcszSysType;
225 LPWSTR lpBuffer;
226 NETSETUP_JOIN_STATUS NetJoinStatus;
227 MEMORYSTATUS MemoryStatus;
228 unsigned int cSeconds, i, j;
229 TIME_ZONE_INFORMATION TimeZoneInfo;
230 HKEY hKey;
231
232 if (!GetSystemDirectoryW(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0])))
233 {
234 wprintf(L"Error! GetSystemDirectory failed.\n");
235 return;
236 }
237
238 GetSystemInfo(&SysInfo);
239
240 // getting computer name
241 dwCharCount = BUFFER_SIZE;
242 if (!GetComputerNameW(Buf, &dwCharCount))
243 wprintf(L"Error! GetComputerName failed.\n");
244 else
245 PrintRow(IDS_HOST_NAME, 0, L"%s", Buf);
246
247 // open CurrentVersion key
248 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
249 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
250 0,
251 KEY_QUERY_VALUE,
252 &hKey) != ERROR_SUCCESS)
253 {
254 wprintf(L"Error! RegOpenKeyEx failed.\n");
255 return;
256 }
257
258 //getting OS Name
259 RegGetSZ(hKey, NULL, L"ProductName", Buf, BUFFER_SIZE);
260 PrintRow(IDS_OS_NAME, 0, L"%s", Buf);
261
262 //getting OS Version
263 ZeroMemory(&VersionInfo, sizeof(VersionInfo));
264 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
265 GetVersionExW(&VersionInfo);
266
267 if (!LoadStringW(GetModuleHandle(NULL), IDS_BUILD, Tmp, BUFFER_SIZE))
268 Tmp[0] = L'\0';
269 PrintRow(IDS_OS_VERSION,
270 0,
271 L"%u.%u.%u %s %s %u",
272 (unsigned)VersionInfo.dwMajorVersion,
273 (unsigned)VersionInfo.dwMinorVersion,
274 (unsigned)VersionInfo.dwBuildNumber,
275 VersionInfo.szCSDVersion,
276 Tmp,
277 (unsigned)VersionInfo.dwBuildNumber);
278
279 //getting OS Manufacturer
280
281 //getting OS Configuration
282
283 //getting OS Build Type
284 RegGetSZ(hKey, NULL, L"CurrentType", Buf, BUFFER_SIZE);
285 PrintRow(IDS_OS_BUILD_TYPE, 0, L"%s", Buf);
286
287 //getting Registered Owner
288 RegGetSZ(hKey, NULL, L"RegisteredOwner", Buf, BUFFER_SIZE);
289 PrintRow(IDS_REG_OWNER, 0, L"%s", Buf);
290
291 //getting Registered Organization
292 RegGetSZ(hKey, NULL, L"RegisteredOrganization", Buf, BUFFER_SIZE);
293 PrintRow(IDS_REG_ORG, 0, L"%s", Buf);
294
295 //getting Product ID
296 RegGetSZ(hKey, NULL, L"ProductId", Buf, BUFFER_SIZE);
297 PrintRow(IDS_PRODUCT_ID, 0, L"%s", Buf);
298
299 //getting Install Date
300 RegGetDWORD(hKey, NULL, L"InstallDate", &dwTimestamp);
301 FormatDateTime((time_t)dwTimestamp, Buf);
302 PrintRow(IDS_INST_DATE, 0, L"%s", Buf);
303
304 // close Current Version key now
305 RegCloseKey(hKey);
306
307 //getting System Up Time
308 cSeconds = GetTickCount() / 1000;
309 if (!LoadStringW(GetModuleHandle(NULL), IDS_UP_TIME_FORMAT, Tmp, BUFFER_SIZE))
310 Tmp[0] = L'\0';
311 swprintf(Buf, Tmp, cSeconds / (60*60*24), (cSeconds / (60*60)) % 24, (cSeconds / 60) % 60, cSeconds % 60);
312 PrintRow(IDS_UP_TIME, 0, L"%s", Buf);
313
314 //getting System Manufacturer; HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\Manufacturer for Win >= 6.0
315 swprintf(Tmp, L"%s\\oeminfo.ini", szSystemDir);
316 GetPrivateProfileStringW(L"General",
317 L"Manufacturer",
318 L"To Be Filled By O.E.M.",
319 Buf,
320 sizeof(Buf)/sizeof(Buf[0]),
321 Tmp);
322 PrintRow(IDS_SYS_MANUFACTURER, 0, L"%s", Buf);
323
324 //getting System Model; HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\Model for Win >= 6.0
325 GetPrivateProfileStringW(L"General",
326 L"Model",
327 L"To Be Filled By O.E.M.",
328 Buf,
329 sizeof(Buf)/sizeof(Buf[0]),
330 Tmp);
331 PrintRow(IDS_SYS_MODEL, 0, L"%s", Buf);
332
333 //getting System type
334 switch (SysInfo.wProcessorArchitecture)
335 {
336 case PROCESSOR_ARCHITECTURE_INTEL:
337 lpcszSysType = L"X86-based PC";
338 break;
339 case PROCESSOR_ARCHITECTURE_IA64:
340 lpcszSysType = L"IA64-based PC";
341 break;
342 case PROCESSOR_ARCHITECTURE_AMD64:
343 lpcszSysType = L"AMD64-based PC";
344 break;
345 default:
346 lpcszSysType = L"Unknown";
347 break;
348 }
349 PrintRow(IDS_SYS_TYPE, 0, L"%s", lpcszSysType);
350
351 //getting Processor(s)
352 if (!LoadStringW(GetModuleHandle(NULL), IDS_PROCESSORS_FORMAT, Tmp, BUFFER_SIZE))
353 Tmp[0] = L'\0';
354 swprintf(Buf, Tmp, (unsigned)SysInfo.dwNumberOfProcessors);
355 PrintRow(IDS_PROCESSORS, 0, L"%s", Buf);
356 for(i = 0; i < (unsigned int)SysInfo.dwNumberOfProcessors; i++)
357 {
358 swprintf(Tmp, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%u", i);
359 j = swprintf(Buf, L"[%02u]: ", i + 1);
360
361 j += RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"Identifier", Buf + j, BUFFER_SIZE - j);
362 if(j + 1 < BUFFER_SIZE)
363 Buf[j++] = L' ';
364 RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"VendorIdentifier", Buf + j, BUFFER_SIZE - j);
365
366 PrintRow(0, 0, L"%s", Buf);
367 }
368
369 //getting BIOS Version
370 RegGetSZ(HKEY_LOCAL_MACHINE,
371 L"HARDWARE\\DESCRIPTION\\System",
372 L"SystemBiosVersion",
373 Buf,
374 BUFFER_SIZE);
375 PrintRow(IDS_BIOS_VERSION, 0, L"%s", Buf);
376
377 //gettings BIOS date
378 RegGetSZ(HKEY_LOCAL_MACHINE,
379 L"HARDWARE\\DESCRIPTION\\System",
380 L"SystemBiosDate",
381 Buf,
382 BUFFER_SIZE);
383 PrintRow(IDS_BIOS_DATE, 0, L"%s", Buf);
384
385 //getting ReactOS Directory
386 if (!GetWindowsDirectoryW(Buf, BUFFER_SIZE))
387 wprintf(L"Error! GetWindowsDirectory failed.");
388 else
389 PrintRow(IDS_ROS_DIR, 0, L"%s", Buf);
390
391 //getting System Directory
392 PrintRow(IDS_SYS_DIR, 0, L"%s", szSystemDir);
393
394 //getting Boot Device
395 RegGetSZ(HKEY_LOCAL_MACHINE,
396 L"SYSTEM\\Setup",
397 L"SystemPartition",
398 Buf,
399 BUFFER_SIZE);
400 PrintRow(IDS_BOOT_DEV, 0, L"%s", Buf);
401
402 //getting System Locale
403 if (GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, Tmp, BUFFER_SIZE))
404 if (RegGetSZ(HKEY_CLASSES_ROOT,
405 L"MIME\\Database\\Rfc1766",
406 Tmp,
407 Buf,
408 BUFFER_SIZE))
409 {
410 /* get rid of @filename,resource */
411 lpBuffer = wcschr(Buf, L';');
412 if (lpBuffer)
413 SHLoadIndirectString(lpBuffer+1, lpBuffer+1, BUFFER_SIZE - (lpBuffer-Buf) - 1, NULL);
414
415 PrintRow(IDS_SYS_LOCALE, 0, L"%s", Buf);
416 }
417
418 //getting Input Locale
419 if (RegGetSZ(HKEY_CURRENT_USER,
420 L"Keyboard Layout\\Preload",
421 L"1",
422 Tmp,
423 BUFFER_SIZE) && wcslen(Tmp) > 4)
424 if (RegGetSZ(HKEY_CLASSES_ROOT,
425 L"MIME\\Database\\Rfc1766",
426 Tmp + 4,
427 Buf,
428 BUFFER_SIZE))
429 {
430 /* get rid of @filename,resource */
431 lpBuffer = wcschr(Buf, L';');
432 if (lpBuffer)
433 SHLoadIndirectString(lpBuffer+1, lpBuffer+1, BUFFER_SIZE - (lpBuffer-Buf) - 1, NULL);
434
435 PrintRow(IDS_INPUT_LOCALE, 0, L"%s", Buf);
436 }
437
438 //getting Time Zone
439 GetTimeZoneInformation(&TimeZoneInfo);
440
441 /* Open Time Zones key */
442 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
443 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
444 0,
445 KEY_ENUMERATE_SUB_KEYS|KEY_READ,
446 &hKey) == ERROR_SUCCESS)
447 {
448 unsigned i;
449
450 /* Find current timezone */
451 dwCharCount = 256; // Windows seems to have a bug - it doesnt accept BUFFER_SIZE here
452 for(i = 0; RegEnumKeyExW(hKey, i, Tmp, &dwCharCount, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++i, dwCharCount = 255)
453 {
454 RegGetSZ(hKey, Tmp, L"Std", Buf, BUFFER_SIZE);
455
456 if(!wcscmp(Buf, TimeZoneInfo.StandardName))
457 {
458 RegGetSZ(hKey, Tmp, L"Display", Buf, BUFFER_SIZE);
459
460 PrintRow(IDS_TIME_ZONE, 0, L"%s", Buf);
461
462 break;
463 }
464 }
465 RegCloseKey(hKey);
466 }
467
468 //getting Total Physical Memory
469 GlobalMemoryStatus(&MemoryStatus);
470 FormatBytes(Buf, MemoryStatus.dwTotalPhys);
471 PrintRow(IDS_TOTAL_PHYS_MEM, 0, L"%s", Buf);
472
473 //getting Available Physical Memory
474 FormatBytes(Buf, MemoryStatus.dwAvailPhys);
475 PrintRow(IDS_AVAIL_PHISICAL_MEM, 0, L"%s", Buf);
476
477 //getting Virtual Memory: Max Size
478 FormatBytes(Buf, MemoryStatus.dwTotalVirtual);
479 PrintRow(IDS_VIRT_MEM_MAX, 0, L"%s", Buf);
480
481 //getting Virtual Memory: Available
482 FormatBytes(Buf, MemoryStatus.dwAvailVirtual);
483 PrintRow(IDS_VIRT_MEM_AVAIL, 0, L"%s", Buf);
484
485 //getting Virtual Memory: In Use
486 FormatBytes(Buf, MemoryStatus.dwTotalVirtual-MemoryStatus.dwAvailVirtual);
487 PrintRow(IDS_VIRT_MEM_INUSE, 0, L"%s", Buf);
488
489 //getting Page File Location(s)
490 if (RegGetSZ(HKEY_LOCAL_MACHINE,
491 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management",
492 L"PagingFiles",
493 Buf,
494 BUFFER_SIZE))
495 {
496 int i;
497
498 for(i = 0; Buf[i]; i++)
499 {
500 if (Buf[i] == L' ')
501 {
502 Buf[i] = L'\0';
503 break;
504 }
505 }
506
507 PrintRow(IDS_PAGEFILE_LOC, 0, L"%s", Buf);
508 }
509
510 //getting Domain
511 if (NetGetJoinInformation (NULL, &lpBuffer, &NetJoinStatus) == NERR_Success)
512 {
513 PrintRow(IDS_DOMAIN, 0, L"%s", lpBuffer);
514
515 NetApiBufferFree(lpBuffer);
516 }
517
518 //getting Logon Server
519
520 //getting NetWork Card(s)
521 if(GetOemStrings(IDS_NETWORK_CARDS, Msg))
522 {
523
524 }
525 }
526
527 /* Main program */
528 int
529 main(int argc, char *argv[])
530 {
531 setlocale(LC_ALL, "");
532
533 if (argc > 1 && (!strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")))
534 {
535 Usage();
536 return 0;
537 }
538
539 AllSysInfo();
540
541 return 0;
542 }