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.

896 lines
20 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. service.c
  5. Abstract:
  6. This file provides access to the service control
  7. manager for starting, stopping, adding, and removing
  8. services.
  9. Environment:
  10. WIN32 User Mode
  11. Author:
  12. Wesley Witt (wesw) 17-Feb-1996
  13. --*/
  14. #include "faxocm.h"
  15. #pragma hdrstop
  16. BOOL
  17. InstallFaxService(
  18. BOOL UseLocalSystem,
  19. BOOL DemandStart,
  20. LPTSTR AccountName,
  21. LPTSTR Password
  22. )
  23. /*++
  24. Routine Description:
  25. Service installation function. This function just
  26. calls the service controller to install the FAX service.
  27. It is required that the FAX service run in the context
  28. of a user so that the service can access MAPI, files on
  29. disk, the network, etc.
  30. Arguments:
  31. UseLocalSystem - Don't use the accountname/password, use LocalSystem
  32. Username - User name where the service runs.
  33. Password - Password for the user name.
  34. Return Value:
  35. Return code. Return zero for success, all other
  36. values indicate errors.
  37. --*/
  38. {
  39. SC_HANDLE hSvcMgr;
  40. SC_HANDLE hService;
  41. DWORD ErrorCode;
  42. DWORD NumberOfTries = 0;
  43. hSvcMgr = OpenSCManager(
  44. NULL,
  45. NULL,
  46. SC_MANAGER_ALL_ACCESS
  47. );
  48. if (!hSvcMgr) {
  49. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  50. return FALSE;
  51. }
  52. try_again:
  53. hService = OpenService(
  54. hSvcMgr,
  55. FAX_SERVICE_NAME,
  56. SERVICE_ALL_ACCESS
  57. );
  58. if (hService) {
  59. CloseServiceHandle( hService );
  60. if (MyDeleteService( FAX_SERVICE_NAME )) {
  61. goto AddService;
  62. }
  63. NumberOfTries += 1;
  64. if (NumberOfTries < 2) {
  65. goto try_again;
  66. } else {
  67. CloseServiceHandle( hSvcMgr );
  68. return FALSE;
  69. }
  70. }
  71. AddService:
  72. if (!UseLocalSystem) {
  73. ErrorCode = SetServiceSecurity( AccountName );
  74. if (ErrorCode) {
  75. DebugPrint(( L"Could not grant access rights to [%s] : error code = 0x%08x", AccountName, ErrorCode ));
  76. SetLastError( ERROR_SERVICE_LOGON_FAILED );
  77. return FALSE;
  78. }
  79. }
  80. hService = CreateService(
  81. hSvcMgr,
  82. FAX_SERVICE_NAME,
  83. GetString(IDS_FAX_DISPLAY_NAME),
  84. SERVICE_ALL_ACCESS,
  85. UseLocalSystem ? SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS : SERVICE_WIN32_OWN_PROCESS,
  86. DemandStart ? SERVICE_DEMAND_START : SERVICE_AUTO_START,
  87. SERVICE_ERROR_NORMAL,
  88. FAX_SERVICE_IMAGE_NAME,
  89. NULL,
  90. NULL,
  91. FAX_SERVICE_DEPENDENCY,
  92. UseLocalSystem ? NULL : AccountName,
  93. UseLocalSystem ? NULL : Password
  94. );
  95. if (!hService) {
  96. DebugPrint(( L"Could not create fax service: error code = %u", GetLastError() ));
  97. return FALSE;
  98. }
  99. SERVICE_DESCRIPTION ServiceDescription;
  100. ServiceDescription.lpDescription = (LPTSTR) GetString( IDS_SERVICE_DESCRIPTION );
  101. ChangeServiceConfig2( hService, SERVICE_CONFIG_DESCRIPTION, (LPVOID)&ServiceDescription);
  102. ErrorCode = SetServiceWorldAccessMask( hService, SERVICE_START );
  103. CloseServiceHandle( hService );
  104. CloseServiceHandle( hSvcMgr );
  105. if (ErrorCode == 0) {
  106. DebugPrint(( L"Could not set SERVICE_START access mask on service, ec=%u", GetLastError() ));
  107. MyDeleteService( FAX_SERVICE_NAME );
  108. }
  109. return ErrorCode;
  110. }
  111. BOOL
  112. RenameFaxService(
  113. VOID
  114. )
  115. /*++
  116. Routine Description:
  117. Renames the FAX service from "Microsoft Fax Service" to "Fax Service".
  118. If the fax svc has any other name or is already named
  119. "Microsoft Fax Service", the service is still renamed.
  120. Arguments:
  121. None
  122. Return Value:
  123. Return code. Return zero for success, indicating the faxsvc was
  124. successfully renamed, all other values indicate errors.
  125. --*/
  126. {
  127. SC_HANDLE hSvcMgr = NULL;
  128. SC_HANDLE hService = NULL;
  129. BOOL bResult;
  130. bResult = FALSE;
  131. //
  132. // get a handle to the fax service so we can look at it's display name
  133. //
  134. hSvcMgr = OpenSCManager(
  135. NULL,
  136. NULL,
  137. SC_MANAGER_ALL_ACCESS
  138. );
  139. if (!hSvcMgr) {
  140. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  141. goto e0;
  142. }
  143. hService = OpenService(
  144. hSvcMgr,
  145. FAX_SERVICE_NAME,
  146. SERVICE_ALL_ACCESS
  147. );
  148. if (!hService) {
  149. DebugPrint(( L"could not open fax service: error code = %u", GetLastError() ));
  150. goto e1;
  151. }
  152. //
  153. // Change the service display name.
  154. // SERVICE_NO_CHANGE and NULL indicate no change to that parameter
  155. //
  156. bResult = ChangeServiceConfig(
  157. hService,
  158. SERVICE_NO_CHANGE,
  159. SERVICE_NO_CHANGE,
  160. SERVICE_NO_CHANGE,
  161. NULL,
  162. NULL,
  163. NULL,
  164. NULL,
  165. NULL,
  166. NULL,
  167. GetString(IDS_FAX_DISPLAY_NAME));
  168. if (hService) CloseServiceHandle( hService );
  169. e1:
  170. if (hSvcMgr) CloseServiceHandle( hSvcMgr );
  171. e0:
  172. return(bResult);
  173. }
  174. DWORD
  175. StartTheService(
  176. LPTSTR ServiceName
  177. )
  178. {
  179. DWORD rVal = 0;
  180. SC_HANDLE hSvcMgr = NULL;
  181. SC_HANDLE hService = NULL;
  182. SERVICE_STATUS Status;
  183. DWORD OldCheckPoint = 0;
  184. DWORD i = 0;
  185. hSvcMgr = OpenSCManager(
  186. NULL,
  187. NULL,
  188. SC_MANAGER_ALL_ACCESS
  189. );
  190. if (!hSvcMgr) {
  191. rVal = GetLastError();
  192. DebugPrint(( L"could not open service manager: error code = %u", rVal ));
  193. goto exit;
  194. }
  195. hService = OpenService(
  196. hSvcMgr,
  197. ServiceName,
  198. SERVICE_ALL_ACCESS
  199. );
  200. if (!hService) {
  201. rVal = GetLastError();
  202. DebugPrint((
  203. L"could not open the %s service: error code = %u",
  204. ServiceName,
  205. rVal
  206. ));
  207. goto exit;
  208. }
  209. //
  210. // the service exists, lets start it
  211. //
  212. if (!StartService( hService, 0, NULL )) {
  213. rVal = GetLastError();
  214. if (rVal == ERROR_SERVICE_ALREADY_RUNNING) {
  215. rVal = ERROR_SUCCESS;
  216. goto exit;
  217. }
  218. DebugPrint((
  219. L"could not start the %s service: error code = %u",
  220. ServiceName,
  221. rVal
  222. ));
  223. goto exit;
  224. }
  225. do {
  226. if (!QueryServiceStatus( hService, &Status )) {
  227. DebugPrint((
  228. L"could not query status for the %s service: error code = %u",
  229. ServiceName,
  230. rVal
  231. ));
  232. break;
  233. }
  234. i += 1;
  235. if (i > 60) {
  236. break;
  237. }
  238. Sleep( 1000 );
  239. } while (Status.dwCurrentState != SERVICE_RUNNING);
  240. if (Status.dwCurrentState != SERVICE_RUNNING) {
  241. rVal = GetLastError();
  242. DebugPrint((
  243. L"could not start the %s service: error code = %u",
  244. ServiceName,
  245. rVal
  246. ));
  247. goto exit;
  248. }
  249. rVal = ERROR_SUCCESS;
  250. exit:
  251. CloseServiceHandle( hService );
  252. CloseServiceHandle( hSvcMgr );
  253. return rVal;
  254. }
  255. DWORD
  256. MyStartService(
  257. LPTSTR ServiceName
  258. )
  259. {
  260. DWORD rVal = 0;
  261. SC_HANDLE hSvcMgr = NULL;
  262. SC_HANDLE hService = NULL;
  263. LPENUM_SERVICE_STATUS EnumServiceStatus = NULL;
  264. hSvcMgr = OpenSCManager(
  265. NULL,
  266. NULL,
  267. SC_MANAGER_ALL_ACCESS
  268. );
  269. if (!hSvcMgr) {
  270. rVal = GetLastError();
  271. DebugPrint(( L"could not open service manager: error code = %u", rVal ));
  272. goto exit;
  273. }
  274. hService = OpenService(
  275. hSvcMgr,
  276. ServiceName,
  277. SERVICE_ALL_ACCESS
  278. );
  279. if (!hService) {
  280. rVal = GetLastError();
  281. DebugPrint((
  282. L"could not open the %s service: error code = %u",
  283. ServiceName,
  284. rVal
  285. ));
  286. goto exit;
  287. }
  288. rVal = StartTheService( ServiceName );
  289. exit:
  290. CloseServiceHandle( hService );
  291. CloseServiceHandle( hSvcMgr );
  292. return rVal;
  293. }
  294. BOOL
  295. StopTheService(
  296. LPTSTR ServiceName
  297. )
  298. {
  299. DWORD rVal = 0;
  300. SC_HANDLE hSvcMgr;
  301. SC_HANDLE hService;
  302. SERVICE_STATUS Status;
  303. DWORD OldCheckPoint;
  304. hSvcMgr = OpenSCManager(
  305. NULL,
  306. NULL,
  307. SC_MANAGER_ALL_ACCESS
  308. );
  309. if (!hSvcMgr) {
  310. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  311. goto exit;
  312. }
  313. hService = OpenService(
  314. hSvcMgr,
  315. ServiceName,
  316. SERVICE_ALL_ACCESS
  317. );
  318. if (!hService) {
  319. DebugPrint((
  320. L"could not open the %s service: error code = %u",
  321. ServiceName,
  322. GetLastError()
  323. ));
  324. goto exit;
  325. }
  326. //
  327. // the service exists, lets stop it
  328. //
  329. ControlService(
  330. hService,
  331. SERVICE_CONTROL_STOP,
  332. &Status
  333. );
  334. if (!QueryServiceStatus( hService, &Status )) {
  335. DebugPrint((
  336. L"could not query status for the %s service: error code = %u",
  337. ServiceName,
  338. GetLastError()
  339. ));
  340. goto exit;
  341. }
  342. while (Status.dwCurrentState == SERVICE_RUNNING) {
  343. OldCheckPoint = Status.dwCheckPoint;
  344. Sleep( Status.dwWaitHint );
  345. if (!QueryServiceStatus( hService, &Status )) {
  346. break;
  347. }
  348. if (OldCheckPoint >= Status.dwCheckPoint) {
  349. break;
  350. }
  351. }
  352. if (Status.dwCurrentState == SERVICE_RUNNING) {
  353. DebugPrint((
  354. L"could not stop the %s service: error code = %u",
  355. ServiceName,
  356. GetLastError()
  357. ));
  358. goto exit;
  359. }
  360. rVal = TRUE;
  361. exit:
  362. CloseServiceHandle( hService );
  363. CloseServiceHandle( hSvcMgr );
  364. return rVal;
  365. }
  366. BOOL
  367. MyStopService(
  368. LPTSTR ServiceName
  369. )
  370. {
  371. DWORD rVal = 0;
  372. SC_HANDLE hSvcMgr;
  373. SC_HANDLE hService;
  374. LPENUM_SERVICE_STATUS EnumServiceStatus = NULL;
  375. DWORD BytesNeeded;
  376. DWORD ServiceCount;
  377. DWORD i;
  378. hSvcMgr = OpenSCManager(
  379. NULL,
  380. NULL,
  381. SC_MANAGER_ALL_ACCESS
  382. );
  383. if (!hSvcMgr) {
  384. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  385. goto exit;
  386. }
  387. hService = OpenService(
  388. hSvcMgr,
  389. ServiceName,
  390. SERVICE_ALL_ACCESS
  391. );
  392. if (!hService) {
  393. DebugPrint((
  394. L"could not open the %s service: error code = %u",
  395. ServiceName,
  396. GetLastError()
  397. ));
  398. goto exit;
  399. }
  400. if (!EnumDependentServices( hService, SERVICE_ACTIVE, NULL, 0, &BytesNeeded, &ServiceCount )) {
  401. if (GetLastError() != ERROR_MORE_DATA) {
  402. DebugPrint(( L"could not enumerate dependent services, ec=%d", GetLastError() ));
  403. goto exit;
  404. }
  405. EnumServiceStatus = (LPENUM_SERVICE_STATUS) MemAlloc( BytesNeeded );
  406. if (!EnumServiceStatus) {
  407. DebugPrint(( L"could not allocate memory for EnumDependentServices()" ));
  408. goto exit;
  409. }
  410. }
  411. if (!EnumDependentServices( hService, SERVICE_ACTIVE, EnumServiceStatus, BytesNeeded, &BytesNeeded, &ServiceCount )) {
  412. DebugPrint(( L"could not enumerate dependent services, ec=%d", GetLastError() ));
  413. goto exit;
  414. }
  415. if (ServiceCount) {
  416. for (i=0; i<ServiceCount; i++) {
  417. StopTheService( EnumServiceStatus[i].lpServiceName );
  418. }
  419. }
  420. StopTheService( ServiceName );
  421. exit:
  422. if (EnumServiceStatus) {
  423. MemFree( EnumServiceStatus );
  424. }
  425. CloseServiceHandle( hService );
  426. CloseServiceHandle( hSvcMgr );
  427. return rVal;
  428. }
  429. DWORD
  430. StartFaxService(
  431. VOID
  432. )
  433. {
  434. return MyStartService( FAX_SERVICE_NAME );
  435. }
  436. BOOL
  437. StopFaxService(
  438. VOID
  439. )
  440. {
  441. return MyStopService( FAX_SERVICE_NAME );
  442. }
  443. BOOL
  444. StartSpoolerService(
  445. VOID
  446. )
  447. {
  448. DWORD Result;
  449. Result = MyStartService( L"Spooler");
  450. if (Result != ERROR_SUCCESS) {
  451. return FALSE;
  452. }
  453. //
  454. // the spooler lies about it's starting state, but
  455. // doesn't provide a way to synchronize the completion
  456. // of it starting. so we just wait for some random time period.
  457. //
  458. Sleep( 1000 * 7 );
  459. return TRUE;
  460. }
  461. BOOL
  462. StopSpoolerService(
  463. VOID
  464. )
  465. {
  466. return MyStopService( L"Spooler" );
  467. }
  468. BOOL
  469. SetServiceDependency(
  470. LPTSTR ServiceName,
  471. LPTSTR DependentServiceName
  472. )
  473. {
  474. BOOL rVal = FALSE;
  475. SC_HANDLE hSvcMgr;
  476. SC_HANDLE hService;
  477. hSvcMgr = OpenSCManager(
  478. NULL,
  479. NULL,
  480. SC_MANAGER_ALL_ACCESS
  481. );
  482. if (!hSvcMgr) {
  483. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  484. goto exit;
  485. }
  486. hService = OpenService(
  487. hSvcMgr,
  488. ServiceName,
  489. SERVICE_ALL_ACCESS
  490. );
  491. if (!hService) {
  492. DebugPrint((
  493. L"could not open the %s service: error code = %u",
  494. ServiceName,
  495. GetLastError()
  496. ));
  497. goto exit;
  498. }
  499. if (!ChangeServiceConfig(
  500. hService, // handle to service
  501. SERVICE_NO_CHANGE, // type of service
  502. SERVICE_NO_CHANGE, // when to start service
  503. SERVICE_NO_CHANGE, // severity if service fails to start
  504. NULL, // pointer to service binary file name
  505. NULL, // pointer to load ordering group name
  506. NULL, // pointer to variable to get tag identifier
  507. DependentServiceName, // pointer to array of dependency names
  508. NULL, // pointer to account name of service
  509. NULL, // pointer to password for service account
  510. NULL // pointer to display name
  511. )) {
  512. DebugPrint(( L"could not open change service configuration, ec=%d", GetLastError() ));
  513. goto exit;
  514. }
  515. rVal = TRUE;
  516. exit:
  517. CloseServiceHandle( hService );
  518. CloseServiceHandle( hSvcMgr );
  519. return rVal;
  520. }
  521. BOOL
  522. SetServiceStart(
  523. LPTSTR ServiceName,
  524. DWORD StartType
  525. )
  526. {
  527. BOOL rVal = FALSE;
  528. SC_HANDLE hSvcMgr;
  529. SC_HANDLE hService;
  530. hSvcMgr = OpenSCManager(
  531. NULL,
  532. NULL,
  533. SC_MANAGER_ALL_ACCESS
  534. );
  535. if (!hSvcMgr) {
  536. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  537. goto exit;
  538. }
  539. hService = OpenService(
  540. hSvcMgr,
  541. ServiceName,
  542. SERVICE_ALL_ACCESS
  543. );
  544. if (!hService) {
  545. DebugPrint((
  546. L"could not open the %s service: error code = %u",
  547. ServiceName,
  548. GetLastError()
  549. ));
  550. goto exit;
  551. }
  552. if (!ChangeServiceConfig(
  553. hService, // handle to service
  554. SERVICE_NO_CHANGE, // type of service
  555. StartType, // when to start service
  556. SERVICE_NO_CHANGE, // severity if service fails to start
  557. NULL, // pointer to service binary file name
  558. NULL, // pointer to load ordering group name
  559. NULL, // pointer to variable to get tag identifier
  560. NULL, // pointer to array of dependency names
  561. NULL, // pointer to account name of service
  562. NULL, // pointer to password for service account
  563. NULL // pointer to display name
  564. ))
  565. {
  566. DebugPrint(( L"could not open change service configuration, ec=%d", GetLastError() ));
  567. goto exit;
  568. }
  569. rVal = TRUE;
  570. exit:
  571. CloseServiceHandle( hService );
  572. CloseServiceHandle( hSvcMgr );
  573. return rVal;
  574. }
  575. BOOL
  576. SetServiceAccount(
  577. LPTSTR ServiceName,
  578. PSECURITY_INFO SecurityInfo
  579. )
  580. {
  581. BOOL rVal = FALSE;
  582. SC_HANDLE hSvcMgr;
  583. SC_HANDLE hService;
  584. hSvcMgr = OpenSCManager(
  585. NULL,
  586. NULL,
  587. SC_MANAGER_ALL_ACCESS
  588. );
  589. if (!hSvcMgr) {
  590. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  591. goto exit;
  592. }
  593. hService = OpenService(
  594. hSvcMgr,
  595. ServiceName,
  596. SERVICE_ALL_ACCESS
  597. );
  598. if (!hService) {
  599. DebugPrint((
  600. L"could not open the %s service: error code = %u",
  601. ServiceName,
  602. GetLastError()
  603. ));
  604. goto exit;
  605. }
  606. if (!ChangeServiceConfig(
  607. hService, // handle to service
  608. SERVICE_NO_CHANGE, // type of service
  609. SERVICE_NO_CHANGE, // when to start service
  610. SERVICE_NO_CHANGE, // severity if service fails to start
  611. NULL, // pointer to service binary file name
  612. NULL, // pointer to load ordering group name
  613. NULL, // pointer to variable to get tag identifier
  614. NULL, // pointer to array of dependency names
  615. SecurityInfo->AccountName, // pointer to account name of service
  616. SecurityInfo->Password, // pointer to password for service account
  617. NULL // pointer to display name
  618. )) {
  619. DebugPrint(( L"could not open change service configuration, ec=%d", GetLastError() ));
  620. goto exit;
  621. }
  622. rVal = TRUE;
  623. exit:
  624. CloseServiceHandle( hService );
  625. CloseServiceHandle( hSvcMgr );
  626. return rVal;
  627. }
  628. BOOL
  629. MyDeleteService(
  630. LPTSTR ServiceName
  631. )
  632. {
  633. SC_HANDLE hSvcMgr = NULL;
  634. SC_HANDLE hService = NULL;
  635. SERVICE_STATUS Status;
  636. DWORD NumberOfTries = 0;
  637. BOOL bSuccess = FALSE;
  638. hSvcMgr = OpenSCManager(
  639. NULL,
  640. NULL,
  641. SC_MANAGER_ALL_ACCESS
  642. );
  643. if (!hSvcMgr) {
  644. return FALSE;
  645. }
  646. hService = OpenService(
  647. hSvcMgr,
  648. ServiceName,
  649. SERVICE_ALL_ACCESS
  650. );
  651. if (hService) {
  652. //
  653. // the service exists, lets be sure that it is stopped
  654. //
  655. Try_Again:
  656. if (!ControlService( hService, SERVICE_CONTROL_STOP, &Status ) &&
  657. GetLastError() == ERROR_INVALID_SERVICE_CONTROL ) {
  658. if (NumberOfTries < 3) {
  659. //
  660. // service is in the "START PENDING" state. Let's wait a bit and try again.
  661. //
  662. NumberOfTries += 1;
  663. Sleep( 2 * 1000 );
  664. goto Try_Again;
  665. } else {
  666. goto Exit;
  667. }
  668. }
  669. //
  670. // now delete it
  671. //
  672. if (!DeleteService( hService )) {
  673. if (GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE) {
  674. bSuccess = TRUE;
  675. }
  676. } else {
  677. bSuccess = TRUE;
  678. }
  679. } else {
  680. //
  681. // service doesn't exist, return TRUE even though we've done nothing
  682. //
  683. bSuccess = TRUE;
  684. }
  685. Exit:
  686. if (hService) {
  687. CloseServiceHandle( hService );
  688. }
  689. if (hSvcMgr) {
  690. CloseServiceHandle( hSvcMgr );
  691. }
  692. return bSuccess;
  693. }
  694. BOOL
  695. DeleteFaxService(
  696. VOID
  697. )
  698. {
  699. return MyDeleteService( FAX_SERVICE_NAME );
  700. }
  701. BOOL
  702. SetFaxServiceAutoStart(
  703. VOID
  704. )
  705. {
  706. return SetServiceStart( FAX_SERVICE_NAME, SERVICE_AUTO_START );
  707. }