📄 dst.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*---------------------------------------------------------------------------*\
* module: dst.cpp
* purpose: DST support. Need to handle the following 3 scenarios
* 1) DST turns on/off when system is running
* 2) DST turns on/off when system is suspended
* 3) DST turns on/off when system is powered off
*
\*---------------------------------------------------------------------------*/
#ifndef NODSTSAMPLE //don't use this if NODSTSAMPLE is defined
#ifdef TASKMANDSTSAMPLE
#include "windows.h"
#include "minshell.h"
#else
#include "explorer.h"
#endif //TASKMANDSTSAMPLE
#include <notify.h>
//keep these consistant with names in public\wceshellfe\oak\ctlpnl\cplmain\regcpl.h
#define RK_CLOCK TEXT("Software\\Microsoft\\Clock")
#define RV_INDST TEXT("HomeDST") //are we in DST?
#define RV_AUTODST TEXT("AutoDST") //do we auto-adjust DST?
#define RV_DSTUI TEXT("ShowDSTUI") //do we show a message at dst change?
#define DSTEVENT _T("ShellDSTEvent")
#define DSTTZEVENT _T("DSTTzChange")
#define DSTTIMEEVENT _T("DSTTimeChange")
#define DSTNOTIFICATION _T("\\\\.\\Notifications\\NamedEvents\\ShellDSTEvent")
#define DSTTIMEZONENOTIFICATION _T("\\\\.\\Notifications\\NamedEvents\\DSTTzChange")
#define DSTTIMENOTIFICATION _T("\\\\.\\Notifications\\NamedEvents\\DSTTimeChange")
#define NUMDSTEVENTS 3
#define TZCHANGEEVENT 0
#define TIMECHANGEEVENT 1
#define DSTCHANGEEVENT 2 // This event must be last so WaitForMultipleObjects algorithm works (see DST_WaitForEvents)
#define MAX_DSTMSGLEN 256
#define MAX_DSTTITLELEN 64
// FILETIME (100-ns intervals) to minutes (10 x 1000 x 1000 x 60)
#define FILETIME_TO_MINUTES (10 * 1000 * 1000 * 60)
#define FIRST_OF_MONTH 1
#define SECOND_OF_MONTH 2
#define THIRD_OF_MONTH 3
#define FOURTH_OF_MONTH 4
#define LAST_OF_MONTH 5
const int AccumDaysByMonth[13] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
DWORD g_dwTime = TIME_ZONE_ID_STANDARD;
/*++
Routine Description:
Determines whether the current date and time is in daylight
or standard time, and notifies the kernel.
Kernel doesn't currently update this in all cases
Manually take care of it to be safe and ensure that subsequent calls
to GetTimeZoneInformation return the correct value
Arguments:
none
Return Value:
current timezone value (same as return values for GetTimeZoneInformation
--*/
void DST_SetDaylightOrStandardTime(void)
{
TIME_ZONE_INFORMATION tzi;
DWORD dwTZ = GetTimeZoneInformation(&tzi);
// If the system supports DST verify that the kernel returned the correct
// value, otherwise make sure the kerel has us in SDT
if (LocaleSupportsDST(&tzi))
{
SYSTEMTIME curTime;
LONGLONG llStandard = 0, llDaylight = 0, llNow = 0;
GetLocalTime(&curTime);
//fix up the date structs if necessary
if (0 == tzi.StandardDate.wYear)
DST_DetermineChangeDate(&tzi.StandardDate);
if (0 == tzi.DaylightDate.wYear)
DST_DetermineChangeDate(&tzi.DaylightDate);
//convert so we can do the math
VERIFY(SystemTimeToFileTime(&tzi.StandardDate, (FILETIME *)&llStandard));
VERIFY(SystemTimeToFileTime(&tzi.DaylightDate, (FILETIME *)&llDaylight));
VERIFY(SystemTimeToFileTime(&curTime, (FILETIME *)&llNow));
//the greater difference determines which zone we are in
if ((llStandard - llNow) < (llDaylight - llNow))
{
DEBUGMSG(ZONE_DST, (_T("DST: Notifying kernel that we are in Daylight time. GetTimeZoneInformation currently thinks we are in %s time."),
TIME_ZONE_ID_DAYLIGHT == dwTZ ? _T("Daylight") : _T("Standard")));
SetDaylightTime(TRUE);
g_dwTime = TIME_ZONE_ID_DAYLIGHT;
}
else
{
DEBUGMSG(ZONE_DST, (_T("DST: Notifying kernel that we are in Standard time. GetTimeZoneInformation currently thinks we are in %s time."),
TIME_ZONE_ID_DAYLIGHT == dwTZ ? _T("Daylight") : _T("Standard")));
SetDaylightTime(FALSE);
g_dwTime = TIME_ZONE_ID_STANDARD;
}
}
else
{
ASSERT(TIME_ZONE_ID_STANDARD == dwTZ);
if (TIME_ZONE_ID_STANDARD != dwTZ)
SetDaylightTime(FALSE);
g_dwTime = TIME_ZONE_ID_STANDARD;
}
}
/*++
Routine Description:
'main' function for DST. Called from shell init, and re-entered from DST_WaitForEvent.
Arguments:
none
Return Value:
none
--*/
void DST_Init(void)
{
//need to know from the start if we are in standard or daylight time
DST_SetDaylightOrStandardTime();
for (;;)
{
HANDLE hDSTEvents[NUMDSTEVENTS];
hDSTEvents[TZCHANGEEVENT] = DST_SetTimezoneChangeEvent();
hDSTEvents[TIMECHANGEEVENT] = DST_SetTimeChangeEvent();
hDSTEvents[DSTCHANGEEVENT] = DST_SetDSTEvent(); // This can be NULL if we are in a non-DST timezone
if (NULL == hDSTEvents[TZCHANGEEVENT])
{
DEBUGCHK( _T("DST: Failed to set TZ change Event"));
break;
}
if (NULL == hDSTEvents[TIMECHANGEEVENT])
{
DEBUGCHK( _T("DST: Failed to set Time change Event"));
break;
}
DST_WaitForEvents(hDSTEvents);
}
}
/*++
Routine Description:
Determines if we should auto-adjust for DST
Arguments:
none
Return Value:
TRUE if we want to auto adjust
FALSE if we don't want to auto adjust
--*/
BOOL DST_Auto(void)
{
DWORD ret = 0;
HKEY hKey = NULL;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_CLOCK, 0, 0, &hKey))
{
DWORD dwSize = sizeof(DWORD);
RegQueryValueEx(hKey, RV_AUTODST, 0, NULL, (LPBYTE)&ret, &dwSize);
RegCloseKey(hKey);
}
#ifdef DEBUG
if (ret)
{
DEBUGMSG(ZONE_DST, ( _T("DST: Auto change for DST is on")));
}
else
{
DEBUGMSG(ZONE_DST, ( _T("DST: Auto change for DST is off")));
}
#endif //DEBUG
return (BOOL)ret;
}
/*++
Routine Description:
Determines if we should show a mesage for DST change
Arguments:
none
Return Value:
TRUE if we want to show a message
FALSE if we don't want to show a message
--*/
BOOL DST_ShowMessage(void)
{
DWORD ret = 0;
HKEY hKey = NULL;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_CLOCK, 0, 0, &hKey))
{
DWORD dwSize = sizeof(DWORD);
RegQueryValueEx(hKey, RV_DSTUI, 0, NULL, (LPBYTE)&ret, &dwSize);
RegCloseKey(hKey);
}
#ifdef DEBUG
if (ret)
{
DEBUGMSG(ZONE_DST, ( _T("DST: Show Message option for DST is on")));
}
else
{
DEBUGMSG(ZONE_DST, ( _T("DST: Show Message option for DST is off")));
}
#endif //DEBUG
return (BOOL)ret;
}
/*++
Routine Description:
Sets Event to be notified when timezone changes
Arguments:
none
Return Value:
HANDLE to timezone event
--*/
HANDLE DST_SetTimezoneChangeEvent(void)
{
HANDLE hTZEvent = CreateEvent(NULL, FALSE, FALSE, DSTTZEVENT);
if (hTZEvent)
{
if (!CeRunAppAtEvent(DSTTIMEZONENOTIFICATION,
NOTIFICATION_EVENT_TZ_CHANGE))
{
CloseHandle(hTZEvent);
hTZEvent = NULL;
}
}
return hTZEvent;
}
/*++
Routine Description:
Sets Event to be notified when time changes
Arguments:
none
Return Value:
HANDLE to timezone event
--*/
HANDLE DST_SetTimeChangeEvent(void)
{
HANDLE hTimeEvent = CreateEvent(NULL, FALSE, FALSE, DSTTIMEEVENT);
if (hTimeEvent)
{
if (!CeRunAppAtEvent(DSTTIMENOTIFICATION,
NOTIFICATION_EVENT_TIME_CHANGE))
{
CloseHandle(hTimeEvent);
hTimeEvent = NULL;
}
}
return hTimeEvent;
}
/*++
Routine Description:
Sets the DST Event
Arguments:
none
Return Value:
Handle to event to be triggered when daylight time turns on (or off)
--*/
HANDLE DST_SetDSTEvent (void)
{
HANDLE hEvent = NULL;
BOOL bEvent = FALSE;
TIME_ZONE_INFORMATION tzi = {0};
SYSTEMTIME curTime, notificationTime;
LONGLONG llNow = 0, llNotification = 0;
DWORD dwTZ = GetTimeZoneInformation(&tzi);
// Only create the event if the locale supports DST
if (!LocaleSupportsDST(&tzi))
return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -