[DHCPCSVC] Make the DHCP client service stoppable

- Make all threads (pipe thread, adapter discovery thread and dispatcher thread) wait on the stop event.
- Close shared resources in the main (dispatcher) thread after the pipe thread and the adapter discovery thread have shut down.

This enables us to stop and restart the DHCP client properly.

CORE-14390
This commit is contained in:
Eric Kohl 2021-08-08 14:09:31 +02:00
parent f486f87796
commit 033b6639e4
7 changed files with 233 additions and 133 deletions

View file

@ -1,5 +1,10 @@
#include <rosdhcp.h> #include <rosdhcp.h>
#define NDEBUG
#include <reactos/debug.h>
extern HANDLE hAdapterStateChangedEvent;
SOCKET DhcpSocket = INVALID_SOCKET; SOCKET DhcpSocket = INVALID_SOCKET;
static LIST_ENTRY AdapterList; static LIST_ENTRY AdapterList;
static WSADATA wsd; static WSADATA wsd;
@ -287,14 +292,13 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
PMIB_IFTABLE Table = (PMIB_IFTABLE) malloc(sizeof(MIB_IFTABLE)); PMIB_IFTABLE Table = (PMIB_IFTABLE) malloc(sizeof(MIB_IFTABLE));
DWORD Error, Size = sizeof(MIB_IFTABLE); DWORD Error, Size = sizeof(MIB_IFTABLE);
PDHCP_ADAPTER Adapter = NULL; PDHCP_ADAPTER Adapter = NULL;
HANDLE AdapterStateChangedEvent = (HANDLE)Context; HANDLE hStopEvent = (HANDLE)Context;
struct interface_info *ifi = NULL; struct interface_info *ifi = NULL;
struct protocol *proto; struct protocol *proto;
int i, AdapterCount = 0, Broadcast; int i, AdapterCount = 0, Broadcast;
/* FIXME: Kill this thread when the service is stopped */ while (TRUE)
{
do {
DH_DbgPrint(MID_TRACE,("Getting Adapter List...\n")); DH_DbgPrint(MID_TRACE,("Getting Adapter List...\n"));
while( (Error = GetIfTable(Table, &Size, 0 )) == while( (Error = GetIfTable(Table, &Size, 0 )) ==
@ -346,7 +350,7 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
got_one, &Adapter->DhclientInfo); got_one, &Adapter->DhclientInfo);
state_init(&Adapter->DhclientInfo); state_init(&Adapter->DhclientInfo);
SetEvent(AdapterStateChangedEvent); SetEvent(hAdapterStateChangedEvent);
} }
} else { } else {
@ -444,7 +448,7 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
ApiLock(); ApiLock();
InsertTailList( &AdapterList, &Adapter->ListEntry ); InsertTailList( &AdapterList, &Adapter->ListEntry );
AdapterCount++; AdapterCount++;
SetEvent(AdapterStateChangedEvent); SetEvent(hAdapterStateChangedEvent);
ApiUnlock(); ApiUnlock();
} else { free( Adapter ); Adapter = 0; } } else { free( Adapter ); Adapter = 0; }
} else { free( Adapter ); Adapter = 0; } } else { free( Adapter ); Adapter = 0; }
@ -458,43 +462,24 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) {
if (Error != NO_ERROR) if (Error != NO_ERROR)
break; break;
#else #else
Sleep(3000); if (WaitForSingleObject(hStopEvent, 3000) == WAIT_OBJECT_0)
{
DPRINT("Stopping the discovery thread!\n");
break;
}
#endif #endif
} while (TRUE); }
DbgPrint("DHCPCSVC: Adapter discovery thread is terminating! (Error: %d)\n", Error); if (Table)
free(Table);
DPRINT("Adapter discovery thread terminated! (Error: %d)\n", Error);
if( Table ) free( Table );
return Error; return Error;
} }
HANDLE StartAdapterDiscovery(VOID) { HANDLE StartAdapterDiscovery(HANDLE hStopEvent) {
HANDLE ThreadHandle, EventHandle; return CreateThread(NULL, 0, AdapterDiscoveryThread, (LPVOID)hStopEvent, 0, NULL);
EventHandle = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if (EventHandle == NULL)
return NULL;
ThreadHandle = CreateThread(NULL,
0,
AdapterDiscoveryThread,
(LPVOID)EventHandle,
0,
NULL);
if (ThreadHandle == NULL)
{
CloseHandle(EventHandle);
return NULL;
}
CloseHandle(ThreadHandle);
return EventHandle;
} }
void AdapterStop() { void AdapterStop() {

View file

@ -13,7 +13,7 @@
static CRITICAL_SECTION ApiCriticalSection; static CRITICAL_SECTION ApiCriticalSection;
extern HANDLE AdapterStateChangedEvent; extern HANDLE hAdapterStateChangedEvent;
VOID ApiInit() { VOID ApiInit() {
InitializeCriticalSection( &ApiCriticalSection ); InitializeCriticalSection( &ApiCriticalSection );
@ -33,7 +33,7 @@ VOID ApiFree() {
/* This represents the service portion of the DHCP client API */ /* This represents the service portion of the DHCP client API */
DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { DWORD DSLeaseIpAddress( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req ) {
COMM_DHCP_REPLY Reply; COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter; PDHCP_ADAPTER Adapter;
struct protocol* proto; struct protocol* proto;
@ -56,16 +56,16 @@ DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
Adapter->DhclientInfo.client->state = S_INIT; Adapter->DhclientInfo.client->state = S_INIT;
state_reboot(&Adapter->DhclientInfo); state_reboot(&Adapter->DhclientInfo);
if (AdapterStateChangedEvent != NULL) if (hAdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent); SetEvent(hAdapterStateChangedEvent);
} }
ApiUnlock(); ApiUnlock();
return Send( &Reply ); return Send(CommPipe, &Reply );
} }
DWORD DSQueryHWInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { DWORD DSQueryHWInfo( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req ) {
COMM_DHCP_REPLY Reply; COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter; PDHCP_ADAPTER Adapter;
@ -84,10 +84,10 @@ DWORD DSQueryHWInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
ApiUnlock(); ApiUnlock();
return Send( &Reply ); return Send(CommPipe, &Reply );
} }
DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { DWORD DSReleaseIpAddressLease( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req ) {
COMM_DHCP_REPLY Reply; COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter; PDHCP_ADAPTER Adapter;
struct protocol* proto; struct protocol* proto;
@ -117,16 +117,16 @@ DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
Adapter->DhclientInfo.client->active = NULL; Adapter->DhclientInfo.client->active = NULL;
Adapter->DhclientInfo.client->state = S_INIT; Adapter->DhclientInfo.client->state = S_INIT;
if (AdapterStateChangedEvent != NULL) if (hAdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent); SetEvent(hAdapterStateChangedEvent);
} }
ApiUnlock(); ApiUnlock();
return Send( &Reply ); return Send(CommPipe, &Reply );
} }
DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { DWORD DSRenewIpAddressLease( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req ) {
COMM_DHCP_REPLY Reply; COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter; PDHCP_ADAPTER Adapter;
struct protocol* proto; struct protocol* proto;
@ -138,7 +138,7 @@ DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
if( !Adapter || Adapter->DhclientState.state == S_STATIC ) { if( !Adapter || Adapter->DhclientState.state == S_STATIC ) {
Reply.Reply = 0; Reply.Reply = 0;
ApiUnlock(); ApiUnlock();
return Send( &Reply ); return Send(CommPipe, &Reply );
} }
Reply.Reply = 1; Reply.Reply = 1;
@ -154,15 +154,15 @@ DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
Adapter->DhclientInfo.client->state = S_INIT; Adapter->DhclientInfo.client->state = S_INIT;
state_reboot(&Adapter->DhclientInfo); state_reboot(&Adapter->DhclientInfo);
if (AdapterStateChangedEvent != NULL) if (hAdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent); SetEvent(hAdapterStateChangedEvent);
ApiUnlock(); ApiUnlock();
return Send( &Reply ); return Send(CommPipe, &Reply );
} }
DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { DWORD DSStaticRefreshParams( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req ) {
NTSTATUS Status; NTSTATUS Status;
COMM_DHCP_REPLY Reply; COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter; PDHCP_ADAPTER Adapter;
@ -197,16 +197,16 @@ DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
&Adapter->NteInstance ); &Adapter->NteInstance );
Reply.Reply = NT_SUCCESS(Status); Reply.Reply = NT_SUCCESS(Status);
if (AdapterStateChangedEvent != NULL) if (hAdapterStateChangedEvent != NULL)
SetEvent(AdapterStateChangedEvent); SetEvent(hAdapterStateChangedEvent);
} }
ApiUnlock(); ApiUnlock();
return Send( &Reply ); return Send(CommPipe, &Reply );
} }
DWORD DSGetAdapterInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { DWORD DSGetAdapterInfo( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req ) {
COMM_DHCP_REPLY Reply; COMM_DHCP_REPLY Reply;
PDHCP_ADAPTER Adapter; PDHCP_ADAPTER Adapter;
@ -240,5 +240,5 @@ DWORD DSGetAdapterInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
ApiUnlock(); ApiUnlock();
return Send( &Reply ); return Send(CommPipe, &Reply );
} }

