xref: /reactos/dll/cpl/timedate/internettime.c (revision 595b846d)
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     /* Use SystemSetTime with SystemTime = TRUE to set System Time */
262     if (!SystemSetTime(&stNew, TRUE))
263          DisplayWin32Error(GetLastError());
264 }
265 
266 
267 static VOID
268 EnableDialogText(HWND hwnd)
269 {
270     BOOL bChecked;
271     UINT uCheck;
272 
273     uCheck = (UINT)SendDlgItemMessageW(hwnd, IDC_AUTOSYNC, BM_GETCHECK, 0, 0);
274     bChecked = (uCheck == BST_CHECKED) ? TRUE : FALSE;
275 
276     EnableWindow(GetDlgItem(hwnd, IDC_SERVERTEXT), bChecked);
277     EnableWindow(GetDlgItem(hwnd, IDC_SERVERLIST), bChecked);
278     EnableWindow(GetDlgItem(hwnd, IDC_UPDATEBUTTON), bChecked);
279     EnableWindow(GetDlgItem(hwnd, IDC_SUCSYNC), bChecked);
280     EnableWindow(GetDlgItem(hwnd, IDC_NEXTSYNC), bChecked);
281 }
282 
283 
284 static VOID
285 GetSyncSetting(HWND hwnd)
286 {
287     HKEY hKey;
288     WCHAR szData[8];
289     DWORD dwSize;
290 
291     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
292                       L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Parameters",
293                       0,
294                       KEY_QUERY_VALUE,
295                       &hKey) == ERROR_SUCCESS)
296     {
297         dwSize = 8 * sizeof(WCHAR);
298         if (RegQueryValueExW(hKey,
299                              L"Type",
300                              NULL,
301                              NULL,
302                              (LPBYTE)szData,
303                              &dwSize) == ERROR_SUCCESS)
304         {
305             if (wcscmp(szData, L"NTP") == 0)
306                 SendDlgItemMessageW(hwnd, IDC_AUTOSYNC, BM_SETCHECK, 0, 0);
307         }
308 
309         RegCloseKey(hKey);
310     }
311 }
312 
313 
314 static VOID
315 OnInitDialog(HWND hwnd)
316 {
317     GetSyncSetting(hwnd);
318     EnableDialogText(hwnd);
319     CreateNTPServerList(hwnd);
320 }
321 
322 
323 /* Property page dialog callback */
324 INT_PTR CALLBACK
325 InetTimePageProc(HWND hwndDlg,
326                  UINT uMsg,
327                  WPARAM wParam,
328                  LPARAM lParam)
329 {
330     switch (uMsg)
331     {
332         case WM_INITDIALOG:
333             OnInitDialog(hwndDlg);
334             break;
335 
336         case WM_COMMAND:
337             switch(LOWORD(wParam))
338             {
339                 case IDC_UPDATEBUTTON:
340                 {
341                     ULONG ulTime;
342 
343                     SetNTPServer(hwndDlg);
344 
345                     ulTime = GetTimeFromServer();
346                     if (ulTime != 0)
347                         UpdateSystemTime(ulTime);
348                 }
349                 break;
350 
351                 case IDC_SERVERLIST:
352                     if (HIWORD(wParam) == CBN_SELCHANGE)
353                     {
354                         /* Enable the 'Apply' button */
355                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
356                     }
357                     break;
358 
359                 case IDC_AUTOSYNC:
360                     if (HIWORD(wParam) == BN_CLICKED)
361                     {
362                         EnableDialogText(hwndDlg);
363 
364                         /* Enable the 'Apply' button */
365                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
366                     }
367                     break;
368             }
369             break;
370 
371         case WM_DESTROY:
372             break;
373 
374         case WM_NOTIFY:
375         {
376             LPNMHDR lpnm = (LPNMHDR)lParam;
377 
378             switch (lpnm->code)
379             {
380                 case PSN_APPLY:
381                     SetNTPServer(hwndDlg);
382                     return TRUE;
383 
384                 default:
385                     break;
386             }
387         }
388         break;
389     }
390 
391     return FALSE;
392 }
393