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

📄 sntp.cxx

📁 Windows CE 6.0 Server 源码
💻 CXX
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*--
Module Name: sntp.cxx
Abstract: service sntp module
--*/
#include <windows.h>
#include <stdio.h>
#include <winsock2.h>

#include <ws2tcpip.h>

#include <svsutil.hxx>
#include <service.h>
#include <notify.h>

#include "../inc/timesvc.h"

#define NOTIFICATION_WAIT_SEC    30

#if ! defined(DNS_MAX_NAME_BUFFER_LENGTH)
#define DNS_MAX_NAME_BUFFER_LENGTH      (256)
#endif

#define NTP_PORT        123
#define NTP_PORT_A        "123"

#define BASE_KEY        L"services\\timesvc"

#define MIN_REFRESH        (5*60*1000)
#define MIN_MULTICAST    (5*60*1000)
#define MIN_TIMEUPDATE    (5*1000)

#define MAX_STACKS    5
#define MAX_SERVERS    10
#define MAX_MCASTS    10

#define MAX_MSZ        1024

static HANDLE hNotifyThread = NULL;
static HANDLE hExitEvent = NULL;

typedef BOOL (*tCeRunAppAtEvent)(WCHAR *pwszAppName, LONG lWhichEvent);
typedef DWORD (*tNotifyAddrChange)(PHANDLE Handle, LPOVERLAPPED overlapped);

#define NTPTIMEOFFSET (0x014F373BFDE04000)
#define FIVETOTHESEVETH (0x001312D)

