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.

293 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ipx\sap\svcsif.c
  5. Abstract:
  6. SAP interface with service controller
  7. (API for standalone SAP agent part of services.exe)
  8. Author:
  9. Vadim Eydelman 05-15-1995
  10. Revision History:
  11. --*/
  12. #include "sapp.h"
  13. // SAP service status (when operating standalone outside of router)
  14. SERVICE_STATUS_HANDLE ServiceStatusHandle;
  15. SERVICE_STATUS ServiceStatus;
  16. volatile HANDLE ServiceThreadHdl;
  17. VOID
  18. ServiceMain (
  19. DWORD argc,
  20. LPTSTR argv[]
  21. );
  22. VOID APIENTRY
  23. ResumeServiceThread (
  24. ULONG_PTR param
  25. ) {
  26. return ;
  27. }
  28. VOID
  29. ServiceHandler (
  30. DWORD fdwControl
  31. ) {
  32. ASSERT (ServiceStatusHandle!=0);
  33. EnterCriticalSection (&OperationalStateLock);
  34. switch (fdwControl) {
  35. case SERVICE_CONTROL_STOP:
  36. case SERVICE_CONTROL_SHUTDOWN:
  37. #if DBG
  38. DbgPrint ("IPXSAP: Service control stop/shutdown.\n");
  39. #endif
  40. if (ServiceIfActive) {
  41. ServiceIfActive = FALSE;
  42. if (ServiceThreadHdl!=NULL) {
  43. BOOL res;
  44. HANDLE localHdl = ServiceThreadHdl;
  45. ServiceThreadHdl = NULL;
  46. #if DBG
  47. DbgPrint ("IPXSAP: Resuming service thread.\n");
  48. #endif
  49. res = QueueUserAPC (
  50. ResumeServiceThread,
  51. localHdl,
  52. 0);
  53. ASSERTMSG ("Could not queue APC to service thread ", res);
  54. CloseHandle (localHdl);
  55. }
  56. ServiceStatus.dwCheckPoint += 1;
  57. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  58. }
  59. else
  60. Trace (DEBUG_FAILURES,
  61. "SAP service has already been told to stop.");
  62. break;
  63. case SERVICE_CONTROL_INTERROGATE:
  64. #if DBG
  65. DbgPrint ("IPXSAP: Service control interrogate.\n");
  66. #endif
  67. switch (OperationalState) {
  68. case OPER_STATE_UP:
  69. if (ServiceIfActive)
  70. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  71. else
  72. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  73. break;
  74. case OPER_STATE_STARTING:
  75. if (ServiceIfActive) {
  76. ServiceStatus.dwCheckPoint += 1;
  77. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  78. }
  79. else
  80. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  81. break;
  82. case OPER_STATE_STOPPING:
  83. if (ServiceIfActive)
  84. // This is the case when router is being stopped
  85. // SAP will be restarted soon
  86. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  87. else {
  88. ServiceStatus.dwCheckPoint += 1;
  89. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  90. }
  91. break;
  92. case OPER_STATE_DOWN:
  93. if (ServiceIfActive) {
  94. // This is the case when service is being started
  95. ServiceStatus.dwCheckPoint += 1;
  96. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  97. }
  98. else
  99. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  100. break;
  101. default:
  102. ASSERTMSG ("SAP is in unknown state ", FALSE);
  103. }
  104. break;
  105. default:
  106. Trace (DEBUG_FAILURES,
  107. "Service control handler called with unknown"
  108. " or unsupported code %d.", fdwControl);
  109. break;
  110. }
  111. #if DBG
  112. DbgPrint ("IPXSAP: Service control setting current state to %d.\n",
  113. ServiceStatus.dwCurrentState);
  114. #endif
  115. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  116. LeaveCriticalSection (&OperationalStateLock);
  117. }
  118. /*++
  119. *******************************************************************
  120. S e r v i c e M a i n
  121. Routine Description:
  122. Entry point to be called by service controller to start SAP agent
  123. (when SAP is not part of the router but is a standalone service,
  124. though running in the router process)
  125. Arguments:
  126. argc - number of string arguments passed to service
  127. argv - array of string arguments passed to service
  128. Return Value:
  129. None
  130. *******************************************************************
  131. --*/
  132. VOID
  133. ServiceMain (
  134. DWORD argc,
  135. LPWSTR argv[]
  136. ) {
  137. DWORD rc;
  138. ServiceStatusHandle = RegisterServiceCtrlHandler (
  139. TEXT("nwsapagent"), ServiceHandler);
  140. if (!ServiceStatusHandle)
  141. {
  142. return;
  143. }
  144. ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  145. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  146. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  147. rc = DuplicateHandle (GetCurrentProcess (),
  148. GetCurrentThread (),
  149. GetCurrentProcess (),
  150. (HANDLE *)&ServiceThreadHdl,
  151. 0,
  152. FALSE,
  153. DUPLICATE_SAME_ACCESS );
  154. ASSERTMSG ("Could not duplicate service thread handle ", rc);
  155. EnterCriticalSection (&OperationalStateLock);
  156. ServiceIfActive = TRUE;
  157. if (RouterIfActive) {
  158. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  159. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
  160. | SERVICE_ACCEPT_SHUTDOWN;
  161. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  162. LeaveCriticalSection (&OperationalStateLock);
  163. #if DBG
  164. DbgPrint ("IPXSAP: Suspending service thread.\n");
  165. #endif
  166. while (ServiceThreadHdl!=NULL) {
  167. SleepEx (INFINITE, TRUE);
  168. #if DBG
  169. DbgPrint ("IPXSAP: Service thread awakened.\n");
  170. #endif
  171. }
  172. #if DBG
  173. DbgPrint ("IPXSAP: Service thread resumed.\n");
  174. #endif
  175. EnterCriticalSection (&OperationalStateLock);
  176. if (!RouterIfActive) {
  177. if (OperationalState==OPER_STATE_UP)
  178. StopSAP ();
  179. LeaveCriticalSection (&OperationalStateLock);
  180. #if DBG
  181. DbgPrint ("IPXSAP: Waiting for main thread to exit.\n");
  182. #endif
  183. rc = WaitForSingleObject (MainThreadHdl, INFINITE);
  184. ASSERTMSG ("Unexpected result from wait for sap main thread ",
  185. rc== WAIT_OBJECT_0);
  186. EnterCriticalSection (&OperationalStateLock);
  187. CloseHandle (MainThreadHdl);
  188. MainThreadHdl = NULL;
  189. }
  190. }
  191. else {
  192. BOOL bInternalNetNumOk;
  193. // [pmay]
  194. // We use this scheme to automatically select the internal network
  195. // number of the machine we're running on. If the net number is configured
  196. // as zero, this function will automatically select a random net num and
  197. // verify it's uniqueness on the net that this machine is attached to.
  198. DbgInitialize (hDLLInstance);
  199. if (AutoValidateInternalNetNum(&bInternalNetNumOk, DEBUG_ADAPTERS) == NO_ERROR) {
  200. if (!bInternalNetNumOk) {
  201. if (PnpAutoSelectInternalNetNumber(DEBUG_ADAPTERS) != NO_ERROR)
  202. Trace(DEBUG_ADAPTERS, "StartRouter: Auto selection of net number failed.");
  203. else
  204. AutoWaitForValidIntNetNum (10, NULL);
  205. }
  206. }
  207. ServiceStatus.dwWin32ExitCode = CreateAllComponents (NULL);
  208. if (ServiceStatus.dwWin32ExitCode==NO_ERROR) {
  209. // We use the thread that we were launched in
  210. // as IO thread
  211. ServiceStatus.dwWin32ExitCode = StartSAP ();
  212. if (ServiceStatus.dwWin32ExitCode==NO_ERROR) {
  213. LeaveCriticalSection (&OperationalStateLock);
  214. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  215. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
  216. | SERVICE_ACCEPT_SHUTDOWN;
  217. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  218. #if DBG
  219. DbgPrint ("IPXSAP: Suspending service thread.\n");
  220. #endif
  221. while (ServiceThreadHdl!=NULL) {
  222. SleepEx (INFINITE, TRUE);
  223. #if DBG
  224. DbgPrint ("IPXSAP: Service thread awakened.\n");
  225. #endif
  226. }
  227. #if DBG
  228. DbgPrint ("IPXSAP: Service thread resumed.\n");
  229. #endif
  230. EnterCriticalSection (&OperationalStateLock);
  231. ServiceIfActive = FALSE;
  232. if (!RouterIfActive) {
  233. if (OperationalState==OPER_STATE_UP)
  234. StopSAP ();
  235. LeaveCriticalSection (&OperationalStateLock);
  236. #if DBG
  237. DbgPrint ("IPXSAP: Waiting for main thread to exit.\n");
  238. #endif
  239. rc = WaitForSingleObject (MainThreadHdl, INFINITE);
  240. ASSERTMSG ("Unexpected result from wait for sap main thread ",
  241. rc== WAIT_OBJECT_0);
  242. EnterCriticalSection (&OperationalStateLock);
  243. }
  244. CloseHandle (MainThreadHdl);
  245. MainThreadHdl = NULL;
  246. }
  247. else {
  248. DeleteAllComponents ();
  249. }
  250. }
  251. }
  252. ServiceIfActive = FALSE;
  253. LeaveCriticalSection (&OperationalStateLock);
  254. #if DBG
  255. DbgPrint ("IPXSAP: Service stopped.\n");
  256. #endif
  257. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  258. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  259. }