📄 sntp.cxx
字号:
//
// 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 + -