PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/reactos/dll/cpl/sysdm/general.c

https://gitlab.com/dj-tech/reactos
C | 583 lines | 434 code | 115 blank | 34 comment | 70 complexity | db460deae5d9aa7269b8ddcdc61556ae MD5 | raw file
  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. #include "precomp.h"
  12. #include <winnls.h>
  13. #include <powrprof.h>
  14. #define ANIM_STEP 2
  15. #define ANIM_TIME 50
  16. typedef struct _IMGINFO
  17. {
  18. HBITMAP hBitmap;
  19. INT cxSource;
  20. INT cySource;
  21. INT iPLanes;
  22. INT iBits;
  23. } IMGINFO, *PIMGINFO;
  24. PIMGINFO pImgInfo = NULL;
  25. BLENDFUNCTION BlendFunc = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
  26. VOID ShowLastWin32Error(HWND hWndOwner)
  27. {
  28. LPTSTR lpMsg;
  29. DWORD LastError;
  30. LastError = GetLastError();
  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. MessageBox(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
  44. LocalFree((LPVOID)lpMsg);
  45. }
  46. static VOID InitLogo(HWND hwndDlg)
  47. {
  48. BITMAP logoBitmap;
  49. BITMAP maskBitmap;
  50. BITMAPINFO bmpi;
  51. HDC hDC = GetDC(hwndDlg);
  52. HDC hDCLogo = CreateCompatibleDC(NULL);
  53. HDC hDCMask = CreateCompatibleDC(NULL);
  54. HBITMAP hMask, hLogo, hAlphaLogo = NULL;
  55. COLORREF *pBits;
  56. INT line, column;
  57. ZeroMemory(pImgInfo, sizeof(*pImgInfo));
  58. ZeroMemory(&bmpi, sizeof(bmpi));
  59. hLogo = (HBITMAP)LoadImage(hApplet, MAKEINTRESOURCE(IDB_ROSBMP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
  60. hMask = (HBITMAP)LoadImage(hApplet, MAKEINTRESOURCE(IDB_ROSMASK), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
  61. if (hLogo != NULL && hMask != NULL)
  62. {
  63. GetObject(hLogo, sizeof(BITMAP), &logoBitmap);
  64. GetObject(hMask, sizeof(BITMAP), &maskBitmap);
  65. if(logoBitmap.bmHeight != maskBitmap.bmHeight || logoBitmap.bmWidth != maskBitmap.bmWidth)
  66. return;
  67. pImgInfo->cxSource = logoBitmap.bmWidth;
  68. pImgInfo->cySource = logoBitmap.bmHeight;
  69. bmpi.bmiHeader.biSize = sizeof(BITMAPINFO);
  70. bmpi.bmiHeader.biWidth = logoBitmap.bmWidth;
  71. bmpi.bmiHeader.biHeight = logoBitmap.bmHeight;
  72. bmpi.bmiHeader.biPlanes = 1;
  73. bmpi.bmiHeader.biBitCount = 32;
  74. bmpi.bmiHeader.biCompression = BI_RGB;
  75. bmpi.bmiHeader.biSizeImage = 4 * logoBitmap.bmWidth * logoBitmap.bmHeight;
  76. hAlphaLogo = CreateDIBSection(hDC, &bmpi, DIB_RGB_COLORS, (PVOID*)&pBits, 0, 0);
  77. if(!hAlphaLogo)
  78. return;
  79. SelectObject(hDCLogo, hLogo);
  80. SelectObject(hDCMask, hMask);
  81. for(line = logoBitmap.bmHeight - 1; line >= 0; line--)
  82. {
  83. for(column = 0; column < logoBitmap.bmWidth; column++)
  84. {
  85. COLORREF alpha = GetPixel(hDCMask, column, line) & 0xFF;
  86. COLORREF Color = GetPixel(hDCLogo, column, line);
  87. DWORD r, g, b;
  88. r = GetRValue(Color) * alpha / 255;
  89. g = GetGValue(Color) * alpha / 255;
  90. b = GetBValue(Color) * alpha / 255;
  91. *pBits++ = b | g << 8 | r << 16 | alpha << 24;
  92. }
  93. }
  94. }
  95. pImgInfo->hBitmap = hAlphaLogo;
  96. pImgInfo->cxSource = logoBitmap.bmWidth;
  97. pImgInfo->cySource = logoBitmap.bmHeight;
  98. pImgInfo->iBits = logoBitmap.bmBitsPixel;
  99. pImgInfo->iPLanes = logoBitmap.bmPlanes;
  100. DeleteObject(hLogo);
  101. DeleteObject(hMask);
  102. DeleteDC(hDCLogo);
  103. DeleteDC(hDCMask);
  104. }
  105. LRESULT CALLBACK RosImageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  106. {
  107. static UINT timerid = 0, top = 0, offset;
  108. static HBITMAP hCreditsBitmap;
  109. switch (uMsg)
  110. {
  111. case WM_LBUTTONDBLCLK:
  112. if (wParam & (MK_CONTROL | MK_SHIFT))
  113. {
  114. if (timerid == 0)
  115. {
  116. HDC hCreditsDC, hLogoDC;
  117. HFONT hFont;
  118. NONCLIENTMETRICS ncm;
  119. RECT rcCredits;
  120. TCHAR szCredits[2048];
  121. INT iDevsHeight;
  122. top = 0;
  123. offset = 0;
  124. hCreditsDC = CreateCompatibleDC(GetDC(NULL));
  125. hLogoDC = CreateCompatibleDC(hCreditsDC);
  126. if (hCreditsDC == NULL || hLogoDC == NULL)
  127. break;
  128. SetRect(&rcCredits, 0, 0, 0, 0);
  129. ncm.cbSize = sizeof(NONCLIENTMETRICS);
  130. SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
  131. hFont = CreateFontIndirect(&ncm.lfMessageFont);
  132. SelectObject(hCreditsDC, hFont);
  133. LoadString(hApplet, IDS_DEVS, szCredits, sizeof(szCredits) / sizeof(TCHAR));
  134. DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CALCRECT);
  135. iDevsHeight = rcCredits.bottom - rcCredits.top;
  136. hCreditsBitmap = CreateBitmap(pImgInfo->cxSource, (2 * pImgInfo->cySource) + iDevsHeight + 1, pImgInfo->iPLanes, pImgInfo->iBits, NULL);
  137. if(!hCreditsBitmap)
  138. break;
  139. SelectObject(hLogoDC, pImgInfo->hBitmap);
  140. SelectObject(hCreditsDC, hCreditsBitmap);
  141. offset += pImgInfo->cySource;
  142. SetRect(&rcCredits, 0, 0, pImgInfo->cxSource, (2 * pImgInfo->cySource) + iDevsHeight + 1);
  143. FillRect(hCreditsDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE));
  144. SetRect(&rcCredits, 0, offset, pImgInfo->cxSource, offset + iDevsHeight + 1);
  145. SetBkMode(hCreditsDC, TRANSPARENT);
  146. OffsetRect(&rcCredits, 1, 1);
  147. SetTextColor(hCreditsDC, GetSysColor(COLOR_BTNSHADOW));
  148. DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CENTER);
  149. OffsetRect(&rcCredits, -1, -1);
  150. SetTextColor(hCreditsDC, GetSysColor(COLOR_WINDOWTEXT));
  151. DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CENTER);
  152. offset += iDevsHeight;
  153. AlphaBlend(hCreditsDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, hLogoDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc);
  154. AlphaBlend(hCreditsDC, 0, offset, pImgInfo->cxSource, pImgInfo->cySource, hLogoDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc);
  155. DeleteDC(hLogoDC);
  156. DeleteDC(hCreditsDC);
  157. timerid = SetTimer(hwnd, 1, ANIM_TIME, NULL);
  158. }
  159. }
  160. break;
  161. case WM_LBUTTONDOWN:
  162. if (timerid)
  163. {
  164. RECT rcCredits;
  165. HDC hDC = GetDC(hwnd);
  166. GetClientRect(hwnd, &rcCredits);
  167. SetRect(&rcCredits, 0, 0, rcCredits.right, pImgInfo->cySource);
  168. FillRect(hDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE));
  169. KillTimer(hwnd, timerid);
  170. DeleteObject(hCreditsBitmap);
  171. InvalidateRect(hwnd, NULL, FALSE);
  172. top = 0;
  173. timerid = 0;
  174. }
  175. break;
  176. case WM_TIMER:
  177. top += ANIM_STEP;
  178. if (top > offset)
  179. {
  180. RECT rcCredits;
  181. HDC hDC = GetDC(hwnd);
  182. GetClientRect(hwnd, &rcCredits);
  183. SetRect(&rcCredits, 0, 0, rcCredits.right, pImgInfo->cySource);
  184. FillRect(hDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE));
  185. KillTimer(hwnd, timerid);
  186. DeleteObject(hCreditsBitmap);
  187. top = 0;
  188. timerid = 0;
  189. }
  190. InvalidateRect(hwnd, NULL, FALSE);
  191. break;
  192. case WM_PAINT:
  193. {
  194. PAINTSTRUCT PS;
  195. HDC hdcMem, hdc;
  196. LONG left;
  197. hdc = wParam != 0 ? (HDC)wParam : BeginPaint(hwnd, &PS);
  198. GetClientRect(hwnd, &PS.rcPaint);
  199. /* Position image in center of dialog */
  200. left = (PS.rcPaint.right - pImgInfo->cxSource) / 2;
  201. hdcMem = CreateCompatibleDC(hdc);
  202. if (hdcMem != NULL)
  203. {
  204. if(timerid != 0)
  205. {
  206. SelectObject(hdcMem, hCreditsBitmap);
  207. BitBlt(hdc, left, PS.rcPaint.top, PS.rcPaint.right - PS.rcPaint.left, PS.rcPaint.top + pImgInfo->cySource, hdcMem, 0, top, SRCCOPY);
  208. }
  209. else
  210. {
  211. SelectObject(hdcMem, pImgInfo->hBitmap);
  212. AlphaBlend(hdc, left, PS.rcPaint.top, pImgInfo->cxSource, pImgInfo->cySource, hdcMem, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc);
  213. }
  214. DeleteDC(hdcMem);
  215. }
  216. if (wParam == 0)
  217. EndPaint(hwnd,&PS);
  218. break;
  219. }
  220. }
  221. return TRUE;
  222. }
  223. static VOID SetRegTextData(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID)
  224. {
  225. LPTSTR lpBuf = NULL;
  226. DWORD BufSize = 0;
  227. DWORD Type;
  228. if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS)
  229. {
  230. lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize);
  231. if (!lpBuf)
  232. return;
  233. if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS)
  234. SetDlgItemText(hwnd, uID, lpBuf);
  235. HeapFree(GetProcessHeap(), 0, lpBuf);
  236. }
  237. }
  238. static INT SetProcNameString(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID1, UINT uID2)
  239. {
  240. LPTSTR lpBuf = NULL;
  241. DWORD BufSize = 0;
  242. DWORD Type;
  243. INT Ret = 0;
  244. TCHAR szBuf[31];
  245. TCHAR* szLastSpace;
  246. INT LastSpace = 0;
  247. if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS)
  248. {
  249. lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize);
  250. if (!lpBuf)
  251. return 0;
  252. if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS)
  253. {
  254. if (BufSize > ((30 + 1) * sizeof(TCHAR)))
  255. {
  256. /* Wrap the Processor Name String like XP does: *
  257. * - Take the first 30 characters and look for the last space. *
  258. * Then wrap the string after this space. *
  259. * - If no space is found, wrap the string after character 30. *
  260. * *
  261. * For example the Processor Name String of a Pentium 4 is right-aligned. *
  262. * With this wrapping the first line looks centered. */
  263. _tcsncpy(szBuf, lpBuf, 30);
  264. szBuf[30] = 0;
  265. szLastSpace = _tcsrchr(szBuf, ' ');
  266. if (szLastSpace == 0)
  267. {
  268. LastSpace = 30;
  269. }
  270. else
  271. {
  272. LastSpace = (szLastSpace - szBuf);
  273. szBuf[LastSpace] = 0;
  274. }
  275. _tcsncpy(szBuf, lpBuf, LastSpace);
  276. SetDlgItemText(hwnd, uID1, szBuf);
  277. SetDlgItemText(hwnd, uID2, lpBuf+LastSpace+1);
  278. /* Return the number of used lines */
  279. Ret = 2;
  280. }
  281. else
  282. {
  283. SetDlgItemText(hwnd, uID1, lpBuf);
  284. Ret = 1;
  285. }
  286. }
  287. HeapFree(GetProcessHeap(), 0, lpBuf);
  288. }
  289. return Ret;
  290. }
  291. static VOID MakeFloatValueString(DOUBLE* dFloatValue, LPTSTR szOutput, LPTSTR szAppend)
  292. {
  293. TCHAR szDecimalSeparator[4];
  294. /* Get the decimal separator for the current locale */
  295. if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSeparator, sizeof(szDecimalSeparator) / sizeof(TCHAR)) > 0)
  296. {
  297. UCHAR uDecimals;
  298. UINT uIntegral;
  299. /* Show the value with two decimals */
  300. uIntegral = (UINT)*dFloatValue;
  301. uDecimals = (UCHAR)((UINT)(*dFloatValue * 100) - uIntegral * 100);
  302. wsprintf(szOutput, _T("%u%s%02u %s"), uIntegral, szDecimalSeparator, uDecimals, szAppend);
  303. }
  304. }
  305. static VOID SetProcSpeed(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID)
  306. {
  307. TCHAR szBuf[64];
  308. DWORD BufSize = sizeof(DWORD);
  309. DWORD Type = REG_SZ;
  310. PROCESSOR_POWER_INFORMATION ppi;
  311. ZeroMemory(&ppi, sizeof(ppi));
  312. if ((CallNtPowerInformation(ProcessorInformation,
  313. NULL,
  314. 0,
  315. (PVOID)&ppi,
  316. sizeof(ppi)) == STATUS_SUCCESS &&
  317. ppi.CurrentMhz != 0) || RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)&ppi.CurrentMhz, &BufSize) == ERROR_SUCCESS)
  318. {
  319. if (ppi.CurrentMhz < 1000)
  320. {
  321. wsprintf(szBuf, _T("%lu MHz"), ppi.CurrentMhz);
  322. }
  323. else
  324. {
  325. double flt = ppi.CurrentMhz / 1000.0;
  326. MakeFloatValueString(&flt, szBuf, _T("GHz"));
  327. }
  328. SetDlgItemText(hwnd, uID, szBuf);
  329. }
  330. }
  331. static VOID GetSystemInformation(HWND hwnd)
  332. {
  333. HKEY hKey;
  334. TCHAR ProcKey[] = _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
  335. MEMORYSTATUSEX MemStat;
  336. TCHAR Buf[32];
  337. INT CurMachineLine = IDC_MACHINELINE1;
  338. /*
  339. * Get Processor information
  340. * although undocumented, this information is being pulled
  341. * directly out of the registry instead of via setupapi as it
  342. * contains all the info we need, and should remain static
  343. */
  344. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ProcKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  345. {
  346. SetRegTextData(hwnd, hKey, _T("VendorIdentifier"), CurMachineLine);
  347. CurMachineLine++;
  348. CurMachineLine += SetProcNameString(hwnd,
  349. hKey,
  350. _T("ProcessorNameString"),
  351. CurMachineLine,
  352. CurMachineLine + 1);
  353. SetProcSpeed(hwnd, hKey, _T("~MHz"), CurMachineLine);
  354. CurMachineLine++;
  355. }
  356. /* Get total physical RAM */
  357. MemStat.dwLength = sizeof(MemStat);
  358. if (GlobalMemoryStatusEx(&MemStat))
  359. {
  360. TCHAR szStr[32];
  361. double dTotalPhys;
  362. if (MemStat.ullTotalPhys > 1024 * 1024 * 1024)
  363. {
  364. UINT i = 0;
  365. static const UINT uStrId[] = { IDS_GIGABYTE, IDS_TERABYTE, IDS_PETABYTE};
  366. // We're dealing with GBs or more
  367. MemStat.ullTotalPhys /= 1024 * 1024;
  368. if (MemStat.ullTotalPhys > 1024 * 1024)
  369. {
  370. // We're dealing with TBs or more
  371. MemStat.ullTotalPhys /= 1024;
  372. i++;
  373. if (MemStat.ullTotalPhys > 1024 * 1024)
  374. {
  375. // We're dealing with PBs or more
  376. MemStat.ullTotalPhys /= 1024;
  377. i++;
  378. dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
  379. }
  380. else
  381. {
  382. dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
  383. }
  384. }
  385. else
  386. {
  387. dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
  388. }
  389. LoadString(hApplet, uStrId[i], szStr, sizeof(szStr) / sizeof(TCHAR));
  390. MakeFloatValueString(&dTotalPhys, Buf, szStr);
  391. }
  392. else
  393. {
  394. // We're dealing with MBs, don't show any decimals
  395. LoadString(hApplet, IDS_MEGABYTE, szStr, sizeof(szStr) / sizeof(TCHAR));
  396. wsprintf(Buf, _T("%u %s"), (UINT)MemStat.ullTotalPhys / 1024 / 1024, szStr);
  397. }
  398. SetDlgItemText(hwnd, CurMachineLine, Buf);
  399. }
  400. }
  401. /* Property page dialog callback */
  402. INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  403. {
  404. UNREFERENCED_PARAMETER(lParam);
  405. UNREFERENCED_PARAMETER(wParam);
  406. switch (uMsg)
  407. {
  408. case WM_INITDIALOG:
  409. pImgInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMGINFO));
  410. if (pImgInfo == NULL)
  411. {
  412. EndDialog(hwndDlg, 0);
  413. return FALSE;
  414. }
  415. InitLogo(hwndDlg);
  416. SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ROSIMG), GWL_WNDPROC, (LONG)RosImageProc);
  417. GetSystemInformation(hwndDlg);
  418. break;
  419. case WM_DESTROY:
  420. HeapFree(GetProcessHeap(), 0, pImgInfo);
  421. break;
  422. case WM_COMMAND:
  423. if (LOWORD(wParam) == IDC_LICENCE)
  424. {
  425. DialogBox(hApplet, MAKEINTRESOURCE(IDD_LICENCE), hwndDlg, LicenceDlgProc);
  426. return TRUE;
  427. }
  428. break;
  429. case WM_DRAWITEM:
  430. {
  431. LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
  432. if (lpDrawItem->CtlID == IDC_ROSIMG)
  433. {
  434. HDC hdcMem;
  435. LONG left;
  436. /* Position image in centre of dialog */
  437. left = (lpDrawItem->rcItem.right - pImgInfo->cxSource) / 2;
  438. hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
  439. if (hdcMem != NULL)
  440. {
  441. SelectObject(hdcMem, pImgInfo->hBitmap);
  442. BitBlt(lpDrawItem->hDC,
  443. left,
  444. lpDrawItem->rcItem.top,
  445. lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
  446. lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
  447. hdcMem,
  448. 0,
  449. 0,
  450. SRCCOPY);
  451. DeleteDC(hdcMem);
  452. }
  453. }
  454. return TRUE;
  455. }
  456. case WM_NOTIFY:
  457. {
  458. NMHDR *nmhdr = (NMHDR *)lParam;
  459. if (nmhdr->idFrom == IDC_ROSHOMEPAGE_LINK && nmhdr->code == NM_CLICK)
  460. {
  461. PNMLINK nml = (PNMLINK)nmhdr;
  462. ShellExecuteW(hwndDlg, L"open", nml->item.szUrl, NULL, NULL, SW_SHOWNORMAL);
  463. }
  464. break;
  465. }
  466. }
  467. return FALSE;
  468. }