📄 timedate.c
字号:
/*
* PROJECT: ReactOS Timedate Control Panel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: lib/cpl/timedate/timedate.c
* PURPOSE: ReactOS Timedate Control Panel
* COPYRIGHT: Copyright 2004-2005 Eric Kohl
* Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
* Copyright 2006 Christoph v. Wittich <Christoph@ActiveVB.de>
*
*/
#include <timedate.h>
typedef struct _TZ_INFO
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} TZ_INFO, *PTZ_INFO;
typedef struct _TIMEZONE_ENTRY
{
struct _TIMEZONE_ENTRY *Prev;
struct _TIMEZONE_ENTRY *Next;
WCHAR Description[64]; /* 'Display' */
WCHAR StandardName[33]; /* 'Std' */
WCHAR DaylightName[33]; /* 'Dlt' */
TZ_INFO TimezoneInfo; /* 'TZI' */
ULONG Index; /* 'Index ' */
} TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
typedef struct _SERVERS
{
CHAR *Address;
WCHAR *Name;
} SERVERS;
#define NUM_APPLETS (1)
LONG APIENTRY
Applet(HWND hwnd, UINT uMsg, LONG wParam, LONG lParam);
HINSTANCE hApplet = 0;
BOOL bSynced = FALSE;
PTIMEZONE_ENTRY TimeZoneListHead = NULL;
PTIMEZONE_ENTRY TimeZoneListTail = NULL;
/* Applets */
APPLET Applets[NUM_APPLETS] =
{
{IDC_CPLICON, IDS_CPLNAME, IDS_CPLDESCRIPTION, Applet}
};
static BOOL
SystemSetLocalTime(LPSYSTEMTIME lpSystemTime)
{
HANDLE hToken;
DWORD PrevSize;
TOKEN_PRIVILEGES priv, previouspriv;
BOOL Ret = FALSE;
/*
* Enable the SeSystemtimePrivilege privilege
*/
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
priv.PrivilegeCount = 1;
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(NULL,
SE_SYSTEMTIME_NAME,
&priv.Privileges[0].Luid))
{
if (AdjustTokenPrivileges(hToken,
FALSE,
&priv,
sizeof(previouspriv),
&previouspriv,
&PrevSize) &&
GetLastError() == ERROR_SUCCESS)
{
/*
* We successfully enabled it, we're permitted to change the system time
* Call SetLocalTime twice to ensure correct results
*/
Ret = SetLocalTime(lpSystemTime) &&
SetLocalTime(lpSystemTime);
/*
* For the sake of security, restore the previous status again
*/
if (previouspriv.PrivilegeCount > 0)
{
AdjustTokenPrivileges(hToken,
FALSE,
&previouspriv,
0,
NULL,
0);
}
}
}
CloseHandle(hToken);
}
return Ret;
}
static VOID
SetLocalSystemTime(HWND hwnd)
{
SYSTEMTIME Time;
if (DateTime_GetSystemTime(GetDlgItem(hwnd,
IDC_TIMEPICKER),
&Time) == GDT_VALID &&
SendMessage(GetDlgItem(hwnd,
IDC_MONTHCALENDAR),
MCCM_GETDATE,
(WPARAM)&Time,
0))
{
SystemSetLocalTime(&Time);
SetWindowLong(hwnd,
DWL_MSGRESULT,
PSNRET_NOERROR);
SendMessage(GetDlgItem(hwnd,
IDC_MONTHCALENDAR),
MCCM_RESET,
(WPARAM)&Time,
0);
/* broadcast the time change message */
SendMessage(HWND_BROADCAST,
WM_TIMECHANGE,
0,
0);
}
}
static VOID
SetTimeZoneName(HWND hwnd)
{
TIME_ZONE_INFORMATION TimeZoneInfo;
WCHAR TimeZoneString[128];
WCHAR TimeZoneText[128];
WCHAR TimeZoneName[128];
DWORD TimeZoneId;
TimeZoneId = GetTimeZoneInformation(&TimeZoneInfo);
LoadStringW(hApplet, IDS_TIMEZONETEXT, TimeZoneText, 128);
switch (TimeZoneId)
{
case TIME_ZONE_ID_STANDARD:
wcscpy(TimeZoneName, TimeZoneInfo.StandardName);
break;
case TIME_ZONE_ID_DAYLIGHT:
wcscpy(TimeZoneName, TimeZoneInfo.DaylightName);
break;
case TIME_ZONE_ID_UNKNOWN:
LoadStringW(hApplet, IDS_TIMEZONEUNKNOWN, TimeZoneName, 128);
break;
case TIME_ZONE_ID_INVALID:
default:
LoadStringW(hApplet, IDS_TIMEZONEINVALID, TimeZoneName, 128);
break;
}
wsprintfW(TimeZoneString, TimeZoneText, TimeZoneName);
SendDlgItemMessageW(hwnd, IDC_TIMEZONE, WM_SETTEXT, 0, (LPARAM)TimeZoneString);
}
static VOID
FillMonthsComboBox(HWND hCombo)
{
SYSTEMTIME LocalDate = {0};
WCHAR szBuf[64];
INT i;
UINT Month;
GetLocalTime(&LocalDate);
SendMessage(hCombo,
CB_RESETCONTENT,
0,
0);
for (Month = 1;
Month <= 13;
Month++)
{
i = GetLocaleInfoW(LOCALE_USER_DEFAULT,
((Month < 13) ? LOCALE_SMONTHNAME1 + Month - 1 : LOCALE_SMONTHNAME13),
szBuf,
sizeof(szBuf) / sizeof(szBuf[0]));
if (i > 1)
{
i = (INT)SendMessage(hCombo,
CB_ADDSTRING,
0,
(LPARAM)szBuf);
if (i != CB_ERR)
{
SendMessage(hCombo,
CB_SETITEMDATA,
(WPARAM)i,
Month);
if (Month == (UINT)LocalDate.wMonth)
{
SendMessage(hCombo,
CB_SETCURSEL,
(WPARAM)i,
0);
}
}
}
}
}
static WORD
GetCBSelectedMonth(HWND hCombo)
{
INT i;
WORD Ret = (WORD)-1;
i = (INT)SendMessage(hCombo,
CB_GETCURSEL,
0,
0);
if (i != CB_ERR)
{
i = (INT)SendMessage(hCombo,
CB_GETITEMDATA,
(WPARAM)i,
0);
if (i >= 1 && i <= 13)
Ret = (WORD)i;
}
return Ret;
}
static VOID
ChangeMonthCalDate(HWND hMonthCal,
WORD Day,
WORD Month,
WORD Year)
{
SendMessage(hMonthCal,
MCCM_SETDATE,
MAKEWPARAM(Day,
Month),
MAKELPARAM(Year,
0));
}
static VOID
AutoUpdateMonthCal(HWND hwndDlg,
PNMMCCAUTOUPDATE lpAutoUpdate)
{
/* update the controls */
FillMonthsComboBox(GetDlgItem(hwndDlg,
IDC_MONTHCB));
}
/* Property page dialog callback */
INT_PTR CALLBACK
DateTimePageProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
SYSTEMTIME st;
GetLocalTime(&st);
switch (uMsg)
{
case WM_INITDIALOG:
FillMonthsComboBox(GetDlgItem(hwndDlg,
IDC_MONTHCB));
SetTimer(hwndDlg, ID_TIMER, 1000, NULL);
/* set range and current year */
SendMessage(GetDlgItem(hwndDlg, IDC_YEAR), UDM_SETRANGE, 0, MAKELONG ((short) 9999, (short) 1900));
SendMessage(GetDlgItem(hwndDlg, IDC_YEAR), UDM_SETPOS, 0, MAKELONG( (short) st.wYear, 0));
#if 0
InitClockWindowClass();
CreateWindowExW(0,
L"ClockWndClass",
L"Clock",
WS_CHILD | WS_VISIBLE,
208, 14, 150, 150,
hwndDlg,
NULL,
hApplet,
NULL);
#endif
break;
case WM_TIMER:
{
SendMessage(GetDlgItem(hwndDlg, IDC_TIMEPICKER), DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM) &st);
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_MONTHCB:
{
if (HIWORD(wParam) == CBN_SELCHANGE)
{
ChangeMonthCalDate(GetDlgItem(hwndDlg,
IDC_MONTHCALENDAR),
-1,
GetCBSelectedMonth((HWND)lParam),
-1);
}
break;
}
}
break;
}
case WM_CTLCOLORSTATIC:
{
if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_YEARTEXT))
return (int) GetSysColorBrush(COLOR_WINDOW);
break;
}
case WM_NOTIFY:
{
LPNMHDR lpnm = (LPNMHDR)lParam;
switch (lpnm->idFrom)
{
case IDC_YEAR:
switch (lpnm->code)
{
case UDN_DELTAPOS:
{
short wYear;
LPNMUPDOWN updown = (LPNMUPDOWN) lpnm;
wYear = SendMessage(GetDlgItem(hwndDlg, IDC_YEAR), UDM_GETPOS, 0, 0);
/* Enable the 'Apply' button */
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
ChangeMonthCalDate(GetDlgItem(hwndDlg,
IDC_MONTHCALENDAR),
-1,
-1,
wYear + updown->iDelta);
break;
}
}
break;
case IDC_TIMEPICKER:
switch (lpnm->code)
{
case DTN_DATETIMECHANGE:
/* Enable the 'Apply' button */
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
}
break;
case IDC_MONTHCALENDAR:
switch (lpnm->code)
{
case MCCN_SELCHANGE:
/* Enable the 'Apply' button */
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
case MCCN_AUTOUPDATE:
AutoUpdateMonthCal(hwndDlg,
(PNMMCCAUTOUPDATE)lpnm);
break;
}
break;
default:
switch (lpnm->code)
{
case PSN_SETACTIVE:
SetTimeZoneName(hwndDlg);
break;
case PSN_APPLY:
SetLocalSystemTime(hwndDlg);
return TRUE;
}
}
}
break;
case WM_TIMECHANGE:
{
/* FIXME - we don't get this message as we're not a top-level window... */
SendMessage(GetDlgItem(hwndDlg,
IDC_MONTHCALENDAR),
MCCM_RESET,
0,
0);
break;
}
case WM_DESTROY:
{
KillTimer(hwndDlg, ID_TIMER);
break;
}
}
return FALSE;
}
static PTIMEZONE_ENTRY
GetLargerTimeZoneEntry(DWORD Index)
{
PTIMEZONE_ENTRY Entry;
Entry = TimeZoneListHead;
while (Entry != NULL)
{
if (Entry->Index >= Index)
return Entry;
Entry = Entry->Next;
}
return NULL;
}
static VOID
CreateTimeZoneList(VOID)
{
WCHAR szKeyName[256];
DWORD dwIndex;
DWORD dwNameSize;
DWORD dwValueSize;
LONG lError;
HKEY hZonesKey;
HKEY hZoneKey;
PTIMEZONE_ENTRY Entry;
PTIMEZONE_ENTRY Current;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
0,
KEY_ENUMERATE_SUB_KEYS,
&hZonesKey))
return;
dwIndex = 0;
while (TRUE)
{
dwNameSize = 256;
lError = RegEnumKeyExW(hZonesKey,
dwIndex,
szKeyName,
&dwNameSize,
NULL,
NULL,
NULL,
NULL);
if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA)
break;
if (RegOpenKeyExW(hZonesKey,
szKeyName,
0,
KEY_QUERY_VALUE,
&hZoneKey))
break;
Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
if (Entry == NULL)
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = 64 * sizeof(WCHAR);
if (RegQueryValueExW(hZoneKey,
L"Display",
NULL,
NULL,
(LPBYTE)&Entry->Description,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = 33 * sizeof(WCHAR);
if (RegQueryValueExW(hZoneKey,
L"Std",
NULL,
NULL,
(LPBYTE)&Entry->StandardName,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = 33 * sizeof(WCHAR);
if (RegQueryValueExW(hZoneKey,
L"Dlt",
NULL,
NULL,
(LPBYTE)&Entry->DaylightName,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = sizeof(DWORD);
if (RegQueryValueExW(hZoneKey,
L"Index",
NULL,
NULL,
(LPBYTE)&Entry->Index,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = sizeof(TZ_INFO);
if (RegQueryValueExW(hZoneKey,
L"TZI",
NULL,
NULL,
(LPBYTE)&Entry->TimezoneInfo,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
RegCloseKey(hZoneKey);
if (TimeZoneListHead == NULL &&
TimeZoneListTail == NULL)
{
Entry->Prev = NULL;
Entry->Next = NULL;
TimeZoneListHead = Entry;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -