2006-06-23 08:13:50 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Timedate Control Panel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2011-11-29 14:55:58 +00:00
|
|
|
* FILE: dll/cpl/timedate/ntpclient.c
|
2006-06-23 08:13:50 +00:00
|
|
|
* PURPOSE: Queries the NTP server
|
|
|
|
* COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2013-01-24 23:00:42 +00:00
|
|
|
#include "timedate.h"
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2014-01-19 10:40:50 +00:00
|
|
|
#include <winsock2.h>
|
|
|
|
|
2006-06-23 08:13:50 +00:00
|
|
|
#define TIMEOUT 4000 /* 4 second timeout */
|
|
|
|
|
2007-04-30 19:05:04 +00:00
|
|
|
typedef struct _INFO
|
|
|
|
{
|
|
|
|
SOCKET Sock;
|
|
|
|
SOCKADDR_IN myAddr;
|
|
|
|
SOCKADDR_IN ntpAddr;
|
|
|
|
NTPPACKET SendPacket;
|
|
|
|
NTPPACKET RecvPacket;
|
|
|
|
} INFO, *PINFO;
|
|
|
|
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2007-04-30 19:05:04 +00:00
|
|
|
static BOOL
|
|
|
|
InitConnection(PINFO pInfo,
|
2007-07-31 22:17:07 +00:00
|
|
|
LPSTR lpAddress)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
|
|
|
WSADATA wsaData;
|
|
|
|
HOSTENT *he;
|
|
|
|
INT Ret;
|
|
|
|
|
|
|
|
Ret = WSAStartup(MAKEWORD(2, 2),
|
|
|
|
&wsaData);
|
|
|
|
if (Ret != 0)
|
|
|
|
return FALSE;
|
|
|
|
|
2007-04-30 19:05:04 +00:00
|
|
|
pInfo->Sock = socket(AF_INET,
|
|
|
|
SOCK_DGRAM,
|
|
|
|
0);
|
|
|
|
if (pInfo->Sock == INVALID_SOCKET)
|
2006-06-23 08:13:50 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
/* Setup server info */
|
2006-06-23 08:13:50 +00:00
|
|
|
he = gethostbyname(lpAddress);
|
|
|
|
if (he != NULL)
|
|
|
|
{
|
2011-11-29 14:55:58 +00:00
|
|
|
/* Setup server socket info */
|
2007-04-30 19:05:04 +00:00
|
|
|
ZeroMemory(&pInfo->ntpAddr, sizeof(SOCKADDR_IN));
|
2011-11-29 14:55:58 +00:00
|
|
|
pInfo->ntpAddr.sin_family = AF_INET; // he->h_addrtype;
|
2007-04-30 19:05:04 +00:00
|
|
|
pInfo->ntpAddr.sin_port = htons(NTPPORT);
|
|
|
|
pInfo->ntpAddr.sin_addr = *((struct in_addr *)he->h_addr);
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-04-30 19:05:04 +00:00
|
|
|
|
|
|
|
static VOID
|
2007-06-07 16:18:38 +00:00
|
|
|
DestroyConnection(VOID)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
|
|
|
WSACleanup();
|
|
|
|
}
|
|
|
|
|
2007-04-30 19:05:04 +00:00
|
|
|
|
|
|
|
static BOOL
|
|
|
|
GetTransmitTime(PTIMEPACKET ptp)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
/* Send some data to wake the server up */
|
2007-04-30 19:05:04 +00:00
|
|
|
static BOOL
|
|
|
|
SendData(PINFO pInfo)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
2008-12-03 17:33:13 +00:00
|
|
|
TIMEPACKET tp = { 0, 0 };
|
2006-06-23 08:13:50 +00:00
|
|
|
INT Ret;
|
|
|
|
|
2007-04-30 19:05:04 +00:00
|
|
|
ZeroMemory(&pInfo->SendPacket, sizeof(pInfo->SendPacket));
|
|
|
|
pInfo->SendPacket.LiVnMode = 27;
|
|
|
|
if (!GetTransmitTime(&tp))
|
|
|
|
return FALSE;
|
|
|
|
pInfo->SendPacket.TransmitTimestamp = tp;
|
|
|
|
|
|
|
|
Ret = sendto(pInfo->Sock,
|
|
|
|
(char *)&pInfo->SendPacket,
|
|
|
|
sizeof(pInfo->SendPacket),
|
2006-06-23 08:13:50 +00:00
|
|
|
0,
|
2007-04-30 19:05:04 +00:00
|
|
|
(SOCKADDR *)&pInfo->ntpAddr,
|
2006-06-23 08:13:50 +00:00
|
|
|
sizeof(SOCKADDR_IN));
|
|
|
|
|
|
|
|
if (Ret == SOCKET_ERROR)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-30 19:05:04 +00:00
|
|
|
static ULONG
|
2013-04-13 21:28:10 +00:00
|
|
|
ReceiveData(PINFO pInfo)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
|
|
|
TIMEVAL timeVal;
|
|
|
|
FD_SET readFDS;
|
|
|
|
INT Ret;
|
|
|
|
ULONG ulTime = 0;
|
|
|
|
|
2016-11-12 21:53:33 +00:00
|
|
|
/* Monitor socket for incoming connections */
|
2006-06-23 08:13:50 +00:00
|
|
|
FD_ZERO(&readFDS);
|
2007-04-30 19:05:04 +00:00
|
|
|
FD_SET(pInfo->Sock, &readFDS);
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
/* Set timeout values */
|
2006-06-23 08:13:50 +00:00
|
|
|
timeVal.tv_sec = TIMEOUT / 1000;
|
|
|
|
timeVal.tv_usec = TIMEOUT % 1000;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
/* Check for data on the socket for TIMEOUT millisecs */
|
2006-06-23 08:13:50 +00:00
|
|
|
Ret = select(0, &readFDS, NULL, NULL, &timeVal);
|
|
|
|
|
|
|
|
if ((Ret != SOCKET_ERROR) && (Ret != 0))
|
|
|
|
{
|
2007-04-30 19:05:04 +00:00
|
|
|
Ret = recvfrom(pInfo->Sock,
|
|
|
|
(char *)&pInfo->RecvPacket,
|
|
|
|
sizeof(pInfo->RecvPacket),
|
2006-06-23 08:13:50 +00:00
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2018-01-16 15:40:03 +00:00
|
|
|
|
2006-06-23 08:13:50 +00:00
|
|
|
if (Ret != SOCKET_ERROR)
|
2018-01-16 15:40:03 +00:00
|
|
|
ulTime = ntohl(pInfo->RecvPacket.TransmitTimestamp.dwInteger);
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ulTime;
|
|
|
|
}
|
2007-04-30 19:05:04 +00:00
|
|
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
ULONG
|
2007-04-30 19:05:04 +00:00
|
|
|
GetServerTime(LPWSTR lpAddress)
|
|
|
|
{
|
|
|
|
PINFO pInfo;
|
|
|
|
LPSTR lpAddr;
|
|
|
|
DWORD dwSize = wcslen(lpAddress) + 1;
|
|
|
|
ULONG ulTime = 0;
|
|
|
|
|
2007-06-07 16:18:38 +00:00
|
|
|
pInfo = (PINFO)HeapAlloc(GetProcessHeap(),
|
2007-10-19 23:21:45 +00:00
|
|
|
0,
|
2007-04-30 19:05:04 +00:00
|
|
|
sizeof(INFO));
|
|
|
|
lpAddr = (LPSTR)HeapAlloc(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
dwSize);
|
|
|
|
|
|
|
|
if (pInfo && lpAddr)
|
|
|
|
{
|
|
|
|
if (WideCharToMultiByte(CP_ACP,
|
|
|
|
0,
|
|
|
|
lpAddress,
|
|
|
|
-1,
|
|
|
|
lpAddr,
|
|
|
|
dwSize,
|
|
|
|
NULL,
|
|
|
|
NULL))
|
|
|
|
{
|
|
|
|
if (InitConnection(pInfo, lpAddr))
|
|
|
|
{
|
|
|
|
if (SendData(pInfo))
|
|
|
|
{
|
2013-04-13 21:28:10 +00:00
|
|
|
ulTime = ReceiveData(pInfo);
|
2007-04-30 19:05:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DestroyConnection();
|
|
|
|
}
|
2007-04-30 22:25:26 +00:00
|
|
|
}
|
2007-04-30 19:05:04 +00:00
|
|
|
|
2007-04-30 22:25:26 +00:00
|
|
|
if (pInfo)
|
2007-04-30 19:05:04 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, pInfo);
|
2007-04-30 22:25:26 +00:00
|
|
|
if (lpAddr)
|
2007-04-30 19:05:04 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, lpAddr);
|
|
|
|
|
|
|
|
return ulTime;
|
|
|
|
}
|