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