149 lines
4 KiB
C
149 lines
4 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
|
||
|
|