View file

@ -122,14 +122,6 @@ init_client(void)
inaddr_any.s_addr = INADDR_ANY; inaddr_any.s_addr = INADDR_ANY;
bootp_packet_handler = do_packet; bootp_packet_handler = do_packet;
if (PipeInit() == INVALID_HANDLE_VALUE)
{
DbgPrint("DHCPCSVC: PipeInit() failed!\n");
AdapterStop();
ApiFree();
return 0; // FALSE
}
return 1; // TRUE return 1; // TRUE
} }

View file

@ -41,6 +41,9 @@
#include <rosdhcp.h> #include <rosdhcp.h>
#define NDEBUG
#include <reactos/debug.h>
//#include <sys/ioctl.h> //#include <sys/ioctl.h>
//#include <net/if_media.h> //#include <net/if_media.h>
@ -48,7 +51,8 @@
//#include <poll.h> //#include <poll.h>
extern SOCKET DhcpSocket; extern SOCKET DhcpSocket;
HANDLE AdapterStateChangedEvent = NULL; extern HANDLE hAdapterStateChangedEvent;
struct protocol *protocols = NULL; struct protocol *protocols = NULL;
struct timeout *timeouts = NULL; struct timeout *timeouts = NULL;
static struct timeout *free_timeouts = NULL; static struct timeout *free_timeouts = NULL;
@ -71,12 +75,7 @@ dispatch(HANDLE hStopEvent)
HANDLE Events[3]; HANDLE Events[3];
int EventCount = 2; int EventCount = 2;
Events[0] = StartAdapterDiscovery(); Events[0] = hAdapterStateChangedEvent;
if (!Events[0])
return;
AdapterStateChangedEvent = Events[0];
Events[1] = hStopEvent; Events[1] = hStopEvent;
Events[2] = WSA_INVALID_EVENT; Events[2] = WSA_INVALID_EVENT;
@ -157,6 +156,7 @@ dispatch(HANDLE hStopEvent)
else if (count == WAIT_OBJECT_0 + 1) else if (count == WAIT_OBJECT_0 + 1)
{ {
/* Stop event signalled */ /* Stop event signalled */
DPRINT("Dispatch thread stop event!\n");
break; break;
} }
else if (count == WAIT_OBJECT_0 + 2) else if (count == WAIT_OBJECT_0 + 2)
@ -183,12 +183,11 @@ dispatch(HANDLE hStopEvent)
} }
} while (1); } while (1);
AdapterStateChangedEvent = NULL;
CloseHandle(Events[0]);
CloseHandle(Events[1]);
WSACloseEvent(Events[2]); WSACloseEvent(Events[2]);
ApiUnlock(); ApiUnlock();
DPRINT("Dispatch thread stopped!\n");
} }
void void

