windows-nt/Source/XPSP1/NT/base/headless/tcsrv/server/unlo.c

149 lines
4 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*
* Copyright (c) Microsoft Corporation
*
* Module Name :
* unlo.c
*
* Shut down and delete functions
* Where possible, code has been obtained from BINL server.
*
* Sadagopan Rajaram -- Oct 14, 1999
*
*/
#include "tcsrv.h"
#include <ntddser.h>
#include "tcsrvc.h"
#include "proto.h"
NTSTATUS
DeleteComPort(
LPTSTR device
)
/*++
Deletes a Com port from the list
--*/
{
BOOL ret;
NTSTATUS Status;
PCOM_PORT_INFO pPrev,pComPortInfo;
HANDLE Thread;
int index,i;
EnterCriticalSection(&GlobalMutex);
if(TCGlobalServiceStatus.dwCurrentState == SERVICE_STOP_PENDING){
// Entire Service is shutting down.
LeaveCriticalSection(&GlobalMutex);
return STATUS_SUCCESS;
} // find the device needed to be deleted.
pComPortInfo = FindDevice(device,&index);
if(!pComPortInfo){
// Bah ! give me an existing device.
LeaveCriticalSection(&GlobalMutex);
return (STATUS_OBJECT_NAME_NOT_FOUND);
}
// Set the terminate event on the com port.
ret = SetEvent(pComPortInfo->Events[3]);
Thread = Threads[index];
LeaveCriticalSection(&GlobalMutex);
// wait for the com port thread to finish.
Status = NtWaitForSingleObject(Thread, FALSE, NULL);
if (Status == WAIT_FAILED) {
// catastrophe
return Status;
}
EnterCriticalSection(&GlobalMutex);
// do this again as another delete or insert may have
// changed the index, though how is beyond me :-)
// if we are already shutting down the service.
if(TCGlobalServiceStatus.dwCurrentState == SERVICE_STOP_PENDING){
// Entire Service is shutting down.
LeaveCriticalSection(&GlobalMutex);
return STATUS_SUCCESS;
}
pComPortInfo = FindDevice(device,&index);
if(!pComPortInfo){
LeaveCriticalSection(&GlobalMutex);
return (STATUS_OBJECT_NAME_NOT_FOUND);
}
if(pComPortInfo == ComPortInfo){
ComPortInfo = pComPortInfo->Next;
}
else{
pPrev = ComPortInfo;
while(pPrev->Next != pComPortInfo){// Can never fail
pPrev = pPrev->Next;
}
pPrev->Next = pComPortInfo->Next;
}
pComPortInfo->Next = NULL;
FreeComPortInfo(pComPortInfo);
NtClose(Threads[index]);
for(i=index;i<ComPorts-1;i++){
// move the threads array to the proper place
Threads[i]=Threads[i+1];
}
ComPorts --;
if(ComPorts == 0){
TCFree(Threads);
Threads=NULL;
}
LeaveCriticalSection(&GlobalMutex);
return(STATUS_SUCCESS);
}
VOID
Shutdown(
NTSTATUS Status
)
/*++
Cleanly shut down the service. delete all threads, cancel all outstanding IRPs.
Close all open sockets.
--*/
{
PCOM_PORT_INFO pTemp;
int i;
SetEvent(TerminateService); // all threads down
// Can do this another way,
// We can take each comport device and
// delete it using the DeleteComPort
// function. But, this allows for maximum
// parallelism even in shutting down :-)
if(Threads){
WaitForMultipleObjects(ComPorts,Threads, TRUE, INFINITE);
// BUGBUG - what if thread is a rougue thread and
// never comes back. Must use some reasonable
// time out.
// Theory says INFINITE is the safest :-)
}
//All threads terminated.
// Now start freeing all global memory
// just using the locks as a safety measure.
EnterCriticalSection(&GlobalMutex);
while(ComPortInfo){
pTemp = ComPortInfo;
ComPortInfo=pTemp->Next;
pTemp->Next = NULL;
FreeComPortInfo(pTemp);
}
TCFree(Threads);
NtClose(TerminateService);
LeaveCriticalSection(&GlobalMutex);
UNINITIALIZE_TRACE_MEMORY
//All done, now print status and exit.
TCGlobalServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus);
TCDebugPrint(("Shutdown Status = %lx\n",Status));
return;
}