xref: /reactos/base/applications/dxdiag/system.c (revision 3e1f4074)
1 /*
2  * PROJECT:     ReactX Diagnosis Application
3  * LICENSE:     LGPL - See COPYING in the top level directory
4  * FILE:        base/applications/dxdiag/system.c
5  * PURPOSE:     ReactX diagnosis system page
6  * COPYRIGHT:   Copyright 2008 Johannes Anderwald
7  *
8  */
9 
10 #include "precomp.h"
11 
12 typedef BOOL (WINAPI *ISWOW64PROC) (HANDLE, PBOOL);
13 
14 BOOL
15 GetRegValue(HKEY hBaseKey, LPWSTR SubKey, LPWSTR ValueName, DWORD Type, LPWSTR Result, DWORD Size)
16 {
17     HKEY hKey;
18     LONG res;
19     DWORD dwType;
20     DWORD dwSize;
21 
22     if (RegOpenKeyExW(hBaseKey, SubKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
23         return FALSE;
24 
25     dwSize = Size;
26     res = RegQueryValueExW(hKey, ValueName, NULL, &dwType, (LPBYTE)Result, &dwSize);
27     RegCloseKey(hKey);
28 
29     if (res != ERROR_SUCCESS)
30         return FALSE;
31 
32     if (dwType != Type)
33         return FALSE;
34 
35     if (Size == sizeof(DWORD))
36         return TRUE;
37 
38     Result[(Size / sizeof(WCHAR))-1] = L'\0';
39     return TRUE;
40 }
41 
42 
43 static
44 BOOL
45 GetDirectXVersion(WCHAR * szBuffer)
46 {
47     WCHAR szVer[20];
48 
49     if (!GetRegValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\DirectX", L"Version", REG_SZ, szVer, sizeof(szVer)))
50         return FALSE;
51 
52     if(!wcscmp(szVer, L"4.02.0095"))
53         wcscpy(szBuffer, L"1.0");
54     else if (!wcscmp(szVer, L"4.03.00.1096"))
55         wcscpy(szBuffer, L"2.0");
56     else if (!wcscmp(szVer, L"4.04.0068"))
57         wcscpy(szBuffer, L"3.0");
58     else if (!wcscmp(szVer, L"4.04.0069"))
59         wcscpy(szBuffer, L"3.0");
60     else if (!wcscmp(szVer, L"4.05.00.0155"))
61         wcscpy(szBuffer, L"5.0");
62     else if (!wcscmp(szVer, L"4.05.01.1721"))
63         wcscpy(szBuffer, L"5.0");
64     else if (!wcscmp(szVer, L"4.05.01.1998"))
65         wcscpy(szBuffer, L"5.0");
66     else if (!wcscmp(szVer, L"4.06.02.0436"))
67         wcscpy(szBuffer, L"6.0");
68     else if (!wcscmp(szVer, L"4.07.00.0700"))
69         wcscpy(szBuffer, L"7.0");
70     else if (!wcscmp(szVer, L"4.07.00.0716"))
71         wcscpy(szBuffer, L"7.0a");
72     else if (!wcscmp(szVer, L"4.08.00.0400"))
73         wcscpy(szBuffer, L"8.0");
74     else if (!wcscmp(szVer, L"4.08.01.0881"))
75         wcscpy(szBuffer, L"8.1");
76     else if (!wcscmp(szVer, L"4.08.01.0810"))
77         wcscpy(szBuffer, L"8.1");
78     else if (!wcscmp(szVer, L"4.09.0000.0900"))
79         wcscpy(szBuffer, L"9.0");
80     else if (!wcscmp(szVer, L"4.09.00.0900"))
81         wcscpy(szBuffer, L"9.0");
82     else if (!wcscmp(szVer, L"4.09.0000.0901"))
83         wcscpy(szBuffer, L"9.0a");
84     else if (!wcscmp(szVer, L"4.09.00.0901"))
85         wcscpy(szBuffer, L"9.0a");
86     else if (!wcscmp(szVer, L"4.09.0000.0902"))
87         wcscpy(szBuffer, L"9.0b");
88     else if (!wcscmp(szVer, L"4.09.00.0902"))
89         wcscpy(szBuffer, L"9.0b");
90     else if (!wcscmp(szVer, L"4.09.00.0904"))
91         wcscpy(szBuffer, L"9.0c");
92     else if (!wcscmp(szVer, L"4.09.0000.0904"))
93         wcscpy(szBuffer, L"9.0c");
94     else
95         return FALSE;
96 
97     return TRUE;
98 }
99 
100 VOID GetSystemCPU(WCHAR *szBuffer)
101 {
102     SYSTEM_INFO archInfo;
103     ISWOW64PROC fnIsWow64Process;
104     BOOL isWow64 = FALSE;
105 
106     /* Find out if the program is running through WOW64 or not. Apparently,
107     IsWow64Process() is not available on all versions of Windows, so the function
108     has to be imported at runtime. If the function cannot be found, then assume
109     the program is not running in WOW64. */
110     fnIsWow64Process = (ISWOW64PROC)GetProcAddress(
111         GetModuleHandleW(L"kernel32"), "IsWow64Process");
112 
113     if (fnIsWow64Process != NULL)
114         fnIsWow64Process(GetCurrentProcess(), &isWow64);
115 
116     /* If the program is compiled as 32-bit, but is running in WOW64, it will
117     automatically report as 32-bit regardless of the actual system architecture.
118     It detects whether or not the program is using WOW64 or not, and then
119     uses GetNativeSystemInfo(). If it is, it will properly report the actual
120     system architecture to the user. */
121     if (isWow64)
122         GetNativeSystemInfo(&archInfo);
123     else
124         GetSystemInfo(&archInfo);
125 
126     /* Now check to see what the system architecture is */
127     if(archInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_UNKNOWN)
128     {
129         switch(archInfo.wProcessorArchitecture)
130         {
131         case PROCESSOR_ARCHITECTURE_INTEL:
132         {
133             wsprintfW(szBuffer, L"32-bit");
134             break;
135         }
136         case PROCESSOR_ARCHITECTURE_AMD64:
137         {
138             wsprintfW(szBuffer, L"64-bit");
139             break;
140         }
141         case PROCESSOR_ARCHITECTURE_IA64:
142         {
143             wsprintfW(szBuffer, L"Itanium");
144             break;
145         }
146         case PROCESSOR_ARCHITECTURE_ARM:
147         {
148             wsprintfW(szBuffer, L"ARM");
149             break;
150         }
151         default:break;
152         }
153     }
154 }
155 
156 static
157 SIZE_T
158 GetBIOSValue(
159     BOOL UseSMBios,
160     PCHAR DmiString,
161     LPWSTR RegValue,
162     PVOID pBuf,
163     DWORD cchBuf,
164     BOOL bTrim)
165 {
166     SIZE_T Length = 0;
167     BOOL Result;
168 
169     if (UseSMBios)
170     {
171         Length = GetSMBiosStringW(DmiString, pBuf, cchBuf, bTrim);
172     }
173     if (Length == 0)
174     {
175         Result = GetRegValue(HKEY_LOCAL_MACHINE, L"Hardware\\Description\\System\\BIOS", RegValue, REG_SZ, pBuf, cchBuf * sizeof(WCHAR));
176         if (Result)
177         {
178             Length = wcslen(pBuf);
179         }
180     }
181     return Length;
182 }
183 
184 static
185 VOID
186 InitializeSystemPage(HWND hwndDlg)
187 {
188     WCHAR szTime[200];
189     WCHAR szOSName[50];
190     DWORD Length;
191     DWORDLONG AvailableBytes, UsedBytes;
192     MEMORYSTATUSEX mem;
193     WCHAR szFormat[50];
194     WCHAR szDesc[50];
195     SYSTEM_INFO SysInfo;
196     OSVERSIONINFO VersionInfo;
197     PVOID SMBiosBuf;
198     PCHAR DmiStrings[ID_STRINGS_MAX] = { 0 };
199     BOOL Result;
200 
201     /* set date/time */
202     szTime[0] = L'\0';
203     Length = GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL, NULL, szTime, _countof(szTime));
204     if (Length)
205     {
206         szTime[Length-1] = L',';
207         szTime[Length++] = L' ';
208     }
209     Length = GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, TIME_FORCE24HOURFORMAT|LOCALE_NOUSEROVERRIDE, NULL, NULL, szTime + Length, _countof(szTime));
210     szTime[_countof(szTime)-1] = L'\0';
211     SendDlgItemMessageW(hwndDlg, IDC_STATIC_TIME, WM_SETTEXT, 0, (LPARAM)szTime);
212 
213     /* set computer name */
214     szTime[0] = L'\0';
215     Length = _countof(szTime);
216     if (GetComputerNameW(szTime, &Length))
217         SendDlgItemMessageW(hwndDlg, IDC_STATIC_COMPUTER, WM_SETTEXT, 0, (LPARAM)szTime);
218 
219     /* set product name */
220     if (GetRegValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"ProductName", REG_SZ, szOSName, sizeof(szOSName)))
221     {
222         if (LoadStringW(hInst, IDS_OS_VERSION, szFormat, _countof(szFormat)))
223         {
224             WCHAR szCpuName[50];
225 
226             ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFO));
227             VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
228 
229             GetSystemCPU(szCpuName);
230 
231             if (GetVersionEx(&VersionInfo))
232             {
233                 szTime[_countof(szTime)-1] = L'\0';
234                 wsprintfW(szTime, szFormat, szOSName, szCpuName, VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, VersionInfo.dwBuildNumber);
235                 SendDlgItemMessageW(hwndDlg, IDC_STATIC_OS, WM_SETTEXT, 0, (LPARAM)szTime);
236             }
237             else
238             {
239                 /* If the version of the OS cannot be retrieved for some reason, then just give the OS Name and Architecture */
240                 szTime[_countof(szTime)-1] = L'\0';
241                 wsprintfW(szTime, L"%s %s", szOSName, szCpuName);
242                 SendDlgItemMessageW(hwndDlg, IDC_STATIC_OS, WM_SETTEXT, 0, (LPARAM)szTime);
243             }
244         }
245     }
246     else
247     {
248         if (LoadStringW(hInst, IDS_VERSION_UNKNOWN, szTime, _countof(szTime)))
249         {
250             szTime[_countof(szTime)-1] = L'\0';
251             SendDlgItemMessage(hwndDlg, IDC_STATIC_VERSION, WM_SETTEXT, 0, (LPARAM)szTime);
252         }
253     }
254 
255     /* FIXME set product language/local language */
256     if (GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SLANGUAGE, szTime, _countof(szTime)))
257         SendDlgItemMessageW(hwndDlg, IDC_STATIC_LANG, WM_SETTEXT, 0, (LPARAM)szTime);
258 
259     /* prepare SMBIOS data */
260     SMBiosBuf = LoadSMBiosData(DmiStrings);
261 
262     /* set system manufacturer */
263     szTime[0] = L'\0';
264     Length = GetBIOSValue(SMBiosBuf != NULL,
265                           DmiStrings[SYS_VENDOR],
266                           L"SystemManufacturer",
267                           szTime, _countof(szTime), FALSE);
268     if (Length > 0)
269     {
270         szTime[_countof(szTime)-1] = L'\0';
271         SendDlgItemMessageW(hwndDlg, IDC_STATIC_MANU, WM_SETTEXT, 0, (LPARAM)szTime);
272     }
273 
274     /* set motherboard model */
275     szTime[0] = L'\0';
276     Length = GetBIOSValue(SMBiosBuf != NULL,
277                           DmiStrings[SYS_PRODUCT],
278                           L"SystemProductName",
279                           szTime, _countof(szTime), FALSE);
280     if (Length > 0)
281     {
282         SendDlgItemMessageW(hwndDlg, IDC_STATIC_MODEL, WM_SETTEXT, 0, (LPARAM)szTime);
283     }
284 
285     /* set bios model */
286     szTime[0] = L'\0';
287     Length = GetBIOSValue(SMBiosBuf != NULL,
288                           DmiStrings[BIOS_VENDOR],
289                           L"BIOSVendor",
290                           szTime, _countof(szTime), TRUE);
291     if (Length > 0)
292     {
293         DWORD Index;
294         DWORD StrLength = _countof(szTime);
295 
296         Index = wcslen(szTime);
297         if (Index + 1 < _countof(szTime))
298         {
299             szTime[Index++] = L' ';
300             szTime[Index] = L'\0';
301         }
302         StrLength -= Index;
303 
304         Length = GetBIOSValue(SMBiosBuf != NULL,
305                               DmiStrings[BIOS_DATE],
306                               L"BIOSReleaseDate",
307                               szTime + Index, StrLength, TRUE);
308         if (Length > 0)
309         {
310             if (Index + StrLength > _countof(szTime) - 15)
311             {
312                 //FIXME  retrieve BiosMajorRelease, BiosMinorRelease
313                 //StrLength = wcslen(szTime + Index);
314                 //szTime[Index+StrLength] = L' ';
315                 //wcscpy(szTime + Index + StrLength, L"Ver: "); //FIXME NON-NLS
316                 //szTime[_countof(szTime)-1] = L'\0';
317             }
318             SendDlgItemMessageW(hwndDlg, IDC_STATIC_BIOS, WM_SETTEXT, 0, (LPARAM)szTime);
319         }
320     }
321 
322     /* clean SMBIOS data */
323     FreeSMBiosData(SMBiosBuf);
324 
325     /* set processor string */
326     Result = GetRegValue(HKEY_LOCAL_MACHINE, L"Hardware\\Description\\System\\CentralProcessor\\0", L"ProcessorNameString", REG_SZ, szDesc, sizeof(szDesc));
327     if (!Result)
328     {
329         /* Processor Brand String not found */
330         /* FIXME: Implement CPU name detection routine */
331 
332         /* Finally try to use Identifier string */
333         Result = GetRegValue(HKEY_LOCAL_MACHINE, L"Hardware\\Description\\System\\CentralProcessor\\0", L"Identifier", REG_SZ, szDesc, sizeof(szDesc));
334     }
335     if (Result)
336     {
337         TrimDmiStringW(szDesc);
338         /* FIXME retrieve current speed */
339         szFormat[0] = L'\0';
340         GetSystemInfo(&SysInfo);
341         if (SysInfo.dwNumberOfProcessors > 1)
342             LoadStringW(hInst, IDS_FORMAT_MPPROC, szFormat, _countof(szFormat));
343         else
344             LoadStringW(hInst, IDS_FORMAT_UNIPROC, szFormat, _countof(szFormat));
345 
346         szFormat[_countof(szFormat)-1] = L'\0';
347         wsprintfW(szTime, szFormat, szDesc, SysInfo.dwNumberOfProcessors);
348         SendDlgItemMessageW(hwndDlg, IDC_STATIC_PROC, WM_SETTEXT, 0, (LPARAM)szTime);
349     }
350 
351     /* retrieve available memory */
352     ZeroMemory(&mem, sizeof(mem));
353     mem.dwLength = sizeof(mem);
354     if (GlobalMemoryStatusEx(&mem))
355     {
356         if (LoadStringW(hInst, IDS_FORMAT_MB, szFormat, _countof(szFormat)))
357         {
358             /* set total mem string */
359             szFormat[_countof(szFormat)-1] = L'\0';
360             wsprintfW(szTime, szFormat, (mem.ullTotalPhys/1048576));
361             SendDlgItemMessageW(hwndDlg, IDC_STATIC_MEM, WM_SETTEXT, 0, (LPARAM)szTime);
362         }
363 
364         if (LoadStringW(hInst, IDS_FORMAT_SWAP, szFormat, _countof(szFormat)))
365         {
366             /* set swap string */
367             AvailableBytes = (mem.ullTotalPageFile-mem.ullTotalPhys)/1048576;
368             UsedBytes = (mem.ullTotalPageFile-mem.ullAvailPageFile)/1048576;
369 
370             szFormat[_countof(szFormat)-1] = L'\0';
371             wsprintfW(szTime, szFormat, (UsedBytes), (AvailableBytes));
372             SendDlgItemMessageW(hwndDlg, IDC_STATIC_SWAP, WM_SETTEXT, 0, (LPARAM)szTime);
373         }
374     }
375     /* set directx version string */
376     wcscpy(szTime, L"ReactX ");
377     if (GetDirectXVersion(szTime + 7))
378     {
379         SendDlgItemMessage(hwndDlg, IDC_STATIC_VERSION, WM_SETTEXT, 0, (LPARAM)szTime);
380     }
381     else
382     {
383         if (LoadStringW(hInst, IDS_VERSION_UNKNOWN, szTime, _countof(szTime)))
384         {
385             szTime[_countof(szTime)-1] = L'\0';
386             SendDlgItemMessage(hwndDlg, IDC_STATIC_VERSION, WM_SETTEXT, 0, (LPARAM)szTime);
387         }
388     }
389 }
390 
391 
392 INT_PTR CALLBACK
393 SystemPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
394 {
395     UNREFERENCED_PARAMETER(lParam);
396     UNREFERENCED_PARAMETER(wParam);
397     switch (message)
398     {
399         case WM_INITDIALOG:
400         {
401             SetWindowPos(hDlg, NULL, 10, 32, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
402             InitializeSystemPage(hDlg);
403             return TRUE;
404         }
405     }
406 
407     return FALSE;
408 }
409