⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dst.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

    // returning from this function causes DST_Init to reset all of our events
    // so we need to turn everything off
    CeRunAppAtEvent(DSTTIMEZONENOTIFICATION, NOTIFICATION_EVENT_NONE);
    CeRunAppAtEvent(DSTTIMENOTIFICATION, NOTIFICATION_EVENT_NONE);
    CeRunAppAtTime(DSTNOTIFICATION, 0);

    // and ditch the handles, except for shutdown event - keep that
    for (int i = 1; i < NUMDSTEVENTS; i++)
    {
        if (NULL != DST_handles[i])
        {
            CloseHandle(DST_handles[i]);
            DST_handles[i] = NULL;
        }
    }

    switch (dwEvent - WAIT_OBJECT_0)
    {
        case SHUTDOWNEVENT :
            DEBUGMSG(ZONE_INIT, (_T("[TIMESVC DST] Shutting down DST system\r\n")));
            return FALSE;

        case TZCHANGEEVENT :
        case TIMECHANGEEVENT :
        {
            // need to redetermine whether we are in daylight or standard time
            DEBUGMSG(ZONE_DST, (_T("[TIMESVC DST] Resetting DST event due to Time, Date, or TZ change\r\n")));
            SetDaylightOrStandardTimeDST(NULL);
        }
        break;

        case DSTCHANGEEVENT :
        {
            if (DST_Auto())
            {
                // stOld contains the current system time (NOT the one before the update)
                // stNew contains new system time if we have to add or subtract 1 hour
                // to process DST/STD time change.
                SYSTEMTIME stOld, stNew;
                LONGLONG llOld, llNew;                

                GetLocalTime(&stOld); 
                SystemTimeToFileTime(&stOld, (FILETIME *)&llOld);

                /*
                    Check the time zone information.  It's possible that this information has
                    changed since the GetTimeZoneInformation call in DST_SetEvent, and
                    this action needs to be based on the current timezone.
                */
                TIME_ZONE_INFORMATION tzi = {0};
                GetTimeZoneInformation(&tzi);
                LONGLONG  llStandard = 0, llDaylight = 0;

                //fix up the date structs if necessary
                if (0 == tzi.StandardDate.wYear)
                    DST_DetermineChangeDate(&tzi.StandardDate, TRUE);
                if (0 == tzi.DaylightDate.wYear)
                    DST_DetermineChangeDate(&tzi.DaylightDate, TRUE);

                //convert so we can do the math
                VERIFY(SystemTimeToFileTime(&tzi.StandardDate, (FILETIME *)&llStandard));
                VERIFY(SystemTimeToFileTime(&tzi.DaylightDate, (FILETIME *)&llDaylight));

                if (((llOld-llDaylight >= 0) && (llOld-llDaylight < DST_TIME_THRESHHOLD)) ||
                    ((llOld-llStandard >= 0) && (llOld-llStandard < DST_TIME_THRESHHOLD))) 
                {
                    // This indicates that it's less than 1 minute after the STD<->DST
                    // boundary.  Always perform the flip after this conditional block.
                }
                else
                {
                    // This indicates that we've had a DST event triggered without
                    // "naturally" crossing over the DST boundary.  This can happen
                    // for instance if the original clock is set to 1/1/04 and the 
                    // new time is set to 11/1/04.  In this case, since TimeSVC had
                    // an event scheduled to go off sometime in 4/04 to handle this
                    // event, the event is handled presently. 

                    // In this case, we *may* not need need to flip from DST<->STD.
                    // We may be in the same DST/Standard setting; i.e. on a system bootup
                    // where clock is default to 1/1/04, and new time is 11/1/04, in both cases
                    // we are in standard time and should not perform the calculations below.
                    // However, going from 1/1/04 to 6/1/04 will require a flip, since one is 
                    // STD and other is DST
                    
                    if ((llDaylight <= llStandard && llDaylight <= llOld && llOld <= llStandard) 
                     || (llDaylight > llStandard && (llDaylight <= llOld || llOld <= llStandard)))
                    {
                        // We are in day light time presently
                        if (TIME_ZONE_ID_DAYLIGHT == g_dwTime)
                            return TRUE; // no need to change
                    }
                    else {
                        // We are in standard time presently
                        if (TIME_ZONE_ID_STANDARD == g_dwTime)
                            return TRUE; // no need to change
                    }
                }

                /*
                    If we're going from Daylight to Standard, we need to move the 
                    clock BACK by g_tzDSTBias (60 minutes usually).  If we're going 
                    from Standard to Daylight we need to move it forward even though
                    g_tzDSTBias is 0.
                */ 
                if (TIME_ZONE_ID_DAYLIGHT == g_dwTime) // clock needs to go back - so we add (g_tzDSTBias is always negative)
                {
                    llNew = llOld + (LONGLONG)((LONGLONG)tzi.DaylightBias * FILETIME_TO_MINUTES);
                    // now flip the time flag  because we're just about to change                   
                    g_dwTime = TIME_ZONE_ID_STANDARD;                        
                    SetDaylightTime(FALSE);   
                }
                else // clock needs to go forward - so we subtract (see above)
                {
                    llNew = llOld - (LONGLONG)((LONGLONG)tzi.DaylightBias * FILETIME_TO_MINUTES);
                    // now flip the time flag  because we're just about to change
                    g_dwTime = TIME_ZONE_ID_DAYLIGHT;                        
                    SetDaylightTime(TRUE);                    
                }

                FileTimeToSystemTime((FILETIME *)&llNew, &stNew);

                
                DEBUGMSG(ZONE_DST, (L"[TIMESVC DST] TZ Change: Updating clock. Old Time =%d:%02d, New Time =%d:%02d\r\n", 
                                stOld.wHour, stOld.wMinute, stNew.wHour, stNew.wMinute));

                SetLocalTime(&stNew);

                DST_ShowMessage ();
            }
        }
        break;
        default :
        {
            DEBUGMSG(ZONE_INIT, (_T("[TIMESVC DST] Shutting down DST system\r\n")));
            return FALSE;
        }
    }

    return TRUE;
}   

