[BROWSEUI]
[reactos.git] / dll / cpl / timedate / ntpclient.c
1 /*
2 * PROJECT: ReactOS Timedate Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/timedate/ntpclient.c
5 * PURPOSE: Queries the NTP server
6 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
7 *
8 */
9
10 #include "timedate.h"
11
12 #include <winsock2.h>
13
14 #define TIMEOUT 4000 /* 4 second timeout */
15
16 typedef struct _INFO
17 {
18 SOCKET Sock;
19 SOCKADDR_IN myAddr;
20 SOCKADDR_IN ntpAddr;
21 NTPPACKET SendPacket;
22 NTPPACKET RecvPacket;
23 } INFO, *PINFO;
24
25
26 static BOOL
27 InitConnection(PINFO pInfo,
28 LPSTR lpAddress)
29 {
30 WSADATA wsaData;
31 HOSTENT *he;
32 INT Ret;
33
34 Ret = WSAStartup(MAKEWORD(2, 2),
35 &wsaData);
36 if (Ret != 0)
37 return FALSE;
38
39 pInfo->Sock = socket(AF_INET,
40 SOCK_DGRAM,
41 0);
42 if (pInfo->Sock == INVALID_SOCKET)
43 return FALSE;
44
45 /* Setup server info */
46 he = gethostbyname(lpAddress);
47 if (he != NULL)
48 {
49 /* Setup server socket info */
50 ZeroMemory(&pInfo->ntpAddr, sizeof(SOCKADDR_IN));
51 pInfo->ntpAddr.sin_family = AF_INET; // he->h_addrtype;
52 pInfo->ntpAddr.sin_port = htons(NTPPORT);
53 pInfo->ntpAddr.sin_addr = *((struct in_addr *)he->h_addr);
54 }
55 else
56 return FALSE;
57
58 return TRUE;
59 }
60
61
62 static VOID
63 DestroyConnection(VOID)
64 {
65 WSACleanup();
66 }
67
68
69 static BOOL
70 GetTransmitTime(PTIMEPACKET ptp)
71 {
72 return TRUE;
73 }
74
75
76 /* Send some data to wake the server up */
77 static BOOL
78 SendData(PINFO pInfo)
79 {
80 TIMEPACKET tp = { 0, 0 };
81 INT Ret;
82
83 ZeroMemory(&pInfo->SendPacket, sizeof(pInfo->SendPacket));
84 pInfo->SendPacket.LiVnMode = 27;
85 if (!GetTransmitTime(&tp))
86 return FALSE;
87 pInfo->SendPacket.TransmitTimestamp = tp;
88
89 Ret = sendto(pInfo->Sock,
90 (char *)&pInfo->SendPacket,
91 sizeof(pInfo->SendPacket),
92 0,
93 (SOCKADDR *)&pInfo->ntpAddr,
94 sizeof(SOCKADDR_IN));
95
96 if (Ret == SOCKET_ERROR)
97 return FALSE;
98
99 return TRUE;
100 }
101
102
103 static ULONG
104 ReceiveData(PINFO pInfo)
105 {
106 TIMEVAL timeVal;
107 FD_SET readFDS;
108 INT Ret;
109 ULONG ulTime = 0;
110
111 /* Monitor socket for incomming connections */
112 FD_ZERO(&readFDS);
113 FD_SET(pInfo->Sock, &readFDS);
114
115 /* Set timeout values */
116 timeVal.tv_sec = TIMEOUT / 1000;
117 timeVal.tv_usec = TIMEOUT % 1000;
118
119 /* Check for data on the socket for TIMEOUT millisecs */
120 Ret = select(0, &readFDS, NULL, NULL, &timeVal);
121
122 if ((Ret != SOCKET_ERROR) && (Ret != 0))
123 {
124
125 Ret = recvfrom(pInfo->Sock,
126 (char *)&pInfo->RecvPacket,
127 sizeof(pInfo->RecvPacket),
128 0,
129 NULL,
130 NULL);
131 if (Ret != SOCKET_ERROR)
132 ulTime = ntohl(ulTime);
133 }
134
135 return ulTime;
136 }
137
138
139 ULONG
140 GetServerTime(LPWSTR lpAddress)
141 {
142 PINFO pInfo;
143 LPSTR lpAddr;
144 DWORD dwSize = wcslen(lpAddress) + 1;
145 ULONG ulTime = 0;
146
147 pInfo = (PINFO)HeapAlloc(GetProcessHeap(),
148 0,
149 sizeof(INFO));
150 lpAddr = (LPSTR)HeapAlloc(GetProcessHeap(),
151 0,
152 dwSize);
153
154 if (pInfo && lpAddr)
155 {
156 if (WideCharToMultiByte(CP_ACP,
157 0,
158 lpAddress,
159 -1,
160 lpAddr,
161 dwSize,
162 NULL,
163 NULL))
164 {
165 if (InitConnection(pInfo, lpAddr))
166 {
167 if (SendData(pInfo))
168 {
169 ulTime = ReceiveData(pInfo);
170 }
171 }
172
173 DestroyConnection();
174 }
175 }
176
177 if (pInfo)
178 HeapFree(GetProcessHeap(), 0, pInfo);
179 if (lpAddr)
180 HeapFree(GetProcessHeap(), 0, lpAddr);
181
182 return ulTime;
183 }