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.

397 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: wiatsvc.cpp
  8. //
  9. // Contents: wait for service to start
  10. //
  11. // History: 19-Jun-00 reidk created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <windows.h>
  15. #include "unicode.h"
  16. #include "errlog.h"
  17. #include "waitsvc.h"
  18. #include <assert.h>
  19. #define WAITSVC_LOGERR_LASTERR(x) if (x) \
  20. { \
  21. ErrLog_LogError(NULL, \
  22. ERRLOG_CLIENT_ID_WAITSVC, \
  23. __LINE__, \
  24. 0, \
  25. FALSE, \
  26. FALSE); \
  27. }
  28. BOOL
  29. WaitForCryptService(
  30. IN LPWSTR pwszService,
  31. IN BOOL *pfDone,
  32. IN BOOL fLogErrors
  33. )
  34. /*++
  35. This routine determines if the protected storage service is
  36. pending start. If the service is pending start, this routine
  37. waits until the service is running before returning to the
  38. caller.
  39. If the Service is running when this routine returns, the
  40. return value is TRUE.
  41. If the service is not running, or an error occurred, the
  42. return value is FALSE.
  43. When the return value is FALSE, the value is only advisory, and may not
  44. indicate the current state of the service. The reasoning here is that
  45. if the service did not start the first time this call is made, is will
  46. not likely be running the next time around, and hence we avoid checking
  47. on subsequent calls.
  48. For current situations, the caller should ignore the return value; when
  49. the return value is FALSE, the caller should just try making the call
  50. into the service. If the service is still down, the call into it will fail
  51. appropriately.
  52. --*/
  53. {
  54. SC_HANDLE schSCM;
  55. SC_HANDLE schService = NULL;
  56. DWORD dwStopCount = 0;
  57. static BOOL fSuccess = FALSE;
  58. BOOL fCheckDisabled = TRUE;
  59. HANDLE hToken = NULL;
  60. BOOL fSystemAccount = FALSE;
  61. BOOL fStartServiceCalled = FALSE;
  62. DWORD dwErr = ERROR_SUCCESS;
  63. if( !FIsWinNT() )
  64. return TRUE;
  65. if( *pfDone )
  66. return fSuccess;
  67. schSCM = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
  68. if(schSCM == NULL)
  69. {
  70. assert(0);
  71. WAITSVC_LOGERR_LASTERR(fLogErrors)
  72. return FALSE;
  73. }
  74. //
  75. // open the protected storage service so we can query it's
  76. // current state.
  77. //
  78. schService = OpenServiceW(schSCM, pwszService, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
  79. if(schService == NULL)
  80. {
  81. WAITSVC_LOGERR_LASTERR(fLogErrors)
  82. fCheckDisabled = FALSE;
  83. schService = OpenServiceW(schSCM, pwszService, SERVICE_QUERY_STATUS);
  84. }
  85. if(schService == NULL)
  86. {
  87. assert(0);
  88. WAITSVC_LOGERR_LASTERR(fLogErrors)
  89. goto cleanup;
  90. }
  91. //
  92. // check if the service is disabled. If it is, bailout.
  93. //
  94. if( fCheckDisabled ) {
  95. LPQUERY_SERVICE_CONFIG pServiceConfig;
  96. BYTE TempBuffer[ 1024 ];
  97. DWORD cbServiceConfig;
  98. pServiceConfig = (LPQUERY_SERVICE_CONFIG)TempBuffer;
  99. cbServiceConfig = sizeof(TempBuffer);
  100. if(QueryServiceConfig( schService, pServiceConfig, cbServiceConfig, &cbServiceConfig )) {
  101. if( pServiceConfig->dwStartType == SERVICE_DISABLED )
  102. {
  103. SetLastError(ERROR_SERVICE_DISABLED);
  104. WAITSVC_LOGERR_LASTERR(fLogErrors)
  105. goto cleanup;
  106. }
  107. }
  108. else
  109. {
  110. assert(0);
  111. WAITSVC_LOGERR_LASTERR(fLogErrors)
  112. goto cleanup;
  113. }
  114. }
  115. //
  116. // check if calling process is SYSTEM account.
  117. // if it is, use a larger timeout value.
  118. //
  119. if( OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) ) {
  120. do {
  121. BYTE FastBuffer[ 256 ];
  122. PTOKEN_USER TokenInformation;
  123. DWORD cbTokenInformation;
  124. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  125. PSID psidLocalSystem;
  126. TokenInformation = (PTOKEN_USER)FastBuffer;
  127. cbTokenInformation = sizeof(FastBuffer);
  128. if(!GetTokenInformation(
  129. hToken,
  130. TokenUser,
  131. TokenInformation,
  132. cbTokenInformation,
  133. &cbTokenInformation
  134. ))
  135. {
  136. WAITSVC_LOGERR_LASTERR(fLogErrors)
  137. break;
  138. }
  139. if(!AllocateAndInitializeSid(
  140. &sia,
  141. 1,
  142. SECURITY_LOCAL_SYSTEM_RID,
  143. 0, 0, 0, 0, 0, 0, 0,
  144. &psidLocalSystem
  145. ))
  146. {
  147. WAITSVC_LOGERR_LASTERR(fLogErrors)
  148. break;
  149. }
  150. fSystemAccount = EqualSid(
  151. psidLocalSystem,
  152. TokenInformation->User.Sid
  153. );
  154. FreeSid( psidLocalSystem );
  155. } while (FALSE);
  156. CloseHandle( hToken );
  157. }
  158. //
  159. // number of seconds to Sleep per loop interation.
  160. //
  161. #define SLEEP_SECONDS (5)
  162. if( fSystemAccount ) {
  163. //
  164. // 15 minutes for SYSTEM account.
  165. //
  166. dwStopCount = 900 / SLEEP_SECONDS;
  167. } else {
  168. //
  169. //
  170. // loop checking the service status every 5 seconds, for up to 2 minutes
  171. // total (120 seconds, 5*24=120)
  172. //
  173. dwStopCount = 120 / SLEEP_SECONDS;
  174. }
  175. for( ; dwStopCount != 0 ; dwStopCount--, Sleep(SLEEP_SECONDS*1000) ) {
  176. SERVICE_STATUS sServiceStatus;
  177. DWORD dwWaitForStatus = 0;
  178. //
  179. // find out current service status
  180. //
  181. if(!QueryServiceStatus( schService, &sServiceStatus ))
  182. {
  183. WAITSVC_LOGERR_LASTERR(fLogErrors)
  184. break;
  185. }
  186. //
  187. // if service is running, indicate success
  188. //
  189. if( sServiceStatus.dwCurrentState == SERVICE_RUNNING ) {
  190. if (fStartServiceCalled)
  191. {
  192. ErrLog_LogString(
  193. NULL,
  194. L"WAITSVC: Service is running: ",
  195. pwszService,
  196. TRUE);
  197. }
  198. fSuccess = TRUE;
  199. break;
  200. }
  201. if( sServiceStatus.dwCurrentState == SERVICE_STOP_PENDING )
  202. {
  203. WAITSVC_LOGERR_LASTERR(fLogErrors)
  204. // Wait until stopped
  205. continue;
  206. }
  207. if( sServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING )
  208. {
  209. WAITSVC_LOGERR_LASTERR(fLogErrors)
  210. // Wait until paused
  211. continue;
  212. }
  213. //
  214. // if start pending, wait and re-query.
  215. //
  216. if( sServiceStatus.dwCurrentState == SERVICE_START_PENDING )
  217. {
  218. // Wait until started
  219. continue;
  220. }
  221. if(SERVICE_STOPPED == sServiceStatus.dwCurrentState)
  222. {
  223. // Attempt to start the service
  224. SC_HANDLE schManualStartService = NULL;
  225. DWORD dwError = ERROR_SUCCESS;
  226. // The service is manual start
  227. // so attempt to start it.
  228. schManualStartService = OpenServiceW(schSCM,
  229. pwszService,
  230. SERVICE_START);
  231. if(NULL == schManualStartService)
  232. {
  233. assert(0);
  234. WAITSVC_LOGERR_LASTERR(fLogErrors)
  235. goto cleanup;
  236. }
  237. ErrLog_LogString(
  238. NULL,
  239. L"WAITSVC: Calling StartService(): ",
  240. pwszService,
  241. TRUE);
  242. fStartServiceCalled = TRUE;
  243. if(!StartService(schManualStartService, 0, NULL))
  244. {
  245. dwError = GetLastError();
  246. }
  247. if(ERROR_SERVICE_ALREADY_RUNNING == dwError)
  248. {
  249. dwError = ERROR_SUCCESS;
  250. }
  251. CloseServiceHandle(schManualStartService);
  252. if(ERROR_SUCCESS != dwError)
  253. {
  254. assert(0);
  255. SetLastError(dwError);
  256. WAITSVC_LOGERR_LASTERR(fLogErrors)
  257. goto cleanup;
  258. }
  259. continue;
  260. }
  261. if(SERVICE_PAUSED == sServiceStatus.dwCurrentState)
  262. {
  263. // Attempt to start the service
  264. SC_HANDLE schManualStartService = NULL;
  265. DWORD dwError = ERROR_SUCCESS;
  266. // The service is manual start
  267. // so attempt to start it.
  268. schManualStartService = OpenServiceW(schSCM,
  269. pwszService,
  270. SERVICE_PAUSE_CONTINUE);
  271. if(NULL == schManualStartService)
  272. {
  273. assert(0);
  274. WAITSVC_LOGERR_LASTERR(fLogErrors)
  275. goto cleanup;
  276. }
  277. if(!ControlService(schManualStartService, SERVICE_CONTROL_CONTINUE, &sServiceStatus))
  278. {
  279. dwError = GetLastError();
  280. }
  281. if(ERROR_SERVICE_ALREADY_RUNNING == dwError)
  282. {
  283. dwError = ERROR_SUCCESS;
  284. }
  285. CloseServiceHandle(schManualStartService);
  286. if(ERROR_SUCCESS != dwError)
  287. {
  288. assert(0);
  289. SetLastError(dwError);
  290. WAITSVC_LOGERR_LASTERR(fLogErrors)
  291. goto cleanup;
  292. }
  293. continue;
  294. }
  295. //
  296. // bail out on any other dwCurrentState
  297. // eg: service stopped, error condition, etc.
  298. //
  299. break;
  300. }
  301. *pfDone = TRUE;
  302. cleanup:
  303. dwErr = GetLastError();
  304. if(schService)
  305. CloseServiceHandle(schService);
  306. CloseServiceHandle(schSCM);
  307. SetLastError(dwErr);
  308. return fSuccess;
  309. }