mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
1896383eb0
CORE-17971
797 lines
24 KiB
C
797 lines
24 KiB
C
/*
|
|
* PROJECT: ReactOS System Control Panel Applet
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll/cpl/sysdm/general.c
|
|
* PURPOSE: General System Information
|
|
* COPYRIGHT: Copyright Thomas Weidenmueller <w3seek@reactos.org>
|
|
* Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
|
|
* Copyright 2006-2007 Colin Finck <mail@colinfinck.de>
|
|
*
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <winnls.h>
|
|
#include <powrprof.h>
|
|
#include <buildno.h>
|
|
|
|
#define ANIM_STEP 2
|
|
#define ANIM_TIME 50
|
|
#define ID_SYSUPTIME_UPDATE_TIMER 1
|
|
|
|
typedef struct _IMGINFO
|
|
{
|
|
HBITMAP hBitmap;
|
|
INT cxSource;
|
|
INT cySource;
|
|
INT iPlanes;
|
|
INT iBits;
|
|
} IMGINFO, *PIMGINFO;
|
|
|
|
typedef ULONGLONG (WINAPI *PFGETTICKCOUNT64)(VOID);
|
|
|
|
static PIMGINFO pImgInfo;
|
|
static const BLENDFUNCTION BlendFunc = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
|
|
static HMODULE hKernel32Vista = NULL;
|
|
static PFGETTICKCOUNT64 pGetTickCount64 = NULL;
|
|
static WCHAR szUptimeFormat[64];
|
|
|
|
VOID ShowLastWin32Error(HWND hWndOwner)
|
|
{
|
|
LPTSTR lpMsg;
|
|
DWORD LastError;
|
|
|
|
LastError = GetLastError();
|
|
if (LastError == ERROR_SUCCESS)
|
|
return;
|
|
|
|
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
LastError,
|
|
LANG_USER_DEFAULT,
|
|
(LPTSTR)&lpMsg,
|
|
0, NULL))
|
|
{
|
|
return;
|
|
}
|
|
|
|
MessageBox(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
|
|
LocalFree(lpMsg);
|
|
}
|
|
|
|
|
|
static VOID InitLogo(HWND hwndDlg)
|
|
{
|
|
BITMAP logoBitmap;
|
|
BITMAP maskBitmap;
|
|
BITMAPINFO bmpi;
|
|
HDC hDC, hDCLogo, hDCMask;
|
|
HBITMAP hMask = NULL, hLogo = NULL;
|
|
HBITMAP hAlphaLogo = NULL;
|
|
COLORREF *pBits;
|
|
INT line, column;
|
|
|
|
hDC = GetDC(hwndDlg);
|
|
hDCLogo = CreateCompatibleDC(NULL);
|
|
hDCMask = CreateCompatibleDC(NULL);
|
|
|
|
if (hDC == NULL || hDCLogo == NULL || hDCMask == NULL)
|
|
goto Cleanup;
|
|
|
|
ZeroMemory(pImgInfo, sizeof(*pImgInfo));
|
|
ZeroMemory(&bmpi, sizeof(bmpi));
|
|
|
|
hLogo = (HBITMAP)LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_ROSBMP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
|
hMask = (HBITMAP)LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_ROSMASK), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
|
|
|
if (hLogo == NULL || hMask == NULL)
|
|
goto Cleanup;
|
|
|
|
GetObject(hLogo, sizeof(logoBitmap), &logoBitmap);
|
|
GetObject(hMask, sizeof(maskBitmap), &maskBitmap);
|
|
|
|
if (logoBitmap.bmHeight != maskBitmap.bmHeight || logoBitmap.bmWidth != maskBitmap.bmWidth)
|
|
goto Cleanup;
|
|
|
|
bmpi.bmiHeader.biSize = sizeof(BITMAPINFO);
|
|
bmpi.bmiHeader.biWidth = logoBitmap.bmWidth;
|
|
bmpi.bmiHeader.biHeight = logoBitmap.bmHeight;
|
|
bmpi.bmiHeader.biPlanes = 1;
|
|
bmpi.bmiHeader.biBitCount = 32;
|
|
bmpi.bmiHeader.biCompression = BI_RGB;
|
|
bmpi.bmiHeader.biSizeImage = 4 * logoBitmap.bmWidth * logoBitmap.bmHeight;
|
|
|
|
/* Create a premultiplied bitmap */
|
|
hAlphaLogo = CreateDIBSection(hDC, &bmpi, DIB_RGB_COLORS, (PVOID*)&pBits, 0, 0);
|
|
if (!hAlphaLogo)
|
|
goto Cleanup;
|
|
|
|
SelectObject(hDCLogo, hLogo);
|
|
SelectObject(hDCMask, hMask);
|
|
|
|
for (line = logoBitmap.bmHeight - 1; line >= 0; line--)
|
|
{
|
|
for (column = 0; column < logoBitmap.bmWidth; column++)
|
|
{
|
|
COLORREF alpha = GetPixel(hDCMask, column, line) & 0xFF;
|
|
COLORREF Color = GetPixel(hDCLogo, column, line);
|
|
DWORD r, g, b;
|
|
|
|
r = GetRValue(Color) * alpha / 255;
|
|
g = GetGValue(Color) * alpha / 255;
|
|
b = GetBValue(Color) * alpha / 255;
|
|
|
|
*pBits++ = b | (g << 8) | (r << 16) | (alpha << 24);
|
|
}
|
|
}
|
|
|
|
pImgInfo->hBitmap = hAlphaLogo;
|
|
pImgInfo->cxSource = logoBitmap.bmWidth;
|
|
pImgInfo->cySource = logoBitmap.bmHeight;
|
|
pImgInfo->iBits = logoBitmap.bmBitsPixel;
|
|
pImgInfo->iPlanes = logoBitmap.bmPlanes;
|
|
|
|
Cleanup:
|
|
if (hMask != NULL) DeleteObject(hMask);
|
|
if (hLogo != NULL) DeleteObject(hLogo);
|
|
if (hDCMask != NULL) DeleteDC(hDCMask);
|
|
if (hDCLogo != NULL) DeleteDC(hDCLogo);
|
|
if (hDC != NULL) ReleaseDC(hwndDlg, hDC);
|
|
}
|
|
|
|
LRESULT CALLBACK RosImageProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static UINT timerid = 0, top = 0, offset;
|
|
static HBITMAP hCreditsBitmap;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_LBUTTONDBLCLK:
|
|
if (wParam & (MK_CONTROL | MK_SHIFT))
|
|
{
|
|
if (timerid == 0)
|
|
{
|
|
HDC hDC;
|
|
HDC hCreditsDC = NULL, hLogoDC = NULL;
|
|
HFONT hFont = NULL;
|
|
NONCLIENTMETRICS ncm;
|
|
RECT rcCredits;
|
|
TCHAR szCredits[2048];
|
|
INT iDevsHeight;
|
|
|
|
hDC = GetDC(NULL);
|
|
if (hDC == NULL)
|
|
goto Cleanup;
|
|
|
|
top = 0;
|
|
offset = 0;
|
|
|
|
hCreditsDC = CreateCompatibleDC(hDC);
|
|
hLogoDC = CreateCompatibleDC(hCreditsDC);
|
|
|
|
if (hCreditsDC == NULL || hLogoDC == NULL)
|
|
goto Cleanup;
|
|
|
|
SetRect(&rcCredits, 0, 0, 0, 0);
|
|
|
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
|
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
|
|
|
|
hFont = CreateFontIndirect(&ncm.lfMessageFont);
|
|
if (!hFont)
|
|
goto Cleanup;
|
|
SelectObject(hCreditsDC, hFont);
|
|
|
|
LoadString(hApplet, IDS_DEVS, szCredits, sizeof(szCredits) / sizeof(TCHAR));
|
|
DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CALCRECT);
|
|
|
|
iDevsHeight = rcCredits.bottom - rcCredits.top;
|
|
|
|
hCreditsBitmap = CreateBitmap(pImgInfo->cxSource, (2 * pImgInfo->cySource) + iDevsHeight + 1, pImgInfo->iPlanes, pImgInfo->iBits, NULL);
|
|
if (!hCreditsBitmap)
|
|
goto Cleanup;
|
|
|
|
SelectObject(hLogoDC, pImgInfo->hBitmap);
|
|
SelectObject(hCreditsDC, hCreditsBitmap);
|
|
|
|
offset += pImgInfo->cySource;
|
|
|
|
SetRect(&rcCredits, 0, 0, pImgInfo->cxSource, (2 * pImgInfo->cySource) + iDevsHeight + 1);
|
|
FillRect(hCreditsDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE));
|
|
|
|
SetRect(&rcCredits, 0, offset, pImgInfo->cxSource, offset + iDevsHeight + 1);
|
|
SetBkMode(hCreditsDC, TRANSPARENT);
|
|
|
|
OffsetRect(&rcCredits, 1, 1);
|
|
SetTextColor(hCreditsDC, GetSysColor(COLOR_BTNSHADOW));
|
|
DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CENTER);
|
|
|
|
OffsetRect(&rcCredits, -1, -1);
|
|
SetTextColor(hCreditsDC, GetSysColor(COLOR_WINDOWTEXT));
|
|
DrawText(hCreditsDC, szCredits, -1, &rcCredits, DT_CENTER);
|
|
|
|
offset += iDevsHeight;
|
|
|
|
AlphaBlend(hCreditsDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, hLogoDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc);
|
|
AlphaBlend(hCreditsDC, 0, offset, pImgInfo->cxSource, pImgInfo->cySource, hLogoDC, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc);
|
|
|
|
timerid = SetTimer(hwnd, 1, ANIM_TIME, NULL);
|
|
|
|
Cleanup:
|
|
if (hFont != NULL) DeleteObject(hFont);
|
|
if (hLogoDC != NULL) DeleteDC(hLogoDC);
|
|
if (hCreditsDC != NULL) DeleteDC(hCreditsDC);
|
|
if (hDC != NULL) ReleaseDC(NULL, hDC);
|
|
}
|
|
}
|
|
break;
|
|
case WM_LBUTTONDOWN:
|
|
if (timerid)
|
|
{
|
|
RECT rcCredits;
|
|
HDC hDC = GetDC(hwnd);
|
|
if (hDC != NULL)
|
|
{
|
|
GetClientRect(hwnd, &rcCredits);
|
|
SetRect(&rcCredits, 0, 0, rcCredits.right, pImgInfo->cySource);
|
|
FillRect(hDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE));
|
|
ReleaseDC(hwnd, hDC);
|
|
}
|
|
KillTimer(hwnd, timerid);
|
|
if (hCreditsBitmap != NULL)
|
|
DeleteObject(hCreditsBitmap);
|
|
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
top = 0;
|
|
timerid = 0;
|
|
}
|
|
break;
|
|
case WM_TIMER:
|
|
top += ANIM_STEP;
|
|
|
|
if (top > offset)
|
|
{
|
|
RECT rcCredits;
|
|
HDC hDC = GetDC(hwnd);
|
|
if (hDC != NULL)
|
|
{
|
|
GetClientRect(hwnd, &rcCredits);
|
|
SetRect(&rcCredits, 0, 0, rcCredits.right, pImgInfo->cySource);
|
|
FillRect(hDC, &rcCredits, GetSysColorBrush(COLOR_3DFACE));
|
|
ReleaseDC(hwnd, hDC);
|
|
}
|
|
KillTimer(hwnd, timerid);
|
|
if (hCreditsBitmap != NULL)
|
|
DeleteObject(hCreditsBitmap);
|
|
|
|
top = 0;
|
|
timerid = 0;
|
|
}
|
|
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
break;
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT PS;
|
|
HDC hdcMem, hdc;
|
|
LONG left;
|
|
|
|
hdc = wParam != 0 ? (HDC)wParam : BeginPaint(hwnd, &PS);
|
|
|
|
GetClientRect(hwnd, &PS.rcPaint);
|
|
|
|
/* Position image in center of dialog */
|
|
left = (PS.rcPaint.right - pImgInfo->cxSource) / 2;
|
|
hdcMem = CreateCompatibleDC(hdc);
|
|
|
|
if (hdcMem != NULL)
|
|
{
|
|
if(timerid != 0)
|
|
{
|
|
SelectObject(hdcMem, hCreditsBitmap);
|
|
BitBlt(hdc, left, PS.rcPaint.top, PS.rcPaint.right - PS.rcPaint.left, PS.rcPaint.top + pImgInfo->cySource, hdcMem, 0, top, SRCCOPY);
|
|
}
|
|
else
|
|
{
|
|
SelectObject(hdcMem, pImgInfo->hBitmap);
|
|
AlphaBlend(hdc, left, PS.rcPaint.top, pImgInfo->cxSource, pImgInfo->cySource, hdcMem, 0, 0, pImgInfo->cxSource, pImgInfo->cySource, BlendFunc);
|
|
}
|
|
|
|
DeleteDC(hdcMem);
|
|
}
|
|
|
|
if (wParam == 0)
|
|
EndPaint(hwnd,&PS);
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static VOID SetRegTextData(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID)
|
|
{
|
|
LPTSTR lpBuf = NULL;
|
|
DWORD BufSize = 0;
|
|
DWORD Type;
|
|
|
|
if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS)
|
|
{
|
|
lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize);
|
|
|
|
if (!lpBuf)
|
|
return;
|
|
|
|
if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS)
|
|
SetDlgItemText(hwnd, uID, lpBuf);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpBuf);
|
|
}
|
|
}
|
|
|
|
static INT SetProcNameString(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID1, UINT uID2)
|
|
{
|
|
LPTSTR lpBuf = NULL;
|
|
DWORD BufSize = 0;
|
|
DWORD Type;
|
|
INT Ret = 0;
|
|
TCHAR szBuf[31];
|
|
TCHAR* szLastSpace;
|
|
INT LastSpace = 0;
|
|
|
|
if (RegQueryValueEx(hKey, Value, NULL, &Type, NULL, &BufSize) == ERROR_SUCCESS)
|
|
{
|
|
lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize);
|
|
|
|
if (!lpBuf)
|
|
return 0;
|
|
|
|
if (RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)lpBuf, &BufSize) == ERROR_SUCCESS)
|
|
{
|
|
if (BufSize > ((30 + 1) * sizeof(TCHAR)))
|
|
{
|
|
/* Wrap the Processor Name String like XP does: *
|
|
* - Take the first 30 characters and look for the last space. *
|
|
* Then wrap the string after this space. *
|
|
* - If no space is found, wrap the string after character 30. *
|
|
* *
|
|
* For example the Processor Name String of a Pentium 4 is right-aligned. *
|
|
* With this wrapping the first line looks centered. */
|
|
|
|
_tcsncpy(szBuf, lpBuf, 30);
|
|
szBuf[30] = 0;
|
|
szLastSpace = _tcsrchr(szBuf, ' ');
|
|
|
|
if (szLastSpace == 0)
|
|
{
|
|
LastSpace = 30;
|
|
}
|
|
else
|
|
{
|
|
LastSpace = (szLastSpace - szBuf);
|
|
szBuf[LastSpace] = 0;
|
|
}
|
|
|
|
_tcsncpy(szBuf, lpBuf, LastSpace);
|
|
|
|
SetDlgItemText(hwnd, uID1, szBuf);
|
|
SetDlgItemText(hwnd, uID2, lpBuf+LastSpace+1);
|
|
|
|
/* Return the number of used lines */
|
|
Ret = 2;
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(hwnd, uID1, lpBuf);
|
|
Ret = 1;
|
|
}
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpBuf);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
static VOID MakeFloatValueString(DOUBLE* dFloatValue, LPTSTR szOutput, LPTSTR szAppend)
|
|
{
|
|
TCHAR szDecimalSeparator[4];
|
|
|
|
/* Get the decimal separator for the current locale */
|
|
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSeparator, sizeof(szDecimalSeparator) / sizeof(TCHAR)) > 0)
|
|
{
|
|
UCHAR uDecimals;
|
|
UINT uIntegral;
|
|
|
|
/* Show the value with two decimals */
|
|
uIntegral = (UINT)*dFloatValue;
|
|
uDecimals = (UCHAR)((UINT)(*dFloatValue * 100) - uIntegral * 100);
|
|
|
|
wsprintf(szOutput, _T("%u%s%02u %s"), uIntegral, szDecimalSeparator, uDecimals, szAppend);
|
|
}
|
|
}
|
|
|
|
static BOOL SetProcSpeed(HWND hwnd, HKEY hKey, LPTSTR Value, UINT uID)
|
|
{
|
|
TCHAR szBuf[64], szHz[16];
|
|
DWORD BufSize = sizeof(DWORD);
|
|
DWORD Type = REG_SZ;
|
|
PROCESSOR_POWER_INFORMATION ppi;
|
|
|
|
ZeroMemory(&ppi, sizeof(ppi));
|
|
|
|
if ((CallNtPowerInformation(ProcessorInformation,
|
|
NULL,
|
|
0,
|
|
(PVOID)&ppi,
|
|
sizeof(ppi)) == STATUS_SUCCESS &&
|
|
ppi.CurrentMhz != 0) || RegQueryValueEx(hKey, Value, NULL, &Type, (PBYTE)&ppi.CurrentMhz, &BufSize) == ERROR_SUCCESS)
|
|
{
|
|
if (ppi.CurrentMhz < 1000)
|
|
{
|
|
if (!LoadString(hApplet, IDS_MEGAHERTZ, szHz, _countof(szHz)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
StringCchPrintf(szBuf, _countof(szBuf), _T("%lu %s"), ppi.CurrentMhz, szHz);
|
|
}
|
|
else
|
|
{
|
|
double flt = ppi.CurrentMhz / 1000.0;
|
|
if (!LoadString(hApplet, IDS_GIGAHERTZ, szHz, _countof(szHz)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
MakeFloatValueString(&flt, szBuf, szHz);
|
|
}
|
|
|
|
SetDlgItemText(hwnd, uID, szBuf);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static VOID GetSystemInformation(HWND hwnd)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR SysKey[] = _T("HARDWARE\\DESCRIPTION\\System");
|
|
TCHAR ProcKey[] = _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
|
|
MEMORYSTATUSEX MemStat;
|
|
TCHAR Buf[32];
|
|
WCHAR SMBiosName[96];
|
|
INT CurMachineLine = IDC_MACHINELINE1;
|
|
|
|
/*
|
|
* Get hardware device name or motherboard name
|
|
* using information from raw SMBIOS data
|
|
*/
|
|
if (GetSystemName(SMBiosName, _countof(SMBiosName)))
|
|
{
|
|
SetDlgItemText(hwnd, CurMachineLine, SMBiosName);
|
|
CurMachineLine++;
|
|
}
|
|
else
|
|
{
|
|
/* If SMBIOS is not available, use System Identifier */
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SysKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
SetRegTextData(hwnd, hKey, _T("Identifier"), CurMachineLine);
|
|
CurMachineLine++;
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
/*
|
|
* Get Processor information
|
|
* although undocumented, this information is being pulled
|
|
* directly out of the registry instead of via setupapi as it
|
|
* contains all the info we need, and should remain static
|
|
*/
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ProcKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
INT PrevMachineLine;
|
|
|
|
SetRegTextData(hwnd, hKey, _T("VendorIdentifier"), CurMachineLine);
|
|
CurMachineLine++;
|
|
|
|
PrevMachineLine = CurMachineLine;
|
|
CurMachineLine += SetProcNameString(hwnd,
|
|
hKey,
|
|
_T("ProcessorNameString"),
|
|
CurMachineLine,
|
|
CurMachineLine + 1);
|
|
|
|
if (CurMachineLine == PrevMachineLine)
|
|
{
|
|
/* TODO: Try obtaining CPU name from WMI (i.e. CIM_Processor) */
|
|
|
|
/* Brand String is not available, use Identifier instead */
|
|
CurMachineLine += SetProcNameString(hwnd,
|
|
hKey,
|
|
_T("Identifier"),
|
|
CurMachineLine,
|
|
CurMachineLine + 1);
|
|
}
|
|
|
|
if (SetProcSpeed(hwnd, hKey, _T("~MHz"), CurMachineLine))
|
|
CurMachineLine++;
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
/* Get total physical RAM */
|
|
MemStat.dwLength = sizeof(MemStat);
|
|
|
|
if (GlobalMemoryStatusEx(&MemStat))
|
|
{
|
|
TCHAR szStr[32];
|
|
double dTotalPhys;
|
|
|
|
if (MemStat.ullTotalPhys > 1024 * 1024 * 1024)
|
|
{
|
|
UINT i = 0;
|
|
static const UINT uStrId[] = { IDS_GIGABYTE, IDS_TERABYTE, IDS_PETABYTE};
|
|
|
|
// We're dealing with GBs or more
|
|
MemStat.ullTotalPhys /= 1024 * 1024;
|
|
|
|
if (MemStat.ullTotalPhys > 1024 * 1024)
|
|
{
|
|
// We're dealing with TBs or more
|
|
MemStat.ullTotalPhys /= 1024;
|
|
i++;
|
|
|
|
if (MemStat.ullTotalPhys > 1024 * 1024)
|
|
{
|
|
// We're dealing with PBs or more
|
|
MemStat.ullTotalPhys /= 1024;
|
|
i++;
|
|
|
|
dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
|
|
}
|
|
else
|
|
{
|
|
dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dTotalPhys = (double)MemStat.ullTotalPhys / 1024;
|
|
}
|
|
|
|
LoadString(hApplet, uStrId[i], szStr, sizeof(szStr) / sizeof(TCHAR));
|
|
MakeFloatValueString(&dTotalPhys, Buf, szStr);
|
|
}
|
|
else
|
|
{
|
|
// We're dealing with MBs, don't show any decimals
|
|
LoadString(hApplet, IDS_MEGABYTE, szStr, sizeof(szStr) / sizeof(TCHAR));
|
|
wsprintf(Buf, _T("%u %s"), (UINT)MemStat.ullTotalPhys / 1024 / 1024, szStr);
|
|
}
|
|
|
|
SetDlgItemText(hwnd, CurMachineLine, Buf);
|
|
}
|
|
}
|
|
|
|
static VOID GetSystemVersion(HWND hwnd)
|
|
{
|
|
HWND hRosVersion;
|
|
SIZE_T lenStr, lenVersion;
|
|
PCWSTR pwszVersion = L" " TEXT(KERNEL_VERSION_RC);
|
|
PWSTR pwszStr;
|
|
|
|
lenVersion = wcslen(pwszVersion);
|
|
if (lenVersion == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
hRosVersion = GetDlgItem(hwnd, IDC_ROSVERSION);
|
|
if (!hRosVersion)
|
|
{
|
|
return;
|
|
}
|
|
lenStr = GetWindowTextLengthW(hRosVersion);
|
|
lenStr += lenVersion + 1;
|
|
pwszStr = HeapAlloc(GetProcessHeap(), 0, lenStr * sizeof(WCHAR));
|
|
if (!pwszStr)
|
|
{
|
|
return;
|
|
}
|
|
GetWindowText(hRosVersion, pwszStr, lenStr);
|
|
|
|
StringCchCatW(pwszStr, lenStr, pwszVersion);
|
|
SetWindowText(hRosVersion, pwszStr);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pwszStr);
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
* An equivalent of GetTickCount64, implemented using QueryPerformanceCounter.
|
|
*
|
|
* @return
|
|
* The number of milliseconds that have elapsed since the system was started.
|
|
*/
|
|
static ULONGLONG GetTickCountQPC(VOID)
|
|
{
|
|
LARGE_INTEGER Counter, Frequency;
|
|
|
|
QueryPerformanceCounter(&Counter);
|
|
QueryPerformanceFrequency(&Frequency);
|
|
|
|
return (Counter.QuadPart * 1000) / Frequency.QuadPart;
|
|
}
|
|
|
|
static VOID GetSystemUptime(HWND hwndDlg)
|
|
{
|
|
HWND hUptimeLabel;
|
|
ULONGLONG cMilliseconds;
|
|
ULONG cSeconds;
|
|
WCHAR szBuf[64];
|
|
|
|
hUptimeLabel = GetDlgItem(hwndDlg, IDC_UPTIME);
|
|
if (!hUptimeLabel)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (pGetTickCount64)
|
|
{
|
|
cMilliseconds = pGetTickCount64();
|
|
}
|
|
else
|
|
{
|
|
cMilliseconds = GetTickCountQPC();
|
|
}
|
|
|
|
cSeconds = cMilliseconds / 1000;
|
|
StringCchPrintfW(szBuf, _countof(szBuf), szUptimeFormat,
|
|
cSeconds / (60*60*24), // Days
|
|
(cSeconds / (60*60)) % 24, // Hours
|
|
(cSeconds / 60) % 60, // Minutes
|
|
cSeconds % 60); // Seconds
|
|
|
|
SetWindowTextW(hUptimeLabel, szBuf);
|
|
|
|
/* Set update timer (reset timeout if the timer exists) */
|
|
SetTimer(hwndDlg, ID_SYSUPTIME_UPDATE_TIMER, 1000 - (cMilliseconds % 1000), NULL);
|
|
}
|
|
|
|
static VOID InitSystemUptime(HWND hwndDlg)
|
|
{
|
|
HMODULE hKernel32;
|
|
|
|
/* Load time format string */
|
|
if (LoadStringW(hApplet, IDS_UPTIME_FORMAT, szUptimeFormat, _countof(szUptimeFormat)) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Load required DLLs */
|
|
hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
|
if (hKernel32)
|
|
{
|
|
pGetTickCount64 = (PFGETTICKCOUNT64)GetProcAddress(hKernel32, "GetTickCount64");
|
|
if (!pGetTickCount64)
|
|
{
|
|
hKernel32Vista = LoadLibraryW(L"kernel32_vista.dll");
|
|
if (hKernel32Vista)
|
|
{
|
|
pGetTickCount64 = (PFGETTICKCOUNT64)GetProcAddress(hKernel32Vista, "GetTickCount64");
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Show system uptime and set update timer */
|
|
GetSystemUptime(hwndDlg);
|
|
}
|
|
|
|
/* Property page dialog callback */
|
|
INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
pImgInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMGINFO));
|
|
if (pImgInfo == NULL)
|
|
{
|
|
EndDialog(hwndDlg, 0);
|
|
return FALSE;
|
|
}
|
|
|
|
InitLogo(hwndDlg);
|
|
SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ROSIMG), GWLP_WNDPROC, (LONG_PTR)RosImageProc);
|
|
GetSystemInformation(hwndDlg);
|
|
GetSystemVersion(hwndDlg);
|
|
InitSystemUptime(hwndDlg);
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
KillTimer(hwndDlg, ID_SYSUPTIME_UPDATE_TIMER);
|
|
|
|
if (hKernel32Vista)
|
|
{
|
|
FreeLibrary(hKernel32Vista);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, pImgInfo);
|
|
break;
|
|
}
|
|
|
|
case WM_TIMER:
|
|
{
|
|
if (wParam == ID_SYSUPTIME_UPDATE_TIMER)
|
|
{
|
|
/* Update system uptime */
|
|
GetSystemUptime(hwndDlg);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
if (LOWORD(wParam) == IDC_LICENCE)
|
|
{
|
|
DialogBox(hApplet, MAKEINTRESOURCE(IDD_LICENCE), hwndDlg, LicenceDlgProc);
|
|
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_DRAWITEM:
|
|
{
|
|
LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
|
|
|
|
if (lpDrawItem->CtlID == IDC_ROSIMG)
|
|
{
|
|
HDC hdcMem;
|
|
LONG left;
|
|
|
|
/* Position image in centre of dialog */
|
|
left = (lpDrawItem->rcItem.right - pImgInfo->cxSource) / 2;
|
|
|
|
hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
|
|
if (hdcMem != NULL)
|
|
{
|
|
SelectObject(hdcMem, pImgInfo->hBitmap);
|
|
BitBlt(lpDrawItem->hDC,
|
|
left,
|
|
lpDrawItem->rcItem.top,
|
|
lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
|
|
lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
|
|
hdcMem,
|
|
0,
|
|
0,
|
|
SRCCOPY);
|
|
DeleteDC(hdcMem);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
NMHDR *nmhdr = (NMHDR *)lParam;
|
|
|
|
if (nmhdr->idFrom == IDC_ROSHOMEPAGE_LINK && nmhdr->code == NM_CLICK)
|
|
{
|
|
PNMLINK nml = (PNMLINK)nmhdr;
|
|
|
|
ShellExecuteW(hwndDlg, L"open", nml->item.szUrl, NULL, NULL, SW_SHOWNORMAL);
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|