View file

@ -11,21 +11,28 @@
#define NDEBUG #define NDEBUG
#include <reactos/debug.h> #include <reactos/debug.h>
static HANDLE CommPipe = INVALID_HANDLE_VALUE, CommThread;
DWORD CommThrId;
#define COMM_PIPE_OUTPUT_BUFFER sizeof(COMM_DHCP_REQ) #define COMM_PIPE_OUTPUT_BUFFER sizeof(COMM_DHCP_REQ)
#define COMM_PIPE_INPUT_BUFFER sizeof(COMM_DHCP_REPLY) #define COMM_PIPE_INPUT_BUFFER sizeof(COMM_DHCP_REPLY)
#define COMM_PIPE_DEFAULT_TIMEOUT 1000 #define COMM_PIPE_DEFAULT_TIMEOUT 1000
DWORD PipeSend( COMM_DHCP_REPLY *Reply ) { DWORD PipeSend( HANDLE CommPipe, COMM_DHCP_REPLY *Reply ) {
DWORD Written = 0; DWORD Written = 0;
OVERLAPPED Overlapped = {0};
BOOL Success = BOOL Success =
WriteFile( CommPipe, WriteFile( CommPipe,
Reply, Reply,
sizeof(*Reply), sizeof(*Reply),
&Written, &Written,
NULL ); &Overlapped);
if (!Success)
{
WaitForSingleObject(CommPipe, INFINITE);
Success = GetOverlappedResult(CommPipe,
&Overlapped,
&Written,
TRUE);
}
return Success ? Written : -1; return Success ? Written : -1;
} }
@ -34,10 +41,57 @@ DWORD WINAPI PipeThreadProc( LPVOID Parameter ) {
COMM_DHCP_REQ Req; COMM_DHCP_REQ Req;
COMM_DHCP_REPLY Reply; COMM_DHCP_REPLY Reply;
BOOL Result, Connected; BOOL Result, Connected;
HANDLE Events[2];
HANDLE CommPipe;
OVERLAPPED Overlapped = {0};
DWORD dwError;
while( TRUE ) { DPRINT("PipeThreadProc(%p)\n", Parameter);
Connected = ConnectNamedPipe( CommPipe, NULL ) ?
TRUE : GetLastError() == ERROR_PIPE_CONNECTED; CommPipe = CreateNamedPipeW
( DHCP_PIPE_NAME,
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1,
COMM_PIPE_OUTPUT_BUFFER,
COMM_PIPE_INPUT_BUFFER,
COMM_PIPE_DEFAULT_TIMEOUT,
NULL );
if (CommPipe == INVALID_HANDLE_VALUE)
{
DbgPrint("DHCP: Could not create named pipe\n");
return FALSE;
}
Events[0] = (HANDLE)Parameter;
Events[1] = CommPipe;
while( TRUE )
{
Connected = ConnectNamedPipe(CommPipe, &Overlapped);
if (!Connected)
{
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
dwError = WaitForMultipleObjects(2, Events, FALSE, INFINITE);
DPRINT("WaitForMultipleObjects() returned %lu\n", dwError);
if (dwError == WAIT_OBJECT_0 + 1)
{
Connected = GetOverlappedResult(CommPipe,
&Overlapped,
&BytesRead,
TRUE);
}
else if (dwError == WAIT_OBJECT_0)
{
CancelIo(CommPipe);
CloseHandle(CommPipe);
CommPipe = INVALID_HANDLE_VALUE;
break;
}
}
}
if (!Connected) { if (!Connected) {
DbgPrint("DHCP: Could not connect named pipe\n"); DbgPrint("DHCP: Could not connect named pipe\n");
@ -46,74 +100,75 @@ DWORD WINAPI PipeThreadProc( LPVOID Parameter ) {
break; break;
} }
Result = ReadFile( CommPipe, &Req, sizeof(Req), &BytesRead, NULL ); Result = ReadFile(CommPipe, &Req, sizeof(Req), &BytesRead, &Overlapped);
if (!Result)
{
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
dwError = WaitForMultipleObjects(2, Events, FALSE, INFINITE);
DPRINT("WaitForMultipleObjects() returned %lu\n", dwError);
if (dwError == WAIT_OBJECT_0 + 1)
{
Result = GetOverlappedResult(CommPipe,
&Overlapped,
&BytesRead,
TRUE);
}
else if (dwError == WAIT_OBJECT_0)
{
CancelIo(CommPipe);
DisconnectNamedPipe( CommPipe );
CloseHandle(CommPipe);
CommPipe = INVALID_HANDLE_VALUE;
break;
}
}
}
if( Result ) { if( Result ) {
switch( Req.Type ) { switch( Req.Type ) {
case DhcpReqQueryHWInfo: case DhcpReqQueryHWInfo:
DSQueryHWInfo( PipeSend, &Req ); DSQueryHWInfo( PipeSend, CommPipe, &Req );
break; break;
case DhcpReqLeaseIpAddress: case DhcpReqLeaseIpAddress:
DSLeaseIpAddress( PipeSend, &Req ); DSLeaseIpAddress( PipeSend, CommPipe, &Req );
break; break;
case DhcpReqReleaseIpAddress: case DhcpReqReleaseIpAddress:
DSReleaseIpAddressLease( PipeSend, &Req ); DSReleaseIpAddressLease( PipeSend, CommPipe, &Req );
break; break;
case DhcpReqRenewIpAddress: case DhcpReqRenewIpAddress:
DSRenewIpAddressLease( PipeSend, &Req ); DSRenewIpAddressLease( PipeSend, CommPipe, &Req );
break; break;
case DhcpReqStaticRefreshParams: case DhcpReqStaticRefreshParams:
DSStaticRefreshParams( PipeSend, &Req ); DSStaticRefreshParams( PipeSend, CommPipe, &Req );
break; break;
case DhcpReqGetAdapterInfo: case DhcpReqGetAdapterInfo:
DSGetAdapterInfo( PipeSend, &Req ); DSGetAdapterInfo( PipeSend, CommPipe, &Req );
break; break;
default: default:
DPRINT1("Unrecognized request type %d\n", Req.Type); DPRINT1("Unrecognized request type %d\n", Req.Type);
ZeroMemory( &Reply, sizeof( COMM_DHCP_REPLY ) ); ZeroMemory( &Reply, sizeof( COMM_DHCP_REPLY ) );
Reply.Reply = 0; Reply.Reply = 0;
PipeSend( &Reply ); PipeSend(CommPipe, &Reply );
break; break;
} }
} }
DisconnectNamedPipe( CommPipe ); DisconnectNamedPipe( CommPipe );
} }
DPRINT("Pipe thread stopped!\n");
return TRUE; return TRUE;
} }
HANDLE PipeInit() { HANDLE PipeInit(HANDLE hStopEvent)
CommPipe = CreateNamedPipeW {
( DHCP_PIPE_NAME, return CreateThread( NULL, 0, PipeThreadProc, (LPVOID)hStopEvent, 0, NULL);
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1,
COMM_PIPE_OUTPUT_BUFFER,
COMM_PIPE_INPUT_BUFFER,
COMM_PIPE_DEFAULT_TIMEOUT,
NULL );
if( CommPipe == INVALID_HANDLE_VALUE ) {
DbgPrint("DHCP: Could not create named pipe\n");
return CommPipe;
}
CommThread = CreateThread( NULL, 0, PipeThreadProc, NULL, 0, &CommThrId );
if( !CommThread ) {
CloseHandle( CommPipe );
CommPipe = INVALID_HANDLE_VALUE;
}
return CommPipe;
}
VOID PipeDestroy() {
CloseHandle( CommPipe );
CommPipe = INVALID_HANDLE_VALUE;
} }

