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.

473 lines
18 KiB

  1. #ifndef _SERVUTIL_H_
  2. #define _SERVUTIL_H_
  3. // forward reference
  4. HRESULT _StopService (LPTSTR szServiceName, BOOL bIncludeDependentServices = FALSE, LPTSTR szMachineName = NULL );
  5. inline HRESULT _ChangeServiceStartType (LPTSTR szServiceName, DWORD dwServiceStartType)
  6. {
  7. HRESULT hr = S_OK;
  8. SC_HANDLE hManager = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_REQUIRED);
  9. if (hManager == NULL)
  10. hr = GetLastError();
  11. else {
  12. // stop service if it's running
  13. SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
  14. if (!hService)
  15. hr = GetLastError();
  16. else {
  17. if (!ChangeServiceConfig (hService,
  18. SERVICE_NO_CHANGE, // service type
  19. dwServiceStartType, // start type
  20. SERVICE_NO_CHANGE, // error control
  21. NULL, NULL, NULL, NULL, NULL, NULL, NULL))
  22. hr = GetLastError();
  23. CloseServiceHandle (hService);
  24. }
  25. CloseServiceHandle (hManager);
  26. }
  27. return HRESULT_FROM_WIN32(hr);
  28. }
  29. inline DWORD _GetServiceStatus (LPTSTR szServiceName, LPTSTR szMachineName = NULL)
  30. {
  31. DWORD dwStatus = 0;
  32. SC_HANDLE hSCManager = OpenSCManager (szMachineName,
  33. NULL, // ServicesActive database
  34. SC_MANAGER_ALL_ACCESS); // full access rights
  35. if (hSCManager != NULL) {
  36. SC_HANDLE hService = OpenService (hSCManager,
  37. szServiceName,
  38. SERVICE_QUERY_STATUS);
  39. if (hService) {
  40. SERVICE_STATUS ss = {0};
  41. if (QueryServiceStatus (hService, &ss))
  42. dwStatus = ss.dwCurrentState;
  43. CloseServiceHandle (hService);
  44. }
  45. CloseServiceHandle (hSCManager);
  46. }
  47. return dwStatus;
  48. }
  49. inline BOOL _IsServiceStartType (LPTSTR szServiceName, DWORD dwServiceStartType)
  50. {
  51. BOOL b = FALSE;
  52. SC_HANDLE hSCManager = OpenSCManager (NULL, // local machine
  53. NULL, // ServicesActive database
  54. SC_MANAGER_ALL_ACCESS); // full access rights
  55. if (hSCManager != NULL) {
  56. SC_HANDLE hService = OpenService (hSCManager,
  57. szServiceName,
  58. SERVICE_ALL_ACCESS);
  59. if (hService) {
  60. DWORD dwSize = 0;
  61. if (0 == QueryServiceConfig (hService, NULL, dwSize, &dwSize))
  62. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  63. QUERY_SERVICE_CONFIG* pQSC = (QUERY_SERVICE_CONFIG*)malloc (dwSize);
  64. if (pQSC) {
  65. if (QueryServiceConfig (hService, pQSC, dwSize, &dwSize)) {
  66. if (pQSC->dwStartType == dwServiceStartType)
  67. b = TRUE;
  68. }
  69. free (pQSC);
  70. }
  71. }
  72. CloseServiceHandle (hService);
  73. }
  74. CloseServiceHandle (hSCManager);
  75. }
  76. return b;
  77. }
  78. inline BOOL _IsServiceStatus (LPTSTR szServiceName, DWORD dwServiceStatus)
  79. {
  80. BOOL b = FALSE;
  81. SC_HANDLE hSCManager = OpenSCManager (NULL, // local machine
  82. NULL, // ServicesActive database
  83. SC_MANAGER_ALL_ACCESS); // full access rights
  84. if (hSCManager != NULL) {
  85. SC_HANDLE hService = OpenService (hSCManager,
  86. szServiceName,
  87. SERVICE_QUERY_STATUS);
  88. if (hService) {
  89. SERVICE_STATUS ss = {0};
  90. if (QueryServiceStatus (hService, &ss))
  91. if (ss.dwCurrentState == dwServiceStatus)
  92. b = TRUE;
  93. CloseServiceHandle (hService);
  94. }
  95. CloseServiceHandle (hSCManager);
  96. }
  97. return b;
  98. }
  99. inline BOOL _IsServiceRunning (LPTSTR szServiceName)
  100. {
  101. return _IsServiceStatus (szServiceName, SERVICE_RUNNING);
  102. }
  103. inline BOOL _IsServiceInstalled (LPTSTR szServiceName)
  104. {
  105. BOOL b = FALSE;
  106. SC_HANDLE hSCManager = OpenSCManager (NULL, // local machine
  107. NULL, // ServicesActive database
  108. SC_MANAGER_ALL_ACCESS); // full access rights
  109. if (hSCManager != NULL) {
  110. SC_HANDLE hService = OpenService (hSCManager,
  111. szServiceName,
  112. SERVICE_QUERY_STATUS);
  113. if (hService) {
  114. b = TRUE;
  115. CloseServiceHandle (hService);
  116. }
  117. CloseServiceHandle (hSCManager);
  118. }
  119. return b;
  120. }
  121. // private inline
  122. inline long __WaitForServiceStatus (SC_HANDLE hService, DWORD dwStatus)
  123. {
  124. SetLastError (0);
  125. int iIOPendingErrors = 0;
  126. SERVICE_STATUS ssStatus;
  127. if (!QueryServiceStatus (hService, &ssStatus))
  128. return GetLastError();
  129. if (dwStatus == SERVICE_STOPPED) {
  130. if (!(ssStatus.dwControlsAccepted & SERVICE_ACCEPT_STOP)) {
  131. // service doesn't accept stop!
  132. // return appropriate error
  133. if (ssStatus.dwCurrentState == dwStatus)
  134. return S_OK;
  135. if (ssStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR) {
  136. if (ssStatus.dwServiceSpecificExitCode == 0)
  137. return ERROR_INVALID_SERVICE_CONTROL;
  138. return ssStatus.dwServiceSpecificExitCode;
  139. }
  140. if (ssStatus.dwWin32ExitCode != 0)
  141. return ssStatus.dwWin32ExitCode;
  142. return ERROR_INVALID_SERVICE_CONTROL;
  143. }
  144. }
  145. DWORD dwOldCheckPoint, dwOldCurrentState;
  146. while (ssStatus.dwCurrentState != dwStatus) {
  147. // Save the current checkpoint.
  148. dwOldCheckPoint = ssStatus.dwCheckPoint;
  149. dwOldCurrentState = ssStatus.dwCurrentState;
  150. // Wait for the specified interval.
  151. int iSleep = ssStatus.dwWaitHint;
  152. if (iSleep > 2500)
  153. iSleep = 2500;
  154. if (iSleep == 0)
  155. iSleep = 100;
  156. Sleep (iSleep);
  157. // Check the status again.
  158. SetLastError (0);
  159. if (!QueryServiceStatus (hService, &ssStatus))
  160. return GetLastError();
  161. // Break if the checkpoint has not been incremented.
  162. if (dwOldCheckPoint == ssStatus.dwCheckPoint)
  163. if (dwOldCurrentState == ssStatus.dwCurrentState) {
  164. // ok: at this point, we're supposed to be done, or there's an error
  165. if (ssStatus.dwCurrentState == dwStatus)
  166. break;
  167. if (ssStatus.dwWin32ExitCode != 0)
  168. break;
  169. // some kinda screw up: we're not done and no error!
  170. // so, give 'em one last chance....
  171. Sleep (1000);
  172. SetLastError (0);
  173. if (!QueryServiceStatus (hService, &ssStatus))
  174. return GetLastError();
  175. if (dwOldCheckPoint == ssStatus.dwCheckPoint)
  176. if (dwOldCurrentState == ssStatus.dwCurrentState) {
  177. // empirical: I keep getting this when actually everything is ok
  178. if (GetLastError() == ERROR_IO_PENDING)
  179. if (iIOPendingErrors++ < 60)
  180. continue;
  181. break;
  182. }
  183. // if we get here, either the checkpoint or status changed, and we can keep going
  184. }
  185. }
  186. if (ssStatus.dwCurrentState == dwStatus)
  187. return S_OK;
  188. if (ssStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR) {
  189. if (ssStatus.dwServiceSpecificExitCode == 0)
  190. return E_FAIL;
  191. return ssStatus.dwServiceSpecificExitCode;
  192. }
  193. if (ssStatus.dwWin32ExitCode != 0)
  194. return ssStatus.dwWin32ExitCode;
  195. // we should never get here
  196. HRESULT hr = GetLastError();
  197. return ERROR_SERVICE_REQUEST_TIMEOUT;
  198. #ifdef BONE_HEADED_WAY
  199. SERVICE_STATUS ssStatus;
  200. // wait for at most 3 minutes
  201. for (int i=0; i<180; i++) {
  202. if (!QueryServiceStatus (hService, &ssStatus))
  203. return HR (GetLastError()); // bad service handle?
  204. if (ssStatus.dwCurrentState == dwStatus)
  205. return S_OK; // all is well
  206. Sleep(1000); // wait a second
  207. }
  208. return HRESULT_FROM_WIN32(ERROR_SERVICE_REQUEST_TIMEOUT);
  209. #endif
  210. }
  211. inline HRESULT _RecursiveStop (SC_HANDLE hService)
  212. {
  213. HRESULT hr = S_OK;
  214. DWORD dwBufSize = 1, dwNumServices = 0;
  215. if (!EnumDependentServices (hService,
  216. SERVICE_ACTIVE,
  217. (LPENUM_SERVICE_STATUS)&dwBufSize,
  218. dwBufSize,
  219. &dwBufSize,
  220. &dwNumServices)) {
  221. // this should fail with ERROR_MORE_DATA, unless there are no dependent services
  222. hr = GetLastError ();
  223. if (hr == ERROR_MORE_DATA) {
  224. hr = S_OK;
  225. ENUM_SERVICE_STATUS * pBuffer = (ENUM_SERVICE_STATUS *)malloc (dwBufSize);
  226. if (!pBuffer)
  227. hr = E_OUTOFMEMORY;
  228. else {
  229. if (!EnumDependentServices (hService,
  230. SERVICE_ACTIVE,
  231. pBuffer,
  232. dwBufSize,
  233. &dwBufSize,
  234. &dwNumServices))
  235. hr = GetLastError(); // shouldn't happen!!!
  236. else {
  237. _ASSERT (dwNumServices > 0);
  238. for (DWORD i=0; i<dwNumServices && S_OK == hr; i++) {
  239. hr = _StopService (pBuffer[i].lpServiceName, FALSE);
  240. }
  241. }
  242. free (pBuffer);
  243. }
  244. }
  245. }
  246. return HRESULT_FROM_WIN32(hr);
  247. }
  248. inline HRESULT _ControlService (LPTSTR szServiceName, DWORD dwControl, LPTSTR szMachineName = NULL )
  249. {
  250. if ( NULL == szServiceName ) return E_INVALIDARG;
  251. if (( SERVICE_CONTROL_PAUSE != dwControl ) && ( SERVICE_CONTROL_CONTINUE != dwControl )) return E_INVALIDARG;
  252. HRESULT hr = S_OK;
  253. SC_HANDLE hManager;
  254. LPTSTR psMachineName = szMachineName;
  255. SERVICE_STATUS ss;
  256. if ( NULL != psMachineName )
  257. {
  258. psMachineName = new TCHAR[ _tcslen( szMachineName ) + 3];
  259. if ( NULL == psMachineName )
  260. return E_OUTOFMEMORY;
  261. _tcscpy( psMachineName, _T( "\\\\" ));
  262. _tcscat( psMachineName, szMachineName );
  263. }
  264. hManager = OpenSCManager(psMachineName, NULL, STANDARD_RIGHTS_REQUIRED);
  265. if ( NULL != psMachineName )
  266. delete [] psMachineName;
  267. if (hManager == NULL)
  268. hr = GetLastError();
  269. else {
  270. SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
  271. if (hService == NULL)
  272. hr = GetLastError();
  273. else {
  274. if (!ControlService( hService, dwControl, &ss ))
  275. hr = GetLastError();
  276. else
  277. {
  278. if ( SERVICE_CONTROL_PAUSE == dwControl )
  279. hr = __WaitForServiceStatus(hService, SERVICE_PAUSED);
  280. if ( SERVICE_CONTROL_CONTINUE == dwControl )
  281. hr = __WaitForServiceStatus(hService, SERVICE_RUNNING);
  282. }
  283. CloseServiceHandle (hService);
  284. }
  285. CloseServiceHandle (hManager);
  286. }
  287. return HRESULT_FROM_WIN32(hr);
  288. }
  289. inline HRESULT _StopService (LPTSTR szServiceName, BOOL bIncludeDependentServices, LPTSTR szMachineName /*= NULL*/ )
  290. {
  291. HRESULT hr = S_OK;
  292. SC_HANDLE hManager;
  293. LPTSTR psMachineName = szMachineName;
  294. if ( NULL != psMachineName )
  295. {
  296. psMachineName = new TCHAR[ _tcslen( szMachineName ) + 3];
  297. if ( NULL == psMachineName )
  298. return E_OUTOFMEMORY;
  299. _tcscpy( psMachineName, _T( "\\\\" ));
  300. _tcscat( psMachineName, szMachineName );
  301. }
  302. hManager = OpenSCManager(psMachineName, NULL, STANDARD_RIGHTS_REQUIRED);
  303. if ( NULL != psMachineName )
  304. delete [] psMachineName;
  305. if (hManager == NULL)
  306. hr = GetLastError();
  307. else {
  308. // stop service if it's running
  309. SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
  310. if (!hService)
  311. hr = GetLastError();
  312. else {
  313. LETS_TRY_AGAIN:
  314. SERVICE_STATUS st;
  315. if (!ControlService (hService, SERVICE_CONTROL_STOP, &st)) {
  316. hr = GetLastError(); // for instance, not running
  317. if (hr == ERROR_DEPENDENT_SERVICES_RUNNING) {
  318. if (bIncludeDependentServices == TRUE) {
  319. hr = _RecursiveStop (hService);
  320. if (hr == S_OK)
  321. goto LETS_TRY_AGAIN; // need to stop this service yet
  322. }
  323. }
  324. } else
  325. hr = __WaitForServiceStatus (hService, SERVICE_STOPPED);
  326. CloseServiceHandle (hService);
  327. }
  328. CloseServiceHandle (hManager);
  329. }
  330. return HRESULT_FROM_WIN32(hr);
  331. }
  332. inline HRESULT _StartService (LPTSTR szServiceName, LPTSTR szMachineName = NULL )
  333. {
  334. HRESULT hr = S_OK;
  335. SC_HANDLE hManager;
  336. LPTSTR psMachineName = szMachineName;
  337. if ( NULL != psMachineName )
  338. {
  339. psMachineName = new TCHAR[ _tcslen( szMachineName ) + 3];
  340. if ( NULL == psMachineName )
  341. return E_OUTOFMEMORY;
  342. _tcscpy( psMachineName, _T( "\\\\" ));
  343. _tcscat( psMachineName, szMachineName );
  344. }
  345. hManager = OpenSCManager(psMachineName, NULL, STANDARD_RIGHTS_REQUIRED);
  346. if ( NULL != psMachineName )
  347. delete [] psMachineName;
  348. if (hManager == NULL)
  349. hr = GetLastError();
  350. else {
  351. SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
  352. if (hService == NULL)
  353. hr = GetLastError();
  354. else {
  355. if (!StartService(hService, 0, NULL))
  356. hr = GetLastError();
  357. else
  358. hr = __WaitForServiceStatus(hService, SERVICE_RUNNING);
  359. CloseServiceHandle (hService);
  360. }
  361. CloseServiceHandle (hManager);
  362. }
  363. return HRESULT_FROM_WIN32(hr);
  364. }
  365. inline HRESULT _RestartService (LPTSTR szServiceName, BOOL bIncludeDependentServices = FALSE)
  366. {
  367. // easy on first
  368. if (bIncludeDependentServices == FALSE) {
  369. _StopService (szServiceName, FALSE);
  370. return _StartService (szServiceName);
  371. }
  372. // get array of dependent services;
  373. DWORD dwNumServices = 0;
  374. ENUM_SERVICE_STATUS * pBuffer = NULL;
  375. HRESULT hr = S_OK, hr1 = S_OK;
  376. SC_HANDLE hManager = OpenSCManager(NULL, NULL, STANDARD_RIGHTS_REQUIRED);
  377. if (hManager == NULL)
  378. hr = GetLastError();
  379. else {
  380. // stop service if it's running
  381. SC_HANDLE hService = OpenService (hManager, szServiceName, SERVICE_ALL_ACCESS);
  382. if (!hService)
  383. hr = GetLastError();
  384. else {
  385. DWORD dwBufSize = 1;
  386. // this should fail with ERROR_MORE_DATA, unless there are no dependent services
  387. if (!EnumDependentServices (hService,
  388. SERVICE_ACTIVE,
  389. (LPENUM_SERVICE_STATUS)&dwBufSize,
  390. dwBufSize,
  391. &dwBufSize,
  392. &dwNumServices)) {
  393. hr = GetLastError ();
  394. if (hr == ERROR_MORE_DATA) {
  395. hr = S_OK;
  396. pBuffer = (ENUM_SERVICE_STATUS *)malloc (dwBufSize);
  397. if (!pBuffer)
  398. hr = E_OUTOFMEMORY;
  399. else {
  400. if (!EnumDependentServices (hService,
  401. SERVICE_ACTIVE,
  402. pBuffer,
  403. dwBufSize,
  404. &dwBufSize,
  405. &dwNumServices))
  406. hr = GetLastError(); // shouldn't happen!!!
  407. }
  408. }
  409. }
  410. CloseServiceHandle (hService);
  411. }
  412. CloseServiceHandle (hManager);
  413. }
  414. if (hr == S_OK) {
  415. // stop dependent services
  416. if (pBuffer && dwNumServices) {
  417. for (DWORD i=0; i<dwNumServices && S_OK == hr; i++) {
  418. hr = _StopService (pBuffer[i].lpServiceName, FALSE);
  419. }
  420. }
  421. if (hr == S_OK) {
  422. // stop this service
  423. hr1 = _RestartService (szServiceName, FALSE);
  424. // always start dependent services
  425. if (pBuffer && dwNumServices) {
  426. for (int i=(int)dwNumServices-1; i>=0 && S_OK == hr; i--) {
  427. hr = _StartService (pBuffer[i].lpServiceName);
  428. }
  429. }
  430. }
  431. }
  432. if (pBuffer != NULL)
  433. free (pBuffer);
  434. if FAILED(hr1)
  435. hr = hr1;
  436. return HRESULT_FROM_WIN32(hr);
  437. }
  438. #endif