2 * PROJECT: ReactOS Timedate Control Panel
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Create W32Time Service that reqularly syncs clock to Internet Time
5 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
10 /* Get the domain name from the registry */
12 GetNTPServerAddress(LPWSTR
*lpAddress
)
22 lRet
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
23 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
27 if (lRet
!= ERROR_SUCCESS
)
30 /* Get data from default value */
31 dwSize
= 4 * sizeof(WCHAR
);
32 lRet
= RegQueryValueExW(hKey
,
38 if (lRet
!= ERROR_SUCCESS
)
42 lRet
= RegQueryValueExW(hKey
,
48 if (lRet
!= ERROR_SUCCESS
)
51 (*lpAddress
) = (LPWSTR
)HeapAlloc(GetProcessHeap(),
54 if ((*lpAddress
) == NULL
)
56 lRet
= ERROR_NOT_ENOUGH_MEMORY
;
60 lRet
= RegQueryValueExW(hKey
,
66 if (lRet
!= ERROR_SUCCESS
)
72 if (lRet
!= ERROR_SUCCESS
)
73 HeapFree(GetProcessHeap(), 0, *lpAddress
);
79 /* Request the time from the current NTP server */
81 GetTimeFromServer(PULONG pulTime
)
86 dwError
= GetNTPServerAddress(&lpAddress
);
87 if (dwError
!= ERROR_SUCCESS
)
92 *pulTime
= GetServerTime(lpAddress
);
95 dwError
= ERROR_GEN_FAILURE
;
98 HeapFree(GetProcessHeap(),
107 SystemSetTime(LPSYSTEMTIME lpSystemTime
)
111 TOKEN_PRIVILEGES priv
, previouspriv
;
115 * Enable the SeSystemtimePrivilege privilege
118 if (OpenProcessToken(GetCurrentProcess(),
119 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
122 priv
.PrivilegeCount
= 1;
123 priv
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
125 if (LookupPrivilegeValueW(NULL
,
127 &priv
.Privileges
[0].Luid
))
129 if (AdjustTokenPrivileges(hToken
,
132 sizeof(previouspriv
),
135 GetLastError() == ERROR_SUCCESS
)
138 * We successfully enabled it, we're permitted to change the time.
140 Ret
= SetSystemTime(lpSystemTime
);
143 * For the sake of security, restore the previous status again
145 if (previouspriv
.PrivilegeCount
> 0)
147 AdjustTokenPrivileges(hToken
,
164 * NTP servers state the number of seconds passed since
165 * 1st Jan, 1900. The time returned from the server
166 * needs adding to that date to get the current Gregorian time
169 UpdateSystemTime(ULONG ulTime
)
175 /* Time at 1st Jan 1900 */
182 stNew
.wMilliseconds
= 0;
184 /* Convert to a file time */
185 if (!SystemTimeToFileTime(&stNew
, &ftNew
))
187 return GetLastError();
190 /* Add on the time passed since 1st Jan 1900 */
191 li
= *(LARGE_INTEGER
*)&ftNew
;
192 li
.QuadPart
+= (LONGLONG
)10000000 * ulTime
;
193 ftNew
= * (FILETIME
*)&li
;
195 /* Convert back to a system time */
196 if (!FileTimeToSystemTime(&ftNew
, &stNew
))
198 return GetLastError();
201 if (!SystemSetTime(&stNew
))
203 return GetLastError();
206 return ERROR_SUCCESS
;
211 W32TimeSyncNow(LPCWSTR cmdline
,
218 dwError
= GetTimeFromServer(&ulTime
);
219 if (dwError
!= ERROR_SUCCESS
)
226 dwError
= UpdateSystemTime(ulTime
);