https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e4898e6e0bd9517233c25…
commit e4898e6e0bd9517233c25f8f862e5a0ae9dce2f1
Author: Doug Lyons <douglyons(a)douglyons.com>
AuthorDate: Sun Jul 7 10:59:11 2019 +0200
Commit: Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Sun Jul 7 12:55:13 2019 +0200
[W32TIME] Implement w32time service. CORE-13001
---
base/services/w32time/ntpclient.c | 6 +-
base/services/w32time/w32time.c | 312 ++++++++++++++++++++++++-------------
base/services/w32time/w32time.h | 2 +
base/services/w32time/w32time.spec | 1 +
boot/bootdata/hivesft.inf | 3 +-
boot/bootdata/hivesys.inf | 16 ++
6 files changed, 230 insertions(+), 110 deletions(-)
diff --git a/base/services/w32time/ntpclient.c b/base/services/w32time/ntpclient.c
index 8ba5910fe13..072772ec955 100644
--- a/base/services/w32time/ntpclient.c
+++ b/base/services/w32time/ntpclient.c
@@ -1,10 +1,8 @@
/*
* PROJECT: ReactOS Timedate Control Panel
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: dll/cpl/timedate/ntpclient.c
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Queries the NTP server
* COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy(a)gmail.com>
- *
*/
#include "w32time.h"
@@ -81,7 +79,7 @@ SendData(PINFO pInfo)
INT Ret;
ZeroMemory(&pInfo->SendPacket, sizeof(pInfo->SendPacket));
- pInfo->SendPacket.LiVnMode = 27;
+ pInfo->SendPacket.LiVnMode = 0x1b; /* 0x1b = 011 011 - version 3 , mode 3
(client) */
if (!GetTransmitTime(&tp))
return FALSE;
pInfo->SendPacket.TransmitTimestamp = tp;
diff --git a/base/services/w32time/w32time.c b/base/services/w32time/w32time.c
index 675bb907d69..c32624f8b9a 100644
--- a/base/services/w32time/w32time.c
+++ b/base/services/w32time/w32time.c
@@ -1,107 +1,20 @@
/*
- * PROJECT: ReactOS Timedate Control Panel
+ * PROJECT: ReactOS W32Time Service
* 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(a)gmail.com>
+ * Copyright 2018 Doug Lyons
*/
#include "w32time.h"
+#include <debug.h>
+#include <strsafe.h>
-/* Get the domain name from the registry */
-static DWORD
-GetNTPServerAddress(LPWSTR *lpAddress)
-{
- HKEY hKey;
- WCHAR szSel[4];
- DWORD dwSize;
- LONG lRet;
-
- *lpAddress = NULL;
- hKey = NULL;
-
- lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
- 0,
- KEY_QUERY_VALUE,
- &hKey);
- if (lRet != ERROR_SUCCESS)
- goto Exit;
-
- /* Get data from default value */
- dwSize = 4 * sizeof(WCHAR);
- lRet = RegQueryValueExW(hKey,
- NULL,
- NULL,
- NULL,
- (LPBYTE)szSel,
- &dwSize);
- if (lRet != ERROR_SUCCESS)
- goto Exit;
-
- dwSize = 0;
- lRet = RegQueryValueExW(hKey,
- szSel,
- NULL,
- NULL,
- NULL,
- &dwSize);
- if (lRet != ERROR_SUCCESS)
- goto Exit;
-
- (*lpAddress) = (LPWSTR)HeapAlloc(GetProcessHeap(),
- 0,
- dwSize);
- if ((*lpAddress) == NULL)
- {
- lRet = ERROR_NOT_ENOUGH_MEMORY;
- goto Exit;
- }
-
- lRet = RegQueryValueExW(hKey,
- szSel,
- NULL,
- NULL,
- (LPBYTE)*lpAddress,
- &dwSize);
- if (lRet != ERROR_SUCCESS)
- goto Exit;
-
-Exit:
- if (hKey)
- RegCloseKey(hKey);
- if (lRet != ERROR_SUCCESS)
- HeapFree(GetProcessHeap(), 0, *lpAddress);
-
- return lRet;
-}
-
-
-/* Request the time from the current NTP server */
-static DWORD
-GetTimeFromServer(PULONG pulTime)
-{
- LPWSTR lpAddress;
- DWORD dwError;
-
- dwError = GetNTPServerAddress(&lpAddress);
- if (dwError != ERROR_SUCCESS)
- {
- return dwError;
- }
-
- *pulTime = GetServerTime(lpAddress);
- if (*pulTime == 0)
- {
- dwError = ERROR_GEN_FAILURE;
- }
-
- HeapFree(GetProcessHeap(),
- 0,
- lpAddress);
-
- return dwError;
-}
+SERVICE_STATUS ServiceStatus;
+SERVICE_STATUS_HANDLE hStatus;
+static WCHAR ServiceName[] = L"W32Time";
+int InitService(VOID);
BOOL
SystemSetTime(LPSYSTEMTIME lpSystemTime)
@@ -207,25 +120,214 @@ UpdateSystemTime(ULONG ulTime)
}
-DWORD WINAPI
-W32TimeSyncNow(LPCWSTR cmdline,
- UINT blocking,
- UINT flags)
+static DWORD
+GetIntervalSetting(VOID)
+{
+ HKEY hKey;
+ DWORD dwData;
+ DWORD dwSize = sizeof(dwData);
+ LONG lRet;
+
+ dwData = 0;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+
L"SYSTEM\\CurrentControlSet\\Services\\W32Time\\TimeProviders\\NtpClient",
+ 0,
+ KEY_QUERY_VALUE,
+ &hKey) == ERROR_SUCCESS)
+ {
+ /* This key holds the update interval in seconds
+ * It is useful for testing to set it to a value of 10 (Decimal)
+ * This will cause the clock to try and update every 10 seconds
+ * So you can change the time and expect it to be set back correctly in 10-20
seconds
+ */
+ lRet = RegQueryValueExW(hKey,
+ L"SpecialPollInterval",
+ NULL,
+ NULL,
+ (LPBYTE)&dwData,
+ &dwSize);
+ RegCloseKey(hKey);
+ }
+
+ if (lRet != ERROR_SUCCESS)
+ return 0;
+ else
+ return dwData;
+}
+
+
+DWORD
+SetTime(VOID)
{
- DWORD dwError;
ULONG ulTime;
+ LONG lRet;
+ HKEY hKey;
+ WCHAR szData[MAX_VALUE_NAME] = L"";
+ DWORD cbName = sizeof(szData);
+
+ DPRINT("Entered SetTime.\n");
- dwError = GetTimeFromServer(&ulTime);
- if (dwError != ERROR_SUCCESS)
+ lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DateTime\\Servers",
+ 0,
+ KEY_QUERY_VALUE,
+ &hKey);
+ if (lRet != ERROR_SUCCESS)
+ {
+ return lRet;
+ }
+
+ lRet = RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)szData, &cbName);
+ if (lRet == ERROR_SUCCESS)
{
- return dwError;
+ cbName = sizeof(szData);
+ lRet = RegQueryValueExW(hKey, szData, NULL, NULL, (LPBYTE)szData, &cbName);
}
+ RegCloseKey(hKey);
+
+ DPRINT("Time Server is '%S'.\n", szData);
+
+ ulTime = GetServerTime(szData);
+
if (ulTime != 0)
{
- dwError = UpdateSystemTime(ulTime);
+ return UpdateSystemTime(ulTime);
}
+ else
+ return ERROR_GEN_FAILURE;
+}
- return dwError;
+
+/* Control handler function */
+VOID WINAPI
+ControlHandler(DWORD request)
+{
+ switch (request)
+ {
+ case SERVICE_CONTROL_STOP:
+ DPRINT("W32Time Service stopped.\n");
+
+ ServiceStatus.dwWin32ExitCode = 0;
+ ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus(hStatus, &ServiceStatus);
+ return;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ DPRINT("W32Time Service stopped.\n");
+
+ ServiceStatus.dwWin32ExitCode = 0;
+ ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus(hStatus, &ServiceStatus);
+ return;
+
+ default:
+ break;
+ }
+
+ /* Report current status */
+ SetServiceStatus(hStatus, &ServiceStatus);
+
+ return;
}
+
+VOID
+WINAPI
+ServiceMain(DWORD argc, LPWSTR *argv)
+{
+ int result;
+ DWORD dwPollInterval;
+
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+
+ ServiceStatus.dwServiceType = SERVICE_WIN32;
+ ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+ ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN;
+ ServiceStatus.dwWin32ExitCode = 0;
+ ServiceStatus.dwServiceSpecificExitCode = 0;
+ ServiceStatus.dwCheckPoint = 0;
+ ServiceStatus.dwWaitHint = 0;
+
+ hStatus = RegisterServiceCtrlHandlerW(ServiceName,
+ ControlHandler);
+ if (!hStatus)
+ {
+ /* Registering Control Handler failed */
+ return;
+ }
+
+ /* We report the running status to SCM. */
+ ServiceStatus.dwCurrentState = SERVICE_RUNNING;
+ SetServiceStatus(hStatus, &ServiceStatus);
+
+ /* The worker loop of a service */
+ while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
+ {
+ dwPollInterval = GetIntervalSetting();
+ result = SetTime();
+
+ if (result)
+ DPRINT("W32Time Service failed to set clock.\n");
+ else
+ DPRINT("W32Time Service successfully set clock.\n");
+
+ if (result)
+ {
+ /* In general we do not want to stop this service for a single
+ * Internet read failure but there may be other reasons for which
+ * we really might want to stop it.
+ * Therefore this code is left here to make it easy to stop this
+ * service when the correct conditions can be determined, but it
+ * is left commented out.
+ ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ ServiceStatus.dwWin32ExitCode = -1;
+ SetServiceStatus(hStatus, &ServiceStatus);
+ return;
+ */
+ }
+
+ Sleep(dwPollInterval * 1000);
+ }
+ return;
+}
+
+
+
+BOOL WINAPI
+DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDLL);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+DWORD WINAPI
+W32TimeSyncNow(LPCWSTR cmdline,
+ UINT blocking,
+ UINT flags)
+{
+ DWORD result;
+ result = SetTime();
+ if (result)
+ {
+ DPRINT("W32TimeSyncNow failed and clock not set.\n");
+ }
+ else
+ {
+ DPRINT("W32TimeSyncNow succeeded and clock set.\n");
+ }
+ return result;
+}
diff --git a/base/services/w32time/w32time.h b/base/services/w32time/w32time.h
index bd65de402c3..87be3d09d68 100644
--- a/base/services/w32time/w32time.h
+++ b/base/services/w32time/w32time.h
@@ -11,7 +11,9 @@
#include <winbase.h>
#include <winnls.h>
#include <winreg.h>
+#include <winsvc.h>
+#define MAX_VALUE_NAME 16383
#define NTPPORT 123
diff --git a/base/services/w32time/w32time.spec b/base/services/w32time/w32time.spec
index 12b8db5bc1e..b4893ff346f 100644
--- a/base/services/w32time/w32time.spec
+++ b/base/services/w32time/w32time.spec
@@ -1 +1,2 @@
18 stdcall W32TimeSyncNow(wstr long long)
+21 stdcall ServiceMain(long ptr)
diff --git a/boot/bootdata/hivesft.inf b/boot/bootdata/hivesft.inf
index 4387338e3f0..330101a29db 100644
--- a/boot/bootdata/hivesft.inf
+++ b/boot/bootdata/hivesft.inf
@@ -1520,6 +1520,7 @@ HKLM,"SOFTWARE\Microsoft\Windows
NT\CurrentVersion\Winlogon\Notify\wlballoon","L
HKLM,"SOFTWARE\Microsoft\Windows
NT\CurrentVersion\Winlogon\Notify\wlballoon","Logon",0x00000000,"RegisterTicketExpiredNotificationEvent"
; Time Zone Servers
+HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers",,0x00000000,"1"
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers","1",0x00000000,"pool.ntp.org"
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers","2",0x00000000,"asia.pool.ntp.org"
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers","3",0x00000000,"europe.pool.ntp.org"
@@ -1780,7 +1781,7 @@
HKLM,"SOFTWARE\Microsoft\Ole","EnableRemoteConnect",0x00000000,"N"
; SvcHost services
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost",,0x00000012
HKLM,"SOFTWARE\Microsoft\Windows
NT\CurrentVersion\SvcHost","DcomLaunch",0x00010000,"DcomLaunch","PlugPlay"
-HKLM,"SOFTWARE\Microsoft\Windows
NT\CurrentVersion\SvcHost","netsvcs",0x00010000,"DHCP","BITS","lanmanserver","lanmanworkstation","Schedule","Themes","winmgmt"
+HKLM,"SOFTWARE\Microsoft\Windows
NT\CurrentVersion\SvcHost","netsvcs",0x00010000,"DHCP","BITS","lanmanserver","lanmanworkstation","Schedule","Themes","winmgmt","W32Time"
; Win32 config
HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows",,0x00000012
diff --git a/boot/bootdata/hivesys.inf b/boot/bootdata/hivesys.inf
index 0f2fc9369eb..8f65a0ac783 100644
--- a/boot/bootdata/hivesys.inf
+++ b/boot/bootdata/hivesys.inf
@@ -2002,6 +2002,19 @@
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ObjectName",0x00000000,"LocalS
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Start",0x00010001,0x00000002
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Type",0x00010001,0x00000110
+; W32TIME service
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","DisplayName",0x00000000,%W32TIME_SERVICE%
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","Description",0x00000000,%W32TIME_SERVICE_DESCRIPTION%
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","Group",0x00000000,"Time"
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","ImagePath",0x00020000,"%SystemRoot%\system32\svchost.exe
-k netsvcs"
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","ObjectName",0x00000000,"LocalSystem"
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","Start",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time","Type",0x00010001,0x00000020
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time\Parameters","ServiceDll",0x00020000,"%SystemRoot%\system32\w32time.dll"
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time\Parameters","Type",0x00010000,"NTP"
+HKLM,"SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient","SpecialPollInterval",0x00010001,0x00093a80
+
; Simple TCP services
HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","Description",0x00000000,%TCPSVCS_SERVICE_DECRIPTION%
HKLM,"SYSTEM\CurrentControlSet\Services\tcpsvcs","DisplayName",0x00000000,%TCPSVCS_SERVICE%
@@ -2245,6 +2258,9 @@ WUAUSERV_SERVICE_DESCRIPTION="AutoUpdate Service stub."
WLANSVC_SERVICE="WLAN Service"
WLANSVC_SERVICE_DESCRIPTION="WLAN Service"
+W32TIME_SERVICE="Time Service"
+W32TIME_SERVICE_DESCRIPTION="ReactOS Time Service"
+
WORKSTATION_SERVICE="Workstation"
WORKSTATION_SERVICE_DESCRIPTION="Responsible for creating and maintaining network
connections to servers."