https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e4898e6e0bd9517233c25f...
commit e4898e6e0bd9517233c25f8f862e5a0ae9dce2f1 Author: Doug Lyons douglyons@douglyons.com AuthorDate: Sun Jul 7 10:59:11 2019 +0200 Commit: Thomas Faber thomas.faber@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@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@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."