windows-nt/Source/XPSP1/NT/termsrv/license/tlserver/server/npipe.cpp

425 lines
9.7 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-1996
//
// File: npipe.c
//
// Contents:
//
// History: 12-09-98 HueiWang Created
//
// Note:
//---------------------------------------------------------------------------
#include "pch.cpp"
#include <tchar.h>
#include <process.h>
#include "server.h"
#include "lscommon.h"
#include "globals.h"
#include "debug.h"
#define NAMEPIPE_BUFFER_SIZE 512
#define NAMEPIPE_INSTANCE 2
unsigned int WINAPI
NamedPipeThread(
void* ptr
);
//---------------------------------------------------------------------
DWORD
InitNamedPipeThread()
/*++
++*/
{
HANDLE hThread = NULL;
unsigned int dwThreadId;
HANDLE hEvent = NULL;
DWORD dwStatus = ERROR_SUCCESS;
HANDLE waithandles[2];
//
// Create a event for namedpipe thread to signal it is ready.
//
hEvent = CreateEvent(
NULL,
FALSE,
FALSE, // non-signal
NULL
);
if(hEvent == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
hThread = (HANDLE)_beginthreadex(
NULL,
0,
NamedPipeThread,
hEvent,
0,
&dwThreadId
);
if(hThread == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
waithandles[0] = hEvent;
waithandles[1] = hThread;
//
// Wait 30 second for thread to complet initialization
//
dwStatus = WaitForMultipleObjects(
sizeof(waithandles)/sizeof(waithandles[0]),
waithandles,
FALSE,
30*1000
);
if(dwStatus == WAIT_OBJECT_0)
{
//
// thread is ready
//
dwStatus = ERROR_SUCCESS;
}
else
{
if(dwStatus == (WAIT_OBJECT_0 + 1))
{
//
// Thread terminate abnormally
//
GetExitCodeThread(
hThread,
&dwStatus
);
}
else
{
dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
}
}
cleanup:
if(hEvent != NULL)
{
CloseHandle(hEvent);
}
if(hThread != NULL)
{
CloseHandle(hThread);
}
return dwStatus;
}
//------------------------------------------------------------------------
typedef struct {
OVERLAPPED ol;
HANDLE hPipeInst;
} PIPEINST, *LPPIPEINST;
//------------------------------------------------------------------------
BOOL
ConnectToNewClient(
HANDLE hPipe,
LPOVERLAPPED lpo
)
/*++
++*/
{
BOOL bSuccess = FALSE;
// Start an overlapped connection for this pipe instance.
bSuccess = ConnectNamedPipe(hPipe, lpo);
//
// Overlapped ConnectNamedPipe should return zero.
//
if(bSuccess == TRUE)
{
return FALSE;
}
switch (GetLastError())
{
// The overlapped connection in progress.
case ERROR_IO_PENDING:
bSuccess = TRUE;
break;
// Client is already connected, so signal an event.
case ERROR_PIPE_CONNECTED:
bSuccess = TRUE;
// If an error occurs during the connect operation...
if(SetEvent(lpo->hEvent))
break;
default:
bSuccess = FALSE;
}
return bSuccess;
}
//------------------------------------------------------------------------
unsigned int WINAPI
NamedPipeThread(
void* ptr
)
/*++
++*/
{
DWORD dwStatus=ERROR_SUCCESS;
DWORD dwIndex;
HANDLE hReady = (HANDLE)ptr;
TCHAR szPipeName[MAX_PATH+1];
PIPEINST Pipe[NAMEPIPE_INSTANCE];
HANDLE hOlEvent[NAMEPIPE_INSTANCE];
DWORD cbMessage, cbRead, cbToRead, cMessages;
BYTE pbMessage[NAMEPIPE_BUFFER_SIZE+1];
HANDLE waitHandles[NAMEPIPE_INSTANCE+1];
BOOL bResult=TRUE;
//SECURITY_ATTRIBUTES SecurityAttributes;
//SECURITY_DESCRIPTOR SecurityDescriptor;
int i;
//------------------------------------------------
ZeroMemory(Pipe, sizeof(Pipe));
ZeroMemory(hOlEvent, sizeof(hOlEvent));
//
// Create a inbound name pipe, server only listen.
//
wsprintf(
szPipeName,
_TEXT("\\\\.\\pipe\\%s"),
_TEXT(SZSERVICENAME)
);
//
// init values
//
for(i = 0; i < NAMEPIPE_INSTANCE; i++)
{
Pipe[i].hPipeInst = INVALID_HANDLE_VALUE;
}
//
// Create namedpipe
//
for(i=0; i < NAMEPIPE_INSTANCE; i++)
{
hOlEvent[i] = CreateEvent(
NULL,
TRUE,
TRUE,
NULL
);
if(hOlEvent[i] == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
Pipe[i].ol.hEvent = hOlEvent[i];
Pipe[i].hPipeInst = CreateNamedPipe(
szPipeName,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
NAMEPIPE_INSTANCE,
0,
NAMEPIPE_BUFFER_SIZE,
NMPWAIT_USE_DEFAULT_WAIT,
NULL // &SecurityAttributes
);
if(Pipe[i].hPipeInst == INVALID_HANDLE_VALUE)
{
dwStatus = GetLastError();
goto cleanup;
}
//
// Initiate connect
//
bResult = ConnectToNewClient(
Pipe[i].hPipeInst,
&(Pipe[i].ol)
);
if(bResult == FALSE)
{
dwStatus = GetLastError();
goto cleanup;
}
}
//
// Signal we are ready
//
SetEvent(hReady);
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_INIT,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("NamedPipe : Ready...\n")
);
waitHandles[0] = GetServiceShutdownHandle();
for(i=1; i <= NAMEPIPE_INSTANCE; i++)
{
waitHandles[i] = hOlEvent[i-1];
}
//
// Forever loop
//
while(TRUE)
{
//
// Wait for pipe or shutdown messages
//
dwStatus = WaitForMultipleObjects(
sizeof(waitHandles)/sizeof(waitHandles[0]),
waitHandles,
FALSE,
INFINITE
);
if(dwStatus == WAIT_FAILED)
{
SetLastError(dwStatus = TLS_E_INTERNAL);
break;
}
if(dwStatus == WAIT_OBJECT_0)
{
//
// shutdown
//
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_INIT,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("NamedPipe : System Shutdown...\n")
);
dwStatus = ERROR_SUCCESS;
break;
}
dwIndex = (dwStatus - 1) - WAIT_OBJECT_0;
if(dwIndex > (NAMEPIPE_INSTANCE-1))
{
//
// some internal error
//
SetLastError(dwStatus = TLS_E_INTERNAL);
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_INIT,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("NamedPipe : Internal Error...\n")
);
break;
}
//
// Read everything and discard it.
//
bResult = GetOverlappedResult(
Pipe[dwIndex].hPipeInst,
&(Pipe[dwIndex].ol),
&cbToRead, // can't count on this value
TRUE
);
if(bResult == TRUE)
{
//
// Junk messages...
//
bResult = ReadFile(
Pipe[dwIndex].hPipeInst,
pbMessage,
sizeof(pbMessage),
&cbRead,
&(Pipe[dwIndex].ol)
);
if(bResult == TRUE && cbRead != 0)
continue;
dwStatus = GetLastError();
if(dwStatus == ERROR_IO_PENDING)
continue;
}
//
// Any error, just disconnect named pipe
//
DisconnectNamedPipe(Pipe[dwIndex].hPipeInst);
ConnectToNewClient(
Pipe[dwIndex].hPipeInst,
&(Pipe[dwIndex].ol)
);
}
cleanup:
for(i = 0; i < NAMEPIPE_INSTANCE; i++)
{
if(Pipe[i].hPipeInst != INVALID_HANDLE_VALUE)
{
CloseHandle(Pipe[i].hPipeInst);
}
if(hOlEvent[i] != NULL)
{
CloseHandle(hOlEvent[i]);
}
}
_endthreadex(dwStatus);
return dwStatus;
}