/* * Copyright (c) Microsoft Corporation * * Module Name : * main.c * * This is the main file containing the service entry and shutdown routines. * Where possible, code has been obtained from BINL server. * * Sadagopan Rajaram -- Oct 14, 1999 * */ #include "tcsrv.h" #include "tcsrvc.h" #include "proto.h" SERVICE_STATUS_HANDLE TCGlobalServiceStatusHandle; SERVICE_STATUS TCGlobalServiceStatus; VOID ServiceEntry( DWORD NumArgs, LPTSTR *ArgsArray ) /*++ Routine Description This is the main routine for the terminal concentrator service. After initialization, the service processes requests on the main socket until a terminate service has been signalled. Arguments: NumArgs - Number of strings in the ArgsArray ArgsArray - String arguments pGlobalData - Contains the necessary global information needed to start the service Return Value: None ++*/ { // Initialize Status fields NTSTATUS status; TCGlobalServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; TCGlobalServiceStatus.dwCurrentState = SERVICE_START_PENDING; TCGlobalServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PARAMCHANGE ; TCGlobalServiceStatus.dwCheckPoint = 1; TCGlobalServiceStatus.dwWaitHint = 60000; // 60 secs. TCGlobalServiceStatus.dwWin32ExitCode = ERROR_SUCCESS; TCGlobalServiceStatus.dwServiceSpecificExitCode = 0; TCGlobalServiceStatusHandle= RegisterServiceCtrlHandler(TCSERV_NAME, ServiceControlHandler ); if(TCGlobalServiceStatusHandle == INVALID_HANDLE_VALUE){ return; } if(!SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus)){ return; } // Open a well known socket for the client to connect. INITIALIZE_TRACE_MEMORY MainSocket = ServerSocket(); if(MainSocket == INVALID_SOCKET){ // gone case . Terminate Service TCDebugPrint(("Cannot open Socket\n")); return; } // Initialize by getting control of the COM ports and starting threads // for each of them. status = Initialize(); if(status != STATUS_SUCCESS){ TCDebugPrint(("Cannot Initialize\n")); Shutdown(status); return; } // Blindly loops around waiting for a request from the control socket and // processes their requests. status = ProcessRequests(MainSocket); if (status != STATUS_SUCCESS){ TCDebugPrint(("Ended with Error")); } Shutdown(status); return; } DWORD ProcessRequests( SOCKET socket ) /*++ Here we sit around waiting for connections. Once we get a connection, we start a thread to get the required parameters and send the information to the thread processing that COM port. --*/ { int status; SOCKET cli_sock; CLIENT_INFO ClientInfo; struct sockaddr_in cli_addr; int addr_len; ULONG argp; NTSTATUS Status; HANDLE ThreadHandle; PHANDLE NewThreads; ULONG ThreadID; status = listen(socket, SOMAXCONN); if (status == SOCKET_ERROR) { TCDebugPrint(("Cannot listen to socket %x\n",WSAGetLastError())); closesocket(socket); return (WSAGetLastError()); } EnterCriticalSection(&GlobalMutex); if(TCGlobalServiceStatus.dwCurrentState != SERVICE_START_PENDING){ LeaveCriticalSection(&GlobalMutex); return STATUS_SUCCESS; } TCGlobalServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus); LeaveCriticalSection(&GlobalMutex); while(1){ cli_sock = accept(socket,NULL,NULL); if (cli_sock == INVALID_SOCKET){ // got to shutdown - no Error here TCDebugPrint(("Main Socket No more %d\n",GetLastError())); return(STATUS_SUCCESS); } // receive the com port that the client wants to connect to. ThreadHandle=CreateThread(NULL, THREAD_ALL_ACCESS, (LPTHREAD_START_ROUTINE) InitializeComPortConnection, (LPVOID) cli_sock, 0, &ThreadID ); if(ThreadHandle == NULL){ closesocket(cli_sock); TCDebugPrint(("Create connection Thread Failure %lx\n",GetLastError())); } else{ NtClose(ThreadHandle); } } return(0); } DWORD InitializeComPortConnection( SOCKET cli_sock ) { PCOM_PORT_INFO pTempInfo; PCONNECTION_INFO pConn; int i; BOOL ret; ULONG par; DWORD status; CLIENT_INFO ClientInfo; status = recv(cli_sock, (PCHAR) &ClientInfo, sizeof(CLIENT_INFO), 0 ); if((status == SOCKET_ERROR) ||( status == 0)){ //something wrong TCDebugPrint(("Receive Problem %x\n",WSAGetLastError())); closesocket(cli_sock); return 0; } ClientInfo.device[MAX_BUFFER_SIZE -1] = 0; EnterCriticalSection(&GlobalMutex); if(TCGlobalServiceStatus.dwCurrentState == SERVICE_STOP_PENDING){ // Entire Service is shutting down. closesocket(cli_sock); LeaveCriticalSection(&GlobalMutex); return 1; } pTempInfo = FindDevice(ClientInfo.device, &i); if(!pTempInfo){ closesocket(cli_sock); TCDebugPrint(("No Such Device\n")); LeaveCriticalSection(&GlobalMutex); return -1; } MutexLock(pTempInfo); if(pTempInfo->ShuttingDown){ // The Com Port alone is shutting down, so // make sure the socket goes away. closesocket(cli_sock); MutexRelease(pTempInfo); LeaveCriticalSection(&GlobalMutex); return -1; } pConn = TCAllocate(sizeof(CONNECTION_INFO),"New Connection"); if(pConn == NULL){ closesocket(cli_sock); MutexRelease(pTempInfo); LeaveCriticalSection(&GlobalMutex); return -1; } pConn->Socket = cli_sock; // Make the socket non-blocking so that receive // does not wait. i = ioctlsocket(cli_sock, FIONBIO, &par ); if(i == SOCKET_ERROR){ TCDebugPrint(("Error in setting socket parameters %d\n",GetLastError())); } pConn->pComPortInfo = pTempInfo; pConn->Next = pTempInfo->Sockets; pTempInfo->Sockets=pConn; pConn->Flags = ClientInfo.len; (pConn->Buffer).buf = pConn->buffer; (pConn->Buffer).len = MAX_BUFFER_SIZE; (pConn->Overlapped).hEvent = (WSAEVENT) pConn; ret = SetEvent(pTempInfo->Events[1]); if(ret == FALSE){ TCDebugPrint(("Cannot signal object %d\n",GetLastError())); } MutexRelease(pTempInfo); LeaveCriticalSection(&GlobalMutex); return 0; }