reactos/base/services/dhcpcsvc/dhcp/pipe.c
Eric Kohl 033b6639e4 [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
2021-08-08 14:10:25 +02:00

175 lines
5.3 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: subsys/system/dhcp/pipe.c
* PURPOSE: DHCP client pipe
* PROGRAMMER: arty
*/
#include <rosdhcp.h>
#define NDEBUG
#include <reactos/debug.h>
#define COMM_PIPE_OUTPUT_BUFFER sizeof(COMM_DHCP_REQ)
#define COMM_PIPE_INPUT_BUFFER sizeof(COMM_DHCP_REPLY)
#define COMM_PIPE_DEFAULT_TIMEOUT 1000
DWORD PipeSend( HANDLE CommPipe, COMM_DHCP_REPLY *Reply ) {
DWORD Written = 0;
OVERLAPPED Overlapped = {0};
BOOL Success =
WriteFile( CommPipe,
Reply,
sizeof(*Reply),
&Written,
&Overlapped);
if (!Success)
{
WaitForSingleObject(CommPipe, INFINITE);
Success = GetOverlappedResult(CommPipe,
&Overlapped,
&Written,
TRUE);
}
return Success ? Written : -1;
}
DWORD WINAPI PipeThreadProc( LPVOID Parameter ) {
DWORD BytesRead;
COMM_DHCP_REQ Req;
COMM_DHCP_REPLY Reply;
BOOL Result, Connected;
HANDLE Events[2];
HANDLE CommPipe;
OVERLAPPED Overlapped = {0};
DWORD dwError;
DPRINT("PipeThreadProc(%p)\n", Parameter);
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) {
DbgPrint("DHCP: Could not connect named pipe\n");
CloseHandle( CommPipe );
CommPipe = INVALID_HANDLE_VALUE;
break;
}
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 ) {
switch( Req.Type ) {
case DhcpReqQueryHWInfo:
DSQueryHWInfo( PipeSend, CommPipe, &Req );
break;
case DhcpReqLeaseIpAddress:
DSLeaseIpAddress( PipeSend, CommPipe, &Req );
break;
case DhcpReqReleaseIpAddress:
DSReleaseIpAddressLease( PipeSend, CommPipe, &Req );
break;
case DhcpReqRenewIpAddress:
DSRenewIpAddressLease( PipeSend, CommPipe, &Req );
break;
case DhcpReqStaticRefreshParams:
DSStaticRefreshParams( PipeSend, CommPipe, &Req );
break;
case DhcpReqGetAdapterInfo:
DSGetAdapterInfo( PipeSend, CommPipe, &Req );
break;
default:
DPRINT1("Unrecognized request type %d\n", Req.Type);
ZeroMemory( &Reply, sizeof( COMM_DHCP_REPLY ) );
Reply.Reply = 0;
PipeSend(CommPipe, &Reply );
break;
}
}
DisconnectNamedPipe( CommPipe );
}
DPRINT("Pipe thread stopped!\n");
return TRUE;
}
HANDLE PipeInit(HANDLE hStopEvent)
{
return CreateThread( NULL, 0, PipeThreadProc, (LPVOID)hStopEvent, 0, NULL);
}