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.

844 lines
18 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 "wizard.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. SERVICE_STATUS Status;
  42. DWORD ErrorCode;
  43. hSvcMgr = OpenSCManager(
  44. NULL,
  45. NULL,
  46. SC_MANAGER_ALL_ACCESS
  47. );
  48. if (!hSvcMgr) {
  49. DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() ));
  50. return FALSE;
  51. }
  52. hService = OpenService(
  53. hSvcMgr,
  54. FAX_SERVICE_NAME,
  55. SERVICE_ALL_ACCESS
  56. );
  57. if (hService) {
  58. //
  59. // the service exists, lets be sure that it is stopped
  60. //
  61. ControlService(
  62. hService,
  63. SERVICE_CONTROL_STOP,
  64. &Status
  65. );
  66. DeleteService( hService );
  67. CloseServiceHandle( hService );
  68. }
  69. if (!UseLocalSystem) {
  70. ErrorCode = SetServiceSecurity( AccountName );
  71. if (ErrorCode) {
  72. DebugPrint(( TEXT("Could not grant access rights to [%s] : error code = 0x%08x"), AccountName, ErrorCode ));
  73. SetLastError( ERROR_SERVICE_LOGON_FAILED );
  74. return FALSE;
  75. }
  76. }
  77. hService = CreateService(
  78. hSvcMgr,
  79. FAX_SERVICE_NAME,
  80. FAX_SERVICE_DISPLAY_NAME,
  81. SERVICE_ALL_ACCESS,
  82. SERVICE_WIN32_OWN_PROCESS,
  83. DemandStart ? SERVICE_DEMAND_START : SERVICE_AUTO_START,
  84. SERVICE_ERROR_NORMAL,
  85. FAX_SERVICE_IMAGE_NAME,
  86. NULL,
  87. NULL,
  88. FAX_SERVICE_DEPENDENCY,
  89. UseLocalSystem ? NULL : AccountName,
  90. UseLocalSystem ? NULL : Password
  91. );
  92. if (!hService) {
  93. DebugPrint(( TEXT("Could not create fax service: error code = %u"), GetLastError() ));
  94. return FALSE;
  95. }
  96. CloseServiceHandle( hService );
  97. CloseServiceHandle( hSvcMgr );
  98. return TRUE;
  99. }
  100. DWORD
  101. StartTheService(
  102. LPTSTR ServiceName
  103. )
  104. {
  105. DWORD rVal = 0;
  106. SC_HANDLE hSvcMgr = NULL;
  107. SC_HANDLE hService = NULL;
  108. SERVICE_STATUS Status;
  109. DWORD OldCheckPoint = 0;
  110. DWORD i = 0;
  111. hSvcMgr = OpenSCManager(
  112. NULL,
  113. NULL,
  114. SC_MANAGER_ALL_ACCESS
  115. );
  116. if (!hSvcMgr) {
  117. rVal = GetLastError();
  118. DebugPrint(( TEXT("could not open service manager: error code = %u"), rVal ));
  119. goto exit;
  120. }
  121. hService = OpenService(
  122. hSvcMgr,
  123. ServiceName,
  124. SERVICE_ALL_ACCESS
  125. );
  126. if (!hService) {
  127. rVal = GetLastError();
  128. DebugPrint((
  129. TEXT("could not open the %s service: error code = %u"),
  130. ServiceName,
  131. rVal
  132. ));
  133. goto exit;
  134. }
  135. //
  136. // the service exists, lets start it
  137. //
  138. if (!StartService( hService, 0, NULL )) {
  139. rVal = GetLastError();
  140. DebugPrint((
  141. TEXT("could not start the %s service: error code = %u"),
  142. ServiceName,
  143. rVal
  144. ));
  145. goto exit;
  146. }
  147. if (!QueryServiceStatus( hService, &Status )) {
  148. rVal = GetLastError();
  149. DebugPrint((
  150. TEXT("could not query status for the %s service: error code = %u"),
  151. ServiceName,
  152. rVal
  153. ));
  154. goto exit;
  155. }
  156. #if 0
  157. while (Status.dwCurrentState != SERVICE_RUNNING) {
  158. OldCheckPoint = Status.dwCheckPoint;
  159. Sleep( Status.dwWaitHint );
  160. if (!QueryServiceStatus( hService, &Status )) {
  161. break;
  162. }
  163. if (OldCheckPoint >= Status.dwCheckPoint) {
  164. break;
  165. }
  166. }
  167. #endif
  168. while (Status.dwCurrentState != SERVICE_RUNNING) {
  169. Sleep( 1000 );
  170. if (!QueryServiceStatus( hService, &Status )) {
  171. break;
  172. }
  173. i += 1;
  174. if (i > 60) {
  175. break;
  176. }
  177. }
  178. if (Status.dwCurrentState != SERVICE_RUNNING) {
  179. rVal = GetLastError();
  180. DebugPrint((
  181. TEXT("could not start the %s service: error code = %u"),
  182. ServiceName,
  183. rVal
  184. ));
  185. goto exit;
  186. }
  187. rVal = ERROR_SUCCESS;
  188. exit:
  189. CloseServiceHandle( hService );
  190. CloseServiceHandle( hSvcMgr );
  191. return rVal;
  192. }
  193. DWORD
  194. MyStartService(
  195. LPTSTR ServiceName
  196. )
  197. {
  198. DWORD rVal = 0;
  199. SC_HANDLE hSvcMgr = NULL;
  200. SC_HANDLE hService = NULL;
  201. LPENUM_SERVICE_STATUS EnumServiceStatus = NULL;
  202. hSvcMgr = OpenSCManager(
  203. NULL,
  204. NULL,
  205. SC_MANAGER_ALL_ACCESS
  206. );
  207. if (!hSvcMgr) {
  208. rVal = GetLastError();
  209. DebugPrint(( TEXT("could not open service manager: error code = %u"), rVal ));
  210. goto exit;
  211. }
  212. hService = OpenService(
  213. hSvcMgr,
  214. ServiceName,
  215. SERVICE_ALL_ACCESS
  216. );
  217. if (!hService) {
  218. rVal = GetLastError();
  219. DebugPrint((
  220. TEXT("could not open the %s service: error code = %u"),
  221. ServiceName,
  222. rVal
  223. ));
  224. goto exit;
  225. }
  226. rVal = StartTheService( ServiceName );
  227. exit:
  228. CloseServiceHandle( hService );
  229. CloseServiceHandle( hSvcMgr );
  230. return rVal;
  231. }
  232. BOOL
  233. StopTheService(
  234. LPTSTR ServiceName
  235. )
  236. {
  237. DWORD rVal = 0;
  238. SC_HANDLE hSvcMgr;
  239. SC_HANDLE hService;
  240. SERVICE_STATUS Status;
  241. DWORD OldCheckPoint;
  242. hSvcMgr = OpenSCManager(
  243. NULL,
  244. NULL,
  245. SC_MANAGER_ALL_ACCESS
  246. );
  247. if (!hSvcMgr) {
  248. DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() ));
  249. goto exit;
  250. }
  251. hService = OpenService(
  252. hSvcMgr,
  253. ServiceName,
  254. SERVICE_ALL_ACCESS
  255. );
  256. if (!hService) {
  257. DebugPrint((
  258. TEXT("could not open the %s service: error code = %u"),
  259. ServiceName,
  260. GetLastError()
  261. ));
  262. goto exit;
  263. }
  264. //
  265. // the service exists, lets stop it
  266. //
  267. ControlService(
  268. hService,
  269. SERVICE_CONTROL_STOP,
  270. &Status
  271. );
  272. if (!QueryServiceStatus( hService, &Status )) {
  273. DebugPrint((
  274. TEXT("could not query status for the %s service: error code = %u"),
  275. ServiceName,
  276. GetLastError()
  277. ));
  278. goto exit;
  279. }
  280. while (Status.dwCurrentState == SERVICE_RUNNING) {
  281. OldCheckPoint = Status.dwCheckPoint;
  282. Sleep( Status.dwWaitHint );
  283. if (!QueryServiceStatus( hService, &Status )) {
  284. break;
  285. }
  286. if (OldCheckPoint >= Status.dwCheckPoint) {
  287. break;
  288. }
  289. }
  290. if (Status.dwCurrentState == SERVICE_RUNNING) {
  291. DebugPrint((
  292. TEXT("could not stop the %s service: error code = %u"),
  293. ServiceName,
  294. GetLastError()
  295. ));
  296. goto exit;
  297. }
  298. rVal = TRUE;
  299. exit:
  300. CloseServiceHandle( hService );
  301. CloseServiceHandle( hSvcMgr );
  302. return rVal;
  303. }
  304. BOOL
  305. MyStopService(
  306. LPTSTR ServiceName
  307. )
  308. {
  309. DWORD rVal = 0;
  310. SC_HANDLE hSvcMgr;
  311. SC_HANDLE hService;
  312. LPENUM_SERVICE_STATUS EnumServiceStatus = NULL;
  313. DWORD BytesNeeded;
  314. DWORD ServiceCount;
  315. DWORD i;
  316. hSvcMgr = OpenSCManager(
  317. NULL,
  318. NULL,
  319. SC_MANAGER_ALL_ACCESS
  320. );
  321. if (!hSvcMgr) {
  322. DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() ));
  323. goto exit;
  324. }
  325. hService = OpenService(
  326. hSvcMgr,
  327. ServiceName,
  328. SERVICE_ALL_ACCESS
  329. );
  330. if (!hService) {
  331. DebugPrint((
  332. TEXT("could not open the %s service: error code = %u"),
  333. ServiceName,
  334. GetLastError()
  335. ));
  336. goto exit;
  337. }
  338. if (!EnumDependentServices( hService, SERVICE_ACTIVE, NULL, 0, &BytesNeeded, &ServiceCount )) {
  339. if (GetLastError() != ERROR_MORE_DATA) {
  340. DebugPrint(( TEXT("could not enumerate dependent services, ec=%d"), GetLastError() ));
  341. goto exit;
  342. }
  343. EnumServiceStatus = (LPENUM_SERVICE_STATUS) MemAlloc( BytesNeeded );
  344. if (!EnumServiceStatus) {
  345. DebugPrint(( TEXT("could not allocate memory for EnumDependentServices()") ));
  346. goto exit;
  347. }
  348. }
  349. if (!EnumDependentServices( hService, SERVICE_ACTIVE, EnumServiceStatus, BytesNeeded, &BytesNeeded, &ServiceCount )) {
  350. DebugPrint(( TEXT("could not enumerate dependent services, ec=%d"), GetLastError() ));
  351. goto exit;
  352. }
  353. if (ServiceCount) {
  354. for (i=0; i<ServiceCount; i++) {
  355. StopTheService( EnumServiceStatus[i].lpServiceName );
  356. }
  357. }
  358. StopTheService( ServiceName );
  359. exit:
  360. if (EnumServiceStatus) {
  361. MemFree( EnumServiceStatus );
  362. }
  363. CloseServiceHandle( hService );
  364. CloseServiceHandle( hSvcMgr );
  365. return rVal;
  366. }
  367. DWORD
  368. StartFaxService(
  369. VOID
  370. )
  371. {
  372. HANDLE FaxServerEvent;
  373. DWORD Rval;
  374. STARTUPINFO si;
  375. PROCESS_INFORMATION pi;
  376. Rval = MyStartService( FAX_SERVICE_NAME );
  377. if (Rval != ERROR_SUCCESS) {
  378. return Rval;
  379. }
  380. FaxServerEvent = OpenEvent( SYNCHRONIZE, FALSE, TEXT("FaxServerEvent") );
  381. if (!FaxServerEvent) {
  382. Rval = GetLastError();
  383. DebugPrint(( TEXT("could not open a handle to the fax service event") ));
  384. return Rval;
  385. }
  386. //
  387. // wait for the server to signal us that the service
  388. // is REALLY ready to use
  389. //
  390. if (WaitForSingleObject( FaxServerEvent, 1000 * 60 ) == WAIT_TIMEOUT) {
  391. Rval = ERROR_SERVICE_REQUEST_TIMEOUT;
  392. } else {
  393. Rval = ERROR_SUCCESS;
  394. }
  395. CloseHandle( FaxServerEvent );
  396. if ((InstallType & FAX_INSTALL_WORKSTATION) && !(InstallMode & INSTALL_UPGRADE)) {
  397. TCHAR Command[256];
  398. TCHAR SysDir[256];
  399. BOOL ProcCreated;
  400. ExpandEnvironmentStrings( TEXT( "%windir%\\system32" ), SysDir, 256 );
  401. _stprintf( Command, TEXT( "%s\\%s" ), SysDir, FAX_MONITOR_CMD );
  402. GetStartupInfo( &si );
  403. ProcCreated = CreateProcess(
  404. NULL,
  405. Command,
  406. NULL,
  407. NULL,
  408. FALSE,
  409. 0,
  410. NULL,
  411. SysDir,
  412. &si,
  413. &pi
  414. );
  415. if (ProcCreated) {
  416. Rval = ERROR_SUCCESS;
  417. } else {
  418. Rval = GetLastError();
  419. DebugPrint(( TEXT( "Could not start faxstat.exe" ) ));
  420. }
  421. }
  422. return Rval;
  423. }
  424. BOOL
  425. StopFaxService(
  426. VOID
  427. )
  428. {
  429. return MyStopService( FAX_SERVICE_NAME );
  430. }
  431. BOOL
  432. StartSpoolerService(
  433. VOID
  434. )
  435. {
  436. if (!MyStartService( TEXT("Spooler") )) {
  437. return FALSE;
  438. }
  439. //
  440. // the spooler lies about it's starting state, but
  441. // doesn't provide a way to synchronize the completion
  442. // of it starting. so we just wait for some random time period.
  443. //
  444. Sleep( 1000 * 7 );
  445. return TRUE;
  446. }
  447. BOOL
  448. StopSpoolerService(
  449. VOID
  450. )
  451. {
  452. return MyStopService( TEXT("Spooler") );
  453. }
  454. BOOL
  455. SetServiceDependency(
  456. LPTSTR ServiceName,
  457. LPTSTR DependentServiceName
  458. )
  459. {
  460. BOOL rVal = FALSE;
  461. SC_HANDLE hSvcMgr;
  462. SC_HANDLE hService;
  463. hSvcMgr = OpenSCManager(
  464. NULL,
  465. NULL,
  466. SC_MANAGER_ALL_ACCESS
  467. );
  468. if (!hSvcMgr) {
  469. DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() ));
  470. goto exit;
  471. }
  472. hService = OpenService(
  473. hSvcMgr,
  474. ServiceName,
  475. SERVICE_ALL_ACCESS
  476. );
  477. if (!hService) {
  478. DebugPrint((
  479. TEXT("could not open the %s service: error code = %u"),
  480. ServiceName,
  481. GetLastError()
  482. ));
  483. goto exit;
  484. }
  485. if (!ChangeServiceConfig(
  486. hService, // handle to service
  487. SERVICE_NO_CHANGE, // type of service
  488. SERVICE_NO_CHANGE, // when to start service
  489. SERVICE_NO_CHANGE, // severity if service fails to start
  490. NULL, // pointer to service binary file name
  491. NULL, // pointer to load ordering group name
  492. NULL, // pointer to variable to get tag identifier
  493. DependentServiceName, // pointer to array of dependency names
  494. NULL, // pointer to account name of service
  495. NULL, // pointer to password for service account
  496. NULL // pointer to display name
  497. )) {
  498. DebugPrint(( TEXT("could not open change service configuration, ec=%d"), GetLastError() ));
  499. goto exit;
  500. }
  501. rVal = TRUE;
  502. exit:
  503. CloseServiceHandle( hService );
  504. CloseServiceHandle( hSvcMgr );
  505. return rVal;
  506. }
  507. BOOL
  508. SetServiceStart(
  509. LPTSTR ServiceName,
  510. DWORD StartType
  511. )
  512. {
  513. BOOL rVal = FALSE;
  514. SC_HANDLE hSvcMgr;
  515. SC_HANDLE hService;
  516. hSvcMgr = OpenSCManager(
  517. NULL,
  518. NULL,
  519. SC_MANAGER_ALL_ACCESS
  520. );
  521. if (!hSvcMgr) {
  522. DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() ));
  523. goto exit;
  524. }
  525. hService = OpenService(
  526. hSvcMgr,
  527. ServiceName,
  528. SERVICE_ALL_ACCESS
  529. );
  530. if (!hService) {
  531. DebugPrint((
  532. TEXT("could not open the %s service: error code = %u"),
  533. ServiceName,
  534. GetLastError()
  535. ));
  536. goto exit;
  537. }
  538. if (!ChangeServiceConfig(
  539. hService, // handle to service
  540. SERVICE_NO_CHANGE, // type of service
  541. StartType, // when to start service
  542. SERVICE_NO_CHANGE, // severity if service fails to start
  543. NULL, // pointer to service binary file name
  544. NULL, // pointer to load ordering group name
  545. NULL, // pointer to variable to get tag identifier
  546. NULL, // pointer to array of dependency names
  547. NULL, // pointer to account name of service
  548. NULL, // pointer to password for service account
  549. NULL // pointer to display name
  550. ))
  551. {
  552. DebugPrint(( TEXT("could not open change service configuration, ec=%d"), GetLastError() ));
  553. goto exit;
  554. }
  555. rVal = TRUE;
  556. exit:
  557. CloseServiceHandle( hService );
  558. CloseServiceHandle( hSvcMgr );
  559. return rVal;
  560. }
  561. BOOL
  562. SetServiceAccount(
  563. LPTSTR ServiceName,
  564. PSECURITY_INFO SecurityInfo
  565. )
  566. {
  567. BOOL rVal = FALSE;
  568. SC_HANDLE hSvcMgr;
  569. SC_HANDLE hService;
  570. hSvcMgr = OpenSCManager(
  571. NULL,
  572. NULL,
  573. SC_MANAGER_ALL_ACCESS
  574. );
  575. if (!hSvcMgr) {
  576. DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() ));
  577. goto exit;
  578. }
  579. hService = OpenService(
  580. hSvcMgr,
  581. ServiceName,
  582. SERVICE_ALL_ACCESS
  583. );
  584. if (!hService) {
  585. DebugPrint((
  586. TEXT("could not open the %s service: error code = %u"),
  587. ServiceName,
  588. GetLastError()
  589. ));
  590. goto exit;
  591. }
  592. if (!ChangeServiceConfig(
  593. hService, // handle to service
  594. SERVICE_NO_CHANGE, // type of service
  595. SERVICE_NO_CHANGE, // when to start service
  596. SERVICE_NO_CHANGE, // severity if service fails to start
  597. NULL, // pointer to service binary file name
  598. NULL, // pointer to load ordering group name
  599. NULL, // pointer to variable to get tag identifier
  600. NULL, // pointer to array of dependency names
  601. SecurityInfo->AccountName, // pointer to account name of service
  602. SecurityInfo->Password, // pointer to password for service account
  603. NULL // pointer to display name
  604. )) {
  605. DebugPrint(( TEXT("could not open change service configuration, ec=%d"), GetLastError() ));
  606. goto exit;
  607. }
  608. rVal = TRUE;
  609. exit:
  610. CloseServiceHandle( hService );
  611. CloseServiceHandle( hSvcMgr );
  612. return rVal;
  613. }
  614. BOOL
  615. MyDeleteService(
  616. LPTSTR ServiceName
  617. )
  618. {
  619. SC_HANDLE hSvcMgr;
  620. SC_HANDLE hService;
  621. SERVICE_STATUS Status;
  622. hSvcMgr = OpenSCManager(
  623. NULL,
  624. NULL,
  625. SC_MANAGER_ALL_ACCESS
  626. );
  627. if (!hSvcMgr) {
  628. return FALSE;
  629. }
  630. hService = OpenService(
  631. hSvcMgr,
  632. ServiceName,
  633. SERVICE_ALL_ACCESS
  634. );
  635. if (hService) {
  636. //
  637. // the service exists, lets be sure that it is stopped
  638. //
  639. ControlService(
  640. hService,
  641. SERVICE_CONTROL_STOP,
  642. &Status
  643. );
  644. DeleteService( hService );
  645. CloseServiceHandle( hService );
  646. }
  647. CloseServiceHandle( hSvcMgr );
  648. return TRUE;
  649. }
  650. BOOL
  651. DeleteFaxService(
  652. VOID
  653. )
  654. {
  655. return MyDeleteService( FAX_SERVICE_NAME );
  656. }
  657. BOOL
  658. SetFaxServiceAutoStart(
  659. VOID
  660. )
  661. {
  662. return SetServiceStart( FAX_SERVICE_NAME, SERVICE_AUTO_START );
  663. }