/* * PROJECT: ReactOS Timedate Control Panel * LICENSE: GPL - See COPYING in the top level directory * FILE: dll/cpl/timedate/internettime.c * PURPOSE: Internet Time property page * COPYRIGHT: Copyright 2006 Ged Murphy * */ #include "timedate.h" static VOID CreateNTPServerList(HWND hwnd) { HWND hList; WCHAR szValName[MAX_VALUE_NAME]; WCHAR szData[256]; DWORD dwIndex = 0; DWORD dwValSize; DWORD dwNameSize; DWORD dwDefault = 1; LONG lRet; HKEY hKey; hList = GetDlgItem(hwnd, IDC_SERVERLIST); lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers", 0, KEY_QUERY_VALUE, &hKey); if (lRet != ERROR_SUCCESS) return; while (TRUE) { dwValSize = MAX_VALUE_NAME * sizeof(WCHAR); szValName[0] = L'\0'; lRet = RegEnumValueW(hKey, dwIndex, szValName, &dwValSize, NULL, NULL, (LPBYTE)szData, &dwNameSize); if (lRet == ERROR_SUCCESS) { /* Get date from default reg value */ if (wcscmp(szValName, L"") == 0) // if (Index == 0) { dwDefault = _wtoi(szData); dwIndex++; } else { SendMessageW(hList, CB_ADDSTRING, 0, (LPARAM)szData); dwIndex++; } } else if (lRet != ERROR_MORE_DATA) { break; } } if (dwDefault < 1 || dwDefault > dwIndex) dwDefault = 1; /* Server reg entries count from 1, * Combo boxes count from 0 */ dwDefault--; SendMessageW(hList, CB_SETCURSEL, dwDefault, 0); RegCloseKey(hKey); } /* Set the selected server in the registry */ static VOID SetNTPServer(HWND hwnd) { HKEY hKey; HWND hList; UINT uSel; WCHAR szSel[4]; LONG lRet; hList = GetDlgItem(hwnd, IDC_SERVERLIST); uSel = (UINT)SendMessageW(hList, CB_GETCURSEL, 0, 0); /* Server reg entries count from 1, * Combo boxes count from 0 */ uSel++; /* Convert to wide char */ _itow(uSel, szSel, 10); lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers", 0, KEY_SET_VALUE, &hKey); if (lRet != ERROR_SUCCESS) { DisplayWin32Error(lRet); return; } lRet = RegSetValueExW(hKey, L"", 0, REG_SZ, (LPBYTE)szSel, (wcslen(szSel) + 1) * sizeof(WCHAR)); if (lRet != ERROR_SUCCESS) DisplayWin32Error(lRet); RegCloseKey(hKey); } /* Get the domain name from the registry */ static BOOL GetNTPServerAddress(LPWSTR *lpAddress) { HKEY hKey; WCHAR szSel[4]; DWORD dwSize; LONG lRet; lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers", 0, KEY_QUERY_VALUE, &hKey); if (lRet != ERROR_SUCCESS) goto fail; /* Get data from default value */ dwSize = 4 * sizeof(WCHAR); lRet = RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)szSel, &dwSize); if (lRet != ERROR_SUCCESS) goto fail; dwSize = 0; lRet = RegQueryValueExW(hKey, szSel, NULL, NULL, NULL, &dwSize); if (lRet != ERROR_SUCCESS) goto fail; (*lpAddress) = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwSize); if ((*lpAddress) == NULL) { lRet = ERROR_NOT_ENOUGH_MEMORY; goto fail; } lRet = RegQueryValueExW(hKey, szSel, NULL, NULL, (LPBYTE)*lpAddress, &dwSize); if (lRet != ERROR_SUCCESS) goto fail; RegCloseKey(hKey); return TRUE; fail: DisplayWin32Error(lRet); if (hKey) RegCloseKey(hKey); HeapFree(GetProcessHeap(), 0, *lpAddress); return FALSE; } /* Request the time from the current NTP server */ static ULONG GetTimeFromServer(VOID) { LPWSTR lpAddress = NULL; ULONG ulTime = 0; if (GetNTPServerAddress(&lpAddress)) { ulTime = GetServerTime(lpAddress); HeapFree(GetProcessHeap(), 0, lpAddress); } return ulTime; } /* * NTP servers state the number of seconds passed since * 1st Jan, 1900. The time returned from the server * needs adding to that date to get the current Gregorian time */ static VOID UpdateSystemTime(ULONG ulTime) { FILETIME ftNew; LARGE_INTEGER li; SYSTEMTIME stNew; /* Time at 1st Jan 1900 */ stNew.wYear = 1900; stNew.wMonth = 1; stNew.wDay = 1; stNew.wHour = 0; stNew.wMinute = 0; stNew.wSecond = 0; stNew.wMilliseconds = 0; /* Convert to a file time */ if (!SystemTimeToFileTime(&stNew, &ftNew)) { DisplayWin32Error(GetLastError()); return; } /* Add on the time passed since 1st Jan 1900 */ li = *(LARGE_INTEGER *)&ftNew; li.QuadPart += (LONGLONG)10000000 * ulTime; ftNew = * (FILETIME *)&li; /* Convert back to a system time */ if (!FileTimeToSystemTime(&ftNew, &stNew)) { DisplayWin32Error(GetLastError()); return; } /* Use SystemSetTime with SystemTime = TRUE to set System Time */ if (!SystemSetTime(&stNew, TRUE)) DisplayWin32Error(GetLastError()); } static VOID EnableDialogText(HWND hwnd) { BOOL bChecked; UINT uCheck; uCheck = (UINT)SendDlgItemMessageW(hwnd, IDC_AUTOSYNC, BM_GETCHECK, 0, 0); bChecked = (uCheck == BST_CHECKED) ? TRUE : FALSE; EnableWindow(GetDlgItem(hwnd, IDC_SERVERTEXT), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_SERVERLIST), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_UPDATEBUTTON), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_SUCSYNC), bChecked); EnableWindow(GetDlgItem(hwnd, IDC_NEXTSYNC), bChecked); } static VOID GetSyncSetting(HWND hwnd) { HKEY hKey; WCHAR szData[8]; DWORD dwSize; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Parameters", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { dwSize = 8 * sizeof(WCHAR); if (RegQueryValueExW(hKey, L"Type", NULL, NULL, (LPBYTE)szData, &dwSize) == ERROR_SUCCESS) { if (wcscmp(szData, L"NTP") == 0) SendDlgItemMessageW(hwnd, IDC_AUTOSYNC, BM_SETCHECK, 0, 0); } RegCloseKey(hKey); } } static VOID OnInitDialog(HWND hwnd) { GetSyncSetting(hwnd); EnableDialogText(hwnd); CreateNTPServerList(hwnd); } /* Property page dialog callback */ INT_PTR CALLBACK InetTimePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: OnInitDialog(hwndDlg); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_UPDATEBUTTON: { ULONG ulTime; SetNTPServer(hwndDlg); ulTime = GetTimeFromServer(); if (ulTime != 0) UpdateSystemTime(ulTime); } break; case IDC_SERVERLIST: if (HIWORD(wParam) == CBN_SELCHANGE) { /* Enable the 'Apply' button */ PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; case IDC_AUTOSYNC: if (HIWORD(wParam) == BN_CLICKED) { EnableDialogText(hwndDlg); /* Enable the 'Apply' button */ PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; } break; case WM_DESTROY: break; case WM_NOTIFY: { LPNMHDR lpnm = (LPNMHDR)lParam; switch (lpnm->code) { case PSN_APPLY: SetNTPServer(hwndDlg); return TRUE; default: break; } } break; } return FALSE; }