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 SysKey[] = _T("HARDWARE\\DESCRIPTION\\System"); 449 TCHAR ProcKey[] = _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"); 450 MEMORYSTATUSEX MemStat; 451 TCHAR Buf[32]; 452 WCHAR SMBiosName[96]; 453 INT CurMachineLine = IDC_MACHINELINE1; 454 455 /* 456 * Get hardware device name or motherboard name 457 * using information from raw SMBIOS data 458 */ 459 if (GetSystemName(SMBiosName, _countof(SMBiosName))) 460 { 461 SetDlgItemText(hwnd, CurMachineLine, SMBiosName); 462 CurMachineLine++; 463 } 464 else 465 { 466 /* If SMBIOS is not available, use System Identifier */ 467 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SysKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 468 { 469 SetRegTextData(hwnd, hKey, _T("Identifier"), CurMachineLine); 470 CurMachineLine++; 471 RegCloseKey(hKey); 472 } 473 } 474 /* 475 * Get Processor information 476 * although undocumented, this information is being pulled 477 * directly out of the registry instead of via setupapi as it 478 * contains all the info we need, and should remain static 479 */ 480 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ProcKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 481 { 482 SetRegTextData(hwnd, hKey, _T("VendorIdentifier"), CurMachineLine); 483 CurMachineLine++; 484 485 CurMachineLine += SetProcNameString(hwnd, 486 hKey, 487 _T("ProcessorNameString"), 488 CurMachineLine, 489 CurMachineLine + 1); 490 491 SetProcSpeed(hwnd, hKey, _T("~MHz"), CurMachineLine); 492 CurMachineLine++; 493 RegCloseKey(hKey); 494 } 495 496 /* Get total physical RAM */ 497 MemStat.dwLength = sizeof(MemStat); 498 499 if (GlobalMemoryStatusEx(&MemStat)) 500 { 501 TCHAR szStr[32]; 502 double dTotalPhys; 503 504 if (MemStat.ullTotalPhys > 1024 * 1024 * 1024) 505 { 506 UINT i = 0; 507 static const UINT uStrId[] = { IDS_GIGABYTE, IDS_TERABYTE, IDS_PETABYTE}; 508 509 // We're dealing with GBs or more 510 MemStat.ullTotalPhys /= 1024 * 1024; 511 512 if (MemStat.ullTotalPhys > 1024 * 1024) 513 { 514 // We're dealing with TBs or more 515 MemStat.ullTotalPhys /= 1024; 516 i++; 517 518 if (MemStat.ullTotalPhys > 1024 * 1024) 519 { 520 // We're dealing with PBs or more 521 MemStat.ullTotalPhys /= 1024; 522 i++; 523 524 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 525 } 526 else 527 { 528 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 529 } 530 } 531 else 532 { 533 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 534 } 535 536 LoadString(hApplet, uStrId[i], szStr, sizeof(szStr) / sizeof(TCHAR)); 537 MakeFloatValueString(&dTotalPhys, Buf, szStr); 538 } 539 else 540 { 541 // We're dealing with MBs, don't show any decimals 542 LoadString(hApplet, IDS_MEGABYTE, szStr, sizeof(szStr) / sizeof(TCHAR)); 543 wsprintf(Buf, _T("%u %s"), (UINT)MemStat.ullTotalPhys / 1024 / 1024, szStr); 544 } 545 546 SetDlgItemText(hwnd, CurMachineLine, Buf); 547 } 548 } 549 550 static VOID GetSystemVersion(HWND hwnd) 551 { 552 HWND hRosVersion; 553 SIZE_T lenStr, lenVersion; 554 PCWSTR pwszVersion = L" " TEXT(KERNEL_VERSION_RC); 555 PWSTR pwszStr; 556 557 lenVersion = wcslen(pwszVersion); 558 if (lenVersion == 0) 559 { 560 return; 561 } 562 563 hRosVersion = GetDlgItem(hwnd, IDC_ROSVERSION); 564 if (!hRosVersion) 565 { 566 return; 567 } 568 lenStr = GetWindowTextLengthW(hRosVersion); 569 lenStr += lenVersion + 1; 570 pwszStr = HeapAlloc(GetProcessHeap(), 0, lenStr * sizeof(WCHAR)); 571 if (!pwszStr) 572 { 573 return; 574 } 575 GetWindowText(hRosVersion, pwszStr, lenStr); 576 577 StringCchCatW(pwszStr, lenStr, pwszVersion); 578 SetWindowText(hRosVersion, pwszStr); 579 580 HeapFree(GetProcessHeap(), 0, pwszStr); 581 } 582 583 ULONGLONG GetSecondsQPC(VOID) 584 { 585 LARGE_INTEGER Counter, Frequency; 586 587 QueryPerformanceCounter(&Counter); 588 QueryPerformanceFrequency(&Frequency); 589 590 return Counter.QuadPart / Frequency.QuadPart; 591 } 592 593 ULONGLONG GetSeconds(VOID) 594 { 595 ULONGLONG (WINAPI * pGetTickCount64)(VOID); 596 ULONGLONG Ticks64; 597 HMODULE hModule = GetModuleHandleW(L"kernel32.dll"); 598 599 pGetTickCount64 = (PVOID)GetProcAddress(hModule, "GetTickCount64"); 600 if (pGetTickCount64) 601 { 602 return pGetTickCount64() / 1000; 603 } 604 605 hModule = LoadLibraryW(L"kernel32_vista.dll"); 606 607 if (!hModule) 608 { 609 return GetSecondsQPC(); 610 } 611 612 pGetTickCount64 = (PVOID)GetProcAddress(hModule, "GetTickCount64"); 613 614 if (pGetTickCount64) 615 { 616 Ticks64 = pGetTickCount64() / 1000; 617 } 618 else 619 { 620 Ticks64 = GetSecondsQPC(); 621 } 622 623 FreeLibrary(hModule); 624 return Ticks64; 625 } 626 627 VOID GetSystemUptime(HWND hwnd) 628 { 629 HWND hRosUptime; 630 WCHAR szBuf[64], szStr[64]; 631 ULONG cSeconds; 632 633 hRosUptime = GetDlgItem(hwnd, IDC_UPTIME); 634 if (!hRosUptime) 635 { 636 return; 637 } 638 if (!LoadStringW(hApplet, IDS_UPTIME_FORMAT, szStr, _countof(szStr))) 639 { 640 return; 641 } 642 cSeconds = GetSeconds(); 643 StringCchPrintfW(szBuf, _countof(szBuf), szStr, 644 cSeconds / (60*60*24), 645 (cSeconds / (60*60)) % 24, 646 (cSeconds / 60) % 60, 647 cSeconds % 60); 648 649 SetWindowTextW(hRosUptime, szBuf); 650 } 651 652 /* Property page dialog callback */ 653 INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 654 { 655 UNREFERENCED_PARAMETER(lParam); 656 UNREFERENCED_PARAMETER(wParam); 657 658 switch (uMsg) 659 { 660 case WM_INITDIALOG: 661 pImgInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMGINFO)); 662 if (pImgInfo == NULL) 663 { 664 EndDialog(hwndDlg, 0); 665 return FALSE; 666 } 667 668 InitLogo(hwndDlg); 669 SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ROSIMG), GWLP_WNDPROC, (LONG_PTR)RosImageProc); 670 GetSystemInformation(hwndDlg); 671 GetSystemVersion(hwndDlg); 672 GetSystemUptime(hwndDlg); 673 break; 674 675 case WM_DESTROY: 676 HeapFree(GetProcessHeap(), 0, pImgInfo); 677 break; 678 679 case WM_COMMAND: 680 if (LOWORD(wParam) == IDC_LICENCE) 681 { 682 DialogBox(hApplet, MAKEINTRESOURCE(IDD_LICENCE), hwndDlg, LicenceDlgProc); 683 684 return TRUE; 685 } 686 break; 687 688 case WM_DRAWITEM: 689 { 690 LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) lParam; 691 692 if (lpDrawItem->CtlID == IDC_ROSIMG) 693 { 694 HDC hdcMem; 695 LONG left; 696 697 /* Position image in centre of dialog */ 698 left = (lpDrawItem->rcItem.right - pImgInfo->cxSource) / 2; 699 700 hdcMem = CreateCompatibleDC(lpDrawItem->hDC); 701 if (hdcMem != NULL) 702 { 703 SelectObject(hdcMem, pImgInfo->hBitmap); 704 BitBlt(lpDrawItem->hDC, 705 left, 706 lpDrawItem->rcItem.top, 707 lpDrawItem->rcItem.right - lpDrawItem->rcItem.left, 708 lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top, 709 hdcMem, 710 0, 711 0, 712 SRCCOPY); 713 DeleteDC(hdcMem); 714 } 715 } 716 return TRUE; 717 } 718 719 case WM_NOTIFY: 720 { 721 NMHDR *nmhdr = (NMHDR *)lParam; 722 723 if (nmhdr->idFrom == IDC_ROSHOMEPAGE_LINK && nmhdr->code == NM_CLICK) 724 { 725 PNMLINK nml = (PNMLINK)nmhdr; 726 727 ShellExecuteW(hwndDlg, L"open", nml->item.szUrl, NULL, NULL, SW_SHOWNORMAL); 728 } 729 break; 730 } 731 732 } 733 734 return FALSE; 735 } 736