[W32TIME] Implement w32time service. CORE-13001

This commit is contained in:
Doug Lyons 2019-07-07 10:59:11 +02:00 committed by Thomas Faber
parent 119c99ef7e
commit e4898e6e0b
No known key found for this signature in database
GPG key ID: 076E7C3D44720826
6 changed files with 232 additions and 112 deletions

View file

@ -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;

View file

@ -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)
}
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)
{
ULONG ulTime;
LONG lRet;
HKEY hKey;
WCHAR szData[MAX_VALUE_NAME] = L"";
DWORD cbName = sizeof(szData);
DPRINT("Entered SetTime.\n");
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)
{
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)
{
return UpdateSystemTime(ulTime);
}
else
return ERROR_GEN_FAILURE;
}
/* 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 dwError;
ULONG ulTime;
dwError = GetTimeFromServer(&ulTime);
if (dwError != ERROR_SUCCESS)
DWORD result;
result = SetTime();
if (result)
{
return dwError;
DPRINT("W32TimeSyncNow failed and clock not set.\n");
}
if (ulTime != 0)
else
{
dwError = UpdateSystemTime(ulTime);
DPRINT("W32TimeSyncNow succeeded and clock set.\n");
}
return dwError;
return result;
}

View file

@ -11,7 +11,9 @@
#include <winbase.h>
#include <winnls.h>
#include <winreg.h>
#include <winsvc.h>
#define MAX_VALUE_NAME 16383
#define NTPPORT 123

View file

@ -1 +1,2 @@
18 stdcall W32TimeSyncNow(wstr long long)
21 stdcall ServiceMain(long ptr)

View file

@ -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

View file

@ -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."