/*++
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
    
--*/
static 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("[TIMESVC DST]  Show Message option for DST is on\r\n")));
    } 
    else
    {
        DEBUGMSG(ZONE_DST, ( _T("[TIMESVC DST]  Show Message option for DST is off\r\n")));
    }
#endif //DEBUG

    if (ret)
    {
        ret = FALSE;

        TCHAR msg[MAX_DSTMSGLEN];
        TCHAR title[MAX_DSTTITLELEN];
        if (LoadString(g_hInst, IDS_DSTCHANGED, msg, MAX_DSTMSGLEN) &&
            LoadString(g_hInst, IDS_DSTTIMEINFO, title, MAX_DSTTITLELEN))
        {
            HMODULE hCoreDll = LoadLibrary (L"coredll.dll");
            if (hCoreDll)
            {
                tMessageBoxW pMessageBox = (tMessageBoxW)GetProcAddress(hCoreDll, L"MessageBoxW");
                tGetForegroundWindow pGetForegroundWindow =(tGetForegroundWindow)GetProcAddress (hCoreDll, L"GetForegroundWindow");
                if (pMessageBox && pGetForegroundWindow)
                {
                    HANDLE hGweApiSetReady = OpenEvent(EVENT_ALL_ACCESS, FALSE, L"SYSTEM/GweApiSetReady");

                    if (hGweApiSetReady)
                    {
                        int fGweReady = (WAIT_OBJECT_0 == WaitForSingleObject (hGweApiSetReady, 30000));
                        CloseHandle (hGweApiSetReady);

                        if (fGweReady)
                        {
                            pMessageBox(pGetForegroundWindow(), msg, title, MB_OK);
                            ret = TRUE;
                        }
                    }
                }

                FreeLibrary (hCoreDll);
            }
        }
    }

    return (BOOL)ret;
}

// Determine first day of week [Sun-Sat] of the first day of the month.
WORD GetFirstWeekDayOfMonth(LPSYSTEMTIME pst) {
    SYSTEMTIME st;
    FILETIME   ft;
    memcpy(&st,pst,sizeof(st));
    st.wDayOfWeek = 0;
    st.wDay = 1;

    // Convert to FILETIME and then back to SYSTEMTIME to get this information.
    SystemTimeToFileTime(&st,&ft);
    FileTimeToSystemTime(&ft,&st);
    ASSERT((st.wDayOfWeek >= 0) && (st.wDayOfWeek <= 6));
    return st.wDayOfWeek;
}

// Convert a SYSTEMITIME in the day-in-month format (ultimatly from 
// TIME_ZONE_INFORMATION) into a real SYSTEMTIME that the system can process.

