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