diff --git a/dll/cpl/timedate/CMakeLists.txt b/dll/cpl/timedate/CMakeLists.txt index d1ad1db070e..5103df0f8dd 100644 --- a/dll/cpl/timedate/CMakeLists.txt +++ b/dll/cpl/timedate/CMakeLists.txt @@ -9,6 +9,7 @@ list(APPEND SOURCE ntpclient.c timedate.c timezone.c + w32time.c timedate.h) file(GLOB timedate_rc_deps resources/*.*) diff --git a/dll/cpl/timedate/dateandtime.c b/dll/cpl/timedate/dateandtime.c index 8470db32bcb..026cd305cfc 100644 --- a/dll/cpl/timedate/dateandtime.c +++ b/dll/cpl/timedate/dateandtime.c @@ -14,8 +14,7 @@ static WNDPROC pOldWndProc = NULL; BOOL -SystemSetTime(LPSYSTEMTIME lpSystemTime, - BOOL SystemTime) +SystemSetLocalTime(LPSYSTEMTIME lpSystemTime) { HANDLE hToken; DWORD PrevSize; @@ -47,19 +46,10 @@ SystemSetTime(LPSYSTEMTIME lpSystemTime, { /* * We successfully enabled it, we're permitted to change the time. - * Check the second parameter for SystemTime and if TRUE set System Time. - * Otherwise, if FALSE set the Local Time. * Call SetLocalTime twice to ensure correct results. */ - if (SystemTime) - { - Ret = SetSystemTime(lpSystemTime); - } - else - { - Ret = SetLocalTime(lpSystemTime) && - SetLocalTime(lpSystemTime); - } + Ret = SetLocalTime(lpSystemTime) && + SetLocalTime(lpSystemTime); /* * For the sake of security, restore the previous status again @@ -96,8 +86,7 @@ SetLocalSystemTime(HWND hwnd) (WPARAM)&Time, 0)) { - /* Set Local Time with SystemTime = FALSE */ - SystemSetTime(&Time, FALSE); + SystemSetLocalTime(&Time); SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, diff --git a/dll/cpl/timedate/internettime.c b/dll/cpl/timedate/internettime.c index 35e724948a4..5a419e40e79 100644 --- a/dll/cpl/timedate/internettime.c +++ b/dll/cpl/timedate/internettime.c @@ -130,140 +130,6 @@ SetNTPServer(HWND hwnd) } -/* 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) { @@ -338,13 +204,8 @@ InetTimePageProc(HWND hwndDlg, { case IDC_UPDATEBUTTON: { - ULONG ulTime; - SetNTPServer(hwndDlg); - - ulTime = GetTimeFromServer(); - if (ulTime != 0) - UpdateSystemTime(ulTime); + SyncTimeNow(); } break; diff --git a/dll/cpl/timedate/timedate.h b/dll/cpl/timedate/timedate.h index dfc54a18c3e..2fdddbd5a06 100644 --- a/dll/cpl/timedate/timedate.h +++ b/dll/cpl/timedate/timedate.h @@ -39,7 +39,7 @@ extern HINSTANCE hApplet; /* dateandtime.c */ INT_PTR CALLBACK DateTimePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -BOOL SystemSetTime(LPSYSTEMTIME lpSystemTime, BOOL SystemTime); +BOOL SystemSetLocalTime(LPSYSTEMTIME lpSystemTime); /* timezone.c */ @@ -94,6 +94,10 @@ typedef struct _NTPPACKET ULONG GetServerTime(LPWSTR lpAddress); +/* w32time.c */ +VOID SyncTimeNow(VOID); + + /* monthcal.c */ #define MCCM_SETDATE (WM_USER + 1) #define MCCM_GETDATE (WM_USER + 2) diff --git a/dll/cpl/timedate/w32time.c b/dll/cpl/timedate/w32time.c new file mode 100644 index 00000000000..a8aed3f4d15 --- /dev/null +++ b/dll/cpl/timedate/w32time.c @@ -0,0 +1,211 @@ +/* + * PROJECT: ReactOS Timedate Control Panel + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Create W32Time Service that reqularly syncs clock to Internet Time + * COPYRIGHT: Copyright 2006 Ged Murphy + */ + +#include "timedate.h" + +/* 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; +} + + +BOOL +SystemSetTime(LPSYSTEMTIME lpSystemTime) +{ + HANDLE hToken; + DWORD PrevSize; + TOKEN_PRIVILEGES priv, previouspriv; + BOOL Ret = FALSE; + + /* + * Enable the SeSystemtimePrivilege privilege + */ + + if (OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken)) + { + priv.PrivilegeCount = 1; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (LookupPrivilegeValueW(NULL, + SE_SYSTEMTIME_NAME, + &priv.Privileges[0].Luid)) + { + if (AdjustTokenPrivileges(hToken, + FALSE, + &priv, + sizeof(previouspriv), + &previouspriv, + &PrevSize) && + GetLastError() == ERROR_SUCCESS) + { + /* + * We successfully enabled it, we're permitted to change the time. + */ + Ret = SetSystemTime(lpSystemTime); + + /* + * For the sake of security, restore the previous status again + */ + if (previouspriv.PrivilegeCount > 0) + { + AdjustTokenPrivileges(hToken, + FALSE, + &previouspriv, + 0, + NULL, + 0); + } + } + } + CloseHandle(hToken); + } + + return Ret; +} + + +/* + * 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; + } + + if (!SystemSetTime(&stNew)) + { + DisplayWin32Error(GetLastError()); + } +} + + +VOID +SyncTimeNow(VOID) +{ + ULONG ulTime; + ulTime = GetTimeFromServer(); + if (ulTime != 0) + UpdateSystemTime(ulTime); +} +