ReactOS  0.4.15-dev-1200-gc3b3fcd
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 
16 static WCHAR ServiceName[] = L"W32Time";
17 
18 int InitService(VOID);
19 
20 BOOL
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  {
61  AdjustTokenPrivileges(hToken,
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  */
82 static DWORD
84 {
85  FILETIME ftNew;
86  LARGE_INTEGER li;
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 
124 static DWORD
126 {
127  HKEY hKey;
128  DWORD dwData;
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);
152  RegCloseKey(hKey);
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 
162 DWORD
164 {
165  ULONG ulTime;
166  LONG lRet;
167  HKEY hKey;
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 
190  RegCloseKey(hKey);
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 */
213 VOID WINAPI
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  return;
235 }
236 
237 
238 VOID
239 WINAPI
241 {
242  int result;
243  DWORD dwInterval;
244 
247 
255 
258  if (!hStatus)
259  {
260  /* Registering Control Handler failed */
261  return;
262  }
263 
264  /* Create the stop event */
266  if (hStopEvent == NULL)
267  {
272  return;
273  }
274 
275  /* Get the interval */
276  dwInterval = GetIntervalSetting();
277 
278  /* We report the running status to SCM. */
281 
282  /* The worker loop of a service */
283  for (;;)
284  {
285  result = SetTime();
286 
287  if (result)
288  DPRINT("W32Time Service failed to set clock.\n");
289  else
290  DPRINT("W32Time Service successfully set clock.\n");
291 
292  if (result)
293  {
294  /* In general we do not want to stop this service for a single
295  * Internet read failure but there may be other reasons for which
296  * we really might want to stop it.
297  * Therefore this code is left here to make it easy to stop this
298  * service when the correct conditions can be determined, but it
299  * is left commented out.
300  ServiceStatus.dwCurrentState = SERVICE_STOPPED;
301  ServiceStatus.dwWin32ExitCode = result;
302  SetServiceStatus(hStatus, &ServiceStatus);
303  return;
304  */
305  }
306 
307  if (WaitForSingleObject(hStopEvent, dwInterval * 1000) == WAIT_OBJECT_0)
308  {
310  hStopEvent = NULL;
311 
316  DPRINT("Stopped W32Time Service\n");
317  return;
318  }
319  }
320  return;
321 }
322 
323 
324 
325 BOOL WINAPI
327  DWORD fdwReason,
329 {
330  switch (fdwReason)
331  {
332  case DLL_PROCESS_ATTACH:
333  DisableThreadLibraryCalls(hinstDLL);
334  break;
335 
336  case DLL_PROCESS_DETACH:
337  break;
338  }
339 
340  return TRUE;
341 }
342 
343 
346  UINT blocking,
347  UINT flags)
348 {
349  DWORD result;
350  result = SetTime();
351  if (result)
352  {
353  DPRINT("W32TimeSyncNow failed and clock not set.\n");
354  }
355  else
356  {
357  DPRINT("W32TimeSyncNow succeeded and clock set.\n");
358  }
359  return result;
360 }
static int argc
Definition: ServiceArgs.c:12
#define CloseHandle
Definition: compat.h:598
BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpPrivilegeName, PLUID lpLuid)
Definition: misc.c:782
#define ERROR_SUCCESS
Definition: deptool.c:10
DWORD dwCurrentState
Definition: winsvc.h:100
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
WORD wMonth
Definition: winbase.h:884
VOID WINAPI W32TmServiceMain(DWORD argc, LPWSTR *argv)
Definition: w32time.c:240
BOOL WINAPI SetSystemTime(IN CONST SYSTEMTIME *lpSystemTime)
Definition: time.c:412
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
static const WCHAR szData[]
Definition: msipriv.h:1195
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
$ULONG PrivilegeCount
Definition: setypes.h:969
static HANDLE ULONG_PTR dwData
Definition: file.c:35
SERVICE_STATUS ServiceStatus
Definition: w32time.c:13
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
#define SERVICE_START_PENDING
Definition: winsvc.h:22
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc)
Definition: sctrl.c:740
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Definition: w32time.c:326
TCHAR * cmdline
Definition: stretchblt.cpp:32
DWORD SetTime(VOID)
Definition: w32time.c:163
#define argv
Definition: mplay32.c:18
static IN DWORD IN LPVOID lpvReserved
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 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:995
SERVICE_STATUS_HANDLE hStatus
Definition: w32time.c:14
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
WORD wYear
Definition: winbase.h:883
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
DWORD dwCheckPoint
Definition: winsvc.h:104
DWORD WINAPI W32TimeSyncNow(LPCWSTR cmdline, UINT blocking, UINT flags)
Definition: w32time.c:345
#define SERVICE_STOPPED
Definition: winsvc.h:21
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static WCHAR ServiceName[]
Definition: w32time.c:16
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SE_SYSTEMTIME_NAME
Definition: winnt_old.h:376
HANDLE hStopEvent
Definition: w32time.c:15
WORD wMinute
Definition: winbase.h:888
VOID WINAPI ControlHandler(DWORD request)
Definition: w32time.c:214
smooth NULL
Definition: ftsmooth.c:416
#define MAX_VALUE_NAME
Definition: control.c:23
void DPRINT(...)
Definition: polytest.cpp:61
static DWORD UpdateSystemTime(ULONG ulTime)
Definition: w32time.c:83
#define DLL_PROCESS_DETACH
Definition: compat.h:130
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
int64_t LONGLONG
Definition: typedefs.h:68
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
#define WAIT_OBJECT_0
Definition: winbase.h:387
#define TOKEN_QUERY
Definition: setypes.h:874
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
__wchar_t WCHAR
Definition: xmlstorage.h:180
DWORD dwWaitHint
Definition: winsvc.h:105
BOOL SystemSetTime(LPSYSTEMTIME lpSystemTime)
Definition: w32time.c:21
#define WINAPI
Definition: msvc.h:6
DWORD dwWin32ExitCode
Definition: winsvc.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD dwServiceType
Definition: winsvc.h:99
GLbitfield flags
Definition: glext.h:7161
WORD wSecond
Definition: winbase.h:889
WORD wMilliseconds
Definition: winbase.h:890
static const WCHAR L[]
Definition: oid.c:1250
#define GetCurrentProcess()
Definition: compat.h:618
BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength)
Definition: security.c:376
#define ERROR_INVALID_DATA
Definition: winerror.h:116
DWORD dwControlsAccepted
Definition: winsvc.h:101
WORD wDay
Definition: winbase.h:886
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
ULONG GetServerTime(LPWSTR lpAddress)
Definition: ntpclient.c:138
int InitService(VOID)
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define SERVICE_WIN32
Definition: cmtypes.h:964
WORD wHour
Definition: winbase.h:887
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:296
static DWORD GetIntervalSetting(VOID)
Definition: w32time.c:125
Definition: tftpd.h:85
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]
Definition: setypes.h:970
unsigned int ULONG
Definition: retypes.h:1
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
WCHAR * LPWSTR
Definition: xmlstorage.h:184
GLuint64EXT * result
Definition: glext.h:11304
#define TOKEN_ADJUST_PRIVILEGES
Definition: setypes.h:876
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
LONGLONG QuadPart
Definition: typedefs.h:114
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12