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.

366 lines
8.3 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. service.c
  5. Abstract:
  6. Functions for restarting fax and spooler services
  7. Environment:
  8. Windows NT fax configuration DLL
  9. Revision History:
  10. 05/28/96 -davidx-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "faxcpl.h"
  16. //
  17. // Name of fax and spooler services
  18. //
  19. #define FAX_SERVICE_NAME TEXT("Fax")
  20. #define SPOOLER_SERVICE_NAME TEXT("Spooler")
  21. //
  22. // Information about list of dependent services which we stopped
  23. //
  24. typedef struct {
  25. PVOID pNext;
  26. TCHAR serviceName[1];
  27. } DEPENDENT_SERVICE_LIST, *PDEPENDENT_SERVICE_LIST;
  28. BOOL
  29. MyStartService(
  30. LPTSTR pServerName,
  31. LPTSTR pServiceName
  32. )
  33. /*++
  34. Routine Description:
  35. Start the specified service on the specified server and
  36. wait for the service to be in the running state
  37. Arguments:
  38. pServerName - Specifies the name of the server computer, NULL for local machine
  39. pServiceName - Specifies the name of the service to be started
  40. Return Value:
  41. TRUE if successful, FALSE if there is an error
  42. --*/
  43. {
  44. SC_HANDLE hSvcMgr = NULL;
  45. SC_HANDLE hService = NULL;
  46. SERVICE_STATUS serviceStatus;
  47. BOOL success = FALSE;
  48. Verbose(("Starting service '%ws' ...\n", pServiceName));
  49. //
  50. // Find the specified service and start executing it
  51. //
  52. if ((hSvcMgr = OpenSCManager(pServerName, NULL, SC_MANAGER_ALL_ACCESS)) &&
  53. (hService = OpenService(hSvcMgr, pServiceName, SERVICE_ALL_ACCESS)) &&
  54. (StartService(hService, 0, NULL) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) &&
  55. QueryServiceStatus(hService, &serviceStatus))
  56. {
  57. while (serviceStatus.dwCurrentState != SERVICE_RUNNING) {
  58. DWORD checkPoint = serviceStatus.dwCheckPoint;
  59. Verbose(("Waiting for service '%ws' to run: state = %d\n",
  60. pServiceName,
  61. serviceStatus.dwCurrentState));
  62. Sleep(serviceStatus.dwWaitHint);
  63. if (!QueryServiceStatus(hService, &serviceStatus) ||
  64. checkPoint == serviceStatus.dwCheckPoint)
  65. {
  66. break;
  67. }
  68. }
  69. success = (serviceStatus.dwCurrentState == SERVICE_RUNNING);
  70. }
  71. //
  72. // Cleanup before returning to the caller
  73. //
  74. if (! success)
  75. Error(("Failed to start service '%ws': %d\n", pServiceName, GetLastError()));
  76. if (hService)
  77. CloseServiceHandle(hService);
  78. if (hSvcMgr)
  79. CloseServiceHandle(hSvcMgr);
  80. return success;
  81. }
  82. BOOL
  83. MyStopService(
  84. LPTSTR pServerName,
  85. LPTSTR pServiceName,
  86. PDEPENDENT_SERVICE_LIST *ppDependentList
  87. )
  88. /*++
  89. Routine Description:
  90. Stop the specified service (as well as any services that depend on it)
  91. on the specified server and wait for the service to be in a non-running state
  92. Arguments:
  93. pServerName - Specifies the name of the server computer, NULL for local machine
  94. pServiceName - Specifies the name of the service to be stopped
  95. ppDependentList - Remember the list of dependent services which we stopped
  96. Return Value:
  97. TRUE if successful, FALSE if there is an error
  98. --*/
  99. {
  100. SC_HANDLE hSvcMgr;
  101. SC_HANDLE hService;
  102. BOOL success = FALSE;
  103. Verbose(("Stopping service '%ws' ...\n", pServiceName));
  104. if ((hSvcMgr = OpenSCManager(pServerName, NULL, SC_MANAGER_ALL_ACCESS)) &&
  105. (hService = OpenService(hSvcMgr, pServiceName, SERVICE_ALL_ACCESS)))
  106. {
  107. LPENUM_SERVICE_STATUS pEnumStatus = NULL;
  108. DWORD cb, count, index;
  109. SERVICE_STATUS serviceStatus;
  110. //
  111. // Find all active services which depend on the current service
  112. // and call ourselves recursively to stop those services first
  113. //
  114. success = TRUE;
  115. if (! EnumDependentServices(hService, SERVICE_ACTIVE, NULL, 0, &cb, &count)) {
  116. if (GetLastError() == ERROR_MORE_DATA &&
  117. (pEnumStatus = (LPENUM_SERVICE_STATUS) MemAlloc(cb)) &&
  118. EnumDependentServices(hService, SERVICE_ACTIVE, pEnumStatus, cb, &cb, &count))
  119. {
  120. for (index=0; success && index < count; index++) {
  121. success = MyStopService(pServerName,
  122. pEnumStatus[index].lpServiceName,
  123. ppDependentList);
  124. }
  125. }
  126. MemFree(pEnumStatus);
  127. }
  128. //
  129. // Stop the current service and wait for it to die
  130. //
  131. if (success) {
  132. ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus);
  133. if (success = QueryServiceStatus(hService, &serviceStatus)) {
  134. while (serviceStatus.dwCurrentState != SERVICE_STOPPED) {
  135. DWORD checkPoint = serviceStatus.dwCheckPoint;
  136. Verbose(("Waiting for service '%ws' to stop: state = %d\n",
  137. pServiceName,
  138. serviceStatus.dwCurrentState));
  139. Sleep(serviceStatus.dwWaitHint);
  140. if (!QueryServiceStatus(hService, &serviceStatus) ||
  141. checkPoint == serviceStatus.dwCheckPoint)
  142. {
  143. break;
  144. }
  145. }
  146. success = (serviceStatus.dwCurrentState == SERVICE_STOPPED);
  147. }
  148. }
  149. }
  150. //
  151. // If the service has been successfully stopped, remember its name
  152. // so that we can restart it later.
  153. //
  154. if (success) {
  155. PDEPENDENT_SERVICE_LIST p;
  156. if (p = MemAlloc(offsetof(DEPENDENT_SERVICE_LIST, serviceName) +
  157. SizeOfString(pServiceName)))
  158. {
  159. _tcscpy(p->serviceName, pServiceName);
  160. p->pNext = *ppDependentList;
  161. *ppDependentList = p;
  162. }
  163. success = (p != NULL);
  164. }
  165. //
  166. // Cleanup before returning to the caller
  167. //
  168. if (! success)
  169. Error(("Failed to stop service '%ws': %d\n", pServiceName, GetLastError()));
  170. if (hService)
  171. CloseServiceHandle(hService);
  172. if (hSvcMgr)
  173. CloseServiceHandle(hSvcMgr);
  174. return success;
  175. }
  176. BOOL
  177. StartFaxService(
  178. LPTSTR pServerName
  179. )
  180. /*++
  181. Routine Description:
  182. Start the fax service and
  183. Arguments:
  184. pServerName - Specifies the name of the server computer, NULL for local machine
  185. Return Value:
  186. TRUE if successful, FALSE if there is an error
  187. --*/
  188. {
  189. BOOL success = FALSE;
  190. //
  191. // Start the fax service and wait for it to be in the running state
  192. //
  193. if (MyStartService(pServerName, FAX_SERVICE_NAME)) {
  194. HANDLE hFaxServerEvent;
  195. //
  196. // Wait for the fax service to complete its initialization
  197. //
  198. if (hFaxServerEvent = OpenEvent(SYNCHRONIZE, FALSE, TEXT("FaxServerEvent"))) {
  199. WaitForSingleObject(hFaxServerEvent, INFINITE);
  200. CloseHandle(hFaxServerEvent);
  201. success = TRUE;
  202. } else
  203. Error(("Couldn't open a handle to the fax service event: %d\n", GetLastError()));
  204. }
  205. return success;
  206. }
  207. BOOL
  208. RestartFaxAndSpoolerServices(
  209. LPTSTR pServerName
  210. )
  211. /*++
  212. Routine Description:
  213. Restart fax and spooler services after fax configuration settings are changed
  214. Arguments:
  215. pServerName - Specifies the name of the server computer, NULL for local machine
  216. Return Value:
  217. TRUE if successful, FALSE if there is an error
  218. --*/
  219. {
  220. PDEPENDENT_SERVICE_LIST p, pDependents = NULL;
  221. BOOL result;
  222. //
  223. // Fax service must be stopped after the spooler service
  224. // because it's a dependent service of the spooler.
  225. //
  226. // Start the fax and spooler services in the opposite order,
  227. // i.e., first start the fax service and then the spooler service.
  228. //
  229. result = MyStopService(pServerName, SPOOLER_SERVICE_NAME, &pDependents) &&
  230. MyStopService(pServerName, FAX_SERVICE_NAME, &pDependents) &&
  231. StartFaxService(pServerName);
  232. //
  233. // Start other services which we have stopped above
  234. //
  235. while (pDependents) {
  236. if (result)
  237. result = MyStartService(pServerName, pDependents->serviceName);
  238. p = pDependents;
  239. pDependents = p->pNext;
  240. MemFree(p);
  241. }
  242. return result;
  243. }