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.

985 lines
31 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. service.cpp
  7. Calls to start and stop services.
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "DynamLnk.h"
  12. #include "cluster.h"
  13. DynamicDLL g_NetApiDLL( _T("NETAPI32.DLL"), g_apchNetApiFunctionNames );
  14. /*---------------------------------------------------------------------------
  15. IsComputerNT
  16. Checks to see if the given computer is running NT
  17. Author: EricDav
  18. ---------------------------------------------------------------------------*/
  19. TFSCORE_API(DWORD)
  20. TFSIsComputerNT
  21. (
  22. LPCTSTR pszComputer,
  23. BOOL * bIsNT
  24. )
  25. {
  26. DWORD err = 0;
  27. BYTE * pbBuffer;
  28. *bIsNT = FALSE;
  29. if ( !g_NetApiDLL.LoadFunctionPointers() )
  30. return err;
  31. err = ((NETSERVERGETINFO) g_NetApiDLL[NET_API_NET_SERVER_GET_INFO])
  32. ( (LPTSTR) pszComputer,
  33. 101,
  34. &pbBuffer );
  35. if (err == NERR_Success)
  36. {
  37. //
  38. // Possible Errors:
  39. // ERROR_ACCESS_DENIED
  40. // ERROR_INVALID_LEVEL
  41. // ERROR_INVALID_PARAMETER
  42. // ERROR_NOT_ENOUGH_MEMORY
  43. //
  44. SERVER_INFO_101 * pServerInfo = (SERVER_INFO_101 *) pbBuffer;
  45. if ( (pServerInfo->sv101_type & SV_TYPE_NT) )
  46. {
  47. *bIsNT = TRUE;
  48. }
  49. err = ERROR_SUCCESS; //Translate the NERR code to a winerror code
  50. }
  51. return err;
  52. }
  53. /*---------------------------------------------------------------------------
  54. IsNTServer
  55. Checks to see if the given computer is running NTS
  56. Author: EricDav
  57. ---------------------------------------------------------------------------*/
  58. TFSCORE_API(DWORD)
  59. TFSIsNTServer
  60. (
  61. LPCTSTR pszComputer,
  62. BOOL * bIsNTS
  63. )
  64. {
  65. DWORD err = 0;
  66. BYTE * pbBuffer;
  67. *bIsNTS = FALSE;
  68. if ( !g_NetApiDLL.LoadFunctionPointers() )
  69. return err;
  70. err = ((NETSERVERGETINFO) g_NetApiDLL[NET_API_NET_SERVER_GET_INFO])
  71. ( (LPTSTR) pszComputer,
  72. 101,
  73. &pbBuffer );
  74. if (err == NERR_Success)
  75. {
  76. //
  77. // Possible Errors:
  78. // ERROR_ACCESS_DENIED
  79. // ERROR_INVALID_LEVEL
  80. // ERROR_INVALID_PARAMETER
  81. // ERROR_NOT_ENOUGH_MEMORY
  82. //
  83. SERVER_INFO_101 * pServerInfo = (SERVER_INFO_101 *) pbBuffer;
  84. if ( (pServerInfo->sv101_type & SV_TYPE_SERVER_NT) ||
  85. (pServerInfo->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
  86. (pServerInfo->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) )
  87. {
  88. *bIsNTS = TRUE;
  89. }
  90. err = ERROR_SUCCESS; //Translate the NERR code to a winerror code
  91. }
  92. return err;
  93. }
  94. /*---------------------------------------------------------------------------
  95. TFSIsServiceRunning
  96. Checks to see if the given service is running on a machine
  97. Author: EricDav
  98. ---------------------------------------------------------------------------*/
  99. TFSCORE_API(DWORD)
  100. TFSIsServiceRunning
  101. (
  102. LPCTSTR pszComputer,
  103. LPCTSTR pszServiceName,
  104. BOOL * fIsRunning
  105. )
  106. {
  107. DWORD err = 0;
  108. DWORD dwStatus;
  109. *fIsRunning = FALSE;
  110. err = TFSGetServiceStatus(pszComputer, pszServiceName, &dwStatus, NULL);
  111. if (err == 0)
  112. *fIsRunning = (BOOL)(dwStatus & SERVICE_RUNNING);
  113. return err;
  114. }
  115. /*!--------------------------------------------------------------------------
  116. TFSGetServiceStatus
  117. Returns ERROR_SUCCESS on API success.
  118. Returns an error code otherwise.
  119. pszComputer - name of the computer to attach to.
  120. pszServiceName - name of the service to check.
  121. pdwServiceStatus - returns the status of the service.
  122. pdwErrorCode - returns the error code returned from the service
  123. (this is NOT the error code from the API itself).
  124. This may be NULL.
  125. Author: KennT
  126. ---------------------------------------------------------------------------*/
  127. TFSCORE_API(DWORD)
  128. TFSGetServiceStatus
  129. (
  130. LPCWSTR pszComputer,
  131. LPCWSTR pszServiceName,
  132. DWORD * pdwServiceStatus,
  133. OPTIONAL DWORD * pdwErrorCode
  134. )
  135. {
  136. DWORD err = 0;
  137. SC_HANDLE hScManager;
  138. Assert(pdwServiceStatus);
  139. *pdwServiceStatus = 0;
  140. if (pdwErrorCode)
  141. *pdwErrorCode = 0;
  142. //
  143. // Find out if the service is running on the given machine
  144. //
  145. hScManager = ::OpenSCManager(pszComputer, NULL, GENERIC_READ);
  146. if (hScManager == NULL)
  147. {
  148. //
  149. // Possible Errors:
  150. // ERROR_ACCESS_DENIED
  151. // ERROR_DATABASE_DOES_NOT_EXIST
  152. // ERROR_INVALID_PARAMETER
  153. //
  154. return GetLastError();
  155. }
  156. SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_QUERY_STATUS);
  157. if (hService == NULL)
  158. {
  159. //
  160. // Possible Errors:
  161. // ERROR_ACCESS_DENIED
  162. // ERROR_INVALID_HANDLE
  163. // ERROR_INVALID_NAME
  164. // ERROR_SERVICE_DOES_NOT_EXIST
  165. //
  166. err = GetLastError();
  167. ::CloseServiceHandle(hScManager);
  168. return err;
  169. }
  170. SERVICE_STATUS serviceStatus;
  171. if (!::QueryServiceStatus(hService, &serviceStatus))
  172. {
  173. //
  174. // Possible Errors:
  175. // ERROR_ACCESS_DENIED
  176. // ERROR_INVALID_HANDLE
  177. //
  178. err = GetLastError();
  179. ::CloseServiceHandle(hService);
  180. ::CloseServiceHandle(hScManager);
  181. return err;
  182. }
  183. *pdwServiceStatus = serviceStatus.dwCurrentState;
  184. // Also return the error code
  185. if (pdwErrorCode)
  186. {
  187. if (serviceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR)
  188. *pdwErrorCode = serviceStatus.dwServiceSpecificExitCode;
  189. else
  190. *pdwErrorCode = serviceStatus.dwWin32ExitCode;
  191. }
  192. ::CloseServiceHandle(hService);
  193. ::CloseServiceHandle(hScManager);
  194. return err;
  195. }
  196. /*---------------------------------------------------------------------------
  197. StartService
  198. Starts the given service on a machine
  199. Author: EricDav
  200. ---------------------------------------------------------------------------*/
  201. TFSCORE_API(DWORD)
  202. TFSStartService
  203. (
  204. LPCTSTR pszComputer,
  205. LPCTSTR pszServiceName,
  206. LPCTSTR pszServiceDesc
  207. )
  208. {
  209. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  210. DWORD err = 0;
  211. err = StartSCMService(pszComputer, pszServiceName, pszServiceDesc);
  212. return err;
  213. }
  214. /*---------------------------------------------------------------------------
  215. StartServiceEx
  216. Starts the given service on a machine, cluster aware
  217. Author: EricDav
  218. ---------------------------------------------------------------------------*/
  219. TFSCORE_API(DWORD)
  220. TFSStartServiceEx
  221. (
  222. LPCTSTR pszComputer,
  223. LPCTSTR pszServiceName,
  224. LPCTSTR pszClusterResourceType,
  225. LPCTSTR pszServiceDesc
  226. )
  227. {
  228. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  229. DWORD err = 0;
  230. if (FIsComputerInRunningCluster(pszComputer))
  231. {
  232. err = ControlClusterService(pszComputer, pszClusterResourceType, pszServiceDesc, TRUE);
  233. }
  234. else
  235. {
  236. err = StartSCMService(pszComputer, pszServiceName, pszServiceDesc);
  237. }
  238. return err;
  239. }
  240. /*---------------------------------------------------------------------------
  241. StopService
  242. Stops the given service on a machine
  243. Author: EricDav
  244. ---------------------------------------------------------------------------*/
  245. TFSCORE_API(DWORD)
  246. TFSStopService
  247. (
  248. LPCTSTR pszComputer,
  249. LPCTSTR pszServiceName,
  250. LPCTSTR pszServiceDesc
  251. )
  252. {
  253. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  254. DWORD err = 0;
  255. err = StopSCMService(pszComputer, pszServiceName, pszServiceDesc);
  256. return err;
  257. }
  258. /*---------------------------------------------------------------------------
  259. StopServiceEx
  260. Stops the given service on a machine, cluster aware
  261. Author: EricDav
  262. ---------------------------------------------------------------------------*/
  263. TFSCORE_API(DWORD)
  264. TFSStopServiceEx
  265. (
  266. LPCTSTR pszComputer,
  267. LPCTSTR pszServiceName,
  268. LPCTSTR pszClusterResourceType,
  269. LPCTSTR pszServiceDesc
  270. )
  271. {
  272. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  273. DWORD err = 0;
  274. if (FIsComputerInRunningCluster(pszComputer))
  275. {
  276. err = ControlClusterService(pszComputer, pszClusterResourceType, pszServiceDesc, FALSE);
  277. }
  278. else
  279. {
  280. err = StopSCMService(pszComputer, pszServiceName, pszServiceDesc);
  281. }
  282. return err;
  283. }
  284. TFSCORE_API(DWORD) TFSGetServiceStartType(LPCWSTR pszComputer, LPCWSTR pszServiceName, DWORD *pdwStartType)
  285. {
  286. DWORD err = 0;
  287. SC_HANDLE hScManager = 0;
  288. SC_HANDLE hService = 0;
  289. HRESULT hr = hrOK;
  290. BOOL fReturn = FALSE;
  291. LPQUERY_SERVICE_CONFIG pqsConfig = NULL;
  292. DWORD cbNeeded = sizeof( QUERY_SERVICE_CONFIG );
  293. DWORD cbSize;
  294. //
  295. // Find out if the service is running on the given machine
  296. //
  297. hScManager = ::OpenSCManager(pszComputer, NULL, GENERIC_READ);
  298. if (hScManager == NULL)
  299. {
  300. //
  301. // Possible Errors:
  302. // ERROR_ACCESS_DENIED
  303. // ERROR_DATABASE_DOES_NOT_EXIST
  304. // ERROR_INVALID_PARAMETER
  305. //
  306. err = GetLastError();
  307. goto Exit;
  308. }
  309. hService = ::OpenService(hScManager, pszServiceName, SERVICE_QUERY_CONFIG);
  310. if (hService == NULL)
  311. {
  312. //
  313. // Possible Errors:
  314. // ERROR_ACCESS_DENIED
  315. // ERROR_INVALID_HANDLE
  316. // ERROR_INVALID_NAME
  317. // ERROR_SERVICE_DOES_NOT_EXIST
  318. //
  319. err = GetLastError();
  320. goto Exit;
  321. }
  322. COM_PROTECT_TRY
  323. {
  324. *pdwStartType = 0;
  325. // loop, allocating the needed size
  326. do
  327. {
  328. delete [] (PBYTE)pqsConfig;
  329. pqsConfig = (LPQUERY_SERVICE_CONFIG) new BYTE[cbNeeded];
  330. cbSize = cbNeeded;
  331. fReturn = ::QueryServiceConfig( hService,
  332. pqsConfig,
  333. cbSize,
  334. &cbNeeded );
  335. *pdwStartType = pqsConfig->dwStartType;
  336. delete [] (PBYTE)pqsConfig;
  337. pqsConfig = NULL;
  338. if (!fReturn && (cbNeeded == cbSize))
  339. {
  340. // error
  341. *pdwStartType = 0;
  342. err = GetLastError();
  343. goto Error;
  344. }
  345. } while (!fReturn && (cbNeeded != cbSize));
  346. COM_PROTECT_ERROR_LABEL;
  347. }
  348. COM_PROTECT_CATCH;
  349. if (!FHrSucceeded(hr))
  350. {
  351. // The only time we should get here (with an hr is for outofmemory)
  352. err = ERROR_OUTOFMEMORY;
  353. }
  354. Exit:
  355. if (err != 0)
  356. {
  357. *pdwStartType = 0;
  358. }
  359. ::CloseServiceHandle(hService);
  360. ::CloseServiceHandle(hScManager);
  361. return err;
  362. }
  363. TFSCORE_API(DWORD) TFSSetServiceStartType(LPCWSTR pszComputer, LPCWSTR pszServiceName, DWORD dwStartType)
  364. {
  365. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  366. DWORD err = 0;
  367. SC_HANDLE hScManager;
  368. //
  369. // Open the SCManager so that we can try to stop the service
  370. //
  371. hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_ALL_ACCESS);
  372. if (hScManager == NULL)
  373. {
  374. //
  375. // Possible Errors:
  376. // ERROR_ACCESS_DENIED
  377. // ERROR_DATABASE_DOES_NOT_EXIST
  378. // ERROR_INVALID_PARAMETER
  379. //
  380. return GetLastError();
  381. }
  382. SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_STOP | SERVICE_ALL_ACCESS);
  383. if (hService == NULL)
  384. {
  385. //
  386. // Possible Errors:
  387. // ERROR_ACCESS_DENIED
  388. // ERROR_INVALID_HANDLE
  389. // ERROR_INVALID_NAME
  390. // ERROR_SERVICE_DOES_NOT_EXIST
  391. //
  392. err = GetLastError();
  393. ::CloseServiceHandle(hScManager);
  394. return err;
  395. }
  396. if (!::ChangeServiceConfig( hService,
  397. SERVICE_NO_CHANGE,
  398. dwStartType,
  399. SERVICE_NO_CHANGE,
  400. NULL,
  401. NULL,
  402. NULL,
  403. NULL,
  404. NULL,
  405. NULL,
  406. NULL))
  407. {
  408. //
  409. // Possible Errors:
  410. // ERROR_ACCESS_DENIED
  411. // ERROR_CIRCULAR_DEPENDENCY
  412. // ERROR_DUP_NAME
  413. // ERROR_INVALID_HANDLE
  414. // ERROR_INVALID_PARAMETER
  415. // ERROR_INVALID_SERVICE_ACCOUNT
  416. // ERROR_SERVICE_MARKED_FOR_DELETE
  417. //
  418. err = ::GetLastError();
  419. ::CloseServiceHandle(hService);
  420. ::CloseServiceHandle(hScManager);
  421. return err;
  422. }
  423. ::CloseServiceHandle(hService);
  424. ::CloseServiceHandle(hScManager);
  425. return err;
  426. }
  427. DWORD
  428. StartSCMService
  429. (
  430. LPCTSTR pszComputer,
  431. LPCTSTR pszServiceName,
  432. LPCTSTR pszServiceDesc
  433. )
  434. {
  435. DWORD err = 0;
  436. SC_HANDLE hScManager;
  437. //
  438. // Open the SCManager so that we can try to start the service
  439. //
  440. hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
  441. if (hScManager == NULL)
  442. {
  443. //
  444. // Possible Errors:
  445. // ERROR_ACCESS_DENIED
  446. // ERROR_DATABASE_DOES_NOT_EXIST
  447. // ERROR_INVALID_PARAMETER
  448. //
  449. return GetLastError();
  450. }
  451. SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_START | SERVICE_QUERY_STATUS);
  452. if (hService == NULL)
  453. {
  454. //
  455. // Possible Errors:
  456. // ERROR_ACCESS_DENIED
  457. // ERROR_INVALID_HANDLE
  458. // ERROR_INVALID_NAME
  459. // ERROR_SERVICE_DOES_NOT_EXIST
  460. //
  461. err = GetLastError();
  462. ::CloseServiceHandle(hScManager);
  463. return err;
  464. }
  465. SERVICE_STATUS serviceStatus;
  466. if (!::QueryServiceStatus(hService, &serviceStatus))
  467. {
  468. //
  469. // Possible Errors:
  470. // ERROR_ACCESS_DENIED
  471. // ERROR_INVALID_HANDLE
  472. //
  473. err = GetLastError();
  474. ::CloseServiceHandle(hService);
  475. ::CloseServiceHandle(hScManager);
  476. return err;
  477. }
  478. // If the service is in a start pending, do not do anything
  479. if (serviceStatus.dwCurrentState == SERVICE_START_PENDING)
  480. {
  481. ::CloseServiceHandle(hService);
  482. ::CloseServiceHandle(hScManager);
  483. err = ERROR_SERVICE_ALREADY_RUNNING;
  484. return err;
  485. }
  486. if (!::StartService(hService, NULL, NULL))
  487. {
  488. //
  489. // Possible Errors:
  490. // ERROR_ACCESS_DENIED
  491. // ERROR_INVALID_HANDLE
  492. // ERROR_PATH_NOT_FOUND
  493. // ERROR_SERVICE_ALREADY_RUNNING
  494. // ERROR_SERVICE_DATABASE_LOCKED
  495. // ERROR_SERVICE_DEPENDENCY_DELETED
  496. // ERROR_SERVICE_DEPENDENCY_FAIL
  497. // ERROR_SERVICE_DISABLED
  498. // ERROR_SERVICE_LOGON_FAILED
  499. // ERROR_SERVICE_MARKED_FOR_DELETE
  500. // ERROR_SERVICE_NO_THREAD
  501. // ERROR_SERVICE_REQUEST_TIMEOUT
  502. //
  503. err = GetLastError();
  504. ::CloseServiceHandle(hService);
  505. ::CloseServiceHandle(hScManager);
  506. return err;
  507. }
  508. //
  509. // Put up the dialog with the funky spinning thing to
  510. // let the user know that something is happening
  511. //
  512. CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, TRUE);
  513. dlgServiceCtrl.DoModal();
  514. err = dlgServiceCtrl.m_dwErr;
  515. //
  516. // Everything started ok, close up and get going
  517. //
  518. ::CloseServiceHandle(hService);
  519. ::CloseServiceHandle(hScManager);
  520. return err;
  521. }
  522. DWORD
  523. StopSCMService
  524. (
  525. LPCTSTR pszComputer,
  526. LPCTSTR pszServiceName,
  527. LPCTSTR pszServiceDesc
  528. )
  529. {
  530. DWORD err = 0;
  531. SC_HANDLE hScManager;
  532. LPENUM_SERVICE_STATUS lpScStatus = NULL;
  533. DWORD dwNumService = 0, dwSize = 0, dwSizeReqd = 0, i = 0;
  534. BOOL bRet;
  535. //
  536. // Open the SCManager so that we can try to stop the service
  537. //
  538. hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
  539. if (hScManager == NULL)
  540. {
  541. //
  542. // Possible Errors:
  543. // ERROR_ACCESS_DENIED
  544. // ERROR_DATABASE_DOES_NOT_EXIST
  545. // ERROR_INVALID_PARAMETER
  546. //
  547. return GetLastError();
  548. }
  549. SC_HANDLE hService = ::OpenService(
  550. hScManager, pszServiceName,
  551. SERVICE_STOP | SERVICE_QUERY_STATUS |
  552. SERVICE_ENUMERATE_DEPENDENTS
  553. );
  554. if (hService == NULL)
  555. {
  556. //
  557. // Possible Errors:
  558. // ERROR_ACCESS_DENIED
  559. // ERROR_INVALID_HANDLE
  560. // ERROR_INVALID_NAME
  561. // ERROR_SERVICE_DOES_NOT_EXIST
  562. //
  563. err = GetLastError();
  564. ::CloseServiceHandle(hScManager);
  565. return err;
  566. }
  567. //
  568. // Stop all dependent services that are currently active.
  569. // Since the number of services is unknown (up front),
  570. // EnumDependentServices is called atleast twice (first
  571. // to get the size of buffer, and second to get the
  572. // list of services). If the number of services changes
  573. // between the calls, then EnumDependentServices is called
  574. // one more time (as per the logic, i < 3).
  575. //
  576. do
  577. {
  578. //
  579. // Enumerate all dependent services
  580. //
  581. bRet = ::EnumDependentServices(
  582. hService, SERVICE_ACTIVE, lpScStatus, dwSize,
  583. &dwSizeReqd, &dwNumService
  584. );
  585. if (!bRet && (GetLastError() == ERROR_MORE_DATA))
  586. {
  587. //
  588. // Not enough buffer to hold the dependent service list,
  589. // delete previous allocation (if any) and allocate new
  590. // buffer of requiste size.
  591. //
  592. if (lpScStatus) { delete lpScStatus; lpScStatus = NULL; }
  593. lpScStatus = reinterpret_cast<LPENUM_SERVICE_STATUS>
  594. (new BYTE[2 * dwSizeReqd]);
  595. if (lpScStatus == NULL)
  596. {
  597. //
  598. // allocation failed, forget about stopping dependent
  599. // services
  600. //
  601. break;
  602. }
  603. //
  604. // Increment attempt count. At most 3 attempts will be made
  605. // to get the list of dependent services
  606. //
  607. dwSize = 2 * dwSizeReqd;
  608. dwSizeReqd = 0;
  609. i++;
  610. }
  611. else
  612. {
  613. //
  614. // Success or failure for other than insufficent buffer reason
  615. //
  616. break;
  617. }
  618. } while( i < 3 );
  619. //
  620. // if dependent service were successfully enumerated
  621. // stop them all
  622. //
  623. if (bRet)
  624. {
  625. for (i = 0; i < dwNumService; i++)
  626. {
  627. StopSCMService(
  628. pszComputer,
  629. lpScStatus[i].lpServiceName,
  630. lpScStatus[i].lpDisplayName
  631. );
  632. }
  633. }
  634. if (lpScStatus) { delete lpScStatus; lpScStatus = NULL; }
  635. //
  636. // Stop the service, now that all dependents have been stopped
  637. //
  638. SERVICE_STATUS serviceStatus;
  639. if (!::ControlService(hService, SERVICE_CONTROL_STOP, &serviceStatus))
  640. {
  641. //
  642. // Possible Errors:
  643. // ERROR_ACCESS_DENIED
  644. // ERROR_DEPENDENT_SERVICES_RUNNING
  645. // ERROR_INVALID_SERVICE_CONTROL
  646. // ERROR_SERVICE_CANNOT_ACCEPT_CTRL
  647. // ERROR_SERVICE_NOT_ACTIVE
  648. // ERROR_SERVICE_REQUEST_TIMEOUT
  649. //
  650. err = GetLastError();
  651. ::CloseServiceHandle(hService);
  652. ::CloseServiceHandle(hScManager);
  653. return err;
  654. }
  655. if ( serviceStatus.dwCurrentState != SERVICE_STOPPED )
  656. {
  657. //
  658. // Put up the dialog with the funky spinning thing to
  659. // let the user know that something is happening
  660. //
  661. CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, FALSE);
  662. dlgServiceCtrl.DoModal();
  663. err = dlgServiceCtrl.m_dwErr;
  664. }
  665. //
  666. // Everything stopped ok, close up and get going
  667. //
  668. ::CloseServiceHandle(hService);
  669. ::CloseServiceHandle(hScManager);
  670. return err;
  671. }
  672. TFSCORE_API(DWORD) TFSPauseService(LPCTSTR pszComputer, LPCTSTR pszServiceName, LPCTSTR pszServiceDesc)
  673. {
  674. return PauseSCMService(pszComputer, pszServiceName, pszServiceDesc);
  675. }
  676. TFSCORE_API(DWORD) TFSResumeService(LPCTSTR pszComputer, LPCTSTR pszServiceName, LPCTSTR pszServiceDesc)
  677. {
  678. return ResumeSCMService(pszComputer, pszServiceName, pszServiceDesc);
  679. }
  680. DWORD
  681. PauseSCMService
  682. (
  683. LPCTSTR pszComputer,
  684. LPCTSTR pszServiceName,
  685. LPCTSTR pszServiceDesc
  686. )
  687. {
  688. DWORD err = 0;
  689. SC_HANDLE hScManager;
  690. //
  691. // Open the SCManager so that we can try to stop the service
  692. //
  693. hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
  694. if (hScManager == NULL)
  695. {
  696. //
  697. // Possible Errors:
  698. // ERROR_ACCESS_DENIED
  699. // ERROR_DATABASE_DOES_NOT_EXIST
  700. // ERROR_INVALID_PARAMETER
  701. //
  702. return GetLastError();
  703. }
  704. SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_STATUS);
  705. if (hService == NULL)
  706. {
  707. //
  708. // Possible Errors:
  709. // ERROR_ACCESS_DENIED
  710. // ERROR_INVALID_HANDLE
  711. // ERROR_INVALID_NAME
  712. // ERROR_SERVICE_DOES_NOT_EXIST
  713. //
  714. err = GetLastError();
  715. ::CloseServiceHandle(hScManager);
  716. return err;
  717. }
  718. SERVICE_STATUS serviceStatus;
  719. if (!::ControlService(hService, SERVICE_CONTROL_PAUSE, &serviceStatus))
  720. {
  721. //
  722. // Possible Errors:
  723. // ERROR_ACCESS_DENIED
  724. // ERROR_DEPENDENT_SERVICES_RUNNING
  725. // ERROR_INVALID_SERVICE_CONTROL
  726. // ERROR_SERVICE_CANNOT_ACCEPT_CTRL
  727. // ERROR_SERVICE_NOT_ACTIVE
  728. // ERROR_SERVICE_REQUEST_TIMEOUT
  729. //
  730. err = GetLastError();
  731. ::CloseServiceHandle(hService);
  732. ::CloseServiceHandle(hScManager);
  733. return err;
  734. }
  735. #if 0
  736. if ( serviceStatus.dwCurrentState != SERVICE_STOPPED )
  737. {
  738. //
  739. // Put up the dialog with the funky spinning thing to
  740. // let the user know that something is happening
  741. //
  742. CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, FALSE);
  743. dlgServiceCtrl.DoModal();
  744. err = dlgServiceCtrl.m_dwErr;
  745. }
  746. #endif
  747. //
  748. // Everything stopped ok, close up and get going
  749. //
  750. ::CloseServiceHandle(hService);
  751. ::CloseServiceHandle(hScManager);
  752. return err;
  753. }
  754. DWORD
  755. ResumeSCMService
  756. (
  757. LPCTSTR pszComputer,
  758. LPCTSTR pszServiceName,
  759. LPCTSTR pszServiceDesc
  760. )
  761. {
  762. DWORD err = 0;
  763. SC_HANDLE hScManager;
  764. //
  765. // Open the SCManager so that we can try to stop the service
  766. //
  767. hScManager = ::OpenSCManager(pszComputer, NULL, SC_MANAGER_CONNECT );
  768. if (hScManager == NULL)
  769. {
  770. //
  771. // Possible Errors:
  772. // ERROR_ACCESS_DENIED
  773. // ERROR_DATABASE_DOES_NOT_EXIST
  774. // ERROR_INVALID_PARAMETER
  775. //
  776. return GetLastError();
  777. }
  778. SC_HANDLE hService = ::OpenService(hScManager, pszServiceName, SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_STATUS);
  779. if (hService == NULL)
  780. {
  781. //
  782. // Possible Errors:
  783. // ERROR_ACCESS_DENIED
  784. // ERROR_INVALID_HANDLE
  785. // ERROR_INVALID_NAME
  786. // ERROR_SERVICE_DOES_NOT_EXIST
  787. //
  788. err = GetLastError();
  789. ::CloseServiceHandle(hScManager);
  790. return err;
  791. }
  792. SERVICE_STATUS serviceStatus;
  793. if (!::ControlService(hService, SERVICE_CONTROL_CONTINUE, &serviceStatus))
  794. {
  795. //
  796. // Possible Errors:
  797. // ERROR_ACCESS_DENIED
  798. // ERROR_DEPENDENT_SERVICES_RUNNING
  799. // ERROR_INVALID_SERVICE_CONTROL
  800. // ERROR_SERVICE_CANNOT_ACCEPT_CTRL
  801. // ERROR_SERVICE_NOT_ACTIVE
  802. // ERROR_SERVICE_REQUEST_TIMEOUT
  803. //
  804. err = GetLastError();
  805. ::CloseServiceHandle(hService);
  806. ::CloseServiceHandle(hScManager);
  807. return err;
  808. }
  809. #if 0
  810. if ( serviceStatus.dwCurrentState != SERVICE_STOPPED )
  811. {
  812. //
  813. // Put up the dialog with the funky spinning thing to
  814. // let the user know that something is happening
  815. //
  816. CServiceCtrlDlg dlgServiceCtrl(hService, pszComputer, pszServiceDesc, FALSE);
  817. dlgServiceCtrl.DoModal();
  818. err = dlgServiceCtrl.m_dwErr;
  819. }
  820. #endif
  821. //
  822. // Everything stopped ok, close up and get going
  823. //
  824. ::CloseServiceHandle(hService);
  825. ::CloseServiceHandle(hScManager);
  826. return err;
  827. }