https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e4898e6e0bd9517233c25f8f862e5a0ae9dce2f1

commit e4898e6e0bd9517233c25f8f862e5a0ae9dce2f1
Author:     Doug Lyons <[email protected]>
AuthorDate: Sun Jul 7 10:59:11 2019 +0200
Commit:     Thomas Faber <[email protected]>
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 <[email protected]>
- *
  */
 
 #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 <[email protected]>
+ *              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."
 

Reply via email to