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

commit 9febc82acf317ea16ddb04cda88e24051bacd8c4
Author:     Eric Kohl <[email protected]>
AuthorDate: Wed Mar 21 21:07:26 2018 +0100
Commit:     Eric Kohl <[email protected]>
CommitDate: Wed Mar 21 21:07:26 2018 +0100

    [DHCPCSVC] Add the ability to stop the DHCP client
    - Use a stop event to terminate the dispatch loop.
    - Report to the services manager that the service can be stopped or 
shut-down while it is running.
    
    CORE-14390
---
 base/services/dhcpcsvc/dhcp/dispatch.c | 48 ++++++++++++++++++++--------------
 base/services/dhcpcsvc/dhcpcsvc.c      | 44 +++++++++++++++----------------
 base/services/dhcpcsvc/include/dhcpd.h |  2 +-
 3 files changed, 51 insertions(+), 43 deletions(-)

diff --git a/base/services/dhcpcsvc/dhcp/dispatch.c 
b/base/services/dhcpcsvc/dhcp/dispatch.c
index d9ef98271a..d72e092804 100644
--- a/base/services/dhcpcsvc/dhcp/dispatch.c
+++ b/base/services/dhcpcsvc/dhcp/dispatch.c
@@ -63,21 +63,23 @@ void (*bootp_packet_handler)(struct interface_info *,
  * bootp_packet_handler hook to try to do something with it.
  */
 void
-dispatch(void)
+dispatch(HANDLE hStopEvent)
 {
     int count, to_msec;
     struct protocol *l;
     time_t howlong, cur_time;
-    HANDLE Events[2];
-    int EventCount = 1;
+    HANDLE Events[3];
+    int EventCount = 2;
 
     Events[0] = StartAdapterDiscovery();
     if (!Events[0])
          return;
+
     AdapterStateChangedEvent = Events[0];
-    
-    Events[1] = WSA_INVALID_EVENT;
-    
+
+    Events[1] = hStopEvent;
+    Events[2] = WSA_INVALID_EVENT;
+
     ApiLock();
 
     do {
@@ -116,29 +118,29 @@ dispatch(void)
             to_msec = INFINITE;
         }
 
-        if (Events[1] == WSA_INVALID_EVENT && DhcpSocket != INVALID_SOCKET)
+        if (Events[2] == WSA_INVALID_EVENT && DhcpSocket != INVALID_SOCKET)
         {
-            Events[1] = WSACreateEvent();
-            if (Events[1] != WSA_INVALID_EVENT)
+            Events[2] = WSACreateEvent();
+            if (Events[2] != WSA_INVALID_EVENT)
             {
-                count = WSAEventSelect(DhcpSocket, Events[1], FD_READ | 
FD_CLOSE);
+                count = WSAEventSelect(DhcpSocket, Events[2], FD_READ | 
FD_CLOSE);
                 if (count != NO_ERROR)
                 {
-                    WSACloseEvent(Events[1]);
-                    Events[1] = WSA_INVALID_EVENT;
+                    WSACloseEvent(Events[2]);
+                    Events[2] = WSA_INVALID_EVENT;
                 }
                 else
                 {
-                    EventCount = 2;
+                    EventCount = 3;
                 }
             }
         }
-        else if (Events[1] != WSA_INVALID_EVENT && DhcpSocket == 
INVALID_SOCKET)
+        else if (Events[2] != WSA_INVALID_EVENT && DhcpSocket == 
INVALID_SOCKET)
         {
-            WSACloseEvent(Events[1]);
-            Events[1] = WSA_INVALID_EVENT;
+            WSACloseEvent(Events[2]);
+            Events[2] = WSA_INVALID_EVENT;
 
-            EventCount = 1;
+            EventCount = 2;
         }
 
         ApiUnlock();
@@ -153,11 +155,16 @@ dispatch(void)
             continue;
         }
         else if (count == WAIT_OBJECT_0 + 1)
+        {
+            /* Stop event signalled */
+            break;
+        }
+        else if (count == WAIT_OBJECT_0 + 2)
         {
             /* Packet received */
-            
+
             /* WSA events are manual reset events */
-            WSAResetEvent(Events[1]);
+            WSAResetEvent(Events[2]);
         }
         else
         {
@@ -178,7 +185,8 @@ dispatch(void)
 
     AdapterStateChangedEvent = NULL;
     CloseHandle(Events[0]);
-    WSACloseEvent(Events[1]);
+    CloseHandle(Events[1]);
+    WSACloseEvent(Events[2]);
 
     ApiUnlock();
 }
diff --git a/base/services/dhcpcsvc/dhcpcsvc.c 
b/base/services/dhcpcsvc/dhcpcsvc.c
index a96e372fc8..bfd3dbf6a5 100644
--- a/base/services/dhcpcsvc/dhcpcsvc.c
+++ b/base/services/dhcpcsvc/dhcpcsvc.c
@@ -16,6 +16,7 @@ static WCHAR ServiceName[] = L"DHCP";
 
 SERVICE_STATUS_HANDLE ServiceStatusHandle = 0;
 SERVICE_STATUS ServiceStatus;
+HANDLE hStopEvent = NULL;
 
 static HANDLE PipeHandle = INVALID_HANDLE_VALUE;
 
@@ -328,17 +329,18 @@ UpdateServiceStatus(DWORD dwState)
     ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
     ServiceStatus.dwCurrentState = dwState;
 
-    ServiceStatus.dwControlsAccepted = 0;
+    if (dwState == SERVICE_RUNNING)
+        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | 
SERVICE_ACCEPT_STOP;
+    else
+        ServiceStatus.dwControlsAccepted = 0;
 
     ServiceStatus.dwWin32ExitCode = 0;
     ServiceStatus.dwServiceSpecificExitCode = 0;
     ServiceStatus.dwCheckPoint = 0;
 
     if (dwState == SERVICE_START_PENDING ||
-        dwState == SERVICE_STOP_PENDING  ||
-        dwState == SERVICE_PAUSE_PENDING ||
-        dwState == SERVICE_CONTINUE_PENDING)
-        ServiceStatus.dwWaitHint = 10000;
+        dwState == SERVICE_STOP_PENDING)
+        ServiceStatus.dwWaitHint = 1000;
     else
         ServiceStatus.dwWaitHint = 0;
 