static BOOL DST_DetermineChangeDate(LPSYSTEMTIME pStTzChange, BOOL fThisYear)
{
    LONGLONG  llChangeDate = 0, llNow = 0;
    SYSTEMTIME stAbsolute; // Conversion from pStTzChange
    SYSTEMTIME stNow; // Current time

    ASSERT((pStTzChange->wDay >= 1) && (pStTzChange->wDay <= 5));
    memcpy(&stAbsolute,pStTzChange,sizeof(stAbsolute));

    GetLocalTime(&stNow);

    // build up the new structure
    if (stAbsolute.wYear == 0) {
        pStTzChange->wYear = stAbsolute.wYear = stNow.wYear;
    }

    // Day of week [Sun-Sat] the first day of week falls on
    WORD wFirstDayInMonth = GetFirstWeekDayOfMonth(&stAbsolute);
    // First day in month [1-7] that is on same day of week as timezone change
    WORD wFirstDayTZChange;

    // Determine the first date in this month that falls on the day of 
    // the week that the time zone change will happen on, eg 
    // first Monday in June 2006 would get wFirstDayTZChange=5.
    if (wFirstDayInMonth > pStTzChange->wDayOfWeek)
        wFirstDayTZChange = (1 + 7 -(wFirstDayInMonth - pStTzChange->wDayOfWeek));
    else
        wFirstDayTZChange = 1 + pStTzChange->wDayOfWeek - wFirstDayInMonth;

    ASSERT((wFirstDayTZChange >= 1) && (wFirstDayTZChange <= 7));

    stAbsolute.wDay = wFirstDayTZChange;

    for (DWORD i = 1; i < pStTzChange->wDay; i++) {
        FILETIME ftTemp;
        // Increment the current week by one, and see if it's a legit date.
        // SystemTimeToFileTime has all the logic to determine if the SystemTime
        // is correct - if it's not in means we've "overshot" the intended date
        // and need to pull back on.  Consider for instance if the TZ Cutover
        // was set to be 5th Thursday in July 2006.  Eventually in this loop
        // we would get to July 34th, which is bogus, so we'd need to pull
        // back to July 27th.
        stAbsolute.wDay += 7;
        if (! SystemTimeToFileTime(&stAbsolute, &ftTemp)) {
            // We overshot, pull back a week
            stAbsolute.wDay -= 7;
            break;
        }
    }

     // Need to determine if the next occurrance of this date is THIS year or NEXT year
    VERIFY(SystemTimeToFileTime(&stAbsolute, (FILETIME *)&llChangeDate));
    VERIFY(SystemTimeToFileTime(&stNow, (FILETIME *)&llNow));

    // In this case, the change-over date was calculated to be in the past.
    // Sometimes this is what we want, othertimes (like when setting up an event
    // to be fired in future) we need to re-perform this calculation so that we
    // get a date in the future.
    if (!fThisYear && (llChangeDate < llNow))
    {
        //need to redetermine the date for next year
        pStTzChange->wYear++;
        return DST_DetermineChangeDate(pStTzChange,TRUE);
    }

    memcpy(pStTzChange,&stAbsolute,sizeof(stAbsolute));
    return TRUE;
}


/*++
Routine Description:
    determines if the current locale supports DST based on
    information in a TIME_ZONE_INFORMATION struct
    
Arguments:
    pointer to a TIME_ZONE_INFORMATION  struct
    
Return Value:
    TRUE if the locale supports DST, FALSE otherwise
    
--*/
static BOOL LocaleSupportsDST(TIME_ZONE_INFORMATION *ptzi)
{
    ASSERT(ptzi);

    // If the month value is zero then this locale does not change for DST
    // it should never be the case that we have a DST date but not a SDT date
    ASSERT(((0 != ptzi->StandardDate.wMonth) && (0 != ptzi->DaylightDate.wMonth)) ||
           ((0 == ptzi->StandardDate.wMonth) && (0 == ptzi->DaylightDate.wMonth)));

    if ((0 != ptzi->StandardDate.wMonth) && (0 != ptzi->DaylightDate.wMonth))
        return TRUE;
    else
        return FALSE;
}

//
//	Public interface section
//
int InitializeDST (HINSTANCE hInst) {
    g_hInst = hInst;
    g_hDSTShutdownEvent = CreateEvent (NULL, TRUE, TRUE, NULL);

    return (g_hDSTShutdownEvent != NULL) ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
}

void DestroyDST (void) {
    CloseHandle (g_hDSTShutdownEvent);
    g_hDSTShutdownEvent = NULL;
    g_hInst = NULL;
}

int RefreshDST (void) {
    return ERROR_SUCCESS;
}

int StartDST (void) {
    if (! g_hInst)
        return ERROR_SERVICE_DOES_NOT_EXIST;

    if (WaitForSingleObject (g_hDSTShutdownEvent, 0) == WAIT_TIMEOUT)
        return ERROR_SERVICE_ALREADY_RUNNING;

    ResetEvent (g_hDSTShutdownEvent);
    g_hDSTThread = CreateThread (NULL, 0, DST_Init, NULL, 0, NULL);
    if (g_hDSTThread == NULL) {
        int iErr = GetLastError ();
        SetEvent (g_hDSTShutdownEvent);
        return iErr;
    }

    return ERROR_SUCCESS;
}

int StopDST (void) {
    if (! g_hInst)
        return ERROR_SERVICE_DOES_NOT_EXIST;

    if (WaitForSingleObject (g_hDSTShutdownEvent, 0) == WAIT_OBJECT_0)
        return ERROR_SERVICE_NOT_ACTIVE;

    SetEvent (g_hDSTShutdownEvent);
    WaitForSingleObject (g_hDSTThread, INFINITE);
    CloseHandle (g_hDSTThread);
    g_hDSTThread = NULL;

    return ERROR_SUCCESS;
}

DWORD GetStateDST (void) {
    if (! g_hInst)
        return SERVICE_STATE_UNINITIALIZED;

    if (WaitForSingleObject (g_hDSTShutdownEvent, 0) == WAIT_OBJECT_0)
        return SERVICE_STATE_OFF;

    return SERVICE_STATE_ON;
}

int   ServiceControlDST (PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut, int *pfProcessed) {
    *pfProcessed = FALSE;
    return ERROR_INVALID_PARAMETER;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -