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.

1879 lines
58 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. service.cpp
  5. Abstract:
  6. Routines to configure/analyze general settings of services plus
  7. some helper APIs
  8. Author:
  9. Jin Huang (jinhuang) 25-Jun-1997
  10. Revision History:
  11. --*/
  12. #include "headers.h"
  13. #include "serverp.h"
  14. #include "service.h"
  15. #include "pfp.h"
  16. //#define SCESVC_DBG 1
  17. DWORD ScepPollOnServiceStartStop(
  18. IN BOOL bPollOnStart,
  19. IN SC_HANDLE hService
  20. );
  21. VOID
  22. ScepStopServiceAndAncestorServices(
  23. IN SC_HANDLE hScManager,
  24. IN PWSTR pszServiceName
  25. );
  26. SCESTATUS
  27. ScepConfigureGeneralServices(
  28. IN PSCECONTEXT hProfile,
  29. IN PSCE_SERVICES pServiceList,
  30. IN DWORD ConfigOptions
  31. )
  32. /*
  33. Routine Descripton:
  34. Configure startup and security descriptor settings for the list of
  35. services passed in.
  36. Arguments:
  37. pServiceList - the list of services to configure
  38. Return Value:
  39. SCE status
  40. */
  41. {
  42. SCESTATUS SceErr=SCESTATUS_SUCCESS;
  43. PSCE_SERVICES pNode;
  44. DWORD nServices=0;
  45. BOOL bDoneSettingSaclDacl = FALSE;
  46. NTSTATUS NtStatus = 0;
  47. SID_IDENTIFIER_AUTHORITY IdAuth=SECURITY_NT_AUTHORITY;
  48. DWORD rcSaveRsop = ERROR_SUCCESS;
  49. PSCESECTION hSectionDomain=NULL;
  50. PSCESECTION hSectionTattoo=NULL;
  51. PSCE_SERVICES pServiceCurrent=NULL;
  52. DWORD ServiceLen=0;
  53. BOOL bIgnoreStartupType = FALSE;
  54. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  55. ScepIsSystemShutDown() ) {
  56. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  57. }
  58. if ( pServiceList != NULL ) {
  59. SC_HANDLE hScManager;
  60. //
  61. // open the manager
  62. //
  63. hScManager = OpenSCManager(
  64. NULL,
  65. NULL,
  66. SC_MANAGER_ALL_ACCESS
  67. // SC_MANAGER_CONNECT |
  68. // SC_MANAGER_QUERY_LOCK_STATUS |
  69. // SC_MANAGER_MODIFY_BOOT_CONFIG
  70. );
  71. SC_HANDLE hService=NULL;
  72. DWORD rc=NO_ERROR;
  73. if ( NULL == hScManager ) {
  74. rc = GetLastError();
  75. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, L"Service Control Manager");
  76. ScepPostProgress(TICKS_GENERAL_SERVICES,
  77. AREA_SYSTEM_SERVICE,
  78. NULL);
  79. return( ScepDosErrorToSceStatus(rc) );
  80. }
  81. LPQUERY_SERVICE_CONFIG pConfig=NULL;
  82. DWORD BytesNeeded;
  83. //
  84. // Adjust privilege for setting SACL
  85. //
  86. rc = SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, NULL );
  87. //
  88. // if can't adjust privilege, ignore (will error out later if SACL is requested)
  89. //
  90. if ( rc != NO_ERROR ) {
  91. ScepLogOutput3(1, rc, SCEDLL_ERROR_ADJUST, L"SE_SECURITY_PRIVILEGE");
  92. rc = NO_ERROR;
  93. }
  94. //
  95. // Adjust privilege for setting ownership (if required)
  96. //
  97. rc = SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, TRUE, NULL );
  98. //
  99. // if can't adjust privilege, ignore (will error out later if acls need to be written)
  100. //
  101. if ( rc != NO_ERROR ) {
  102. ScepLogOutput3(1, rc, SCEDLL_ERROR_ADJUST, L"SE_TAKE_OWNERSHIP_PRIVILEGE");
  103. rc = NO_ERROR;
  104. }
  105. //
  106. // get AdminsSid in case need to take ownership later
  107. //
  108. NtStatus = RtlAllocateAndInitializeSid(
  109. &IdAuth,
  110. 2,
  111. SECURITY_BUILTIN_DOMAIN_RID,
  112. DOMAIN_ALIAS_RID_ADMINS,
  113. 0,
  114. 0,
  115. 0,
  116. 0,
  117. 0,
  118. 0,
  119. &AdminsSid );
  120. //
  121. // open the policy/tattoo tables
  122. //
  123. if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
  124. ScepTattooOpenPolicySections(
  125. hProfile,
  126. szServiceGeneral,
  127. &hSectionDomain,
  128. &hSectionTattoo
  129. );
  130. }
  131. //
  132. // Loop through each service to set general setting
  133. //
  134. for ( pNode=pServiceList;
  135. pNode != NULL && rc == NO_ERROR; pNode = pNode->Next ) {
  136. //
  137. // to ignore startup type, the inf template will have svcname,,"SDDL"
  138. // on import, the database gets svcname,0,"SDDL"
  139. // so we have to ignore the startuptype of 0 for this service
  140. //
  141. if (pNode->Startup == 0) {
  142. bIgnoreStartupType = TRUE;
  143. }
  144. //
  145. // print the service name
  146. //
  147. if ( nServices < TICKS_GENERAL_SERVICES ) {
  148. ScepPostProgress(1,
  149. AREA_SYSTEM_SERVICE,
  150. pNode->ServiceName);
  151. nServices++;
  152. }
  153. ScepLogOutput3(2,0, SCEDLL_SCP_CONFIGURE, pNode->ServiceName);
  154. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  155. ScepIsSystemShutDown() ) {
  156. rc = ERROR_NOT_SUPPORTED;
  157. break;
  158. }
  159. ServiceLen = 0;
  160. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  161. hSectionDomain && hSectionTattoo ) {
  162. //
  163. // check if we need to query current setting for the service
  164. //
  165. ServiceLen = wcslen(pNode->ServiceName);
  166. if ( ScepTattooIfQueryNeeded(hSectionDomain, hSectionTattoo,
  167. pNode->ServiceName, ServiceLen, NULL, NULL ) ) {
  168. rc = ScepQueryAndAddService(
  169. hScManager,
  170. pNode->ServiceName,
  171. NULL,
  172. &pServiceCurrent
  173. );
  174. if ( ERROR_SUCCESS != rc ) {
  175. ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_QUERY,rc,pNode->ServiceName);
  176. rc = NO_ERROR;
  177. } else {
  178. ScepLogOutput3(3,0,SCESRV_POLICY_TATTOO_QUERY,pNode->ServiceName);
  179. }
  180. }
  181. }
  182. bDoneSettingSaclDacl = FALSE;
  183. rcSaveRsop = ERROR_SUCCESS;
  184. //
  185. // open the service
  186. //
  187. hService = OpenService(
  188. hScManager,
  189. pNode->ServiceName,
  190. SERVICE_QUERY_CONFIG |
  191. SERVICE_CHANGE_CONFIG |
  192. READ_CONTROL |
  193. WRITE_DAC |
  194. // WRITE_OWNER | owner can't be set for a service
  195. ACCESS_SYSTEM_SECURITY
  196. );
  197. // if access was denied, try to take ownership
  198. // and try to open service again
  199. if (hService == NULL &&
  200. (ERROR_ACCESS_DENIED == (rc = GetLastError())) &&
  201. pNode->General.pSecurityDescriptor) {
  202. DWORD rcTakeOwnership = NO_ERROR;
  203. if (AdminsSid) {
  204. if ( NO_ERROR == (rcTakeOwnership = SetNamedSecurityInfo(
  205. (LPWSTR)pNode->ServiceName,
  206. SE_SERVICE,
  207. OWNER_SECURITY_INFORMATION,
  208. AdminsSid,
  209. NULL,
  210. NULL,
  211. NULL
  212. ))) {
  213. //
  214. // ownership changed, open service again and set SACL and DACL
  215. // get a handle to set security
  216. //
  217. if ( hService = OpenService(
  218. hScManager,
  219. pNode->ServiceName,
  220. READ_CONTROL |
  221. WRITE_DAC |
  222. ACCESS_SYSTEM_SECURITY
  223. )) {
  224. if ( SetServiceObjectSecurity(
  225. hService,
  226. pNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  227. pNode->General.pSecurityDescriptor
  228. ) ) {
  229. bDoneSettingSaclDacl = TRUE;
  230. CloseServiceHandle(hService);
  231. hService = NULL;
  232. //
  233. // re-open the service only if there are other config info
  234. // to set (startup type).
  235. // So when NOSTARTTYPE is set, do not need to reopen the service
  236. //
  237. if (FALSE == bIgnoreStartupType) {
  238. if (!(hService = OpenService(
  239. hScManager,
  240. pNode->ServiceName,
  241. SERVICE_QUERY_CONFIG |
  242. SERVICE_CHANGE_CONFIG
  243. )) ) {
  244. rc = GetLastError();
  245. }
  246. else {
  247. //
  248. //clear any error we have seen so far since everything has succeeded
  249. //
  250. rc = NO_ERROR;
  251. }
  252. }
  253. } else {
  254. //
  255. // shouldn't fail here unless Service Control Manager
  256. // fails for some reason.
  257. //
  258. rc = GetLastError();
  259. }
  260. } else {
  261. //
  262. // still fail to open the service to set DACL. this should
  263. // not happen for admin logons since the current logon is
  264. // one of the owner. But for normal user logon, this could
  265. // fail (actually normal user logon should fail to set
  266. // the owner
  267. rc = GetLastError();
  268. }
  269. }
  270. } else {
  271. //
  272. // AdminSid failed to be initialized, get the error
  273. //
  274. rcTakeOwnership = RtlNtStatusToDosError(NtStatus);
  275. }
  276. if ( NO_ERROR != rcTakeOwnership || NO_ERROR != rc ) {
  277. //
  278. // log the error occurred in take ownership process
  279. // reset error back to access denied so it will also be
  280. // logged as failure to open the service
  281. //
  282. if (NO_ERROR != rcTakeOwnership)
  283. ScepLogOutput3(2,rcTakeOwnership, SCEDLL_ERROR_TAKE_OWNER, (LPWSTR)pNode->ServiceName);
  284. else
  285. ScepLogOutput3(2, rc, SCEDLL_ERROR_OPEN, (LPWSTR)pNode->ServiceName);
  286. rc = ERROR_ACCESS_DENIED;
  287. }
  288. }
  289. if ( hService != NULL ) {
  290. if (bIgnoreStartupType == TRUE) {
  291. //
  292. // do not configure service start type
  293. //
  294. if ( pNode->General.pSecurityDescriptor != NULL ) {
  295. if ( !SetServiceObjectSecurity(
  296. hService,
  297. pNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  298. pNode->General.pSecurityDescriptor
  299. ) ) {
  300. rc = GetLastError();
  301. }
  302. else
  303. bDoneSettingSaclDacl = TRUE;
  304. }
  305. } else {
  306. //
  307. // Phase-1 (in phase-2 the service will be started/stopped real-time)
  308. //
  309. //
  310. // query the length of config
  311. //
  312. if ( !QueryServiceConfig(
  313. hService,
  314. NULL,
  315. 0,
  316. &BytesNeeded
  317. ) ) {
  318. rc = GetLastError();
  319. if ( rc == ERROR_INSUFFICIENT_BUFFER ) {
  320. pConfig = (LPQUERY_SERVICE_CONFIG)ScepAlloc(0, BytesNeeded);
  321. if ( pConfig != NULL ) {
  322. //
  323. // the real query of config
  324. //
  325. if ( QueryServiceConfig(
  326. hService,
  327. pConfig,
  328. BytesNeeded,
  329. &BytesNeeded
  330. ) ) {
  331. rc = ERROR_SUCCESS;
  332. //
  333. // change pConfig->dwStartType to the new value
  334. //
  335. if ( pNode->Startup != (BYTE)(pConfig->dwStartType) ) {
  336. //
  337. // configure the service startup
  338. //
  339. if ( !ChangeServiceConfig(
  340. hService,
  341. pConfig->dwServiceType,
  342. pNode->Startup,
  343. pConfig->dwErrorControl,
  344. pConfig->lpBinaryPathName,
  345. pConfig->lpLoadOrderGroup,
  346. NULL,
  347. pConfig->lpDependencies,
  348. NULL,
  349. NULL,
  350. pConfig->lpDisplayName
  351. ) ) {
  352. rc = GetLastError();
  353. }
  354. }
  355. if ( rc == NO_ERROR &&
  356. pNode->General.pSecurityDescriptor != NULL &&
  357. !bDoneSettingSaclDacl) {
  358. if ( !SetServiceObjectSecurity(
  359. hService,
  360. pNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  361. pNode->General.pSecurityDescriptor
  362. ) ) {
  363. rc = GetLastError();
  364. }
  365. else
  366. bDoneSettingSaclDacl = TRUE;
  367. }
  368. } else {
  369. rc = GetLastError();
  370. ScepLogOutput3(3,rc, SCEDLL_ERROR_QUERY_INFO, pNode->ServiceName);
  371. }
  372. ScepFree(pConfig);
  373. pConfig = NULL;
  374. } else {
  375. //
  376. // cannot allocate pConfig
  377. //
  378. rc = ERROR_NOT_ENOUGH_MEMORY;
  379. }
  380. } else {
  381. ScepLogOutput3(3,rc, SCEDLL_ERROR_QUERY_INFO, pNode->ServiceName);
  382. }
  383. } else {
  384. //
  385. // should not fall in here
  386. //
  387. rc = ERROR_SUCCESS;
  388. }
  389. }
  390. CloseServiceHandle (hService);
  391. hService = NULL;
  392. if ( rc != NO_ERROR ) {
  393. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_CONFIGURE, pNode->ServiceName);
  394. rcSaveRsop = rc;
  395. if ( ERROR_INVALID_OWNER == rc ||
  396. ERROR_INVALID_PRIMARY_GROUP == rc ||
  397. ERROR_INVALID_SECURITY_DESCR == rc ||
  398. ERROR_INVALID_ACL == rc ||
  399. ERROR_ACCESS_DENIED == rc ) {
  400. gWarningCode = rc;
  401. rc = NO_ERROR;
  402. }
  403. }
  404. } else {
  405. //
  406. // cannot open the service or some error taking ownership
  407. //
  408. if (rc != NO_ERROR) {
  409. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, pNode->ServiceName);
  410. // either of setting security/startup type failed - save it for RSOP log
  411. rcSaveRsop = (rcSaveRsop == ERROR_SUCCESS ? rc: rcSaveRsop);
  412. if ( rc == ERROR_SERVICE_DOES_NOT_EXIST )
  413. rc = NO_ERROR;
  414. }
  415. }
  416. if (ConfigOptions & SCE_RSOP_CALLBACK)
  417. ScepRsopLog(SCE_RSOP_SERVICES_INFO,
  418. rcSaveRsop != NO_ERROR ? rcSaveRsop : rc,
  419. pNode->ServiceName,
  420. 0,
  421. 0);
  422. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  423. hSectionDomain && hSectionTattoo ) {
  424. //
  425. // manage the tattoo value of this one
  426. //
  427. ScepTattooManageOneServiceValue(
  428. hSectionDomain,
  429. hSectionTattoo,
  430. pNode->ServiceName,
  431. ServiceLen,
  432. pServiceCurrent,
  433. rc
  434. );
  435. }
  436. if ( pServiceCurrent ) {
  437. SceFreePSCE_SERVICES(pServiceCurrent);
  438. pServiceCurrent = NULL;
  439. }
  440. bIgnoreStartupType = FALSE;
  441. }
  442. if ( !(ConfigOptions & SCE_SERVICE_NO_REALTIME_ENFORCE) ) {
  443. //
  444. // real-time start/stop only if NOT in setup/dcpromo
  445. // i.e. whenever SCE_SETUP_SERVICE_NOSTARTTYPE was used before
  446. //
  447. //
  448. // Phase-2 (in phase-1 the startup-type was only configured but not enforced real-time)
  449. //
  450. for ( pNode=pServiceList; pNode != NULL ; pNode = pNode->Next ) {
  451. if (pNode->Startup == SERVICE_DISABLED) {
  452. //
  453. // we should also stop the ancestor services
  454. //
  455. ScepStopServiceAndAncestorServices(hScManager, pNode->ServiceName);
  456. }
  457. else if (pNode->Startup == SERVICE_AUTO_START) {
  458. //
  459. // if the service type is "automatic", we should start the service
  460. // Note: dependencies are already taken care of by SCM
  461. //
  462. if ( hService = OpenService(
  463. hScManager,
  464. pNode->ServiceName,
  465. SERVICE_START | SERVICE_QUERY_STATUS
  466. )) {
  467. SERVICE_STATUS ServiceStatus;
  468. if (!StartService(hService,
  469. 0,
  470. NULL
  471. )) {
  472. if ( ERROR_SERVICE_ALREADY_RUNNING != GetLastError() ) {
  473. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_START, pNode->ServiceName);
  474. }
  475. }
  476. else {
  477. DWORD dwError;
  478. dwError = ScepPollOnServiceStartStop( TRUE , hService );
  479. if ( dwError != ERROR_SUCCESS ) {
  480. ScepLogOutput3(2, dwError, SCEDLL_SCP_ERROR_START, pNode->ServiceName);
  481. }
  482. }
  483. CloseServiceHandle (hService);
  484. hService = NULL;
  485. } else {
  486. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_OPENFORSTART, pNode->ServiceName);
  487. }
  488. }
  489. }
  490. }
  491. CloseServiceHandle (hScManager);
  492. if (AdminsSid) {
  493. RtlFreeSid(AdminsSid);
  494. AdminsSid = NULL;
  495. }
  496. SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, FALSE, NULL );
  497. SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, NULL );
  498. SceErr = ScepDosErrorToSceStatus(rc);
  499. }
  500. if ( nServices < TICKS_GENERAL_SERVICES ) {
  501. ScepPostProgress(TICKS_GENERAL_SERVICES-nServices,
  502. AREA_SYSTEM_SERVICE,
  503. NULL);
  504. }
  505. SceJetCloseSection(&hSectionDomain, TRUE);
  506. SceJetCloseSection(&hSectionTattoo, TRUE);
  507. return(SceErr);
  508. }
  509. DWORD ScepPollOnServiceStartStop(
  510. IN BOOL bPollOnStart,
  511. IN SC_HANDLE hService
  512. )
  513. /*
  514. Routine Descripton:
  515. This routine polls on a service until it is really started
  516. or stopped using time-slice hints.
  517. Arguments:
  518. bPollOnStart - if TRUE (FALSE), polls until really started (stopped)
  519. hService - handle to service to poll on
  520. Return Value:
  521. win32 error code - ERROR_SUCCESS or other error
  522. */
  523. {
  524. SERVICE_STATUS ssStatus;
  525. DWORD dwOldCheckPoint;
  526. DWORD dwStartTickCount;
  527. DWORD dwWaitTime;
  528. DWORD dwStatus = ERROR_SUCCESS;
  529. //
  530. // Check the status until the service is no longer pending (start or stop)
  531. //
  532. if (!QueryServiceStatus(
  533. hService,
  534. &ssStatus) )
  535. {
  536. dwStatus = GetLastError();
  537. goto ExitHandler;
  538. }
  539. //
  540. // Save the tick count and initial checkpoint.
  541. //
  542. dwStartTickCount = GetTickCount();
  543. dwOldCheckPoint = ssStatus.dwCheckPoint;
  544. //
  545. // Poll until service has started or stopped
  546. //
  547. while (!((bPollOnStart && ssStatus.dwCurrentState == SERVICE_RUNNING) ||
  548. (!bPollOnStart && ssStatus.dwCurrentState == SERVICE_STOPPED )))
  549. {
  550. //
  551. // Do not wait longer than the wait hint. A good interval is
  552. // one tenth the wait hint, but no less than 1 second and no
  553. // more than 10 seconds.
  554. //
  555. dwWaitTime = ssStatus.dwWaitHint / 10;
  556. if( dwWaitTime < 1000 )
  557. dwWaitTime = 1000;
  558. else if ( dwWaitTime > 10000 )
  559. dwWaitTime = 10000;
  560. Sleep( dwWaitTime );
  561. //
  562. // Check the status again.
  563. //
  564. if (!QueryServiceStatus(
  565. hService,
  566. &ssStatus) )
  567. {
  568. dwStatus = GetLastError();
  569. goto ExitHandler;
  570. }
  571. if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
  572. {
  573. //
  574. // The service is making progress since the checkpoint has been updated.
  575. //
  576. dwStartTickCount = GetTickCount();
  577. dwOldCheckPoint = ssStatus.dwCheckPoint;
  578. }
  579. else
  580. {
  581. if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
  582. {
  583. //
  584. // No progress made within the wait hint - stop polling
  585. //
  586. break;
  587. }
  588. }
  589. }
  590. //
  591. // final check on desired condition
  592. //
  593. if (!((bPollOnStart && ssStatus.dwCurrentState == SERVICE_RUNNING) ||
  594. (!bPollOnStart && ssStatus.dwCurrentState == SERVICE_STOPPED )))
  595. dwStatus = ERROR_SERVICE_REQUEST_TIMEOUT;
  596. ExitHandler:
  597. return dwStatus;
  598. }
  599. VOID
  600. ScepStopServiceAndAncestorServices(
  601. IN SC_HANDLE hScManager,
  602. IN PWSTR pszServiceName
  603. )
  604. /*
  605. Routine Description:
  606. Stop the named service and all other services that are dependent on it.
  607. Arguments:
  608. hScManager - handle to the Service Control Manager
  609. pszServiceName - name of the service to be stopped
  610. Return Value:
  611. None:
  612. */
  613. {
  614. SC_HANDLE hService=NULL;
  615. LPENUM_SERVICE_STATUS pArrServices = NULL;
  616. if ( hService = OpenService(
  617. hScManager,
  618. pszServiceName,
  619. SERVICE_STOP | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_QUERY_STATUS
  620. )) {
  621. //
  622. // get an array of ancestor services, greatest-ancestor first
  623. //
  624. DWORD dwBufSizeSupplied = 0;
  625. DWORD dwBufSizeRequired = 0;
  626. DWORD dwNumServicesReturned = 0;
  627. //
  628. // first, get the required size of the array
  629. //
  630. if (!EnumDependentServices(
  631. hService,
  632. SERVICE_STATE_ALL,
  633. pArrServices,
  634. 0,
  635. &dwBufSizeRequired,
  636. &dwNumServicesReturned
  637. )) {
  638. if (ERROR_MORE_DATA != GetLastError()) {
  639. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_STOP, pszServiceName);
  640. goto ExitHandler;
  641. }
  642. }
  643. pArrServices = (ENUM_SERVICE_STATUS *) LocalAlloc (LMEM_ZEROINIT, dwBufSizeRequired);
  644. if (pArrServices == NULL) {
  645. ScepLogOutput3(2, ERROR_NOT_ENOUGH_MEMORY, SCEDLL_SCP_ERROR_STOP, pszServiceName);
  646. goto ExitHandler;
  647. }
  648. //
  649. // second, get the array of dependent services
  650. //
  651. if (!EnumDependentServices(
  652. hService,
  653. SERVICE_STATE_ALL,
  654. pArrServices,
  655. dwBufSizeRequired,
  656. &dwBufSizeRequired,
  657. &dwNumServicesReturned
  658. )) {
  659. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_STOP, pszServiceName);
  660. goto ExitHandler;
  661. }
  662. //
  663. // first stop all the ancestor services
  664. // if any of them fails to stop, log it and continue
  665. //
  666. for (DWORD dwServiceIndex = 0; dwServiceIndex < dwNumServicesReturned; dwServiceIndex++ ) {
  667. SC_HANDLE hAncestorService = NULL;
  668. if ( hAncestorService = OpenService(
  669. hScManager,
  670. pArrServices[dwServiceIndex].lpServiceName,
  671. SERVICE_STOP | SERVICE_QUERY_STATUS
  672. )) {
  673. SERVICE_STATUS ServiceStatus;
  674. if (!ControlService(hAncestorService,
  675. SERVICE_CONTROL_STOP,
  676. &ServiceStatus
  677. )) {
  678. if ( ERROR_SERVICE_NOT_ACTIVE != GetLastError() ) {
  679. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_STOP, pArrServices[dwServiceIndex].lpServiceName);
  680. }
  681. }
  682. else {
  683. //
  684. // move on only if this service stopped
  685. //
  686. DWORD dwError;
  687. dwError = ScepPollOnServiceStartStop( FALSE , hAncestorService );
  688. if ( dwError != ERROR_SUCCESS ) {
  689. ScepLogOutput3(2, dwError, SCEDLL_SCP_ERROR_STOP, pArrServices[dwServiceIndex].lpServiceName);
  690. }
  691. }
  692. CloseServiceHandle (hAncestorService);
  693. hAncestorService = NULL;
  694. } else {
  695. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_OPENFORSTOP, pArrServices[dwServiceIndex].lpServiceName);
  696. }
  697. }
  698. LocalFree ( pArrServices );
  699. pArrServices = NULL;
  700. //
  701. // finally, stop the service itself
  702. //
  703. SERVICE_STATUS ServiceStatus;
  704. if (!ControlService(hService,
  705. SERVICE_CONTROL_STOP,
  706. &ServiceStatus
  707. )) {
  708. if ( ERROR_SERVICE_NOT_ACTIVE != GetLastError() ) {
  709. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_STOP, pszServiceName);
  710. }
  711. }
  712. else {
  713. DWORD dwError;
  714. dwError = ScepPollOnServiceStartStop( FALSE , hService );
  715. if ( dwError != ERROR_SUCCESS ) {
  716. ScepLogOutput3(2, dwError, SCEDLL_SCP_ERROR_STOP, pszServiceName);
  717. }
  718. }
  719. CloseServiceHandle (hService);
  720. hService = NULL;
  721. } else {
  722. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_OPENFORSTOP, pszServiceName);
  723. }
  724. ExitHandler:
  725. if ( hService )
  726. CloseServiceHandle (hService);
  727. if ( pArrServices )
  728. LocalFree ( pArrServices );
  729. }
  730. SCESTATUS
  731. ScepAnalyzeGeneralServices(
  732. IN PSCECONTEXT hProfile,
  733. IN DWORD Options
  734. )
  735. /*
  736. Routine Description:
  737. Analyze all available services on the current system.
  738. The base profile (SCEP) is in hProfile
  739. Arguments:
  740. hProfile - the database context handle
  741. Return Value:
  742. SCE status
  743. */
  744. {
  745. if ( hProfile == NULL ) {
  746. ScepPostProgress(TICKS_GENERAL_SERVICES,
  747. AREA_SYSTEM_SERVICE,
  748. NULL);
  749. return(SCESTATUS_INVALID_PARAMETER);
  750. }
  751. SCESTATUS rc;
  752. PSCE_SERVICES pServiceList=NULL;
  753. DWORD nServices=0;
  754. rc = SceEnumerateServices( &pServiceList, FALSE );
  755. rc = ScepDosErrorToSceStatus(rc);
  756. if ( rc == SCESTATUS_SUCCESS ) {
  757. PSCESECTION hSectionScep=NULL, hSectionSap=NULL;
  758. //
  759. // open the sap section. If it is not there, creates it
  760. //
  761. rc = ScepStartANewSection(
  762. hProfile,
  763. &hSectionSap,
  764. (Options & SCE_GENERATE_ROLLBACK) ? SCEJET_TABLE_SMP : SCEJET_TABLE_SAP,
  765. szServiceGeneral
  766. );
  767. if ( rc == SCESTATUS_SUCCESS ) {
  768. PSCE_SERVICES pNode = pServiceList;
  769. //
  770. // open SCEP section. should be success always because the StartANewSection
  771. // creates the section if it is not there
  772. //
  773. rc = ScepOpenSectionForName(
  774. hProfile,
  775. (Options & SCE_GENERATE_ROLLBACK) ? SCE_ENGINE_SMP : SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
  776. szServiceGeneral,
  777. &hSectionScep
  778. );
  779. if ( rc == SCESTATUS_SUCCESS ) {
  780. //
  781. // analyze each service
  782. //
  783. PSCE_SERVICES pOneService=NULL;
  784. BOOL IsDifferent;
  785. for ( pNode=pServiceList;
  786. pNode != NULL; pNode=pNode->Next ) {
  787. ScepLogOutput3(2, 0, SCEDLL_SAP_ANALYZE, pNode->ServiceName);
  788. if ( nServices < TICKS_SPECIFIC_SERVICES ) {
  789. ScepPostProgress(1,
  790. AREA_SYSTEM_SERVICE,
  791. NULL);
  792. nServices++;
  793. }
  794. //
  795. // get setting from the SMP profile
  796. //
  797. rc = ScepGetSingleServiceSetting(
  798. hSectionScep,
  799. pNode->ServiceName,
  800. &pOneService
  801. );
  802. if ( rc == SCESTATUS_SUCCESS ) {
  803. //
  804. // there is a SMP entry for the service, compare and save
  805. //
  806. rc = ScepCompareSingleServiceSetting(
  807. pOneService,
  808. pNode,
  809. &IsDifferent
  810. );
  811. if ( rc == SCESTATUS_SUCCESS && IsDifferent ) {
  812. //
  813. // write the service as mismatch
  814. //
  815. pNode->Status = (Options & SCE_GENERATE_ROLLBACK) ? 0 : SCE_STATUS_MISMATCH;
  816. pNode->SeInfo = pOneService->SeInfo;
  817. rc = ScepSetSingleServiceSetting(
  818. hSectionSap,
  819. pNode
  820. );
  821. }
  822. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  823. //
  824. // this service is not defined
  825. //
  826. if ( !(Options & SCE_GENERATE_ROLLBACK) ) {
  827. //
  828. // save the record with not configured status
  829. //
  830. pNode->Status = SCE_STATUS_NOT_CONFIGURED;
  831. rc = ScepSetSingleServiceSetting(
  832. hSectionSap,
  833. pNode
  834. );
  835. } else {
  836. //
  837. // ignore this one
  838. //
  839. rc = SCESTATUS_SUCCESS;
  840. }
  841. }
  842. SceFreePSCE_SERVICES(pOneService);
  843. pOneService = NULL;
  844. if ( rc != SCESTATUS_SUCCESS ) {
  845. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  846. SCEDLL_SAP_ERROR_ANALYZE, pNode->ServiceName);
  847. if ( SCESTATUS_ACCESS_DENIED == rc ) {
  848. gWarningCode = ScepSceStatusToDosError(rc);
  849. if ( !(Options & SCE_GENERATE_ROLLBACK) ) {
  850. //
  851. // raise a error status
  852. //
  853. pNode->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  854. rc = ScepSetSingleServiceSetting(
  855. hSectionSap,
  856. pNode
  857. );
  858. }
  859. rc = SCESTATUS_SUCCESS;
  860. } else {
  861. break;
  862. }
  863. }
  864. }
  865. SceJetCloseSection(&hSectionScep, TRUE);
  866. }
  867. if ( !(Options & SCE_GENERATE_ROLLBACK ) ) {
  868. //
  869. // raise any error item
  870. //
  871. for ( PSCE_SERVICES pNodeTmp=pNode; pNodeTmp != NULL; pNodeTmp = pNodeTmp->Next ) {
  872. pNodeTmp->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  873. ScepSetSingleServiceSetting(
  874. hSectionSap,
  875. pNode
  876. );
  877. }
  878. }
  879. SceJetCloseSection(&hSectionSap, TRUE);
  880. }
  881. if ( rc != SCESTATUS_SUCCESS )
  882. ScepLogOutput3(1, ScepSceStatusToDosError(rc), SCEDLL_SAP_ERROR_OUT);
  883. }
  884. if ( nServices < TICKS_GENERAL_SERVICES ) {
  885. ScepPostProgress(TICKS_GENERAL_SERVICES-nServices,
  886. AREA_SYSTEM_SERVICE,
  887. NULL);
  888. }
  889. SceFreePSCE_SERVICES(pServiceList);
  890. return(rc);
  891. }
  892. SCESTATUS
  893. ScepGetSingleServiceSetting(
  894. IN PSCESECTION hSection,
  895. IN PWSTR ServiceName,
  896. OUT PSCE_SERVICES *pOneService
  897. )
  898. /*
  899. Routine Description:
  900. Get service settings for the service from the section
  901. Arguments:
  902. hSection - the section handle
  903. ServiceName - the service name
  904. pOneService - the service settings
  905. Return Value:
  906. SCE status
  907. */
  908. {
  909. if ( hSection == NULL || ServiceName == NULL || pOneService == NULL ) {
  910. return(SCESTATUS_INVALID_PARAMETER);
  911. }
  912. SCESTATUS rc;
  913. DWORD ValueLen;
  914. //
  915. // seek to the record and get length for name and value
  916. //
  917. rc = SceJetGetValue(
  918. hSection,
  919. SCEJET_EXACT_MATCH_NO_CASE,
  920. ServiceName,
  921. NULL,
  922. 0,
  923. NULL,
  924. NULL,
  925. 0,
  926. &ValueLen
  927. );
  928. if ( rc == SCESTATUS_SUCCESS ) {
  929. PWSTR Value=NULL;
  930. //
  931. // allocate memory for the service name and value string
  932. //
  933. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  934. if ( Value != NULL ) {
  935. //
  936. // Get the service and its value
  937. //
  938. rc = SceJetGetValue(
  939. hSection,
  940. SCEJET_CURRENT,
  941. NULL,
  942. NULL,
  943. 0,
  944. NULL,
  945. Value,
  946. ValueLen,
  947. &ValueLen
  948. );
  949. if ( rc == SCESTATUS_SUCCESS ) {
  950. Value[ValueLen/2] = L'\0';
  951. DWORD Win32Rc=NO_ERROR;
  952. PSECURITY_DESCRIPTOR pTempSD=NULL;
  953. DWORD SDsize=0;
  954. SECURITY_INFORMATION SeInfo=0;
  955. if ( ValueLen >= 2 && Value[1] != L'\0' ) {
  956. //
  957. // convert to security descriptor
  958. //
  959. Win32Rc = ConvertTextSecurityDescriptor(
  960. Value+1,
  961. &pTempSD,
  962. &SDsize,
  963. &SeInfo
  964. );
  965. }
  966. if ( Win32Rc == NO_ERROR ) {
  967. ScepChangeAclRevision(pTempSD, ACL_REVISION);
  968. //
  969. // create this service node
  970. //
  971. *pOneService = (PSCE_SERVICES)ScepAlloc( LMEM_FIXED, sizeof(SCE_SERVICES) );
  972. if ( *pOneService != NULL ) {
  973. (*pOneService)->ServiceName = (PWSTR)ScepAlloc(LMEM_FIXED,
  974. (wcslen(ServiceName)+1)*sizeof(WCHAR));
  975. if ( (*pOneService)->ServiceName != NULL ) {
  976. wcscpy( (*pOneService)->ServiceName, ServiceName);
  977. (*pOneService)->DisplayName = NULL;
  978. (*pOneService)->Status = *((BYTE *)Value);
  979. (*pOneService)->Startup = *((BYTE *)Value+1);
  980. (*pOneService)->General.pSecurityDescriptor = pTempSD;
  981. (*pOneService)->SeInfo = SeInfo;
  982. (*pOneService)->Next = NULL;
  983. //
  984. // DO NOT free the following buffers
  985. //
  986. pTempSD = NULL;
  987. } else {
  988. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  989. ScepFree(*pOneService);
  990. }
  991. } else {
  992. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  993. }
  994. if ( pTempSD != NULL ) {
  995. ScepFree(pTempSD);
  996. }
  997. } else {
  998. rc = ScepDosErrorToSceStatus(Win32Rc);
  999. }
  1000. }
  1001. ScepFree(Value);
  1002. } else
  1003. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1004. }
  1005. return(rc);
  1006. }
  1007. SCESTATUS
  1008. ScepCompareSingleServiceSetting(
  1009. IN PSCE_SERVICES pNode1,
  1010. IN PSCE_SERVICES pNode2,
  1011. OUT PBOOL pIsDifferent
  1012. )
  1013. /*
  1014. Routine Description:
  1015. Comare two service settings.
  1016. Arguments:
  1017. pNode1 - the first service
  1018. pNode2 - the second service
  1019. pIsDifferent - output TRUE if different
  1020. Return Value:
  1021. SCE status
  1022. */
  1023. {
  1024. SCESTATUS rc=SCESTATUS_SUCCESS;
  1025. //
  1026. // if Startup == 0, we should ignore comparing the startup types symmetrically
  1027. //
  1028. if ( pNode1->Startup == 0 || pNode2->Startup == 0 || pNode1->Startup == pNode2->Startup ) {
  1029. BYTE resultSD = 0;
  1030. rc = ScepCompareObjectSecurity(
  1031. SE_SERVICE,
  1032. FALSE,
  1033. pNode1->General.pSecurityDescriptor,
  1034. pNode2->General.pSecurityDescriptor,
  1035. pNode1->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  1036. &resultSD
  1037. );
  1038. if ( resultSD ) {
  1039. *pIsDifferent = TRUE;
  1040. } else
  1041. *pIsDifferent = FALSE;
  1042. } else
  1043. *pIsDifferent = TRUE;
  1044. return(rc);
  1045. }
  1046. SCESTATUS
  1047. ScepSetSingleServiceSetting(
  1048. IN PSCESECTION hSection,
  1049. IN PSCE_SERVICES pOneService
  1050. )
  1051. /*
  1052. Routine Description:
  1053. Set service settings for the service from the section
  1054. Arguments:
  1055. hSection - the section handle
  1056. pOneService - the service settings
  1057. Return Value:
  1058. SCE status
  1059. */
  1060. {
  1061. if ( hSection == NULL || pOneService == NULL ) {
  1062. return(SCESTATUS_INVALID_PARAMETER);
  1063. }
  1064. SCESTATUS rc=SCESTATUS_SUCCESS;
  1065. PWSTR SDspec=NULL;
  1066. DWORD SDsize=0;
  1067. if ( (pOneService->Status != SCE_STATUS_NOT_ANALYZED) &&
  1068. (pOneService->Status != SCE_STATUS_ERROR_NOT_AVAILABLE) &&
  1069. (pOneService->General.pSecurityDescriptor != NULL) ) {
  1070. DWORD Win32Rc;
  1071. Win32Rc = ConvertSecurityDescriptorToText (
  1072. pOneService->General.pSecurityDescriptor,
  1073. pOneService->SeInfo,
  1074. &SDspec,
  1075. &SDsize // number of w-chars
  1076. );
  1077. rc = ScepDosErrorToSceStatus(Win32Rc);
  1078. }
  1079. if ( rc == SCESTATUS_SUCCESS ) {
  1080. PWSTR Value=NULL;
  1081. DWORD ValueLen;
  1082. ValueLen = (SDsize+1)*sizeof(WCHAR);
  1083. Value = (PWSTR)ScepAlloc( (UINT)0, ValueLen+sizeof(WCHAR) );
  1084. if ( Value != NULL ) {
  1085. //
  1086. // The first byte is status, the second byte is startup
  1087. //
  1088. *((BYTE *)Value) = pOneService->Status;
  1089. *((BYTE *)Value+1) = pOneService->Startup;
  1090. if ( SDspec != NULL ) {
  1091. wcscpy(Value+1, SDspec);
  1092. }
  1093. Value[SDsize+1] = L'\0'; //terminate this string
  1094. //
  1095. // set the value
  1096. //
  1097. rc = SceJetSetLine(
  1098. hSection,
  1099. pOneService->ServiceName,
  1100. FALSE,
  1101. Value,
  1102. ValueLen,
  1103. 0
  1104. );
  1105. ScepFree( Value );
  1106. switch ( pOneService->Status ) {
  1107. case SCE_STATUS_ERROR_NOT_AVAILABLE:
  1108. ScepLogOutput3(2, 0, SCEDLL_STATUS_ERROR, pOneService->ServiceName);
  1109. break;
  1110. case SCE_STATUS_NOT_CONFIGURED:
  1111. ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, pOneService->ServiceName);
  1112. break;
  1113. case SCE_STATUS_NOT_ANALYZED:
  1114. ScepLogOutput3(2, 0, SCEDLL_STATUS_NEW, pOneService->ServiceName);
  1115. break;
  1116. default:
  1117. ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, pOneService->ServiceName);
  1118. break;
  1119. }
  1120. } else
  1121. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1122. }
  1123. if ( SDspec != NULL ) {
  1124. ScepFree( SDspec );
  1125. }
  1126. return(rc);
  1127. }
  1128. SCESTATUS
  1129. ScepInvokeSpecificServices(
  1130. IN PSCECONTEXT hProfile,
  1131. IN BOOL bConfigure,
  1132. IN SCE_ATTACHMENT_TYPE aType
  1133. )
  1134. /*
  1135. Routine Description:
  1136. Call each service engine for configure or analyze
  1137. Arguments:
  1138. hProfile - the profile handle
  1139. bConfigure - TRUE = to configure, FALSE=to analyze
  1140. aType - attachment type "services" or "policy"
  1141. Return Value:
  1142. SCE status
  1143. */
  1144. {
  1145. //
  1146. // for posting progress
  1147. //
  1148. DWORD nServices=0;
  1149. AREA_INFORMATION Area=0;
  1150. DWORD nMaxTicks=0;
  1151. switch(aType) {
  1152. case SCE_ATTACHMENT_SERVICE:
  1153. Area = AREA_SYSTEM_SERVICE;
  1154. nMaxTicks = TICKS_SPECIFIC_SERVICES;
  1155. break;
  1156. case SCE_ATTACHMENT_POLICY:
  1157. Area = AREA_SECURITY_POLICY;
  1158. nMaxTicks = TICKS_SPECIFIC_POLICIES;
  1159. break;
  1160. }
  1161. if ( hProfile == NULL ) {
  1162. ScepPostProgress(nMaxTicks,
  1163. Area,
  1164. NULL);
  1165. return(SCESTATUS_INVALID_PARAMETER);
  1166. }
  1167. //
  1168. // call available service engines to configure specific setting
  1169. //
  1170. SCESTATUS SceErr ;
  1171. PSCE_SERVICES pSvcEngineList=NULL;
  1172. SCEP_HANDLE sceHandle;
  1173. SCESVC_CALLBACK_INFO sceCbInfo;
  1174. SceErr = ScepEnumServiceEngines(&pSvcEngineList, aType);
  1175. if ( SceErr == SCESTATUS_SUCCESS) {
  1176. HINSTANCE hDll;
  1177. PF_ConfigAnalyzeService pfTemp;
  1178. for ( PSCE_SERVICES pNode=pSvcEngineList;
  1179. pNode != NULL; pNode = pNode->Next ) {
  1180. ScepLogOutput3(2, 0, SCEDLL_LOAD_ATTACHMENT, pNode->ServiceName);
  1181. if ( nServices < nMaxTicks ) {
  1182. ScepPostProgress(1, Area, pNode->ServiceName);
  1183. nServices++;
  1184. }
  1185. //
  1186. // load the dll.
  1187. //
  1188. hDll = LoadLibrary(pNode->General.ServiceEngineName);
  1189. if ( hDll != NULL ) {
  1190. if ( bConfigure ) {
  1191. //
  1192. // call SceSvcAttachmentConfig from the dll
  1193. //
  1194. pfTemp = (PF_ConfigAnalyzeService)
  1195. GetProcAddress(hDll,
  1196. "SceSvcAttachmentConfig") ;
  1197. } else {
  1198. //
  1199. // call SceSvcAttachmentAnalyze from the dll
  1200. //
  1201. pfTemp = (PF_ConfigAnalyzeService)
  1202. GetProcAddress(hDll,
  1203. "SceSvcAttachmentAnalyze") ;
  1204. }
  1205. if ( pfTemp != NULL ) {
  1206. //
  1207. // prepare the handle first
  1208. //
  1209. sceHandle.hProfile = (PVOID)hProfile;
  1210. sceHandle.ServiceName = (PCWSTR)(pNode->ServiceName);
  1211. sceCbInfo.sceHandle = &sceHandle;
  1212. sceCbInfo.pfQueryInfo = &SceCbQueryInfo;
  1213. sceCbInfo.pfSetInfo = &SceCbSetInfo;
  1214. sceCbInfo.pfFreeInfo = &SceSvcpFreeMemory;
  1215. sceCbInfo.pfLogInfo = &ScepLogOutput2;
  1216. //
  1217. // call the SceSvcAttachmentConfig/Analyze from the DLL
  1218. //
  1219. __try {
  1220. SceErr = (*pfTemp)((PSCESVC_CALLBACK_INFO)&sceCbInfo);
  1221. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1222. SceErr = SCESTATUS_SERVICE_NOT_SUPPORT;
  1223. }
  1224. } else {
  1225. //
  1226. // this API is not supported
  1227. //
  1228. SceErr = SCESTATUS_SERVICE_NOT_SUPPORT;
  1229. }
  1230. //
  1231. // try to free the library handle. If it fails, just leave it
  1232. // to to the process to terminate
  1233. //
  1234. FreeLibrary(hDll);
  1235. } else
  1236. SceErr = SCESTATUS_SERVICE_NOT_SUPPORT;
  1237. if ( SceErr == SCESTATUS_SERVICE_NOT_SUPPORT ) {
  1238. if ( bConfigure )
  1239. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  1240. SCEDLL_SCP_NOT_SUPPORT);
  1241. else
  1242. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  1243. SCEDLL_SAP_NOT_SUPPORT);
  1244. SceErr = SCESTATUS_SUCCESS;
  1245. } else if ( SceErr != SCESTATUS_SUCCESS &&
  1246. SceErr != SCESTATUS_RECORD_NOT_FOUND ) {
  1247. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  1248. SCEDLL_ERROR_LOAD, pNode->ServiceName);
  1249. }
  1250. if ( SceErr != SCESTATUS_SUCCESS &&
  1251. SceErr != SCESTATUS_SERVICE_NOT_SUPPORT &&
  1252. SceErr != SCESTATUS_RECORD_NOT_FOUND )
  1253. break;
  1254. }
  1255. //
  1256. // free the buffer
  1257. //
  1258. SceFreePSCE_SERVICES(pSvcEngineList);
  1259. } else if ( SceErr != SCESTATUS_SUCCESS &&
  1260. SceErr != SCESTATUS_PROFILE_NOT_FOUND &&
  1261. SceErr != SCESTATUS_RECORD_NOT_FOUND ) {
  1262. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  1263. SCEDLL_SAP_ERROR_ENUMERATE, L"services");
  1264. }
  1265. if ( SceErr == SCESTATUS_PROFILE_NOT_FOUND ||
  1266. SceErr == SCESTATUS_RECORD_NOT_FOUND ||
  1267. SceErr == SCESTATUS_SERVICE_NOT_SUPPORT ) {
  1268. //
  1269. // no service engine defined
  1270. //
  1271. SceErr = SCESTATUS_SUCCESS;
  1272. }
  1273. if ( nServices < nMaxTicks ) {
  1274. ScepPostProgress(nMaxTicks-nServices,
  1275. Area,
  1276. NULL);
  1277. }
  1278. return(SceErr);
  1279. }
  1280. SCESTATUS
  1281. ScepEnumServiceEngines(
  1282. OUT PSCE_SERVICES *pSvcEngineList,
  1283. IN SCE_ATTACHMENT_TYPE aType
  1284. )
  1285. /*
  1286. Routine Description:
  1287. Query all services which has a service engine for security manager
  1288. The service engine information is in the registry:
  1289. MACHINE\Software\Microsoft\Windows NT\CurrentVersion\SeCEdit
  1290. Arguments:
  1291. pSvcEngineList - the service engine list
  1292. aType - attachment type (service or policy)
  1293. Return Value:
  1294. SCE status
  1295. */
  1296. {
  1297. if ( pSvcEngineList == NULL ) {
  1298. return(SCESTATUS_INVALID_PARAMETER);
  1299. }
  1300. DWORD Win32Rc;
  1301. HKEY hKey=NULL;
  1302. switch ( aType ) {
  1303. case SCE_ATTACHMENT_SERVICE:
  1304. Win32Rc = RegOpenKeyEx(
  1305. HKEY_LOCAL_MACHINE,
  1306. SCE_ROOT_SERVICE_PATH,
  1307. 0,
  1308. KEY_READ,
  1309. &hKey
  1310. );
  1311. break;
  1312. case SCE_ATTACHMENT_POLICY:
  1313. Win32Rc = RegOpenKeyEx(
  1314. HKEY_LOCAL_MACHINE,
  1315. SCE_ROOT_POLICY_PATH,
  1316. 0,
  1317. KEY_READ,
  1318. &hKey
  1319. );
  1320. break;
  1321. default:
  1322. return SCESTATUS_INVALID_PARAMETER;
  1323. }
  1324. if ( Win32Rc == ERROR_SUCCESS ) {
  1325. TCHAR Buffer[MAX_PATH];
  1326. DWORD BufSize;
  1327. DWORD index = 0;
  1328. DWORD EnumRc;
  1329. FILETIME LastWriteTime;
  1330. PWSTR BufTmp=NULL;
  1331. PWSTR EngineName=NULL;
  1332. DWORD RegType;
  1333. //
  1334. // enumerate all subkeys of the key
  1335. //
  1336. do {
  1337. memset(Buffer, '\0', MAX_PATH*sizeof(WCHAR));
  1338. BufSize = MAX_PATH;
  1339. EnumRc = RegEnumKeyEx(
  1340. hKey,
  1341. index,
  1342. Buffer,
  1343. &BufSize,
  1344. NULL,
  1345. NULL,
  1346. NULL,
  1347. &LastWriteTime);
  1348. if ( EnumRc == ERROR_SUCCESS ) {
  1349. index++;
  1350. //
  1351. // get the service name, query service engine name
  1352. //
  1353. BufSize += wcslen(SCE_ROOT_SERVICE_PATH) + 1; //62;
  1354. BufTmp = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  1355. if ( BufTmp != NULL ) {
  1356. switch ( aType ) {
  1357. case SCE_ATTACHMENT_SERVICE:
  1358. swprintf(BufTmp, L"%s\\%s", SCE_ROOT_SERVICE_PATH, Buffer);
  1359. Win32Rc = ScepRegQueryValue(
  1360. HKEY_LOCAL_MACHINE,
  1361. BufTmp,
  1362. L"ServiceAttachmentPath",
  1363. (PVOID *)&EngineName,
  1364. &RegType,
  1365. NULL
  1366. );
  1367. break;
  1368. case SCE_ATTACHMENT_POLICY:
  1369. // policies
  1370. swprintf(BufTmp, L"%s\\%s", SCE_ROOT_POLICY_PATH, Buffer);
  1371. Win32Rc = ScepRegQueryValue(
  1372. HKEY_LOCAL_MACHINE,
  1373. BufTmp,
  1374. L"PolicyAttachmentPath",
  1375. (PVOID *)&EngineName,
  1376. &RegType,
  1377. NULL
  1378. );
  1379. break;
  1380. }
  1381. if ( Win32Rc == ERROR_SUCCESS ) {
  1382. //
  1383. // get the service engine name and service name
  1384. // add them to the service node
  1385. //
  1386. Win32Rc = ScepAddOneServiceToList(
  1387. Buffer, // service name
  1388. NULL,
  1389. 0,
  1390. (PVOID)EngineName,
  1391. 0,
  1392. FALSE,
  1393. pSvcEngineList
  1394. );
  1395. //
  1396. // free the buffer if it's not added to the list
  1397. //
  1398. if ( Win32Rc != ERROR_SUCCESS && EngineName ) {
  1399. ScepFree(EngineName);
  1400. }
  1401. EngineName = NULL;
  1402. } else if ( Win32Rc == ERROR_FILE_NOT_FOUND ) {
  1403. //
  1404. // if no service engine name, ignore this service
  1405. //
  1406. Win32Rc = ERROR_SUCCESS;
  1407. }
  1408. ScepFree(BufTmp);
  1409. BufTmp = NULL;
  1410. } else {
  1411. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1412. }
  1413. if ( Win32Rc != ERROR_SUCCESS ) {
  1414. break;
  1415. }
  1416. }
  1417. } while ( EnumRc != ERROR_NO_MORE_ITEMS );
  1418. RegCloseKey(hKey);
  1419. //
  1420. // remember the error code from enumeration
  1421. //
  1422. if ( EnumRc != ERROR_SUCCESS && EnumRc != ERROR_NO_MORE_ITEMS ) {
  1423. if ( Win32Rc == ERROR_SUCCESS )
  1424. Win32Rc = EnumRc;
  1425. }
  1426. }
  1427. if ( Win32Rc != NO_ERROR && *pSvcEngineList != NULL ) {
  1428. //
  1429. // free memory allocated for the list
  1430. //
  1431. SceFreePSCE_SERVICES(*pSvcEngineList);
  1432. *pSvcEngineList = NULL;
  1433. }
  1434. return( ScepDosErrorToSceStatus(Win32Rc) );
  1435. }