@@ -355,17 +357,10 @@ ServiceControlHandler(DWORD dwControl,
     switch (dwControl)
     {
         case SERVICE_CONTROL_STOP:
+        case SERVICE_CONTROL_SHUTDOWN:
             UpdateServiceStatus(SERVICE_STOP_PENDING);
-            UpdateServiceStatus(SERVICE_STOPPED);
-            return ERROR_SUCCESS;
-
-        case SERVICE_CONTROL_PAUSE:
-            UpdateServiceStatus(SERVICE_PAUSED);
-            return ERROR_SUCCESS;
-
-        case SERVICE_CONTROL_CONTINUE:
-            UpdateServiceStatus(SERVICE_START_PENDING);
-            UpdateServiceStatus(SERVICE_RUNNING);
+            if (hStopEvent != NULL)
+                SetEvent(hStopEvent);
             return ERROR_SUCCESS;
 
         case SERVICE_CONTROL_INTERROGATE:
@@ -373,12 +368,7 @@ ServiceControlHandler(DWORD dwControl,
                              &ServiceStatus);
             return ERROR_SUCCESS;
 
-        case SERVICE_CONTROL_SHUTDOWN:
-            UpdateServiceStatus(SERVICE_STOP_PENDING);
-            UpdateServiceStatus(SERVICE_STOPPED);
-            return ERROR_SUCCESS;
-
-        default :
+        default:
             return ERROR_CALL_NOT_IMPLEMENTED;
     }
 }
@@ -397,6 +387,16 @@ ServiceMain(DWORD argc, LPWSTR* argv)
 
     UpdateServiceStatus(SERVICE_START_PENDING);
 
+    /* Create the stop event */
+    hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (hStopEvent == NULL)
+    {
+        UpdateServiceStatus(SERVICE_STOPPED);
+        return;
+    }
+
+    UpdateServiceStatus(SERVICE_START_PENDING);
+
     if (!init_client())
     {
         DPRINT1("DHCPCSVC: init_client() failed!\n");
@@ -411,7 +411,7 @@ ServiceMain(DWORD argc, LPWSTR* argv)
     DH_DbgPrint(MID_TRACE,("Going into dispatch()\n"));
     DH_DbgPrint(MID_TRACE,("DHCPCSVC: DHCP service is starting up\n"));
 
-    dispatch();
+    dispatch(hStopEvent);
 
     DH_DbgPrint(MID_TRACE,("DHCPCSVC: DHCP service is shutting down\n"));
     stop_client();
diff --git a/base/services/dhcpcsvc/include/dhcpd.h 
b/base/services/dhcpcsvc/include/dhcpd.h
index d6a2fa405b..b7b01b4e00 100644
--- a/base/services/dhcpcsvc/include/dhcpd.h
+++ b/base/services/dhcpcsvc/include/dhcpd.h
@@ -351,7 +351,7 @@ extern void (*bootp_packet_handler)(struct interface_info *,
     struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *);
 void discover_interfaces(struct interface_info *);
 void reinitialize_interfaces(void);
-void dispatch(void);
+void dispatch(HANDLE hStopEvent);
 void got_one(struct protocol *);
 void add_timeout(time_t, void (*)(void *), void *);
 void cancel_timeout(void (*)(void *), void *);

Reply via email to