Leaked source code of windows server 2003
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.

296 lines
8.7 KiB

  1. /*
  2. * Copyright (c) Microsoft Corporation
  3. *
  4. * Module Name :
  5. * handler.c
  6. *
  7. * Service Handler functions
  8. * Where possible, code has been obtained from BINL server.
  9. *
  10. * Sadagopan Rajaram -- Oct 25, 1999
  11. *
  12. */
  13. #include "tcsrv.h"
  14. #include "tcsrvc.h"
  15. #include "proto.h"
  16. VOID
  17. ServiceControlHandler(
  18. IN DWORD Opcode
  19. )
  20. /*++
  21. Routine Description:
  22. This is the service control handler of the Terminal Concentrator
  23. Arguments:
  24. Opcode - Supplies a value which specifies the action for the
  25. service to perform.
  26. Return Value:
  27. None.
  28. --*/
  29. {
  30. DWORD Error;
  31. switch (Opcode) {
  32. case SERVICE_CONTROL_STOP:
  33. case SERVICE_CONTROL_SHUTDOWN:
  34. EnterCriticalSection(&GlobalMutex);
  35. // We set the global state to a stop pending while the
  36. // com ports destroy themselves.
  37. // This is triggered by destroying the main socket.
  38. TCGlobalServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  39. SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus);
  40. closesocket(MainSocket);
  41. LeaveCriticalSection(&GlobalMutex);
  42. break;
  43. case SERVICE_CONTROL_PARAMCHANGE:
  44. EnterCriticalSection(&GlobalMutex);
  45. // If we are not currently running, but have been sent too many
  46. // control parameter change requests, we say return.
  47. if(TCGlobalServiceStatus.dwCurrentState != SERVICE_RUNNING){
  48. LeaveCriticalSection(&GlobalMutex);
  49. return;
  50. }
  51. TCGlobalServiceStatus.dwCurrentState = SERVICE_PAUSED;
  52. SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus);
  53. LeaveCriticalSection(&GlobalMutex);
  54. // Does the actual work of munging through the registry and
  55. // finding out changes.
  56. UpdateChanges();
  57. break;
  58. }
  59. return;
  60. }
  61. VOID UpdateChanges(
  62. )
  63. /*++
  64. Reads the parameters from the registry and then tries to add or delete com
  65. ports as necessary
  66. --*/
  67. {
  68. PCOM_PORT_INFO pTempInfo;
  69. PCOM_PORT_INFO pTemp;
  70. PCOM_PORT_INFO addedPorts;
  71. LPTSTR device;
  72. LPTSTR name;
  73. BOOLEAN addPort;
  74. HKEY hKey, hParameter;
  75. NTSTATUS Status;
  76. int index;
  77. LONG RetVal;
  78. HANDLE lock;
  79. addedPorts = NULL;
  80. hKey = NULL;
  81. EnterCriticalSection(&GlobalMutex);
  82. pTempInfo = ComPortInfo;
  83. while(pTempInfo != NULL){
  84. // Sets the flag of Deleted to TRUE
  85. // for all COM ports. If they are found
  86. // unchanged in the registry, we can leave
  87. // them. Changing session names are ok.
  88. pTempInfo->Deleted = TRUE;
  89. pTempInfo= pTempInfo->Next;
  90. }
  91. LeaveCriticalSection(&GlobalMutex);
  92. RetVal = TCLock(&lock);
  93. if(RetVal != ERROR_SUCCESS){
  94. TCDebugPrint(("Cannot Lock Registry %d\n", RetVal));
  95. goto end;
  96. }
  97. RetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  98. HKEY_TCSERV_PARAMETER_KEY,
  99. 0,
  100. KEY_ALL_ACCESS,
  101. &hKey
  102. );
  103. if(RetVal != ERROR_SUCCESS){
  104. TCUnlock(lock);
  105. TCDebugPrint(("Cannot open Registry Key %d\n", RetVal));
  106. goto end;
  107. }
  108. // Read the correct parameters from the registry until you get no more.
  109. index= 0;
  110. while(1) {
  111. RetVal = GetNextParameter(hKey,
  112. index,
  113. &hParameter,
  114. &name
  115. );
  116. if (RetVal == ERROR_NO_MORE_ITEMS) {
  117. TCUnlock(lock);
  118. TCDebugPrint(("Done with registry %d\n",index));
  119. break;
  120. }
  121. if(RetVal != ERROR_SUCCESS){
  122. TCUnlock(lock);
  123. TCDebugPrint(("Error reading registry %d\n",RetVal));
  124. goto end;
  125. }
  126. RetVal = GetNameOfDeviceFromRegistry(hParameter,
  127. &device
  128. );
  129. if(RetVal != ERROR_SUCCESS){
  130. TCFree(name);
  131. continue;
  132. }
  133. pTempInfo = GetComPortParameters(hParameter);
  134. RegCloseKey(hParameter);
  135. if(pTempInfo == NULL){
  136. TCFree(name);
  137. TCFree(device);
  138. RegCloseKey(hKey);
  139. TCUnlock(lock);
  140. goto end;
  141. }
  142. pTempInfo->Device.Buffer = device;
  143. pTempInfo->Name.Buffer = name;
  144. pTempInfo->Name.Length = _tcslen(pTempInfo->Name.Buffer)*sizeof(TCHAR);
  145. pTempInfo->Device.Length = _tcslen(pTempInfo->Device.Buffer) * sizeof(TCHAR);
  146. EnterCriticalSection(&GlobalMutex);
  147. if(TCGlobalServiceStatus.dwCurrentState != SERVICE_PAUSED){
  148. // Somehow, the service has been shut down.
  149. RegCloseKey(hKey);
  150. FreeComPortInfo(pTempInfo);
  151. LeaveCriticalSection(&GlobalMutex);
  152. TCUnlock(lock);
  153. goto end;
  154. }
  155. pTemp = ComPortInfo;
  156. addPort = TRUE;
  157. while(pTemp){
  158. RetVal = ComPortInfoCompare(pTemp, pTempInfo);
  159. if(RetVal == SAME_ALL){
  160. pTemp->Deleted = FALSE;
  161. addPort = FALSE;
  162. break;
  163. }
  164. if (RetVal == SAME_DEVICE) {
  165. // User has changed configuration
  166. // settings
  167. addPort = TRUE;
  168. break;
  169. }
  170. if (RetVal == DIFFERENT_SESSION) {
  171. // Only session name has changed. So, we do not
  172. // need to delete the device.
  173. pTemp->Deleted = FALSE;
  174. addPort = FALSE;
  175. TCFree(pTemp->Name.Buffer);
  176. pTemp->Name.Buffer = pTempInfo->Name.Buffer;
  177. pTempInfo->Name.Buffer = NULL;
  178. break;
  179. }
  180. // Different devices, so continue searching
  181. pTemp=pTemp->Next;
  182. }
  183. LeaveCriticalSection(&GlobalMutex);
  184. if (addPort == FALSE) {
  185. FreeComPortInfo(pTempInfo);
  186. }
  187. else{
  188. pTempInfo->Next = addedPorts;
  189. addedPorts= pTempInfo;
  190. }
  191. index++;
  192. }
  193. while(1){
  194. EnterCriticalSection(&GlobalMutex);
  195. if(TCGlobalServiceStatus.dwCurrentState != SERVICE_PAUSED){
  196. LeaveCriticalSection(&GlobalMutex);
  197. goto end;
  198. }
  199. pTempInfo = ComPortInfo;
  200. device = NULL;
  201. while(pTempInfo){
  202. if(pTempInfo->Deleted){
  203. // This is true if the configuration settings are
  204. // changed or if the device has been really deleted.
  205. device = pTempInfo->Device.Buffer;
  206. break;
  207. }
  208. pTempInfo = pTempInfo->Next;
  209. }
  210. LeaveCriticalSection(&GlobalMutex);
  211. if(device){
  212. Status = DeleteComPort(device);
  213. }
  214. else{
  215. break;
  216. }
  217. }
  218. while(addedPorts){
  219. pTempInfo = addedPorts;
  220. addedPorts = addedPorts->Next;
  221. Status = AddComPort(pTempInfo);
  222. if(Status != STATUS_SUCCESS){
  223. FreeComPortInfo(pTempInfo);
  224. TCDebugPrint(("Could not Initialize Com Port %x\n",Status));
  225. }
  226. }
  227. end:
  228. while (addedPorts) {
  229. // We may have come here after an error condition.
  230. pTempInfo = addedPorts;
  231. addedPorts = pTempInfo->Next;
  232. pTempInfo->Next = NULL;
  233. FreeComPortInfo(pTempInfo);
  234. }
  235. EnterCriticalSection(&GlobalMutex);
  236. if(TCGlobalServiceStatus.dwCurrentState != SERVICE_PAUSED){
  237. LeaveCriticalSection(&GlobalMutex);
  238. return ;
  239. }
  240. TCGlobalServiceStatus.dwCurrentState = SERVICE_RUNNING;
  241. SetServiceStatus(TCGlobalServiceStatusHandle, &TCGlobalServiceStatus);
  242. LeaveCriticalSection(&GlobalMutex);
  243. return;
  244. }
  245. int
  246. ComPortInfoCompare(
  247. PCOM_PORT_INFO com1,
  248. PCOM_PORT_INFO com2
  249. )
  250. {
  251. int ret;
  252. if (_tcscmp(com1->Device.Buffer, com2->Device.Buffer)) {
  253. // Different Devices
  254. return DIFFERENT_DEVICES;
  255. }
  256. // Same device
  257. ret = SAME_DEVICE;
  258. if ((com1->Parity != com2->Parity) ||
  259. (com1->StopBits != com2->StopBits) ||
  260. (com1->WordLength != com2->WordLength)||
  261. (com1->BaudRate != com2->BaudRate)){
  262. return ret;
  263. }
  264. if (_tcscmp(com1->Name.Buffer, com2->Name.Buffer)) {
  265. // Different Devices
  266. return DIFFERENT_SESSION;
  267. }
  268. return SAME_ALL;
  269. }