Delete all Trailing spaces in code.
[reactos.git] / reactos / dll / cpl / sysdm / general.c
1 /*
2 * PROJECT: ReactOS System Control Panel Applet
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/sysdm/general.c
5 * PURPOSE: General System Information
6 * COPYRIGHT: Copyright Thomas Weidenmueller <w3seek@reactos.org>
7 * Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
8 * Copyright 2006-2007 Colin Finck <mail@colinfinck.de>
9 *
10 */
11
12
13 #include "precomp.h"
14
15 typedef struct _IMGINFO
16 {
17 HBITMAP hBitmap;
18 INT cxSource;
19 INT cySource;
20 } IMGINFO, *PIMGINFO;
21
22
23 void
24 ShowLastWin32Error(HWND hWndOwner)
25 {
26 LPTSTR lpMsg;
27 DWORD LastError;
28
29 LastError = GetLastError();
30
31 if((LastError == 0) ||
32 !FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
33 FORMAT_MESSAGE_FROM_SYSTEM,
34 NULL,
35 LastError,
36 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
37 (LPTSTR)&lpMsg,
38 0,
39 NULL))
40 {
41 return;
42 }
43
44 MessageBox(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
45
46 LocalFree((LPVOID)lpMsg);
47 }
48
49
50 static VOID
51 InitImageInfo(PIMGINFO ImgInfo)
52 {
53 BITMAP bitmap;
54
55 ZeroMemory(ImgInfo, sizeof(*ImgInfo));
56
57 ImgInfo->hBitmap = LoadImage(hApplet,
58 MAKEINTRESOURCE(IDB_ROSBMP),
59 IMAGE_BITMAP,
60 0,
61 0,
62 LR_DEFAULTCOLOR);
63
64 if (ImgInfo->hBitmap != NULL)
65 {
66 GetObject(ImgInfo->hBitmap, sizeof(BITMAP), &bitmap);
67
68 ImgInfo->cxSource = bitmap.bmWidth;
69 ImgInfo->cySource = bitmap.bmHeight;
70 }
71 }
72
73
74 static VOID
75 SetRegTextData(HWND hwnd,
76 HKEY hKey,
77 LPTSTR Value,
78 UINT uID)
79 {
80 LPTSTR lpBuf = NULL;
81 DWORD BufSize = 0;
82 DWORD Type;
83
84 if (RegQueryValueEx(hKey,
85 Value,
86 NULL,
87 &Type,
88 NULL,
89 &BufSize) == ERROR_SUCCESS)
90 {
91 lpBuf = HeapAlloc(GetProcessHeap(),
92 0,
93 BufSize);
94 if (!lpBuf) return;
95
96 if (RegQueryValueEx(hKey,
97 Value,
98 NULL,
99 &Type,
100 (PBYTE)lpBuf,
101 &BufSize) == ERROR_SUCCESS)
102 {
103 SetDlgItemText(hwnd,
104 uID,
105 lpBuf);
106 }
107
108 HeapFree(GetProcessHeap(),
109 0,
110 lpBuf);
111 }
112 }
113
114 static INT
115 SetProcNameString(HWND hwnd,
116 HKEY hKey,
117 LPTSTR Value,
118 UINT uID1,
119 UINT uID2)
120 {
121 LPTSTR lpBuf = NULL;
122 DWORD BufSize = 0;
123 DWORD Type;
124 INT Ret = 0;
125 TCHAR szBuf[31];
126 TCHAR* szLastSpace;
127 INT LastSpace = 0;
128
129 if (RegQueryValueEx(hKey,
130 Value,
131 NULL,
132 &Type,
133 NULL,
134 &BufSize) == ERROR_SUCCESS)
135 {
136 lpBuf = HeapAlloc(GetProcessHeap(),
137 0,
138 BufSize);
139 if (!lpBuf) return 0;
140
141 if (RegQueryValueEx(hKey,
142 Value,
143 NULL,
144 &Type,
145 (PBYTE)lpBuf,
146 &BufSize) == ERROR_SUCCESS)
147 {
148 if(BufSize > ((30 + 1) * sizeof(TCHAR)))
149 {
150 /* Wrap the Processor Name String like XP does: *
151 * - Take the first 30 characters and look for the last space. *
152 * Then wrap the string after this space. *
153 * - If no space is found, wrap the string after character 30. *
154 * *
155 * For example the Processor Name String of a Pentium 4 is right-aligned. *
156 * With this wrapping the first line looks centered. */
157
158 _tcsncpy(szBuf, lpBuf, 30);
159 szBuf[30] = 0;
160 szLastSpace = _tcsrchr(szBuf, ' ');
161
162 if(szLastSpace == 0)
163 LastSpace = 30;
164 else
165 {
166 LastSpace = (szLastSpace - szBuf);
167 szBuf[LastSpace] = 0;
168 }
169
170 _tcsncpy(szBuf, lpBuf, LastSpace);
171
172 SetDlgItemText(hwnd,
173 uID1,
174 szBuf);
175
176 SetDlgItemText(hwnd,
177 uID2,
178 lpBuf+LastSpace+1);
179
180 /* Return the number of used lines */
181 Ret = 2;
182 }
183 else
184 {
185 SetDlgItemText(hwnd,
186 uID1,
187 lpBuf);
188
189 Ret = 1;
190 }
191 }
192
193 HeapFree(GetProcessHeap(),
194 0,
195 lpBuf);
196 }
197
198 return Ret;
199 }
200
201 static VOID
202 SetProcSpeed(HWND hwnd,
203 HKEY hKey,
204 LPTSTR Value,
205 UINT uID)
206
207 {
208 TCHAR szBuf[64];
209 DWORD BufSize = sizeof(DWORD);
210 DWORD Type = REG_SZ;
211 PROCESSOR_POWER_INFORMATION ppi;
212
213 ZeroMemory(&ppi,
214 sizeof(ppi));
215
216 if ((CallNtPowerInformation(ProcessorInformation,
217 NULL,
218 0,
219 (PVOID)&ppi,
220 sizeof(ppi)) == STATUS_SUCCESS &&
221 ppi.CurrentMhz != 0) ||
222 RegQueryValueEx(hKey,
223 Value,
224 NULL,
225 &Type,
226 (PBYTE)&ppi.CurrentMhz,
227 &BufSize) == ERROR_SUCCESS)
228 {
229 if (ppi.CurrentMhz < 1000)
230 {
231 _stprintf(szBuf, _T("%lu MHz"), ppi.CurrentMhz);
232 }
233 else
234 {
235 double flt = ppi.CurrentMhz / 1000.0;
236 _stprintf(szBuf, _T("%.2f GHz"), flt);
237 }
238
239 SetDlgItemText(hwnd,
240 uID,
241 szBuf);
242 }
243 }
244
245 static VOID
246 GetSystemInformation(HWND hwnd)
247 {
248 HKEY hKey;
249 TCHAR ProcKey[] = _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
250 MEMORYSTATUSEX MemStat;
251 TCHAR Buf[32];
252 INT CurMachineLine = IDC_MACHINELINE1;
253
254
255 /* Get Processor information *
256 * although undocumented, this information is being pulled
257 * directly out of the registry instead of via setupapi as it
258 * contains all the info we need, and should remain static
259 */
260 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
261 ProcKey,
262 0,
263 KEY_READ,
264 &hKey) == ERROR_SUCCESS)
265 {
266 SetRegTextData(hwnd,
267 hKey,
268 _T("VendorIdentifier"),
269 CurMachineLine);
270 CurMachineLine++;
271
272 CurMachineLine += SetProcNameString(hwnd,
273 hKey,
274 _T("ProcessorNameString"),
275 CurMachineLine,
276 CurMachineLine + 1);
277
278 SetProcSpeed(hwnd,
279 hKey,
280 _T("~MHz"),
281 CurMachineLine);
282 CurMachineLine++;
283 }
284
285
286 /* Get total physical RAM */
287 MemStat.dwLength = sizeof(MemStat);
288 if (GlobalMemoryStatusEx(&MemStat))
289 {
290 TCHAR szStr[32];
291 double dTotalPhys;
292 UINT i = 0;
293 static const UINT uStrId[] = {
294 IDS_MEGABYTE,
295 IDS_GIGABYTE,
296 IDS_TERABYTE,
297 IDS_PETABYTE
298 };
299
300 if (MemStat.ullTotalPhys > 1024 * 1024 * 1024)
301 {
302 /* We're dealing with GBs or more */
303 MemStat.ullTotalPhys /= 1024 * 1024;
304 i++;
305
306 if (MemStat.ullTotalPhys > 1024 * 1024)
307 {
308 /* We're dealing with TBs or more */
309 MemStat.ullTotalPhys /= 1024;
310 i++;
311
312 if (MemStat.ullTotalPhys > 1024 * 1024)
313 {
314 /* We're dealing with PBs or more */
315 MemStat.ullTotalPhys /= 1024;
316 i++;
317
318 dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
319 }
320 else
321 dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
322 }
323 else
324 dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
325 }
326 else
327 {
328 /* We're daling with MBs */
329 dTotalPhys = (double)MemStat.ullTotalPhys / 1024 / 1024;
330 }
331
332 if (LoadString(hApplet, uStrId[i], szStr, sizeof(szStr) / sizeof(szStr[0])))
333 {
334 if( _stprintf(Buf, _T("%.2f %s"), dTotalPhys, szStr) )
335 {
336 SetDlgItemText(hwnd,
337 CurMachineLine,
338 Buf);
339 }
340 }
341 }
342 }
343
344
345 /* Property page dialog callback */
346 INT_PTR CALLBACK
347 GeneralPageProc(HWND hwndDlg,
348 UINT uMsg,
349 WPARAM wParam,
350 LPARAM lParam)
351 {
352 static IMGINFO ImgInfo;
353
354 UNREFERENCED_PARAMETER(lParam);
355 UNREFERENCED_PARAMETER(wParam);
356
357 switch(uMsg)
358 {
359 case WM_INITDIALOG:
360 {
361 InitImageInfo(&ImgInfo);
362 GetSystemInformation(hwndDlg);
363 }
364 break;
365
366 case WM_COMMAND:
367 {
368 if (LOWORD(wParam) == IDC_LICENCE)
369 {
370 DialogBox(hApplet,
371 MAKEINTRESOURCE(IDD_LICENCE),
372 hwndDlg,
373 LicenceDlgProc);
374
375 return TRUE;
376 }
377 }
378 break;
379
380 case WM_DRAWITEM:
381 {
382 LPDRAWITEMSTRUCT lpDrawItem;
383 lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
384 if(lpDrawItem->CtlID == IDC_ROSIMG)
385 {
386 HDC hdcMem;
387 LONG left;
388
389 /* position image in centre of dialog */
390 left = (lpDrawItem->rcItem.right - ImgInfo.cxSource) / 2;
391
392 hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
393 if (hdcMem != NULL)
394 {
395 SelectObject(hdcMem, ImgInfo.hBitmap);
396 BitBlt(lpDrawItem->hDC,
397 left,
398 lpDrawItem->rcItem.top,
399 lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
400 lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
401 hdcMem,
402 0,
403 0,
404 SRCCOPY);
405 DeleteDC(hdcMem);
406 }
407 }
408 return TRUE;
409 }
410
411 case WM_NOTIFY:
412 {
413 NMHDR *nmhdr = (NMHDR *)lParam;
414
415 if (nmhdr->idFrom == IDC_ROSHOMEPAGE_LINK && nmhdr->code == NM_CLICK)
416 {
417 PNMLINK nml = (PNMLINK)nmhdr;
418
419 ShellExecuteW(hwndDlg,
420 L"open",
421 nml->item.szUrl,
422 NULL,
423 NULL,
424 SW_SHOWNORMAL);
425 }
426 break;
427 }
428
429 }
430
431 return FALSE;
432 }