View file

@ -17,8 +17,10 @@ static WCHAR ServiceName[] = L"DHCP";
SERVICE_STATUS_HANDLE ServiceStatusHandle = 0; SERVICE_STATUS_HANDLE ServiceStatusHandle = 0;
SERVICE_STATUS ServiceStatus; SERVICE_STATUS ServiceStatus;
HANDLE hStopEvent = NULL; HANDLE hStopEvent = NULL;
HANDLE hAdapterStateChangedEvent = NULL;
static HANDLE PipeHandle = INVALID_HANDLE_VALUE; static HANDLE PipeHandle = INVALID_HANDLE_VALUE;
extern SOCKET DhcpSocket;
DWORD APIENTRY DWORD APIENTRY
DhcpCApiInitialize(LPDWORD Version) DhcpCApiInitialize(LPDWORD Version)
@ -391,6 +393,10 @@ ServiceControlHandler(DWORD dwControl,
VOID WINAPI VOID WINAPI
ServiceMain(DWORD argc, LPWSTR* argv) ServiceMain(DWORD argc, LPWSTR* argv)
{ {
HANDLE hPipeThread = INVALID_HANDLE_VALUE;
HANDLE hDiscoveryThread = INVALID_HANDLE_VALUE;
DWORD ret;
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
ServiceControlHandler, ServiceControlHandler,
NULL); NULL);
@ -403,18 +409,52 @@ ServiceMain(DWORD argc, LPWSTR* argv)
UpdateServiceStatus(SERVICE_START_PENDING); UpdateServiceStatus(SERVICE_START_PENDING);
/* Create the stop event */ /* Create the stop event */
hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); hStopEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (hStopEvent == NULL) if (hStopEvent == NULL)
{ {
UpdateServiceStatus(SERVICE_STOPPED); UpdateServiceStatus(SERVICE_STOPPED);
return; return;
} }
hAdapterStateChangedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hAdapterStateChangedEvent == NULL)
{
CloseHandle(hStopEvent);
UpdateServiceStatus(SERVICE_STOPPED);
return;
}
UpdateServiceStatus(SERVICE_START_PENDING); UpdateServiceStatus(SERVICE_START_PENDING);
if (!init_client()) if (!init_client())
{ {
DPRINT1("DHCPCSVC: init_client() failed!\n"); DbgPrint("DHCPCSVC: init_client() failed!\n");
CloseHandle(hAdapterStateChangedEvent);
CloseHandle(hStopEvent);
UpdateServiceStatus(SERVICE_STOPPED);
return;
}
UpdateServiceStatus(SERVICE_START_PENDING);
hPipeThread = PipeInit(hStopEvent);
if (hPipeThread == INVALID_HANDLE_VALUE)
{
DbgPrint("DHCPCSVC: PipeInit() failed!\n");
stop_client();
CloseHandle(hAdapterStateChangedEvent);
CloseHandle(hStopEvent);
UpdateServiceStatus(SERVICE_STOPPED);
return;
}
hDiscoveryThread = StartAdapterDiscovery(hStopEvent);
if (hDiscoveryThread == INVALID_HANDLE_VALUE)
{
DbgPrint("DHCPCSVC: StartAdapterDiscovery() failed!\n");
stop_client();
CloseHandle(hAdapterStateChangedEvent);
CloseHandle(hStopEvent);
UpdateServiceStatus(SERVICE_STOPPED); UpdateServiceStatus(SERVICE_STOPPED);
return; return;
} }
@ -429,8 +469,37 @@ ServiceMain(DWORD argc, LPWSTR* argv)
dispatch(hStopEvent); dispatch(hStopEvent);
DH_DbgPrint(MID_TRACE,("DHCPCSVC: DHCP service is shutting down\n")); DH_DbgPrint(MID_TRACE,("DHCPCSVC: DHCP service is shutting down\n"));
stop_client(); stop_client();
DPRINT("Wait for pipe thread to close! %p\n", hPipeThread);
if (hPipeThread != INVALID_HANDLE_VALUE)
{
DPRINT("Waiting for pipe thread\n");
ret = WaitForSingleObject(hPipeThread, 5000);
DPRINT("Done %lx\n", ret);
}
DPRINT("Wait for discovery thread to close! %p\n", hDiscoveryThread);
if (hDiscoveryThread != INVALID_HANDLE_VALUE)
{
DPRINT("Waiting for discovery thread\n");
ret = WaitForSingleObject(hDiscoveryThread, 5000);
DPRINT("Done %lx\n", ret);
}
DPRINT("Closing events!\n");
CloseHandle(hAdapterStateChangedEvent);
CloseHandle(hStopEvent);
if (DhcpSocket != INVALID_SOCKET)
closesocket(DhcpSocket);
CloseHandle(hDiscoveryThread);
CloseHandle(hPipeThread);
DPRINT("Done!\n");
UpdateServiceStatus(SERVICE_STOPPED); UpdateServiceStatus(SERVICE_STOPPED);
} }

