[BROWSEUI]
[reactos.git] / dll / cpl / timedate / internettime.c
1 /*
2 * PROJECT: ReactOS Timedate Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/timedate/internettime.c
5 * PURPOSE: Internet Time property page
6 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
7 *
8 */
9
10 #include "timedate.h"
11
12 static VOID
13 CreateNTPServerList(HWND hwnd)
14 {
15 HWND hList;
16 WCHAR szValName[MAX_VALUE_NAME];
17 WCHAR szData[256];
18 DWORD dwIndex = 0;
19 DWORD dwValSize;
20 DWORD dwNameSize;
21 DWORD dwDefault = 1;
22 LONG lRet;
23 HKEY hKey;
24
25 hList = GetDlgItem(hwnd,
26 IDC_SERVERLIST);
27
28 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
29 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
30 0,
31 KEY_QUERY_VALUE,
32 &hKey);
33 if (lRet != ERROR_SUCCESS)
34 return;
35
36 while (TRUE)
37 {
38 dwValSize = MAX_VALUE_NAME * sizeof(WCHAR);
39 szValName[0] = L'\0';
40 lRet = RegEnumValueW(hKey,
41 dwIndex,
42 szValName,
43 &dwValSize,
44 NULL,
45 NULL,
46 (LPBYTE)szData,
47 &dwNameSize);
48 if (lRet == ERROR_SUCCESS)
49 {
50 /* Get date from default reg value */
51 if (wcscmp(szValName, L"") == 0) // if (Index == 0)
52 {
53 dwDefault = _wtoi(szData);
54 dwIndex++;
55 }
56 else
57 {
58 SendMessageW(hList,
59 CB_ADDSTRING,
60 0,
61 (LPARAM)szData);
62 dwIndex++;
63 }
64 }
65 else if (lRet != ERROR_MORE_DATA)
66 {
67 break;
68 }
69 }
70
71 if (dwDefault < 1 || dwDefault > dwIndex)
72 dwDefault = 1;
73
74 /* Server reg entries count from 1,
75 * Combo boxes count from 0 */
76 dwDefault--;
77
78 SendMessageW(hList,
79 CB_SETCURSEL,
80 dwDefault,
81 0);
82
83 RegCloseKey(hKey);
84 }
85
86
87 /* Set the selected server in the registry */
88 static VOID
89 SetNTPServer(HWND hwnd)
90 {
91 HKEY hKey;
92 HWND hList;
93 UINT uSel;
94 WCHAR szSel[4];
95 LONG lRet;
96
97 hList = GetDlgItem(hwnd,
98 IDC_SERVERLIST);
99
100 uSel = (UINT)SendMessageW(hList, CB_GETCURSEL, 0, 0);
101
102 /* Server reg entries count from 1,
103 * Combo boxes count from 0 */
104 uSel++;
105
106 /* Convert to wide char */
107 _itow(uSel, szSel, 10);
108
109 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
110 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
111 0,
112 KEY_SET_VALUE,
113 &hKey);
114 if (lRet != ERROR_SUCCESS)
115 {
116 DisplayWin32Error(lRet);
117 return;
118 }
119
120 lRet = RegSetValueExW(hKey,
121 L"",
122 0,
123 REG_SZ,
124 (LPBYTE)szSel,
125 (wcslen(szSel) + 1) * sizeof(WCHAR));
126 if (lRet != ERROR_SUCCESS)
127 DisplayWin32Error(lRet);
128
129 RegCloseKey(hKey);
130 }
131
132
133 /* Get the domain name from the registry */
134 static BOOL
135 GetNTPServerAddress(LPWSTR *lpAddress)
136 {
137 HKEY hKey;
138 WCHAR szSel[4];
139 DWORD dwSize;
140 LONG lRet;
141
142 lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
143 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
144 0,
145 KEY_QUERY_VALUE,
146 &hKey);
147 if (lRet != ERROR_SUCCESS)
148 goto fail;
149
150 /* Get data from default value */
151 dwSize = 4 * sizeof(WCHAR);
152 lRet = RegQueryValueExW(hKey,
153 NULL,
154 NULL,
155 NULL,
156 (LPBYTE)szSel,
157 &dwSize);
158 if (lRet != ERROR_SUCCESS)
159 goto fail;
160
161 dwSize = 0;
162 lRet = RegQueryValueExW(hKey,
163 szSel,
164 NULL,
165 NULL,
166 NULL,
167 &dwSize);
168 if (lRet != ERROR_SUCCESS)
169 goto fail;
170
171 (*lpAddress) = (LPWSTR)HeapAlloc(GetProcessHeap(),
172 0,
173 dwSize);
174 if ((*lpAddress) == NULL)
175 {
176 lRet = ERROR_NOT_ENOUGH_MEMORY;
177 goto fail;
178 }
179
180 lRet = RegQueryValueExW(hKey,
181 szSel,
182 NULL,
183 NULL,
184 (LPBYTE)*lpAddress,
185 &dwSize);
186 if (lRet != ERROR_SUCCESS)
187 goto fail;
188
189 RegCloseKey(hKey);
190
191 return TRUE;
192
193 fail:
194 DisplayWin32Error(lRet);
195 if (hKey)
196 RegCloseKey(hKey);
197 HeapFree(GetProcessHeap(), 0, *lpAddress);
198 return FALSE;
199 }
200
201
202 /* Request the time from the current NTP server */
203 static ULONG
204 GetTimeFromServer(VOID)
205 {
206 LPWSTR lpAddress = NULL;
207 ULONG ulTime = 0;
208
209 if (GetNTPServerAddress(&lpAddress))
210 {
211 ulTime = GetServerTime(lpAddress);
212
213 HeapFree(GetProcessHeap(),
214 0,
215 lpAddress);
216 }
217
218 return ulTime;
219 }
220
221 /*
222 * NTP servers state the number of seconds passed since
223 * 1st Jan, 1900. The time returned from the server
224 * needs adding to that date to get the current Gregorian time
225 */
226 static VOID
227 UpdateSystemTime(ULONG ulTime)
228 {
229 FILETIME ftNew;
230 LARGE_INTEGER li;
231 SYSTEMTIME stNew;
232
233 /* Time at 1st Jan 1900 */
234 stNew.wYear = 1900;
235 stNew.wMonth = 1;
236 stNew.wDay = 1;
237 stNew.wHour = 0;
238 stNew.wMinute = 0;
239 stNew.wSecond = 0;
240 stNew.wMilliseconds = 0;
241
242 /* Convert to a file time */
243 if (!SystemTimeToFileTime(&stNew, &ftNew))
244 {
245 DisplayWin32Error(GetLastError());
246 return;
247 }
248
249 /* Add on the time passed since 1st Jan 1900 */
250 li = *(LARGE_INTEGER *)&ftNew;
251 li.QuadPart += (LONGLONG)10000000 * ulTime;
252 ftNew = * (FILETIME *)&li;
253
254 /* Convert back to a system time */
255 if (!FileTimeToSystemTime(&ftNew, &stNew))
256 {
257 DisplayWin32Error(GetLastError());
258 return;
259 }
260
261 if (!SystemSetLocalTime(&stNew))
262 DisplayWin32Error(GetLastError());
263 }
264
265
266 static VOID
267 EnableDialogText(HWND hwnd)
268 {
269 BOOL bChecked;
270 UINT uCheck;
271
272 uCheck = (UINT)SendDlgItemMessageW(hwnd, IDC_AUTOSYNC, BM_GETCHECK, 0, 0);
273 bChecked = (uCheck == BST_CHECKED) ? TRUE : FALSE;
274
275 EnableWindow(GetDlgItem(hwnd, IDC_SERVERTEXT), bChecked);
276 EnableWindow(GetDlgItem(hwnd, IDC_SERVERLIST), bChecked);
277 EnableWindow(GetDlgItem(hwnd, IDC_UPDATEBUTTON), bChecked);
278 EnableWindow(GetDlgItem(hwnd, IDC_SUCSYNC), bChecked);
279 EnableWindow(GetDlgItem(hwnd, IDC_NEXTSYNC), bChecked);
280 }
281
282
283 static VOID
284 GetSyncSetting(HWND hwnd)
285 {
286 HKEY hKey;
287 WCHAR szData[8];
288 DWORD dwSize;
289
290 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
291 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Parameters",
292 0,
293 KEY_QUERY_VALUE,
294 &hKey) == ERROR_SUCCESS)
295 {
296 dwSize = 8 * sizeof(WCHAR);
297 if (RegQueryValueExW(hKey,
298 L"Type",
299 NULL,
300 NULL,
301 (LPBYTE)szData,
302 &dwSize) == ERROR_SUCCESS)
303 {
304 if (wcscmp(szData, L"NTP") == 0)
305 SendDlgItemMessageW(hwnd, IDC_AUTOSYNC, BM_SETCHECK, 0, 0);
306 }
307
308 RegCloseKey(hKey);
309 }
310 }
311
312
313 static VOID
314 OnInitDialog(HWND hwnd)
315 {
316 GetSyncSetting(hwnd);
317 EnableDialogText(hwnd);
318 CreateNTPServerList(hwnd);
319 }
320
321
322 /* Property page dialog callback */
323 INT_PTR CALLBACK
324 InetTimePageProc(HWND hwndDlg,
325 UINT uMsg,
326 WPARAM wParam,
327 LPARAM lParam)
328 {
329 switch (uMsg)
330 {
331 case WM_INITDIALOG:
332 OnInitDialog(hwndDlg);
333 break;
334
335 case WM_COMMAND:
336 switch(LOWORD(wParam))
337 {
338 case IDC_UPDATEBUTTON:
339 {
340 ULONG ulTime;
341
342 SetNTPServer(hwndDlg);
343
344 ulTime = GetTimeFromServer();
345 if (ulTime != 0)
346 UpdateSystemTime(ulTime);
347 }
348 break;
349
350 case IDC_SERVERLIST:
351 if (HIWORD(wParam) == CBN_SELCHANGE)
352 {
353 /* Enable the 'Apply' button */
354 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
355 }
356 break;
357
358 case IDC_AUTOSYNC:
359 if (HIWORD(wParam) == BN_CLICKED)
360 {
361 EnableDialogText(hwndDlg);
362
363 /* Enable the 'Apply' button */
364 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
365 }
366 break;
367 }
368 break;
369
370 case WM_DESTROY:
371 break;
372
373 case WM_NOTIFY:
374 {
375 LPNMHDR lpnm = (LPNMHDR)lParam;
376
377 switch (lpnm->code)
378 {
379 case PSN_APPLY:
380 SetNTPServer(hwndDlg);
381 return TRUE;
382
383 default:
384 break;
385 }
386 }
387 break;
388 }
389
390 return FALSE;
391 }