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.

354 lines
12 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include <winsvc.h>
  4. #include <winsock.h>
  5. #include <nspapi.h>
  6. #include <tchar.h>
  7. #define PROCESS_SIZE 16
  8. INT InetStartService( LPCTSTR lpServiceName );
  9. TCHAR gServicesWhichMustBeRestarted[20][PROCESS_SIZE];
  10. int gServicesWhichMustBeRestarted_nextuse;
  11. int gServicesWhichMustBeRestarted_total;
  12. int ServicesRestartList_EntryExists(LPCTSTR szServiceName)
  13. {
  14. int iFoundMatch = FALSE;
  15. // loop thru the whole list
  16. for(int i=0; i < gServicesWhichMustBeRestarted_total;i++)
  17. {
  18. if (_tcsicmp(gServicesWhichMustBeRestarted[i], szServiceName) == 0)
  19. {
  20. iFoundMatch = TRUE;
  21. break;
  22. }
  23. }
  24. return iFoundMatch;
  25. }
  26. int ServicesRestartList_Add(LPCTSTR szServiceName)
  27. {
  28. DbgPrint(("ServicesRestartList_Add() on Service %S"), szServiceName);
  29. // check if this value already exists in the globalarary
  30. if (ServicesRestartList_EntryExists(szServiceName)) {return FALSE;}
  31. // move info into global array
  32. if (gServicesWhichMustBeRestarted_nextuse <= 20)
  33. {
  34. _tcscpy(gServicesWhichMustBeRestarted[gServicesWhichMustBeRestarted_nextuse],szServiceName);
  35. // increment counter to array
  36. // increment next use space
  37. ++gServicesWhichMustBeRestarted_total;
  38. ++gServicesWhichMustBeRestarted_nextuse;
  39. }
  40. return TRUE;
  41. }
  42. int ServicesRestartList_RestartServices(void)
  43. {
  44. int iReturn = FALSE;
  45. INT err = 0;
  46. // loop thru the whole list and restart the services in reverse
  47. // order from how they were entered?
  48. if (gServicesWhichMustBeRestarted_total >= 1)
  49. {
  50. DbgPrint(("RestartServices() Start."));
  51. for(int i=0; i < gServicesWhichMustBeRestarted_total;i++)
  52. {
  53. err = InetStartService(gServicesWhichMustBeRestarted[i]);
  54. DbgPrint(("Start service %S. err=%x"), gServicesWhichMustBeRestarted[i], err);
  55. }
  56. DbgPrint(("RestartServices() End."));
  57. }
  58. return iReturn;
  59. }
  60. INT InetStartService( LPCTSTR lpServiceName )
  61. {
  62. INT err = 0;
  63. const DWORD dwSvcSleepInterval = 500 ;
  64. const DWORD dwSvcMaxSleep = 180000 ;
  65. SC_HANDLE hScManager = NULL;
  66. SC_HANDLE hService = NULL;
  67. DbgPrint(("Starting %S service..."), lpServiceName);
  68. do {
  69. // set up the service first
  70. if ((hScManager = OpenSCManager( NULL, NULL, GENERIC_ALL )) == NULL ||
  71. (hService = ::OpenService( hScManager, lpServiceName, GENERIC_ALL )) == NULL )
  72. {
  73. err = GetLastError();
  74. break;
  75. }
  76. SERVICE_STATUS svcStatus;
  77. if ( !QueryServiceStatus( hService, &svcStatus ))
  78. {
  79. err = ::GetLastError();
  80. break;
  81. }
  82. if ( svcStatus.dwCurrentState == SERVICE_RUNNING )
  83. break; // service already started and running
  84. if ( !::StartService( hService, 0, NULL ))
  85. {
  86. err = ::GetLastError();
  87. break;
  88. }
  89. // Wait for the service to attain "running" status; but
  90. // wait no more than 3 minute.
  91. DWORD dwSleepTotal;
  92. for ( dwSleepTotal = 0 ; dwSleepTotal < dwSvcMaxSleep
  93. && (QueryServiceStatus( hService, &svcStatus ))
  94. //&& svcStatus.dwCurrentState == SERVICE_START_PENDING ;
  95. && svcStatus.dwCurrentState != SERVICE_RUNNING ;
  96. dwSleepTotal += dwSvcSleepInterval )
  97. {
  98. ::Sleep( dwSvcSleepInterval ) ;
  99. }
  100. if ( svcStatus.dwCurrentState != SERVICE_RUNNING )
  101. {
  102. err = dwSleepTotal > dwSvcMaxSleep ?
  103. ERROR_SERVICE_REQUEST_TIMEOUT :
  104. svcStatus.dwWin32ExitCode;
  105. break;
  106. }
  107. } while ( FALSE );
  108. if (hService)
  109. CloseServiceHandle(hService);
  110. if (hScManager)
  111. CloseServiceHandle(hScManager);
  112. DbgPrint(("Service started with 0x%x"), err);
  113. return(err);
  114. }
  115. //
  116. //Routine Description:
  117. // Stop the named service and all those services which depend upon it.
  118. // And if the service is hung and can't be stopped, then kill the darn thing.
  119. //
  120. //Arguments:
  121. // ServiceName (Name of service to stop)
  122. //
  123. //Return Status:
  124. // TRUE - Indicates service successfully stopped
  125. // FALSE - Timeout occurred.
  126. //
  127. int StopServiceAndDependencies(LPCTSTR ServiceName, int AddToRestartList)
  128. {
  129. DbgPrint(("StopServiceAndDependencies():%S Service"), ServiceName);
  130. int Err = 0;
  131. int iBeforeServiceStatus = 0;
  132. SC_HANDLE ScManagerHandle = NULL;
  133. SC_HANDLE ServiceHandle = NULL;
  134. SERVICE_STATUS ServiceStatus;
  135. DWORD Timeout;
  136. DWORD TimeoutMaxSecs = 60 * 10; //10mins -- iisadmin may take a long time
  137. int iReturn = FALSE;
  138. //
  139. // Open a handle to the Service.
  140. //
  141. ScManagerHandle = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT );
  142. if (ScManagerHandle == NULL)
  143. {
  144. Err = GetLastError();
  145. DbgPrint(("StopServiceAndDependencies():OpenSCManager: Err on Service %S Err=0x%x FAILED"), ServiceName, Err);
  146. goto Cleanup;
  147. }
  148. ServiceHandle = OpenService(ScManagerHandle,ServiceName,SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_STOP | SERVICE_QUERY_CONFIG );
  149. if ( ServiceHandle == NULL )
  150. {
  151. Err = GetLastError();
  152. if (Err == ERROR_SERVICE_DOES_NOT_EXIST)
  153. {
  154. iReturn = TRUE;
  155. DbgPrint(("StopServiceAndDependencies():%S Service does not exist."), ServiceName);
  156. }
  157. else
  158. {
  159. DbgPrint(("StopServiceAndDependencies():OpenService: Err on Service %S Err=0x%x FAILED"), ServiceName, Err);
  160. }
  161. goto Cleanup;
  162. }
  163. // Get the before service status.
  164. if (QueryServiceStatus(ServiceHandle, &ServiceStatus))
  165. {
  166. iBeforeServiceStatus = ServiceStatus.dwCurrentState;
  167. }
  168. //
  169. // Ask the service to stop.
  170. //
  171. if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) )
  172. {
  173. Err = GetLastError();
  174. // If there are dependent services running,
  175. // determine their names and stop them.
  176. if ( Err == ERROR_DEPENDENT_SERVICES_RUNNING )
  177. {
  178. BYTE ConfigBuffer[4096];
  179. LPENUM_SERVICE_STATUS ServiceConfig = (LPENUM_SERVICE_STATUS) &ConfigBuffer;
  180. DWORD BytesNeeded;
  181. DWORD ServiceCount;
  182. DWORD ServiceIndex;
  183. //
  184. // Get the names of the dependent services.
  185. //
  186. if ( !EnumDependentServices( ServiceHandle,SERVICE_ACTIVE,ServiceConfig,sizeof(ConfigBuffer),&BytesNeeded,&ServiceCount ) )
  187. {
  188. Err = GetLastError();
  189. DbgPrint(("StopServiceAndDependencies():EnumDependentServices: Err on Service %S Err=0x%x FAILED"), ServiceName, Err);
  190. goto Cleanup;
  191. }
  192. //
  193. // Stop those services.
  194. //
  195. for ( ServiceIndex=0; ServiceIndex<ServiceCount; ServiceIndex++ )
  196. {
  197. StopServiceAndDependencies( ServiceConfig[ServiceIndex].lpServiceName, AddToRestartList);
  198. }
  199. //
  200. // Ask the original service to stop.
  201. //
  202. if ( !ControlService( ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus) )
  203. {
  204. Err = GetLastError();
  205. // check if the service is already stopped..
  206. if ( Err == ERROR_SERVICE_CANNOT_ACCEPT_CTRL || Err == ERROR_SERVICE_NOT_ACTIVE)
  207. {
  208. // check if the service is alread stopped.
  209. if (QueryServiceStatus( ServiceHandle, &ServiceStatus ))
  210. {
  211. if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED || ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  212. {
  213. iReturn = TRUE;
  214. goto Cleanup;
  215. }
  216. }
  217. }
  218. else
  219. {
  220. // The service must be in a hung mode. Let's kill it.
  221. // Todo: NYI
  222. DbgPrint(("StopServiceAndDependencies():'%S' Service must be in a hung mode. unable to stop it."), ServiceName);
  223. //KillService(ServiceHandle);
  224. //goto WaitLoop;
  225. }
  226. goto Cleanup;
  227. }
  228. }
  229. else
  230. {
  231. // check if the service is already stopped..
  232. if ( Err == ERROR_SERVICE_CANNOT_ACCEPT_CTRL || Err == ERROR_SERVICE_NOT_ACTIVE)
  233. {
  234. // check if the service is alread stopped.
  235. if (QueryServiceStatus( ServiceHandle, &ServiceStatus ))
  236. {
  237. if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED || ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  238. {
  239. Err = ServiceStatus.dwCurrentState;
  240. iReturn = TRUE;
  241. goto Cleanup;
  242. }
  243. }
  244. }
  245. else
  246. {
  247. // The service must be in a hung mode. Let's kill it.
  248. DbgPrint(("StopServiceAndDependencies():'%S' Service must be in a hung mode."), ServiceName);
  249. //KillService(ServiceHandle);
  250. //goto WaitLoop;
  251. }
  252. goto Cleanup;
  253. }
  254. }
  255. else
  256. {
  257. // We successfully asked the service to stop...
  258. }
  259. // Loop waiting for the service to stop.
  260. for ( Timeout=0; Timeout<TimeoutMaxSecs; Timeout++ )
  261. {
  262. // Return or continue waiting depending on the state of the service.
  263. if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED )
  264. {
  265. // The service successfully stopped.
  266. DbgPrint(("StopServiceAndDependencies(): %S Service stopped."), ServiceName);
  267. iReturn = TRUE;
  268. goto Cleanup;
  269. }
  270. // Wait a second for the service to finish stopping.
  271. Sleep( 1000 );
  272. // Query the status of the service again.
  273. if (! QueryServiceStatus( ServiceHandle, &ServiceStatus ))
  274. {
  275. Err = GetLastError();
  276. DbgPrint(("StopServiceAndDependencies():QueryServiceStatus: Err on Service %S Err=0x%x FAILED"), ServiceName, Err);
  277. goto Cleanup;
  278. }
  279. #if 0
  280. // if the service we are trying to stop is a driver,
  281. // then heck we should just get out of here..
  282. if (TRUE == IsThisServiceADriver(ServiceName))
  283. {
  284. DbgPrint(("StopServiceAndDependencies(): %S service is a driver, and can only be removed upon reboot."), ServiceName);
  285. goto Cleanup;
  286. }
  287. #endif
  288. }
  289. // if we get here then the service failed to stop.
  290. DbgPrint(("StopServiceAndDependencies(): failed to stop %S service."), ServiceName);
  291. Cleanup:
  292. if ( ScManagerHandle != NULL ) {(VOID) CloseServiceHandle(ScManagerHandle);}
  293. if ( ServiceHandle != NULL ) {(VOID) CloseServiceHandle(ServiceHandle);}
  294. // if we successfully stopped this service, then
  295. // add it to the restart service list
  296. if (iReturn == TRUE)
  297. {
  298. if (iBeforeServiceStatus == SERVICE_RUNNING)
  299. {
  300. if (AddToRestartList) {ServicesRestartList_Add(ServiceName);}
  301. }
  302. }
  303. return iReturn;
  304. }