Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
7.0 KiB

  1. /*
  2. * Copyright (c) Microsoft Corporation
  3. *
  4. * Module Name :
  5. * main.c
  6. *
  7. * This is the main file containing the service entry and shutdown routines.
  8. * Where possible, code has been obtained from BINL server.
  9. *
  10. * Sadagopan Rajaram -- Oct 14, 1999
  11. *
  12. */
  13. #include "tcsrv.h"
  14. #include "tcsrvc.h"
  15. #include "proto.h"
  16. SERVICE_STATUS_HANDLE TCGlobalServiceStatusHandle;
  17. SERVICE_STATUS TCGlobalServiceStatus;
  18. VOID
  19. ServiceEntry(
  20. DWORD NumArgs,
  21. LPTSTR *ArgsArray
  22. )
  23. /*++
  24. Routine Description
  25. This is the main routine for the terminal concentrator service. After
  26. initialization, the service processes requests on the main socket until
  27. a terminate service has been signalled.
  28. Arguments:
  29. NumArgs - Number of strings in the ArgsArray
  30. ArgsArray - String arguments
  31. pGlobalData - Contains the necessary global information needed to start
  32. the service
  33. Return Value:
  34. None
  35. ++*/
  36. {
  37. // Initialize Status fields
  38. NTSTATUS status;
  39. TCGlobalServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  40. TCGlobalServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  41. TCGlobalServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN
  42. |SERVICE_ACCEPT_STOP
  43. |SERVICE_ACCEPT_PARAMCHANGE ;
  44. TCGlobalServiceStatus.dwCheckPoint = 1;
  45. TCGlobalServiceStatus.dwWaitHint = 60000; // 60 secs.
  46. TCGlobalServiceStatus.dwWin32ExitCode = ERROR_SUCCESS;
  47. TCGlobalServiceStatus.dwServiceSpecificExitCode = 0;
  48. TCGlobalServiceStatusHandle= RegisterServiceCtrlHandler(TCSERV_NAME,
  49. ServiceControlHandler
  50. );
  51. if(TCGlobalServiceStatusHandle == INVALID_HANDLE_VALUE){
  52. return;
  53. }
  54. if(!SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus)){
  55. return;
  56. }
  57. // Open a well known socket for the client to connect.
  58. INITIALIZE_TRACE_MEMORY
  59. MainSocket = ServerSocket();
  60. if(MainSocket == INVALID_SOCKET){
  61. // gone case . Terminate Service
  62. TCDebugPrint(("Cannot open Socket\n"));
  63. return;
  64. }
  65. // Initialize by getting control of the COM ports and starting threads
  66. // for each of them.
  67. status = Initialize();
  68. if(status != STATUS_SUCCESS){
  69. TCDebugPrint(("Cannot Initialize\n"));
  70. Shutdown(status);
  71. return;
  72. }
  73. // Blindly loops around waiting for a request from the control socket and
  74. // processes their requests.
  75. status = ProcessRequests(MainSocket);
  76. if (status != STATUS_SUCCESS){
  77. TCDebugPrint(("Ended with Error"));
  78. }
  79. Shutdown(status);
  80. return;
  81. }
  82. DWORD
  83. ProcessRequests(
  84. SOCKET socket
  85. )
  86. /*++
  87. Here we sit around waiting for connections.
  88. Once we get a connection, we start a thread to get the required parameters
  89. and send the information to the thread processing that COM port.
  90. --*/
  91. {
  92. int status;
  93. SOCKET cli_sock;
  94. CLIENT_INFO ClientInfo;
  95. struct sockaddr_in cli_addr;
  96. int addr_len;
  97. ULONG argp;
  98. NTSTATUS Status;
  99. HANDLE ThreadHandle;
  100. PHANDLE NewThreads;
  101. ULONG ThreadID;
  102. status = listen(socket, SOMAXCONN);
  103. if (status == SOCKET_ERROR) {
  104. TCDebugPrint(("Cannot listen to socket %x\n",WSAGetLastError()));
  105. closesocket(socket);
  106. return (WSAGetLastError());
  107. }
  108. EnterCriticalSection(&GlobalMutex);
  109. if(TCGlobalServiceStatus.dwCurrentState != SERVICE_START_PENDING){
  110. LeaveCriticalSection(&GlobalMutex);
  111. return STATUS_SUCCESS;
  112. }
  113. TCGlobalServiceStatus.dwCurrentState = SERVICE_RUNNING;
  114. SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus);
  115. LeaveCriticalSection(&GlobalMutex);
  116. while(1){
  117. cli_sock = accept(socket,NULL,NULL);
  118. if (cli_sock == INVALID_SOCKET){
  119. // got to shutdown - no Error here
  120. TCDebugPrint(("Main Socket No more %d\n",GetLastError()));
  121. return(STATUS_SUCCESS);
  122. }
  123. // receive the com port that the client wants to connect to.
  124. ThreadHandle=CreateThread(NULL,
  125. THREAD_ALL_ACCESS,
  126. (LPTHREAD_START_ROUTINE) InitializeComPortConnection,
  127. (LPVOID) cli_sock,
  128. 0,
  129. &ThreadID
  130. );
  131. if(ThreadHandle == NULL){
  132. closesocket(cli_sock);
  133. TCDebugPrint(("Create connection Thread Failure %lx\n",GetLastError()));
  134. }
  135. else{
  136. NtClose(ThreadHandle);
  137. }
  138. }
  139. return(0);
  140. }
  141. DWORD
  142. InitializeComPortConnection(
  143. SOCKET cli_sock
  144. )
  145. {
  146. PCOM_PORT_INFO pTempInfo;
  147. PCONNECTION_INFO pConn;
  148. int i;
  149. BOOL ret;
  150. ULONG par;
  151. DWORD status;
  152. CLIENT_INFO ClientInfo;
  153. status = recv(cli_sock,
  154. (PCHAR) &ClientInfo,
  155. sizeof(CLIENT_INFO),
  156. 0
  157. );
  158. if((status == SOCKET_ERROR) ||( status == 0)){
  159. //something wrong
  160. TCDebugPrint(("Receive Problem %x\n",WSAGetLastError()));
  161. closesocket(cli_sock);
  162. return 0;
  163. }
  164. ClientInfo.device[MAX_BUFFER_SIZE -1] = 0;
  165. EnterCriticalSection(&GlobalMutex);
  166. if(TCGlobalServiceStatus.dwCurrentState == SERVICE_STOP_PENDING){
  167. // Entire Service is shutting down.
  168. closesocket(cli_sock);
  169. LeaveCriticalSection(&GlobalMutex);
  170. return 1;
  171. }
  172. pTempInfo = FindDevice(ClientInfo.device, &i);
  173. if(!pTempInfo){
  174. closesocket(cli_sock);
  175. TCDebugPrint(("No Such Device\n"));
  176. LeaveCriticalSection(&GlobalMutex);
  177. return -1;
  178. }
  179. MutexLock(pTempInfo);
  180. if(pTempInfo->ShuttingDown){
  181. // The Com Port alone is shutting down, so
  182. // make sure the socket goes away.
  183. closesocket(cli_sock);
  184. MutexRelease(pTempInfo);
  185. LeaveCriticalSection(&GlobalMutex);
  186. return -1;
  187. }
  188. pConn = TCAllocate(sizeof(CONNECTION_INFO),"New Connection");
  189. if(pConn == NULL){
  190. closesocket(cli_sock);
  191. MutexRelease(pTempInfo);
  192. LeaveCriticalSection(&GlobalMutex);
  193. return -1;
  194. }
  195. pConn->Socket = cli_sock;
  196. // Make the socket non-blocking so that receive
  197. // does not wait.
  198. i = ioctlsocket(cli_sock,
  199. FIONBIO,
  200. &par
  201. );
  202. if(i == SOCKET_ERROR){
  203. TCDebugPrint(("Error in setting socket parameters %d\n",GetLastError()));
  204. }
  205. pConn->pComPortInfo = pTempInfo;
  206. pConn->Next = pTempInfo->Sockets;
  207. pTempInfo->Sockets=pConn;
  208. pConn->Flags = ClientInfo.len;
  209. (pConn->Buffer).buf = pConn->buffer;
  210. (pConn->Buffer).len = MAX_BUFFER_SIZE;
  211. (pConn->Overlapped).hEvent = (WSAEVENT) pConn;
  212. ret = SetEvent(pTempInfo->Events[1]);
  213. if(ret == FALSE){
  214. TCDebugPrint(("Cannot signal object %d\n",GetLastError()));
  215. }
  216. MutexRelease(pTempInfo);
  217. LeaveCriticalSection(&GlobalMutex);
  218. return 0;
  219. }