/*
                         1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |LI | VN  |Mode |    Stratum    |     Poll      |   Precision   |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Root Delay                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                       Root Dispersion                         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                     Reference Identifier                      |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                   Reference Timestamp (64)                    |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                   Originate Timestamp (64)                    |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                    Receive Timestamp (64)                     |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                    Transmit Timestamp (64)                    |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                 Key Identifier (optional) (32)                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                               |
      |                                                               |
      |                 Message Digest (optional) (128)               |
      |                                                               |
      |                                                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/

///////////////////////////////////////////////////////////////////////
//
//        Base Classes
//
//
class NTP_REQUEST {
private:
    union {
        struct {
            unsigned char i_lvm, i_stratum, i_poll, i_prec;
            unsigned char i_root_delay[4];
            unsigned char i_root_dispersion[4];
            unsigned char i_ref_identifier[4];
            unsigned char i_ref_stamp[8];
            unsigned char i_orig_stamp[8];
            unsigned char i_recv_stamp[8];
            unsigned char i_trans_stamp[8];
        };
        unsigned __int64 ll;
    };

public:
    unsigned int li (void) {
        return (i_lvm >> 6) & 0x03;
    }

    void set_li (unsigned int l) {
        i_lvm = (i_lvm & 0x3f) | ((l & 0x3) << 6);
    }

    unsigned int vn (void) {
        return (i_lvm >> 3) & 0x07;
    }

    void set_vn (unsigned int v) {
        i_lvm = (i_lvm & 0xc7) | ((v & 0x7) << 3);
    }

    unsigned int mode (void) {
        return i_lvm & 0x07;
    }

    void set_mode (unsigned int m) {
        i_lvm = (i_lvm & 0xf8) | (m & 0x7);
    }

    unsigned int stratum (void) {
        return i_stratum;
    }

    void set_stratum (unsigned int s) {
        i_stratum = s;
    }

    unsigned int poll (void) {
        return i_poll;
    }

    void set_poll (unsigned int p) {
        i_poll = p;
    }

    unsigned int precision (void) {
        return i_prec;
    }

    void set_precision (unsigned int p) {
        i_prec = p;
    }

    unsigned int root_delay (void) {
        return (i_root_delay[0] << 24) | (i_root_delay[1] << 16) | (i_root_delay[2] << 8) | i_root_delay[3];
    }

    void set_root_delay (unsigned int rd) {
        i_root_delay[0] = (unsigned char)(rd >> 24);
        i_root_delay[1] = (unsigned char)(rd >> 16);
        i_root_delay[2] = (unsigned char)(rd >>  8);
        i_root_delay[3] = (unsigned char) rd;
    }

    unsigned int root_dispersion (void) {
        return (i_root_dispersion[0] << 24) | (i_root_dispersion[1] << 16) | (i_root_dispersion[2] << 8) | i_root_dispersion[3];
    }

    void set_root_dispersion (unsigned int rd) {
        i_root_dispersion[0] = (unsigned char)(rd >> 24);
        i_root_dispersion[1] = (unsigned char)(rd >> 16);
        i_root_dispersion[2] = (unsigned char)(rd >>  8);
        i_root_dispersion[3] = (unsigned char) rd;
    }

    unsigned int ref_id (void) {
        return (i_ref_identifier[0] << 24) | (i_ref_identifier[1] << 16) | (i_ref_identifier[2] << 8) | i_ref_identifier[3];
    }

    void set_ref_id (unsigned int rid) {
        i_ref_identifier[0] = (unsigned char)(rid >> 24);
        i_ref_identifier[1] = (unsigned char)(rid >> 16);
        i_ref_identifier[2] = (unsigned char)(rid >>  8);
        i_ref_identifier[3] = (unsigned char) rid;
    }

    unsigned __int64 ref_stamp (void) {
        return *(unsigned __int64 *)i_ref_stamp;
    }

    void set_ref_stamp (unsigned __int64 ll) {
        *(unsigned __int64 *)i_ref_stamp = ll;
    }

    unsigned __int64 orig_stamp (void) {
        return *(unsigned __int64 *)i_orig_stamp;
    }

    void set_orig_stamp (unsigned __int64 ll) {
        *(unsigned __int64 *)i_orig_stamp = ll;
    }

    unsigned __int64 recv_stamp (void) {
        return *(unsigned __int64 *)i_recv_stamp;
    }

    void set_recv_stamp (unsigned __int64 ll) {
        *(unsigned __int64 *)i_recv_stamp = ll;
    }

    unsigned __int64 trans_stamp (void) {
        return *(unsigned __int64 *)i_trans_stamp;
    }

    void set_trans_stamp (unsigned __int64 ll) {
        *(unsigned __int64 *)i_trans_stamp = ll;
    }
};

enum When {
    Now,
    Shortly,
    Later
};

class TimeState : public SVSSynch {
    SVSThreadPool    *pEvents;

    SOCKET        saServer[MAX_STACKS];
    int        iSock;

    DWORD        dwRefreshMS;
    DWORD           dwRecoveryRefreshMS;
    DWORD        dwAdjustThreshMS;
    DWORD           dwMulticastPeriodMS;

    SVSCookie        ckNextRefresh;
    SVSCookie        ckNextMulticast;

    char    sntp_servers[MAX_SERVERS][DNS_MAX_NAME_BUFFER_LENGTH];
    char    sntp_mcasts[MAX_MCASTS][DNS_MAX_NAME_BUFFER_LENGTH];

    int        cServers;
    int        cMcasts;

    union {
        struct {
            unsigned int fStarted           : 1;
            unsigned int fHaveClient        : 1;
            unsigned int fHaveServer        : 1;
            unsigned int fSystemTimeCorrect : 1;
            unsigned int fRefreshRequired   : 1;
            unsigned int fForceTimeToServer : 1;
        };
        unsigned int uiFlags;
    };

    void ReInit (void) {
        DEBUGMSG(ZONE_TRACE, (L"[TIMESVC] State reinitialized\r\n"));

        pEvents = 0;
                for (int i = 0 ; i < SVSUTIL_ARRLEN(saServer) ; ++i)
            saServer[i] = INVALID_SOCKET;

        iSock = 0;


        llLastSyncTimeXX = 0;
        ckNextRefresh = ckNextMulticast = 0;

        memset (sntp_servers, 0, sizeof(sntp_servers));
        memset (sntp_mcasts,  0, sizeof(sntp_mcasts));
        cServers = 0;
        cMcasts  = 0;

        dwRefreshMS = dwRecoveryRefreshMS = dwAdjustThreshMS = dwMulticastPeriodMS = 0;

        uiFlags = 0;
    }

public:
    unsigned __int64        llLastSyncTimeXX;

    int IsStarted (void) { return fStarted; }
    int LastUpdateFailed (void) { return fRefreshRequired; }

    int RefreshConfig (void);
    int ForcedUpdate (void);
    int UpdateNowOrLater (enum When, int fForceTime = FALSE);
    int TimeChanged (void);

    int Start (void);
    SVSThreadPool *Stop (void);

    TimeState (void) {
        ReInit ();
    }

    int IsTimeAccurate(void) {
        // Trust the time if we have a local clock, or if 
        // we have a client and there is no refresh required (its up-to-date).
    	return fSystemTimeCorrect || (! fRefreshRequired && fHaveClient);
    };

    friend DWORD WINAPI RxThread (LPVOID lpUnused);
    friend DWORD WINAPI TimeRefreshThread (LPVOID lpUnused);
    friend DWORD WINAPI MulticastThread (LPVOID lpUnused);
    friend DWORD WINAPI GetTimeOffsetOnServer (LPVOID lpArg);
};

struct GetTimeOffset {
    __int64         llOffset;
    unsigned char   cchServer[DNS_MAX_NAME_BUFFER_LENGTH];
};

static int GetAddressList (HKEY hk, WCHAR *szValue, char *pItems, int cItems, int cItemSize, int *piCount) {
    *piCount = 0;

    union {
        DWORD   dw;
        in_addr ia;
        WCHAR   szM[MAX_MSZ];
    } u;

    DWORD dwType;
    DWORD dwSize = sizeof(u);

    if (ERROR_SUCCESS != RegQueryValueEx (hk, szValue, NULL, &dwType, (LPBYTE)&u, &dwSize))
        return ERROR_SUCCESS;

    u.szM[MAX_MSZ-1] = '\0';
    u.szM[MAX_MSZ-2] = '\0';

    if (dwType == REG_DWORD) {    // Legacy: ip address
        if (dwSize == sizeof(DWORD)) {
            *piCount = 1;
            strcpy (pItems, inet_ntoa (u.ia));
            return ERROR_SUCCESS;
        }
    }

    if (dwType == REG_SZ) {        // Legacy: single name
        int cc = WideCharToMultiByte (CP_ACP, 0, u.szM, -1, pItems, cItemSize, NULL, NULL);
        if (cc > 0) {
            *piCount = 1;
            return ERROR_SUCCESS;
        }
    }

    if (dwType == REG_MULTI_SZ) {    // List of names/addresses
        WCHAR *p = u.szM;
        while (*p) {
            int cc = cItems ? WideCharToMultiByte (CP_ACP, 0, p, -1, pItems, cItemSize, NULL, NULL) : 0;
            if (cc == 0) {
                *piCount = 0;
                break;
            }

            ++*piCount;
            pItems += cItemSize;
            cItems--;

            p += wcslen (p) + 1;
        }

        return ERROR_SUCCESS;
    }

    return ERROR_BAD_CONFIGURATION;
}


///////////////////////////////////////////////////////////////////////
//
//        Base Classes - implementation
//
//
int TimeState::RefreshConfig (void) {
    DEBUGMSG(ZONE_INIT, (L"[TIMESVC] Refreshing configuration\r\n"));

    HKEY hk;
    int iErr = ERROR_BAD_CONFIGURATION;

    ReInit ();

    if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, BASE_KEY, 0, KEY_READ, &hk)) {
        iErr = GetAddressList (hk, L"server", (char *)sntp_servers, SVSUTIL_ARRLEN(sntp_servers), SVSUTIL_ARRLEN(sntp_servers[0]), &cServers);

        if (cServers) {
            iErr = ERROR_SUCCESS;

            DWORD dw;
            DWORD dwType = 0;
            DWORD dwSize = sizeof(dw);

            if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"AutoUpdate", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
                    (dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
                fHaveClient = TRUE;

            if (fHaveClient) {
                dwType = 0;
                dwSize = sizeof(dwRefreshMS);
                if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"refresh", NULL, &dwType, (LPBYTE)&dwRefreshMS, &dwSize)) &&
                    (dwType == REG_DWORD) && (dwSize == sizeof(DWORD)) && (dwRefreshMS >= MIN_REFRESH)) {
                    ;
                } else {
                    iErr = ERROR_BAD_CONFIGURATION;    // Require refresh key if we have a client
                    RETAILMSG(1, (L"[TIMESVC] Configuration error: refresh rate incorrect. Aborting.\r\n"));
                }
            }

            if ((iErr == ERROR_SUCCESS) && fHaveClient) {
                iErr = ERROR_BAD_CONFIGURATION;    // Require accelerated refresh key if we have a client

                dwType = 0;
                dwSize = sizeof(dwRecoveryRefreshMS);
                if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"recoveryrefresh", NULL, &dwType, (LPBYTE)&dwRecoveryRefreshMS, &dwSize)) &&
                    (dwType == REG_DWORD) && (dwSize == sizeof(DWORD)) && (dwRecoveryRefreshMS >= MIN_REFRESH) && (dwRecoveryRefreshMS <= dwRefreshMS)) {
                    iErr = ERROR_SUCCESS;
                } else {
                    RETAILMSG(1, (L"[TIMESVC] Configuration error: accelerated refresh rate incorrect. Aborting.\r\n"));
                }
            }

            if ((iErr == ERROR_SUCCESS) && fHaveClient) {
                iErr = ERROR_BAD_CONFIGURATION;    // Require threshold if we have a client

                dwType = 0;
                dwSize = sizeof(dw);

                if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"threshold", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
                    (dwType == REG_DWORD) && (dwSize == sizeof(dw))) {
                    dwAdjustThreshMS = dw;

                    iErr = ERROR_SUCCESS;
                } else {
                    RETAILMSG(1, (L"[TIMESVC] Configuration error: time adjustment threshold incorrect. Aborting.\r\n"));
                }

            }

⌨️ 快捷键说明

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