[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
This commit is contained in:
Eric Kohl 2018-03-21 21:07:26 +01:00
parent 8b84b1c6b3
commit 9febc82acf
3 changed files with 51 additions and 43 deletions

View file

@ -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();
}

View file

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

View file

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