2018-06-03 10:33:24 +00:00
|
|
|
/*
|
|
|
|
* 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 <gedmurphy@gmail.com>
|
|
|
|
*/
|
|
|
|
|
2018-06-03 14:28:57 +00:00
|
|
|
#include "w32time.h"
|
2018-06-03 10:33:24 +00:00
|
|
|
|
|
|
|
/* Get the domain name from the registry */
|
2018-06-03 13:35:42 +00:00
|
|
|
static DWORD
|
2018-06-03 10:33:24 +00:00
|
|
|
GetNTPServerAddress(LPWSTR *lpAddress)
|
|
|
|
{
|
|
|
|
HKEY hKey;
|
|
|
|
WCHAR szSel[4];
|
|
|
|
DWORD dwSize;
|
|
|
|
LONG lRet;
|
|
|
|
|
2018-06-03 13:35:42 +00:00
|
|
|
*lpAddress = NULL;
|
|
|
|
hKey = NULL;
|
|
|
|
|
2018-06-03 10:33:24 +00:00
|
|
|
lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
|
|
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
|
|
|
|
0,
|
|
|
|
KEY_QUERY_VALUE,
|
|
|
|
&hKey);
|
|
|
|
if (lRet != ERROR_SUCCESS)
|
2018-06-03 13:35:42 +00:00
|
|
|
goto Exit;
|
2018-06-03 10:33:24 +00:00
|
|
|
|
|
|
|
/* Get data from default value */
|
|
|
|
dwSize = 4 * sizeof(WCHAR);
|
|
|
|
lRet = RegQueryValueExW(hKey,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szSel,
|
|
|
|
&dwSize);
|
|
|
|
if (lRet != ERROR_SUCCESS)
|
2018-06-03 13:35:42 +00:00
|
|
|
goto Exit;
|
2018-06-03 10:33:24 +00:00
|
|
|
|
|
|
|
dwSize = 0;
|
|
|
|
lRet = RegQueryValueExW(hKey,
|
|
|
|
szSel,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&dwSize);
|
|
|
|
if (lRet != ERROR_SUCCESS)
|
2018-06-03 13:35:42 +00:00
|
|
|
goto Exit;
|
2018-06-03 10:33:24 +00:00
|
|
|
|
|
|
|
(*lpAddress) = (LPWSTR)HeapAlloc(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
dwSize);
|
|
|
|
if ((*lpAddress) == NULL)
|
|
|
|
{
|
|
|
|
lRet = ERROR_NOT_ENOUGH_MEMORY;
|
2018-06-03 13:35:42 +00:00
|
|
|
goto Exit;
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lRet = RegQueryValueExW(hKey,
|
|
|
|
szSel,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)*lpAddress,
|
|
|
|
&dwSize);
|
|
|
|
if (lRet != ERROR_SUCCESS)
|
2018-06-03 13:35:42 +00:00
|
|
|
goto Exit;
|
2018-06-03 10:33:24 +00:00
|
|
|
|
2018-06-03 13:35:42 +00:00
|
|
|
Exit:
|
2018-06-03 10:33:24 +00:00
|
|
|
if (hKey)
|
|
|
|
RegCloseKey(hKey);
|
2018-06-03 13:35:42 +00:00
|
|
|
if (lRet != ERROR_SUCCESS)
|
|
|
|
HeapFree(GetProcessHeap(), 0, *lpAddress);
|
|
|
|
|
|
|
|
return lRet;
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Request the time from the current NTP server */
|
2018-06-03 13:35:42 +00:00
|
|
|
static DWORD
|
|
|
|
GetTimeFromServer(PULONG pulTime)
|
2018-06-03 10:33:24 +00:00
|
|
|
{
|
2018-06-03 13:35:42 +00:00
|
|
|
LPWSTR lpAddress;
|
|
|
|
DWORD dwError;
|
2018-06-03 10:33:24 +00:00
|
|
|
|
2018-06-03 13:35:42 +00:00
|
|
|
dwError = GetNTPServerAddress(&lpAddress);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
2018-06-03 10:33:24 +00:00
|
|
|
{
|
2018-06-03 13:35:42 +00:00
|
|
|
return dwError;
|
|
|
|
}
|
2018-06-03 10:33:24 +00:00
|
|
|
|
2018-06-03 13:35:42 +00:00
|
|
|
*pulTime = GetServerTime(lpAddress);
|
|
|
|
if (*pulTime == 0)
|
|
|
|
{
|
|
|
|
dwError = ERROR_GEN_FAILURE;
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|
2018-06-03 13:35:42 +00:00
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
lpAddress);
|
|
|
|
|
|
|
|
return dwError;
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
2018-06-03 13:35:42 +00:00
|
|
|
static DWORD
|
2018-06-03 10:33:24 +00:00
|
|
|
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))
|
|
|
|
{
|
2018-06-03 13:35:42 +00:00
|
|
|
return GetLastError();
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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))
|
|
|
|
{
|
2018-06-03 13:35:42 +00:00
|
|
|
return GetLastError();
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!SystemSetTime(&stNew))
|
|
|
|
{
|
2018-06-03 13:35:42 +00:00
|
|
|
return GetLastError();
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
2018-06-03 13:35:42 +00:00
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-03 14:28:57 +00:00
|
|
|
DWORD WINAPI
|
|
|
|
W32TimeSyncNow(LPCWSTR cmdline,
|
|
|
|
UINT blocking,
|
|
|
|
UINT flags)
|
2018-06-03 10:33:24 +00:00
|
|
|
{
|
2018-06-03 13:35:42 +00:00
|
|
|
DWORD dwError;
|
2018-06-03 10:33:24 +00:00
|
|
|
ULONG ulTime;
|
2018-06-03 14:28:57 +00:00
|
|
|
|
2018-06-03 13:35:42 +00:00
|
|
|
dwError = GetTimeFromServer(&ulTime);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
2018-06-03 10:33:24 +00:00
|
|
|
if (ulTime != 0)
|
2018-06-03 13:35:42 +00:00
|
|
|
{
|
|
|
|
dwError = UpdateSystemTime(ulTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
return dwError;
|
2018-06-03 10:33:24 +00:00
|
|
|
}
|
|
|
|
|