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 #include "precomp.h" 13 14 #include <winnls.h> 15 #include <powrprof.h> 16 #include <buildno.h> 17 #include <strsafe.h> 18 19 #define ANIM_STEP 2 20 #define ANIM_TIME 50 21 22 typedef struct _IMGINFO 23 { 24 HBITMAP hBitmap; 25 INT cxSource; 26 INT cySource; 27 INT iPlanes; 28 INT iBits; 29 } IMGINFO, *PIMGINFO; 30 31 static PIMGINFO pImgInfo; 32 static const BLENDFUNCTION BlendFunc = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; 33 34 VOID ShowLastWin32Error(HWND hWndOwner) 35 { 36 LPTSTR lpMsg; 37 DWORD LastError; 38 39 LastError = GetLastError(); 40 if (LastError == ERROR_SUCCESS) 41 return; 42 43 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 44 FORMAT_MESSAGE_FROM_SYSTEM | 45 FORMAT_MESSAGE_IGNORE_INSERTS, 46 NULL, 47 LastError, 48 LANG_USER_DEFAULT, 49 (LPTSTR)&lpMsg, 50 0, NULL)) 51 { 52 return; 53 } 54 55 MessageBox(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR); 56 LocalFree(lpMsg); 57 } 58 59 60 static VOID InitLogo(HWND hwndDlg) 61 { 62 BITMAP logoBitmap; 63 BITMAP maskBitmap; 64 BITMAPINFO bmpi; 65 HDC hDC, hDCLogo, hDCMask; 66 HBITMAP hMask = NULL, hLogo = NULL; 67 HBITMAP hAlphaLogo = NULL; 68 COLORREF *pBits; 69 INT line, column; 70 71 hDC = GetDC(hwndDlg); 72 hDCLogo = CreateCompatibleDC(NULL); 73 hDCMask = CreateCompatibleDC(NULL); 74 75 if (hDC == NULL || hDCLogo == NULL || hDCMask == NULL) 76 goto Cleanup; 77 78 ZeroMemory(pImgInfo, sizeof(*pImgInfo)); 79 ZeroMemory(&bmpi, sizeof(bmpi)); 80 81 hLogo = (HBITMAP)LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_ROSBMP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); 82 hMask = (HBITMAP)LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_ROSMASK), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); 83 84 if (hLogo == NULL || hMask == NULL) 85 goto Cleanup; 86 87 GetObject(hLogo, sizeof(logoBitmap), &logoBitmap); 88 GetObject(hMask, sizeof(maskBitmap), &maskBitmap); 89 90 if (logoBitmap.bmHeight != maskBitmap.bmHeight || logoBitmap.bmWidth != maskBitmap.bmWidth) 91 goto Cleanup; 92 93 bmpi.bmiHeader.biSize = sizeof(BITMAPINFO); 94 bmpi.bmiHeader.biWidth = logoBitmap.bmWidth; 95 bmpi.bmiHeader.biHeight = logoBitmap.bmHeight; 96 bmpi.bmiHeader.biPlanes = 1; 97 bmpi.bmiHeader.biBitCount = 32; 98 bmpi.bmiHeader.biCompression = BI_RGB; 99 bmpi.bmiHeader.biSizeImage = 4 * logoBitmap.bmWidth * logoBitmap.bmHeight; 100 101 /* Create a premultiplied bitmap */ 102 hAlphaLogo = CreateDIBSection(hDC, &bmpi, DIB_RGB_COLORS, (PVOID*)&pBits, 0, 0); 103 if (!hAlphaLogo) 104 goto Cleanup; 105 106 SelectObject(hDCLogo, hLogo); 107 SelectObject(hDCMask, hMask); 108 109 for (line = logoBitmap.bmHeight - 1; line >= 0; line--) 110 { 111 for (column = 0; column < logoBitmap.bmWidth; column++) 112 { 113 COLORREF alpha = GetPixel(hDCMask, column, line) & 0xFF; 114 COLORREF Color = GetPixel(hDCLogo, column, line); 115 DWORD r, g, b; 116 117 r = GetRValue(Color) * alpha / 255; 118 g = GetGValue(Color) * alpha / 255; 119 b = GetBValue(Color) * alpha / 255; 120 121 *pBits++ = b | (g << 8) | (r << 16) | (alpha << 24); 122 } 123 } 124 125 pImgInfo->hBitmap = hAlphaLogo; 126 pImgInfo->cxSource = logoBitmap.bmWidth; 127 pImgInfo->cySource = logoBitmap.bmHeight; 128 pImgInfo->iBits = logoBitmap.bmBitsPixel; 129 pImgInfo->iPlanes = logoBitmap.bmPlanes; 130 131 Cleanup: 132 if (hMask != NULL) DeleteObject(hMask); 133 if (hLogo != NULL) DeleteObject(hLogo); 134 if (hDCMask != NULL) DeleteDC(hDCMask); 135 if (hDCLogo != NULL) DeleteDC(hDCLogo); 136 if (hDC != NULL) ReleaseDC(hwndDlg, hDC); 137 } 138 139 LRESULT CALLBACK RosImageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 140 { 141 static UINT timerid = 0, top = 0, offset; 142 static HBITMAP hCreditsBitmap; 143 144 switch (uMsg) 145 { 146 case WM_LBUTTONDBLCLK: 147 if (wParam & (MK_CONTROL | MK_SHIFT)) 148 { 149 if (timerid == 0) 150 { 151 HDC hDC; 152 HDC hCreditsDC = NULL, hLogoDC = NULL; 153 HFONT hFont = NULL; 154 NONCLIENTMETRICS ncm; 155 RECT rcCredits; 156 TCHAR szCredits[2048]; 157 INT iDevsHeight; 158 159 hDC = GetDC(NULL); 160 if (hDC == NULL) 161 goto Cleanup; 162 163 top = 0; 164 offset = 0; 165 166 hCreditsDC = CreateCompatibleDC(hDC); 167 hLogoDC = CreateCompatibleDC(hCreditsDC); 168 169 if (hCreditsDC == NULL || hLogoDC == NULL) 170 goto Cleanup; 171 172 SetRect(&rcCredits, 0, 0, 0, 0); 173 174 ncm.cbSize = sizeof(NONCLIENTMETRICS); 175 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); 176 177 hFont = CreateFontIndirect(&ncm.lfMessageFont); 178 if (!hFont) 179 goto Cleanup; 180 SelectObject(hCreditsDC, hFont); 181 182 LoadString(hApplet, IDS_DEVS, szCredits, sizeof(szCredits) / sizeof(TCHAR)); 183 DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CALCRECT); 184 185 iDevsHeight = rcCredits.bottom - rcCredits.top; 186 187 hCreditsBitmap = CreateBitmap(pImgInfo->cxSource, (2 * pImgInfo->cySource) + iDevsHeight + 1, pImgInfo->iPlanes, pImgInfo->iBits, NULL); 188 if (!hCreditsBitmap) 189 goto Cleanup; 190 191 SelectObject(hLogoDC, pImgInfo->hBitmap); 192 SelectObject(hCreditsDC, hCreditsBitmap); 193 194 offset += pImgInfo->cySource; 195 196 SetRect(&rcCredits, 0, 0, pImgInfo->cxSource, (2 * pImgInfo->cySource) + iDevsHeight + 1); 197 FillRect(hCreditsDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE)); 198 199 SetRect(&rcCredits, 0, offset, pImgInfo->cxSource, offset + iDevsHeight + 1); 200 SetBkMode(hCreditsDC, TRANSPARENT); 201 202 OffsetRect(&rcCredits, 1, 1); 203 SetTextColor(hCreditsDC, GetSysColor(COLOR_BTNSHADOW)); 204 DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CENTER); 205 206 OffsetRect(&rcCredits, -1, -1); 207 SetTextColor(hCreditsDC, GetSysColor(COLOR_WINDOWTEXT)); 208 DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CENTER); 209 210 offset += iDevsHeight; 211 212 AlphaBlend(hCreditsDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, hLogoDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc); 213 AlphaBlend(hCreditsDC, 0, offset, pImgInfo->cxSource, pImgInfo->cySource, hLogoDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc); 214 215 timerid = SetTimer(hwnd, 1, ANIM_TIME, NULL); 216 217 Cleanup: 218 if (hFont != NULL) DeleteObject(hFont); 219 if (hLogoDC != NULL) DeleteDC(hLogoDC); 220 if (hCreditsDC != NULL) DeleteDC(hCreditsDC); 221 if (hDC != NULL) ReleaseDC(NULL, hDC); 222 } 223 } 224 break; 225 case WM_LBUTTONDOWN: 226 if (timerid) 227 { 228 RECT rcCredits; 229 HDC hDC = GetDC(hwnd); 230 if (hDC != NULL) 231 { 232 GetClientRect(hwnd, &rcCredits); 233 SetRect(&rcCredits, 0, 0, rcCredits.right, pImgInfo->cySource); 234 FillRect(hDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE)); 235 ReleaseDC(hwnd, hDC); 236 } 237 KillTimer(hwnd, timerid); 238 if (hCreditsBitmap != NULL) 239 DeleteObject(hCreditsBitmap); 240 241 InvalidateRect(hwnd, NULL, FALSE); 242 top = 0; 243 timerid = 0; 244 } 245 break; 246 case WM_TIMER: 247 top += ANIM_STEP; 248 249 if (top > offset) 250 { 251 RECT rcCredits; 252 HDC hDC = GetDC(hwnd); 253 if (hDC != NULL) 254 { 255 GetClientRect(hwnd, &rcCredits); 256 SetRect(&rcCredits, 0, 0, rcCredits.right, pImgInfo->cySource); 257 FillRect(hDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE)); 258 ReleaseDC(hwnd, hDC); 259 } 260 KillTimer(hwnd, timerid); 261 if (hCreditsBitmap != NULL) 262 DeleteObject(hCreditsBitmap); 263 264 top = 0; 265 timerid = 0; 266 } 267 268 InvalidateRect(hwnd, NULL, FALSE); 269 break; 270 case WM_PAINT: 271 { 272 PAINTSTRUCT PS; 273 HDC hdcMem, hdc; 274 LONG left; 275 276 hdc = wParam != 0 ? (HDC)wParam : BeginPaint(hwnd, &PS); 277 278 GetClientRect(hwnd, &PS.rcPaint); 279 280 /* Position image in center of dialog */ 281 left = (PS.rcPaint.right - pImgInfo->cxSource) / 2; 282 hdcMem = CreateCompatibleDC(hdc); 283 284 if (hdcMem != NULL) 285 { 286 if(timerid != 0) 287 { 288 SelectObject(hdcMem, hCreditsBitmap); 289 BitBlt(hdc, left, PS.rcPaint.top, PS.rcPaint.right - PS.rcPaint.left, PS.rcPaint.top + pImgInfo->cySource, hdcMem, 0, top, SRCCOPY); 290 } 291 else 292 { 293 SelectObject(hdcMem, pImgInfo->hBitmap); 294 AlphaBlend(hdc, left, PS.rcPaint.top, pImgInfo->cxSource, pImgInfo->cySource, hdcMem, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc); 295 } 296 297 DeleteDC(hdcMem); 298 } 299 300 if (wParam == 0) 301 EndPaint(hwnd,&PS); 302 break; 303 } 304 } 305 return TRUE; 306 } 307 308 static VOID SetRegTextData(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID) 309 { 310 LPTSTR lpBuf = NULL; 311 DWORD BufSize = 0; 312 DWORD Type; 313 314 if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS) 315 { 316 lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize); 317 318 if (!lpBuf) 319 return; 320 321 if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS) 322 SetDlgItemText(hwnd, uID, lpBuf); 323 324 HeapFree(GetProcessHeap(), 0, lpBuf); 325 } 326 } 327 328 static INT SetProcNameString(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID1, UINT uID2) 329 { 330 LPTSTR lpBuf = NULL; 331 DWORD BufSize = 0; 332 DWORD Type; 333 INT Ret = 0; 334 TCHAR szBuf[31]; 335 TCHAR* szLastSpace; 336 INT LastSpace = 0; 337 338 if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS) 339 { 340 lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize); 341 342 if (!lpBuf) 343 return 0; 344 345 if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS) 346 { 347 if (BufSize > ((30 + 1) * sizeof(TCHAR))) 348 { 349 /* Wrap the Processor Name String like XP does: * 350 * - Take the first 30 characters and look for the last space. * 351 * Then wrap the string after this space. * 352 * - If no space is found, wrap the string after character 30. * 353 * * 354 * For example the Processor Name String of a Pentium 4 is right-aligned. * 355 * With this wrapping the first line looks centered. */ 356 357 _tcsncpy(szBuf, lpBuf, 30); 358 szBuf[30] = 0; 359 szLastSpace = _tcsrchr(szBuf, ' '); 360 361 if (szLastSpace == 0) 362 { 363 LastSpace = 30; 364 } 365 else 366 { 367 LastSpace = (szLastSpace - szBuf); 368 szBuf[LastSpace] = 0; 369 } 370 371 _tcsncpy(szBuf, lpBuf, LastSpace); 372 373 SetDlgItemText(hwnd, uID1, szBuf); 374 SetDlgItemText(hwnd, uID2, lpBuf+LastSpace+1); 375 376 /* Return the number of used lines */ 377 Ret = 2; 378 } 379 else 380 { 381 SetDlgItemText(hwnd, uID1, lpBuf); 382 Ret = 1; 383 } 384 } 385 386 HeapFree(GetProcessHeap(), 0, lpBuf); 387 } 388 389 return Ret; 390 } 391 392 static VOID MakeFloatValueString(DOUBLE* dFloatValue, LPTSTR szOutput, LPTSTR szAppend) 393 { 394 TCHAR szDecimalSeparator[4]; 395 396 /* Get the decimal separator for the current locale */ 397 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSeparator, sizeof(szDecimalSeparator) / sizeof(TCHAR)) > 0) 398 { 399 UCHAR uDecimals; 400 UINT uIntegral; 401 402 /* Show the value with two decimals */ 403 uIntegral = (UINT)*dFloatValue; 404 uDecimals = (UCHAR)((UINT)(*dFloatValue * 100) - uIntegral * 100); 405 406 wsprintf(szOutput, _T("%u%s%02u %s"), uIntegral, szDecimalSeparator, uDecimals, szAppend); 407 } 408 } 409 410 static VOID SetProcSpeed(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID) 411 { 412 TCHAR szBuf[64], szHz[16]; 413 DWORD BufSize = sizeof(DWORD); 414 DWORD Type = REG_SZ; 415 PROCESSOR_POWER_INFORMATION ppi; 416 417 ZeroMemory(&ppi, sizeof(ppi)); 418 419 if ((CallNtPowerInformation(ProcessorInformation, 420 NULL, 421 0, 422 (PVOID)&ppi, 423 sizeof(ppi)) == STATUS_SUCCESS && 424 ppi.CurrentMhz != 0) || RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)&ppi.CurrentMhz, &BufSize) == ERROR_SUCCESS) 425 { 426 if (ppi.CurrentMhz < 1000) 427 { 428 if (!LoadString(hApplet, IDS_MEGAHERTZ, szHz, _countof(szHz))) 429 { 430 return; 431 } 432 StringCchPrintf(szBuf, _countof(szBuf), _T("%lu %s"), ppi.CurrentMhz, szHz); 433 } 434 else 435 { 436 double flt = ppi.CurrentMhz / 1000.0; 437 if (!LoadString(hApplet, IDS_GIGAHERTZ, szHz, _countof(szHz))) 438 { 439 return; 440 } 441 MakeFloatValueString(&flt, szBuf, szHz); 442 } 443 444 SetDlgItemText(hwnd, uID, szBuf); 445 } 446 } 447 448 static VOID GetSystemInformation(HWND hwnd) 449 { 450 HKEY hKey; 451 TCHAR SysKey[] = _T("HARDWARE\\DESCRIPTION\\System"); 452 TCHAR ProcKey[] = _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"); 453 MEMORYSTATUSEX MemStat; 454 TCHAR Buf[32]; 455 WCHAR SMBiosName[96]; 456 INT CurMachineLine = IDC_MACHINELINE1; 457 458 /* 459 * Get hardware device name or motherboard name 460 * using information from raw SMBIOS data 461 */ 462 if (GetSystemName(SMBiosName, _countof(SMBiosName))) 463 { 464 SetDlgItemText(hwnd, CurMachineLine, SMBiosName); 465 CurMachineLine++; 466 } 467 else 468 { 469 /* If SMBIOS is not available, use System Identifier */ 470 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SysKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 471 { 472 SetRegTextData(hwnd, hKey, _T("Identifier"), CurMachineLine); 473 CurMachineLine++; 474 RegCloseKey(hKey); 475 } 476 } 477 /* 478 * Get Processor information 479 * although undocumented, this information is being pulled 480 * directly out of the registry instead of via setupapi as it 481 * contains all the info we need, and should remain static 482 */ 483 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ProcKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 484 { 485 INT PrevMachineLine; 486 487 SetRegTextData(hwnd, hKey, _T("VendorIdentifier"), CurMachineLine); 488 CurMachineLine++; 489 490 PrevMachineLine = CurMachineLine; 491 CurMachineLine += SetProcNameString(hwnd, 492 hKey, 493 _T("ProcessorNameString"), 494 CurMachineLine, 495 CurMachineLine + 1); 496 497 if (CurMachineLine == PrevMachineLine) 498 { 499 /* TODO: Try obtaining CPU name from WMI (i.e. CIM_Processor) */ 500 501 /* Brand String is not available, use Identifier instead */ 502 CurMachineLine += SetProcNameString(hwnd, 503 hKey, 504 _T("Identifier"), 505 CurMachineLine, 506 CurMachineLine + 1); 507 } 508 509 SetProcSpeed(hwnd, hKey, _T("~MHz"), CurMachineLine); 510 CurMachineLine++; 511 RegCloseKey(hKey); 512 } 513 514 /* Get total physical RAM */ 515 MemStat.dwLength = sizeof(MemStat); 516 517 if (GlobalMemoryStatusEx(&MemStat)) 518 { 519 TCHAR szStr[32]; 520 double dTotalPhys; 521 522 if (MemStat.ullTotalPhys > 1024 * 1024 * 1024) 523 { 524 UINT i = 0; 525 static const UINT uStrId[] = { IDS_GIGABYTE, IDS_TERABYTE, IDS_PETABYTE}; 526 527 // We're dealing with GBs or more 528 MemStat.ullTotalPhys /= 1024 * 1024; 529 530 if (MemStat.ullTotalPhys > 1024 * 1024) 531 { 532 // We're dealing with TBs or more 533 MemStat.ullTotalPhys /= 1024; 534 i++; 535 536 if (MemStat.ullTotalPhys > 1024 * 1024) 537 { 538 // We're dealing with PBs or more 539 MemStat.ullTotalPhys /= 1024; 540 i++; 541 542 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 543 } 544 else 545 { 546 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 547 } 548 } 549 else 550 { 551 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 552 } 553 554 LoadString(hApplet, uStrId[i], szStr, sizeof(szStr) / sizeof(TCHAR)); 555 MakeFloatValueString(&dTotalPhys, Buf, szStr); 556 } 557 else 558 { 559 // We're dealing with MBs, don't show any decimals 560 LoadString(hApplet, IDS_MEGABYTE, szStr, sizeof(szStr) / sizeof(TCHAR)); 561 wsprintf(Buf, _T("%u %s"), (UINT)MemStat.ullTotalPhys / 1024 / 1024, szStr); 562 } 563 564 SetDlgItemText(hwnd, CurMachineLine, Buf); 565 } 566 } 567 568 static VOID GetSystemVersion(HWND hwnd) 569 { 570 HWND hRosVersion; 571 SIZE_T lenStr, lenVersion; 572 PCWSTR pwszVersion = L" " TEXT(KERNEL_VERSION_RC); 573 PWSTR pwszStr; 574 575 lenVersion = wcslen(pwszVersion); 576 if (lenVersion == 0) 577 { 578 return; 579 } 580 581 hRosVersion = GetDlgItem(hwnd, IDC_ROSVERSION); 582 if (!hRosVersion) 583 { 584 return; 585 } 586 lenStr = GetWindowTextLengthW(hRosVersion); 587 lenStr += lenVersion + 1; 588 pwszStr = HeapAlloc(GetProcessHeap(), 0, lenStr * sizeof(WCHAR)); 589 if (!pwszStr) 590 { 591 return; 592 } 593 GetWindowText(hRosVersion, pwszStr, lenStr); 594 595 StringCchCatW(pwszStr, lenStr, pwszVersion); 596 SetWindowText(hRosVersion, pwszStr); 597 598 HeapFree(GetProcessHeap(), 0, pwszStr); 599 } 600 601 ULONGLONG GetSecondsQPC(VOID) 602 { 603 LARGE_INTEGER Counter, Frequency; 604 605 QueryPerformanceCounter(&Counter); 606 QueryPerformanceFrequency(&Frequency); 607 608 return Counter.QuadPart / Frequency.QuadPart; 609 } 610 611 ULONGLONG GetSeconds(VOID) 612 { 613 ULONGLONG (WINAPI * pGetTickCount64)(VOID); 614 ULONGLONG Ticks64; 615 HMODULE hModule = GetModuleHandleW(L"kernel32.dll"); 616 617 pGetTickCount64 = (PVOID)GetProcAddress(hModule, "GetTickCount64"); 618 if (pGetTickCount64) 619 { 620 return pGetTickCount64() / 1000; 621 } 622 623 hModule = LoadLibraryW(L"kernel32_vista.dll"); 624 625 if (!hModule) 626 { 627 return GetSecondsQPC(); 628 } 629 630 pGetTickCount64 = (PVOID)GetProcAddress(hModule, "GetTickCount64"); 631 632 if (pGetTickCount64) 633 { 634 Ticks64 = pGetTickCount64() / 1000; 635 } 636 else 637 { 638 Ticks64 = GetSecondsQPC(); 639 } 640 641 FreeLibrary(hModule); 642 return Ticks64; 643 } 644 645 VOID GetSystemUptime(HWND hwnd) 646 { 647 HWND hRosUptime; 648 WCHAR szBuf[64], szStr[64]; 649 ULONG cSeconds; 650 651 hRosUptime = GetDlgItem(hwnd, IDC_UPTIME); 652 if (!hRosUptime) 653 { 654 return; 655 } 656 if (!LoadStringW(hApplet, IDS_UPTIME_FORMAT, szStr, _countof(szStr))) 657 { 658 return; 659 } 660 cSeconds = GetSeconds(); 661 StringCchPrintfW(szBuf, _countof(szBuf), szStr, 662 cSeconds / (60*60*24), 663 (cSeconds / (60*60)) % 24, 664 (cSeconds / 60) % 60, 665 cSeconds % 60); 666 667 SetWindowTextW(hRosUptime, szBuf); 668 } 669 670 /* Property page dialog callback */ 671 INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 672 { 673 UNREFERENCED_PARAMETER(lParam); 674 UNREFERENCED_PARAMETER(wParam); 675 676 switch (uMsg) 677 { 678 case WM_INITDIALOG: 679 pImgInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMGINFO)); 680 if (pImgInfo == NULL) 681 { 682 EndDialog(hwndDlg, 0); 683 return FALSE; 684 } 685 686 InitLogo(hwndDlg); 687 SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ROSIMG), GWLP_WNDPROC, (LONG_PTR)RosImageProc); 688 GetSystemInformation(hwndDlg); 689 GetSystemVersion(hwndDlg); 690 GetSystemUptime(hwndDlg); 691 break; 692 693 case WM_DESTROY: 694 HeapFree(GetProcessHeap(), 0, pImgInfo); 695 break; 696 697 case WM_COMMAND: 698 if (LOWORD(wParam) == IDC_LICENCE) 699 { 700 DialogBox(hApplet, MAKEINTRESOURCE(IDD_LICENCE), hwndDlg, LicenceDlgProc); 701 702 return TRUE; 703 } 704 break; 705 706 case WM_DRAWITEM: 707 { 708 LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) lParam; 709 710 if (lpDrawItem->CtlID == IDC_ROSIMG) 711 { 712 HDC hdcMem; 713 LONG left; 714 715 /* Position image in centre of dialog */ 716 left = (lpDrawItem->rcItem.right - pImgInfo->cxSource) / 2; 717 718 hdcMem = CreateCompatibleDC(lpDrawItem->hDC); 719 if (hdcMem != NULL) 720 { 721 SelectObject(hdcMem, pImgInfo->hBitmap); 722 BitBlt(lpDrawItem->hDC, 723 left, 724 lpDrawItem->rcItem.top, 725 lpDrawItem->rcItem.right - lpDrawItem->rcItem.left, 726 lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top, 727 hdcMem, 728 0, 729 0, 730 SRCCOPY); 731 DeleteDC(hdcMem); 732 } 733 } 734 return TRUE; 735 } 736 737 case WM_NOTIFY: 738 { 739 NMHDR *nmhdr = (NMHDR *)lParam; 740 741 if (nmhdr->idFrom == IDC_ROSHOMEPAGE_LINK && nmhdr->code == NM_CLICK) 742 { 743 PNMLINK nml = (PNMLINK)nmhdr; 744 745 ShellExecuteW(hwndDlg, L"open", nml->item.szUrl, NULL, NULL, SW_SHOWNORMAL); 746 } 747 break; 748 } 749 750 } 751 752 return FALSE; 753 } 754