ReactOS 0.4.15-dev-7788-g1ad9096
w32time.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS W32Time Service
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>
6 * Copyright 2018 Doug Lyons
7 */
8
9#include "w32time.h"
10#include <debug.h>
11#include <strsafe.h>
12
16static WCHAR ServiceName[] = L"W32Time";
17
19
20BOOL
22{
23 HANDLE hToken;
24 DWORD PrevSize;
25 TOKEN_PRIVILEGES priv, previouspriv;
26 BOOL Ret = FALSE;
27
28 /*
29 * Enable the SeSystemtimePrivilege privilege
30 */
31
34 &hToken))
35 {
36 priv.PrivilegeCount = 1;
38
41 &priv.Privileges[0].Luid))
42 {
43 if (AdjustTokenPrivileges(hToken,
44 FALSE,
45 &priv,
46 sizeof(previouspriv),
47 &previouspriv,
48 &PrevSize) &&
50 {
51 /*
52 * We successfully enabled it, we're permitted to change the time.
53 */
54 Ret = SetSystemTime(lpSystemTime);
55
56 /*
57 * For the sake of security, restore the previous status again
58 */
59 if (previouspriv.PrivilegeCount > 0)
60 {
62 FALSE,
63 &previouspriv,
64 0,
65 NULL,
66 0);
67 }
68 }
69 }
70 CloseHandle(hToken);
71 }
72
73 return Ret;
74}
75
76
77/*
78 * NTP servers state the number of seconds passed since
79 * 1st Jan, 1900. The time returned from the server
80 * needs adding to that date to get the current Gregorian time
81 */
82static DWORD
84{
85 FILETIME ftNew;
87 SYSTEMTIME stNew;
88
89 /* Time at 1st Jan 1900 */
90 stNew.wYear = 1900;
91 stNew.wMonth = 1;
92 stNew.wDay = 1;
93 stNew.wHour = 0;
94 stNew.wMinute = 0;
95 stNew.wSecond = 0;
96 stNew.wMilliseconds = 0;
97
98 /* Convert to a file time */
99 if (!SystemTimeToFileTime(&stNew, &ftNew))
100 {
101 return GetLastError();
102 }
103
104 /* Add on the time passed since 1st Jan 1900 */
105 li = *(LARGE_INTEGER *)&ftNew;
106 li.QuadPart += (LONGLONG)10000000 * ulTime;
107 ftNew = * (FILETIME *)&li;
108
109 /* Convert back to a system time */
110 if (!FileTimeToSystemTime(&ftNew, &stNew))
111 {
112 return GetLastError();
113 }
114
115 if (!SystemSetTime(&stNew))
116 {
117 return GetLastError();
118 }
119
120 return ERROR_SUCCESS;
121}
122
123
124static DWORD
126{
127 HKEY hKey;
129 DWORD dwSize = sizeof(dwData);
130 LONG lRet;
131
132 dwData = 0;
134 L"SYSTEM\\CurrentControlSet\\Services\\W32Time\\TimeProviders\\NtpClient",
135 0,
137 &hKey);
138 if (lRet == ERROR_SUCCESS)
139 {
140 /*
141 * This key holds the update interval in seconds.
142 * It is useful for testing to set it to a value of 10 (Decimal).
143 * This will cause the clock to try and update every 10 seconds.
144 * So you can change the time and expect it to be set back correctly in 10-20 seconds.
145 */
146 lRet = RegQueryValueExW(hKey,
147 L"SpecialPollInterval",
148 NULL,
149 NULL,
150 (LPBYTE)&dwData,
151 &dwSize);
153 }
154
155 if (lRet != ERROR_SUCCESS || dwData < 120)
156 return 9 * 60 * 60; // 9 hours, because Windows uses 9 hrs, 6 mins and 8 seconds by default.
157 else
158 return dwData;
159}
160
161
162DWORD
164{
165 ULONG ulTime;
166 LONG lRet;
167 HKEY hKey;
168 WCHAR szData[MAX_VALUE_NAME] = L"";
169 DWORD cbName = sizeof(szData);
170
171 DPRINT("Entered SetTime.\n");
172
174 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
175 0,
177 &hKey);
178 if (lRet != ERROR_SUCCESS)
179 {
180 return lRet;
181 }
182
183 lRet = RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)szData, &cbName);
184 if (lRet == ERROR_SUCCESS)
185 {
186 cbName = sizeof(szData);
187 lRet = RegQueryValueExW(hKey, szData, NULL, NULL, (LPBYTE)szData, &cbName);
188 }
189
191
192 DPRINT("Time Server is '%S'.\n", szData);
193
194 /* Is the given string empty? */
195 if (cbName == 0 || szData[0] == '\0')
196 {
197 DPRINT("The time NTP server couldn't be found, the string is empty!\n");
198 return ERROR_INVALID_DATA;
199 }
200
201 ulTime = GetServerTime(szData);
202
203 if (ulTime != 0)
204 {
205 return UpdateSystemTime(ulTime);
206 }
207 else
208 return ERROR_GEN_FAILURE;
209}
210
211
212/* Control handler function */
215{
216 switch (request)
217 {
220 DPRINT("Stopping W32Time Service\n");
221
225
226 if (hStopEvent)
228 return;
229
230 default:
231 break;
232 }
233}
234
235
236VOID
237WINAPI
239{
240 LONG error;
241 DWORD dwInterval;
242 HKEY hKey;
243 WCHAR szData[8];
244 DWORD cbData;
245 BOOL bNoSync;
246
249
257
260 if (!hStatus)
261 {
262 /* Registering Control Handler failed */
263 return;
264 }
265
266 /* Create the stop event */
268 if (hStopEvent == NULL)
269 {
274 return;
275 }
276
277 /* Get the interval */
278 dwInterval = GetIntervalSetting();
279
280 /* We report the running status to SCM. */
283
284 /* The service's worker loop */
285 for (;;)
286 {
287 /* The default is NoSync */
288 bNoSync = TRUE;
289
290 /* TODO: Use RegNotifyChangeKeyValue() when implemented */
292 L"SYSTEM\\CurrentControlSet\\Services\\W32Time\\Parameters",
293 0,
295 &hKey) == ERROR_SUCCESS)
296 {
297 cbData = sizeof(szData);
298 RegQueryValueExW(hKey, L"Type", NULL, NULL, (LPBYTE)szData, &cbData);
299 szData[ARRAYSIZE(szData) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
300 bNoSync = (_wcsicmp(szData, L"NoSync") == 0);
302 }
303
304 if (!bNoSync)
305 {
306 error = SetTime();
307 if (error != ERROR_SUCCESS)
308 {
309 DPRINT("W32Time Service failed to set clock: 0x%08lX\n", error);
310#if 0
311 /*
312 * In general, we do not want to stop this service for a single
313 * Internet read failure but there may be other reasons for which
314 * we really might want to stop it. Therefore this code is left here.
315 */
319 return;
320#endif
321 }
322 }
323
324 if (WaitForSingleObject(hStopEvent, dwInterval * 1000) == WAIT_OBJECT_0)
325 {
328
333 DPRINT("Stopped W32Time Service\n");
334 return;
335 }
336 }
337}
338
339
342 DWORD fdwReason,
344{
345 switch (fdwReason)
346 {
349 break;
350
352 break;
353 }
354
355 return TRUE;
356}
357
358
361 UINT blocking,
362 UINT flags)
363{
365 result = SetTime();
366 if (result)
367 {
368 DPRINT("W32TimeSyncNow failed and clock not set.\n");
369 }
370 else
371 {
372 DPRINT("W32TimeSyncNow succeeded and clock set.\n");
373 }
374 return result;
375}
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
static int argc
Definition: ServiceArgs.c:12
#define MAX_VALUE_NAME
Definition: control.c:28
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3362
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4132
BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpPrivilegeName, PLUID lpLuid)
Definition: misc.c:782
BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength)
Definition: security.c:374
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
#define CloseHandle
Definition: compat.h:739
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define GetCurrentProcess()
Definition: compat.h:759
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
BOOL WINAPI SetSystemTime(IN CONST SYSTEMTIME *lpSystemTime)
Definition: time.c:412
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
LARGE_INTEGER li
Definition: fxtimerapi.cpp:235
GLbitfield flags
Definition: glext.h:7161
GLuint64EXT * result
Definition: glext.h:11304
static IN DWORD IN LPVOID lpvReserved
#define error(str)
Definition: mkdosfs.c:1605
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static HANDLE ULONG_PTR dwData
Definition: file.c:35
#define argv
Definition: mplay32.c:18
unsigned int UINT
Definition: ndis.h:50
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
ULONG GetServerTime(LPWSTR lpAddress)
Definition: ntpclient.c:138
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc)
Definition: sctrl.c:742
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:997
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define DPRINT
Definition: sndvol32.h:71
TCHAR * cmdline
Definition: stretchblt.cpp:32
DWORD dwServiceType
Definition: winsvc.h:99
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwControlsAccepted
Definition: winsvc.h:101
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCurrentState
Definition: winsvc.h:100
DWORD dwCheckPoint
Definition: winsvc.h:104
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
WORD wYear
Definition: winbase.h:905
WORD wMilliseconds
Definition: winbase.h:912
WORD wMonth
Definition: winbase.h:906
WORD wHour
Definition: winbase.h:909
WORD wSecond
Definition: winbase.h:911
WORD wMinute
Definition: winbase.h:910
WORD wDay
Definition: winbase.h:908
$ULONG PrivilegeCount
Definition: setypes.h:1023
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]
Definition: setypes.h:1024
Definition: tftpd.h:86
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
unsigned char * LPBYTE
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
static WCHAR ServiceName[]
Definition: w32time.c:16
DWORD WINAPI W32TimeSyncNow(LPCWSTR cmdline, UINT blocking, UINT flags)
Definition: w32time.c:360
int InitService(VOID)
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Definition: w32time.c:341
SERVICE_STATUS_HANDLE hStatus
Definition: w32time.c:14
static DWORD GetIntervalSetting(VOID)
Definition: w32time.c:125
static DWORD UpdateSystemTime(ULONG ulTime)
Definition: w32time.c:83
HANDLE hStopEvent
Definition: w32time.c:15
VOID WINAPI ControlHandler(DWORD request)
Definition: w32time.c:214
DWORD SetTime(VOID)
Definition: w32time.c:163
VOID WINAPI W32TmServiceMain(DWORD argc, LPWSTR *argv)
Definition: w32time.c:238
SERVICE_STATUS ServiceStatus
Definition: w32time.c:13
BOOL SystemSetTime(LPSYSTEMTIME lpSystemTime)
Definition: w32time.c:21
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define WINAPI
Definition: msvc.h:6
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define SE_SYSTEMTIME_NAME
Definition: winnt_old.h:377
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
#define SERVICE_WIN32
Definition: cmtypes.h:964
#define TOKEN_ADJUST_PRIVILEGES
Definition: setypes.h:930
#define TOKEN_QUERY
Definition: setypes.h:928
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185