|
|
/*
* Copyright (c) Microsoft Corporation * * Module Name : * handler.c * * Service Handler functions * Where possible, code has been obtained from BINL server. * * Sadagopan Rajaram -- Oct 25, 1999 * */ #include "tcsrv.h"
#include "tcsrvc.h"
#include "proto.h"
VOID ServiceControlHandler( IN DWORD Opcode ) /*++
Routine Description:
This is the service control handler of the Terminal Concentrator
Arguments:
Opcode - Supplies a value which specifies the action for the service to perform.
Return Value:
None.
--*/ { DWORD Error;
switch (Opcode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: EnterCriticalSection(&GlobalMutex); // We set the global state to a stop pending while the
// com ports destroy themselves.
// This is triggered by destroying the main socket.
TCGlobalServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus); closesocket(MainSocket); LeaveCriticalSection(&GlobalMutex); break; case SERVICE_CONTROL_PARAMCHANGE:
EnterCriticalSection(&GlobalMutex); // If we are not currently running, but have been sent too many
// control parameter change requests, we say return.
if(TCGlobalServiceStatus.dwCurrentState != SERVICE_RUNNING){ LeaveCriticalSection(&GlobalMutex); return; } TCGlobalServiceStatus.dwCurrentState = SERVICE_PAUSED; SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus); LeaveCriticalSection(&GlobalMutex); // Does the actual work of munging through the registry and
// finding out changes.
UpdateChanges(); break; }
return; }
VOID UpdateChanges( ) /*++
Reads the parameters from the registry and then tries to add or delete com ports as necessary --*/ {
PCOM_PORT_INFO pTempInfo; PCOM_PORT_INFO pTemp; PCOM_PORT_INFO addedPorts; LPTSTR device; LPTSTR name; BOOLEAN addPort; HKEY hKey, hParameter; NTSTATUS Status; int index; LONG RetVal; HANDLE lock; addedPorts = NULL; hKey = NULL;
EnterCriticalSection(&GlobalMutex); pTempInfo = ComPortInfo; while(pTempInfo != NULL){ // Sets the flag of Deleted to TRUE
// for all COM ports. If they are found
// unchanged in the registry, we can leave
// them. Changing session names are ok.
pTempInfo->Deleted = TRUE; pTempInfo= pTempInfo->Next; } LeaveCriticalSection(&GlobalMutex); RetVal = TCLock(&lock); if(RetVal != ERROR_SUCCESS){ TCDebugPrint(("Cannot Lock Registry %d\n", RetVal)); goto end; } RetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, HKEY_TCSERV_PARAMETER_KEY, 0, KEY_ALL_ACCESS, &hKey ); if(RetVal != ERROR_SUCCESS){ TCUnlock(lock); TCDebugPrint(("Cannot open Registry Key %d\n", RetVal)); goto end; } // Read the correct parameters from the registry until you get no more.
index= 0; while(1) { RetVal = GetNextParameter(hKey, index, &hParameter, &name ); if (RetVal == ERROR_NO_MORE_ITEMS) { TCUnlock(lock); TCDebugPrint(("Done with registry %d\n",index)); break; } if(RetVal != ERROR_SUCCESS){ TCUnlock(lock); TCDebugPrint(("Error reading registry %d\n",RetVal)); goto end; } RetVal = GetNameOfDeviceFromRegistry(hParameter, &device ); if(RetVal != ERROR_SUCCESS){ TCFree(name); continue; } pTempInfo = GetComPortParameters(hParameter); RegCloseKey(hParameter); if(pTempInfo == NULL){ TCFree(name); TCFree(device); RegCloseKey(hKey); TCUnlock(lock); goto end; } pTempInfo->Device.Buffer = device; pTempInfo->Name.Buffer = name; pTempInfo->Name.Length = _tcslen(pTempInfo->Name.Buffer)*sizeof(TCHAR); pTempInfo->Device.Length = _tcslen(pTempInfo->Device.Buffer) * sizeof(TCHAR);
EnterCriticalSection(&GlobalMutex); if(TCGlobalServiceStatus.dwCurrentState != SERVICE_PAUSED){ // Somehow, the service has been shut down.
RegCloseKey(hKey); FreeComPortInfo(pTempInfo); LeaveCriticalSection(&GlobalMutex); TCUnlock(lock); goto end; } pTemp = ComPortInfo; addPort = TRUE; while(pTemp){ RetVal = ComPortInfoCompare(pTemp, pTempInfo); if(RetVal == SAME_ALL){ pTemp->Deleted = FALSE; addPort = FALSE; break; } if (RetVal == SAME_DEVICE) { // User has changed configuration
// settings
addPort = TRUE; break; } if (RetVal == DIFFERENT_SESSION) { // Only session name has changed. So, we do not
// need to delete the device.
pTemp->Deleted = FALSE; addPort = FALSE; TCFree(pTemp->Name.Buffer); pTemp->Name.Buffer = pTempInfo->Name.Buffer; pTempInfo->Name.Buffer = NULL; break; } // Different devices, so continue searching
pTemp=pTemp->Next; } LeaveCriticalSection(&GlobalMutex); if (addPort == FALSE) { FreeComPortInfo(pTempInfo); } else{ pTempInfo->Next = addedPorts; addedPorts= pTempInfo; } index++; }
while(1){ EnterCriticalSection(&GlobalMutex); if(TCGlobalServiceStatus.dwCurrentState != SERVICE_PAUSED){ LeaveCriticalSection(&GlobalMutex); goto end; } pTempInfo = ComPortInfo; device = NULL; while(pTempInfo){ if(pTempInfo->Deleted){ // This is true if the configuration settings are
// changed or if the device has been really deleted.
device = pTempInfo->Device.Buffer; break; } pTempInfo = pTempInfo->Next; } LeaveCriticalSection(&GlobalMutex); if(device){ Status = DeleteComPort(device); } else{ break; } }
while(addedPorts){ pTempInfo = addedPorts; addedPorts = addedPorts->Next; Status = AddComPort(pTempInfo); if(Status != STATUS_SUCCESS){ FreeComPortInfo(pTempInfo); TCDebugPrint(("Could not Initialize Com Port %x\n",Status)); } } end: while (addedPorts) { // We may have come here after an error condition.
pTempInfo = addedPorts; addedPorts = pTempInfo->Next; pTempInfo->Next = NULL; FreeComPortInfo(pTempInfo);
} EnterCriticalSection(&GlobalMutex); if(TCGlobalServiceStatus.dwCurrentState != SERVICE_PAUSED){ LeaveCriticalSection(&GlobalMutex); return ; } TCGlobalServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus); LeaveCriticalSection(&GlobalMutex); return;
}
int ComPortInfoCompare( PCOM_PORT_INFO com1, PCOM_PORT_INFO com2 ) { int ret;
if (_tcscmp(com1->Device.Buffer, com2->Device.Buffer)) { // Different Devices
return DIFFERENT_DEVICES; } // Same device
ret = SAME_DEVICE; if ((com1->Parity != com2->Parity) || (com1->StopBits != com2->StopBits) || (com1->WordLength != com2->WordLength)|| (com1->BaudRate != com2->BaudRate)){ return ret; } if (_tcscmp(com1->Name.Buffer, com2->Name.Buffer)) { // Different Devices
return DIFFERENT_SESSION; } return SAME_ALL; }
|