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 top = 0; 238 timerid = 0; 239 } 240 241 InvalidateRect(hwnd, NULL, FALSE); 242 break; 243 case WM_TIMER: 244 top += ANIM_STEP; 245 246 if (top > offset) 247 { 248 RECT rcCredits; 249 HDC hDC = GetDC(hwnd); 250 if (hDC != NULL) 251 { 252 GetClientRect(hwnd, &rcCredits); 253 SetRect(&rcCredits, 0, 0, rcCredits.right, pImgInfo->cySource); 254 FillRect(hDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE)); 255 ReleaseDC(hwnd, hDC); 256 } 257 KillTimer(hwnd, timerid); 258 if (hCreditsBitmap != NULL) 259 DeleteObject(hCreditsBitmap); 260 261 top = 0; 262 timerid = 0; 263 } 264 265 InvalidateRect(hwnd, NULL, FALSE); 266 break; 267 case WM_PAINT: 268 { 269 PAINTSTRUCT PS; 270 HDC hdcMem, hdc; 271 LONG left; 272 273 hdc = wParam != 0 ? (HDC)wParam : BeginPaint(hwnd, &PS); 274 275 GetClientRect(hwnd, &PS.rcPaint); 276 277 /* Position image in center of dialog */ 278 left = (PS.rcPaint.right - pImgInfo->cxSource) / 2; 279 hdcMem = CreateCompatibleDC(hdc); 280 281 if (hdcMem != NULL) 282 { 283 if(timerid != 0) 284 { 285 SelectObject(hdcMem, hCreditsBitmap); 286 BitBlt(hdc, left, PS.rcPaint.top, PS.rcPaint.right - PS.rcPaint.left, PS.rcPaint.top + pImgInfo->cySource, hdcMem, 0, top, SRCCOPY); 287 } 288 else 289 { 290 SelectObject(hdcMem, pImgInfo->hBitmap); 291 AlphaBlend(hdc, left, PS.rcPaint.top, pImgInfo->cxSource, pImgInfo->cySource, hdcMem, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc); 292 } 293 294 DeleteDC(hdcMem); 295 } 296 297 if (wParam == 0) 298 EndPaint(hwnd,&PS); 299 break; 300 } 301 } 302 return TRUE; 303 } 304 305 static VOID SetRegTextData(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID) 306 { 307 LPTSTR lpBuf = NULL; 308 DWORD BufSize = 0; 309 DWORD Type; 310 311 if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS) 312 { 313 lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize); 314 315 if (!lpBuf) 316 return; 317 318 if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS) 319 SetDlgItemText(hwnd, uID, lpBuf); 320 321 HeapFree(GetProcessHeap(), 0, lpBuf); 322 } 323 } 324 325 static INT SetProcNameString(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID1, UINT uID2) 326 { 327 LPTSTR lpBuf = NULL; 328 DWORD BufSize = 0; 329 DWORD Type; 330 INT Ret = 0; 331 TCHAR szBuf[31]; 332 TCHAR* szLastSpace; 333 INT LastSpace = 0; 334 335 if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS) 336 { 337 lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize); 338 339 if (!lpBuf) 340 return 0; 341 342 if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS) 343 { 344 if (BufSize > ((30 + 1) * sizeof(TCHAR))) 345 { 346 /* Wrap the Processor Name String like XP does: * 347 * - Take the first 30 characters and look for the last space. * 348 * Then wrap the string after this space. * 349 * - If no space is found, wrap the string after character 30. * 350 * * 351 * For example the Processor Name String of a Pentium 4 is right-aligned. * 352 * With this wrapping the first line looks centered. */ 353 354 _tcsncpy(szBuf, lpBuf, 30); 355 szBuf[30] = 0; 356 szLastSpace = _tcsrchr(szBuf, ' '); 357 358 if (szLastSpace == 0) 359 { 360 LastSpace = 30; 361 } 362 else 363 { 364 LastSpace = (szLastSpace - szBuf); 365 szBuf[LastSpace] = 0; 366 } 367 368 _tcsncpy(szBuf, lpBuf, LastSpace); 369 370 SetDlgItemText(hwnd, uID1, szBuf); 371 SetDlgItemText(hwnd, uID2, lpBuf+LastSpace+1); 372 373 /* Return the number of used lines */ 374 Ret = 2; 375 } 376 else 377 { 378 SetDlgItemText(hwnd, uID1, lpBuf); 379 Ret = 1; 380 } 381 } 382 383 HeapFree(GetProcessHeap(), 0, lpBuf); 384 } 385 386 return Ret; 387 } 388 389 static VOID MakeFloatValueString(DOUBLE* dFloatValue, LPTSTR szOutput, LPTSTR szAppend) 390 { 391 TCHAR szDecimalSeparator[4]; 392 393 /* Get the decimal separator for the current locale */ 394 if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSeparator, sizeof(szDecimalSeparator) / sizeof(TCHAR)) > 0) 395 { 396 UCHAR uDecimals; 397 UINT uIntegral; 398 399 /* Show the value with two decimals */ 400 uIntegral = (UINT)*dFloatValue; 401 uDecimals = (UCHAR)((UINT)(*dFloatValue * 100) - uIntegral * 100); 402 403 wsprintf(szOutput, _T("%u%s%02u %s"), uIntegral, szDecimalSeparator, uDecimals, szAppend); 404 } 405 } 406 407 static VOID SetProcSpeed(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID) 408 { 409 TCHAR szBuf[64], szHz[16]; 410 DWORD BufSize = sizeof(DWORD); 411 DWORD Type = REG_SZ; 412 PROCESSOR_POWER_INFORMATION ppi; 413 414 ZeroMemory(&ppi, sizeof(ppi)); 415 416 if ((CallNtPowerInformation(ProcessorInformation, 417 NULL, 418 0, 419 (PVOID)&ppi, 420 sizeof(ppi)) == STATUS_SUCCESS && 421 ppi.CurrentMhz != 0) || RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)&ppi.CurrentMhz, &BufSize) == ERROR_SUCCESS) 422 { 423 if (ppi.CurrentMhz < 1000) 424 { 425 if (!LoadString(hApplet, IDS_MEGAHERTZ, szHz, _countof(szHz))) 426 { 427 return; 428 } 429 StringCchPrintf(szBuf, _countof(szBuf), _T("%lu %s"), ppi.CurrentMhz, szHz); 430 } 431 else 432 { 433 double flt = ppi.CurrentMhz / 1000.0; 434 if (!LoadString(hApplet, IDS_GIGAHERTZ, szHz, _countof(szHz))) 435 { 436 return; 437 } 438 MakeFloatValueString(&flt, szBuf, szHz); 439 } 440 441 SetDlgItemText(hwnd, uID, szBuf); 442 } 443 } 444 445 static VOID GetSystemInformation(HWND hwnd) 446 { 447 HKEY hKey; 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 /* 464 * Get Processor information 465 * although undocumented, this information is being pulled 466 * directly out of the registry instead of via setupapi as it 467 * contains all the info we need, and should remain static 468 */ 469 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ProcKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 470 { 471 SetRegTextData(hwnd, hKey, _T("VendorIdentifier"), CurMachineLine); 472 CurMachineLine++; 473 474 CurMachineLine += SetProcNameString(hwnd, 475 hKey, 476 _T("ProcessorNameString"), 477 CurMachineLine, 478 CurMachineLine + 1); 479 480 SetProcSpeed(hwnd, hKey, _T("~MHz"), CurMachineLine); 481 CurMachineLine++; 482 } 483 484 /* Get total physical RAM */ 485 MemStat.dwLength = sizeof(MemStat); 486 487 if (GlobalMemoryStatusEx(&MemStat)) 488 { 489 TCHAR szStr[32]; 490 double dTotalPhys; 491 492 if (MemStat.ullTotalPhys > 1024 * 1024 * 1024) 493 { 494 UINT i = 0; 495 static const UINT uStrId[] = { IDS_GIGABYTE, IDS_TERABYTE, IDS_PETABYTE}; 496 497 // We're dealing with GBs or more 498 MemStat.ullTotalPhys /= 1024 * 1024; 499 500 if (MemStat.ullTotalPhys > 1024 * 1024) 501 { 502 // We're dealing with TBs or more 503 MemStat.ullTotalPhys /= 1024; 504 i++; 505 506 if (MemStat.ullTotalPhys > 1024 * 1024) 507 { 508 // We're dealing with PBs or more 509 MemStat.ullTotalPhys /= 1024; 510 i++; 511 512 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 513 } 514 else 515 { 516 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 517 } 518 } 519 else 520 { 521 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 522 } 523 524 LoadString(hApplet, uStrId[i], szStr, sizeof(szStr) / sizeof(TCHAR)); 525 MakeFloatValueString(&dTotalPhys, Buf, szStr); 526 } 527 else 528 { 529 // We're dealing with MBs, don't show any decimals 530 LoadString(hApplet, IDS_MEGABYTE, szStr, sizeof(szStr) / sizeof(TCHAR)); 531 wsprintf(Buf, _T("%u %s"), (UINT)MemStat.ullTotalPhys / 1024 / 1024, szStr); 532 } 533 534 SetDlgItemText(hwnd, CurMachineLine, Buf); 535 } 536 } 537 538 static VOID GetSystemVersion(HWND hwnd) 539 { 540 HWND hRosVersion; 541 SIZE_T lenStr, lenVersion; 542 PCWSTR pwszVersion = L" " TEXT(KERNEL_VERSION_RC); 543 PWSTR pwszStr; 544 545 lenVersion = wcslen(pwszVersion); 546 if (lenVersion == 0) 547 { 548 return; 549 } 550 551 hRosVersion = GetDlgItem(hwnd, IDC_ROSVERSION); 552 if (!hRosVersion) 553 { 554 return; 555 } 556 lenStr = GetWindowTextLengthW(hRosVersion); 557 lenStr += lenVersion + 1; 558 pwszStr = HeapAlloc(GetProcessHeap(), 0, lenStr * sizeof(WCHAR)); 559 if (!pwszStr) 560 { 561 return; 562 } 563 GetWindowText(hRosVersion, pwszStr, lenStr); 564 565 StringCchCatW(pwszStr, lenStr, pwszVersion); 566 SetWindowText(hRosVersion, pwszStr); 567 568 HeapFree(GetProcessHeap(), 0, pwszStr); 569 } 570 571 ULONGLONG GetSecondsQPC(VOID) 572 { 573 LARGE_INTEGER Counter, Frequency; 574 575 QueryPerformanceCounter(&Counter); 576 QueryPerformanceFrequency(&Frequency); 577 578 return Counter.QuadPart / Frequency.QuadPart; 579 } 580 581 ULONGLONG GetSeconds(VOID) 582 { 583 ULONGLONG (WINAPI * pGetTickCount64)(VOID); 584 ULONGLONG Ticks64; 585 HMODULE hModule = GetModuleHandleW(L"kernel32.dll"); 586 587 pGetTickCount64 = (PVOID)GetProcAddress(hModule, "GetTickCount64"); 588 if (pGetTickCount64) 589 { 590 return pGetTickCount64() / 1000; 591 } 592 593 hModule = LoadLibraryW(L"kernel32_vista.dll"); 594 595 if (!hModule) 596 { 597 return GetSecondsQPC(); 598 } 599 600 pGetTickCount64 = (PVOID)GetProcAddress(hModule, "GetTickCount64"); 601 602 if (pGetTickCount64) 603 { 604 Ticks64 = pGetTickCount64() / 1000; 605 } 606 else 607 { 608 Ticks64 = GetSecondsQPC(); 609 } 610 611 FreeLibrary(hModule); 612 return Ticks64; 613 } 614 615 VOID GetSystemUptime(HWND hwnd) 616 { 617 HWND hRosUptime; 618 WCHAR szBuf[64], szStr[64]; 619 ULONG cSeconds; 620 621 hRosUptime = GetDlgItem(hwnd, IDC_UPTIME); 622 if (!hRosUptime) 623 { 624 return; 625 } 626 if (!LoadStringW(hApplet, IDS_UPTIME_FORMAT, szStr, _countof(szStr))) 627 { 628 return; 629 } 630 cSeconds = GetSeconds(); 631 StringCchPrintfW(szBuf, _countof(szBuf), szStr, 632 cSeconds / (60*60*24), 633 (cSeconds / (60*60)) % 24, 634 (cSeconds / 60) % 60, 635 cSeconds % 60); 636 637 SetWindowTextW(hRosUptime, szBuf); 638 } 639 640 /* Property page dialog callback */ 641 INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 642 { 643 UNREFERENCED_PARAMETER(lParam); 644 UNREFERENCED_PARAMETER(wParam); 645 646 switch (uMsg) 647 { 648 case WM_INITDIALOG: 649 pImgInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMGINFO)); 650 if (pImgInfo == NULL) 651 { 652 EndDialog(hwndDlg, 0); 653 return FALSE; 654 } 655 656 InitLogo(hwndDlg); 657 SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ROSIMG), GWLP_WNDPROC, (LONG_PTR)RosImageProc); 658 GetSystemInformation(hwndDlg); 659 GetSystemVersion(hwndDlg); 660 GetSystemUptime(hwndDlg); 661 break; 662 663 case WM_DESTROY: 664 HeapFree(GetProcessHeap(), 0, pImgInfo); 665 break; 666 667 case WM_COMMAND: 668 if (LOWORD(wParam) == IDC_LICENCE) 669 { 670 DialogBox(hApplet, MAKEINTRESOURCE(IDD_LICENCE), hwndDlg, LicenceDlgProc); 671 672 return TRUE; 673 } 674 break; 675 676 case WM_DRAWITEM: 677 { 678 LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) lParam; 679 680 if (lpDrawItem->CtlID == IDC_ROSIMG) 681 { 682 HDC hdcMem; 683 LONG left; 684 685 /* Position image in centre of dialog */ 686 left = (lpDrawItem->rcItem.right - pImgInfo->cxSource) / 2; 687 688 hdcMem = CreateCompatibleDC(lpDrawItem->hDC); 689 if (hdcMem != NULL) 690 { 691 SelectObject(hdcMem, pImgInfo->hBitmap); 692 BitBlt(lpDrawItem->hDC, 693 left, 694 lpDrawItem->rcItem.top, 695 lpDrawItem->rcItem.right - lpDrawItem->rcItem.left, 696 lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top, 697 hdcMem, 698 0, 699 0, 700 SRCCOPY); 701 DeleteDC(hdcMem); 702 } 703 } 704 return TRUE; 705 } 706 707 case WM_NOTIFY: 708 { 709 NMHDR *nmhdr = (NMHDR *)lParam; 710 711 if (nmhdr->idFrom == IDC_ROSHOMEPAGE_LINK && nmhdr->code == NM_CLICK) 712 { 713 PNMLINK nml = (PNMLINK)nmhdr; 714 715 ShellExecuteW(hwndDlg, L"open", nml->item.szUrl, NULL, NULL, SW_SHOWNORMAL); 716 } 717 break; 718 } 719 720 } 721 722 return FALSE; 723 } 724