View file

@ -76,7 +76,7 @@ typedef struct _DHCP_ADAPTER {
unsigned char recv_buf[1]; unsigned char recv_buf[1];
} DHCP_ADAPTER, *PDHCP_ADAPTER; } DHCP_ADAPTER, *PDHCP_ADAPTER;
typedef DWORD (*PipeSendFunc)( COMM_DHCP_REPLY *Reply ); typedef DWORD (*PipeSendFunc)(HANDLE CommPipe, COMM_DHCP_REPLY *Reply );
#define random rand #define random rand
#define srandom srand #define srandom srand
@ -85,24 +85,24 @@ int init_client(void);
void stop_client(void); void stop_client(void);
void AdapterInit(VOID); void AdapterInit(VOID);
HANDLE StartAdapterDiscovery(VOID); HANDLE StartAdapterDiscovery(HANDLE hStopEvent);
void AdapterStop(VOID); void AdapterStop(VOID);
extern PDHCP_ADAPTER AdapterGetFirst(VOID); extern PDHCP_ADAPTER AdapterGetFirst(VOID);
extern PDHCP_ADAPTER AdapterGetNext(PDHCP_ADAPTER); extern PDHCP_ADAPTER AdapterGetNext(PDHCP_ADAPTER);
extern PDHCP_ADAPTER AdapterFindIndex( unsigned int AdapterIndex ); extern PDHCP_ADAPTER AdapterFindIndex( unsigned int AdapterIndex );
extern PDHCP_ADAPTER AdapterFindInfo( struct interface_info *info ); extern PDHCP_ADAPTER AdapterFindInfo( struct interface_info *info );
extern PDHCP_ADAPTER AdapterFindByHardwareAddress( u_int8_t haddr[16], u_int8_t hlen ); extern PDHCP_ADAPTER AdapterFindByHardwareAddress( u_int8_t haddr[16], u_int8_t hlen );
extern HANDLE PipeInit(VOID); extern HANDLE PipeInit(HANDLE hStopEvent);
extern VOID ApiInit(VOID); extern VOID ApiInit(VOID);
extern VOID ApiFree(VOID); extern VOID ApiFree(VOID);
extern VOID ApiLock(VOID); extern VOID ApiLock(VOID);
extern VOID ApiUnlock(VOID); extern VOID ApiUnlock(VOID);
extern DWORD DSQueryHWInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ); extern DWORD DSQueryHWInfo( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req );
extern DWORD DSLeaseIpAddress( PipeSendFunc Send, COMM_DHCP_REQ *Req ); extern DWORD DSLeaseIpAddress( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req );
extern DWORD DSRenewIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ); extern DWORD DSRenewIpAddressLease( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req );
extern DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ); extern DWORD DSReleaseIpAddressLease( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req );
extern DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req ); extern DWORD DSStaticRefreshParams( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req );
extern DWORD DSGetAdapterInfo( PipeSendFunc Send, COMM_DHCP_REQ *Req ); extern DWORD DSGetAdapterInfo( PipeSendFunc Send, HANDLE CommPipe, COMM_DHCP_REQ *Req );
extern int inet_aton(const char *s, struct in_addr *addr); extern int inet_aton(const char *s, struct in_addr *addr);
int warn( char *format, ... ); int warn( char *format, ... );