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.

2958 lines
90 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. depend.cxx
  5. Abstract:
  6. This module contains routines which handle service start and
  7. stop dependencies:
  8. ScInitAutoStart
  9. ScAutoStartServices
  10. ScStartServiceAndDependencies
  11. ScSetServiceStartRequest
  12. ScMarkGroupStartNow
  13. RI_ScGetCurrentGroupStateW
  14. ScStartMarkedServices
  15. ScHandleServiceFailure
  16. ScDependenciesStarted
  17. ScLookForHungServices
  18. ScHandleBadDependencies
  19. ScServiceToStartDependOn
  20. ScNotifyChangeState
  21. ScDependentsStopped
  22. ScEnumDependents
  23. ScFoundDuplicateDependent
  24. ScInHardwareProfile
  25. Author:
  26. Rita Wong (ritaw) 03-Apr-1992
  27. Environment:
  28. Win32
  29. Revision History:
  30. 11-Jun-2000 JSchwart
  31. Add no-reboot support for machine name change during OOBE
  32. setup and initial boot
  33. 08-Jan-1997 AnirudhS
  34. Remove I_ScGetCurrentGroupStateW as it is no longer used. In
  35. ScStartServiceAndDependencies, get an exclusive grouplist lock
  36. once more, instead of a shared one.
  37. 11-Jun-1996 AnirudhS
  38. During setup/upgrade, don't event-log failure of a service to start
  39. due to a dependent service not starting. (The most common case of
  40. this is a service that runs in a domain account, and hence has an
  41. implicit dependency on netlogon, which is disabled during setup.)
  42. 03-Nov-1995 AnirudhS
  43. Don't try to start a service that isn't in the current hardware
  44. profile.
  45. 30-Oct-1995 AnirudhS
  46. ScStartMarkedServices: If ScStartService says that a service is
  47. already running, treat this as a success.
  48. 15-Aug-1995 AnirudhS
  49. Added I_ScGetCurrentGroupStateW.
  50. Changed while loops to for loops and if stmts to switch stmts for
  51. improved readability.
  52. 16-Aug-1994 Danl
  53. ScLookForHungServices: If a long waitHint was passed in, the sleep
  54. time would be set to a huge number (like 4.9 days). This was
  55. changed so that if the waitHint is over 100 seconds, then the
  56. sleep time is limited to 10 seconds, but the number of iterations
  57. for the polling goes up.
  58. 09-Jun-1994 Danl
  59. Begin working on making sure NetLogon is started if we are
  60. going to start a service that runs in an account. This requires
  61. making a dependency on NetLogon.
  62. 21-Apr-1992 JohnRo
  63. Use SC_LOG0(), FORMAT_ equates, etc
  64. 03-Apr-1992 ritaw
  65. created
  66. --*/
  67. #include "precomp.hxx"
  68. #include <string.h> // memcpy
  69. #include <stdlib.h> // wcslen
  70. #include <winerror.h>
  71. #include <lmcons.h> // NET_API_STATUS
  72. #include <srvann.h> // I_ScGetCurrentGroupStateW and related definitions
  73. #include <cfgmgr32.h> // PNP manager functions
  74. #include <pnp.h> // PNP manager functions, server side
  75. #include <cfgmgrp.h> // PNP manager functions, server side, internal (PNP_GET_HWPROFFLAGS)
  76. #include <regstr.h> // CSCONFIGFLAG_ constants
  77. #include <tstr.h> // WCSSIZE
  78. #include <sclib.h> // ScCopyStringToBufferW
  79. #include <svcslib.h> // SetupInProgress
  80. #include <winsvcp.h> // OOBE setup event names
  81. #include "start.h" // ScStartService
  82. #include "depend.h"
  83. #include "info.h" // ScQueryServiceStatus
  84. #include "bootcfg.h" // ScRevertToLastKnownGood
  85. #include "driver.h" // ScGetDriverStatus
  86. #include "lockapi.h" // ScLockDatabase
  87. #include "account.h" // SC_LOCAL_SYSTEM_USER_NAME
  88. #include "scconfig.h" // ScRegCloseKey
  89. #define SERVICE_START_TIMEOUT 80000 // 80 seconds
  90. #define LENGTH(array) (sizeof(array)/sizeof((array)[0]))
  91. #define GROUP_NOT_STARTED 0x00000000
  92. #define GROUP_ONE_STARTED 0x00000001
  93. #define GROUP_START_FAIL 0x00000002
  94. #define REG_KEY_SETUP_ALLOW_START L"System\\Setup\\AllowStart"
  95. //
  96. // TDI GROUP SPECIAL: The PNP_TDI group is treated as a subgroup of
  97. // the TDI group for dependency purposes (though not for group start
  98. // ordering purposes). This is implemented via the following macros.
  99. // A service BELONGS_TO a group either if it is a member of that group,
  100. // or if the group is the TDI group and the service is a member of the
  101. // PNP_TDI group.
  102. // IS_SUBGROUP returns true if Group1 is equal to or a subgroup of Group2.
  103. //
  104. #define IS_SUBGROUP(Group1, Group2) \
  105. ((Group1) == (Group2) || \
  106. (Group2) == ScGlobalTDIGroup && (Group1) == ScGlobalPNP_TDIGroup)
  107. #define BELONGS_TO(Service, Group) \
  108. IS_SUBGROUP((Service)->MemberOfGroup, (Group))
  109. //-------------------------------------------------------------------//
  110. // //
  111. // Static global variables //
  112. // //
  113. //-------------------------------------------------------------------//
  114. //
  115. // For notifying us that a service has gone from start-pending state
  116. // to running or stopped state.
  117. //
  118. /* static */ HANDLE ScServiceChangeStateEvent = NULL;
  119. //
  120. // For serializing start requests
  121. //
  122. /* static */ CRITICAL_SECTION ScServiceStartCriticalSection;
  123. //
  124. // For telling internal routines when auto-start is in progress
  125. //
  126. BOOL ScAutoStartInProgress;
  127. //-------------------------------------------------------------------//
  128. // //
  129. // Local function prototypes //
  130. // //
  131. //-------------------------------------------------------------------//
  132. VOID
  133. ScSetServiceStartRequest(
  134. IN LPSERVICE_RECORD ServiceRecord,
  135. IN BOOL DemandStarting
  136. );
  137. BOOL
  138. ScMarkGroupStartNow(
  139. IN LPLOAD_ORDER_GROUP Group
  140. );
  141. DWORD
  142. ScGetCurrentGroupState(
  143. LPLOAD_ORDER_GROUP Group
  144. );
  145. DWORD
  146. ScStartMarkedServices(
  147. IN LPSERVICE_RECORD ServiceToStart OPTIONAL,
  148. IN DWORD NumArgs,
  149. IN LPSTRING_PTRSW CmdArgs,
  150. IN BOOL WaitForAll
  151. );
  152. VOID
  153. ScHandleServiceFailure(
  154. IN LPSERVICE_RECORD Service
  155. );
  156. BOOL
  157. ScDependenciesStarted(
  158. IN LPSERVICE_RECORD Service,
  159. OUT BOOL *IsBadDependencies,
  160. OUT BOOL *AllStarted,
  161. OUT BOOL *ExistsBlockedService
  162. );
  163. BOOL
  164. IsDependOnLaterGroup(
  165. IN LPLOAD_ORDER_GROUP ServiceGroup,
  166. IN LPLOAD_ORDER_GROUP DependOnGroup,
  167. IN DEPEND_TYPE DependType
  168. );
  169. VOID
  170. ScCleanupStartFailure(
  171. LPSERVICE_RECORD Service,
  172. DWORD StartError
  173. );
  174. VOID
  175. ScLookForHungServices(
  176. VOID
  177. );
  178. VOID
  179. ScHandleBadDependencies(
  180. VOID
  181. );
  182. BOOL
  183. ScServiceToStartDependOn(
  184. LPSERVICE_RECORD ServiceToStart OPTIONAL,
  185. LPSERVICE_RECORD StartPendingService
  186. );
  187. BOOL
  188. ScFoundDuplicateDependent(
  189. IN LPWSTR ServiceName,
  190. IN LPENUM_SERVICE_STATUS_WOW64 EnumBuffer,
  191. IN LPENUM_SERVICE_STATUS_WOW64 BufferEnd
  192. );
  193. #ifndef _CAIRO_
  194. VOID
  195. ScCheckNetLogonDepend(
  196. LPSERVICE_RECORD ServiceRecord,
  197. BOOL DemandStarting
  198. );
  199. #endif // _CAIRO_
  200. BOOL
  201. ScInitAutoStart(
  202. VOID
  203. )
  204. /*++
  205. Routine Description:
  206. This function creates the event for notifying the service controller
  207. that one of the automatically started service is running and creates
  208. the mutex for serializing start requests.
  209. Arguments:
  210. None.
  211. Return Value:
  212. TRUE - Event and mutex were created successfully. FALSE otherwise.
  213. --*/
  214. {
  215. //
  216. // Create event which indicates that some service that has been
  217. // automatically started is now running or stopped.
  218. //
  219. if ((ScServiceChangeStateEvent =
  220. CreateEvent(
  221. NULL, // Event attributes
  222. TRUE, // Event must be manually reset
  223. FALSE, // Initial state not signalled
  224. NULL
  225. )) == (HANDLE) NULL) {
  226. return FALSE;
  227. }
  228. //
  229. // Create critical section which is used to serialize start requests:
  230. // if auto-starting services, and a user tries to demand start
  231. // a service, auto-starting has to complete before we process the
  232. // demand start.
  233. //
  234. InitializeCriticalSection(&ScServiceStartCriticalSection);
  235. return TRUE;
  236. }
  237. DWORD
  238. ScAutoStartServices(
  239. IN OUT LPSC_RPC_LOCK lpLock
  240. )
  241. /*++
  242. Routine Description:
  243. This function automatically starts all services that must be
  244. auto-started, in group order.
  245. This routine may not return because we may instigate a reboot to
  246. revert to last-known-good.
  247. Arguments:
  248. None.
  249. Return Value:
  250. None.
  251. --*/
  252. {
  253. BOOL fIsOOBE;
  254. ScAutoStartInProgress = TRUE;
  255. //
  256. // Set current request flag of all auto-start services as well as
  257. // their dependencies
  258. //
  259. SetupInProgress(NULL, &fIsOOBE);
  260. if (fIsOOBE)
  261. {
  262. #define NUM_OOBE_SERVICES 2
  263. DWORD dwError;
  264. DWORD dwTries = 0;
  265. LPSERVICE_RECORD ServiceRecord = NULL;
  266. HANDLE hPnPDone;
  267. HANDLE hMachineNameDone;
  268. LPWSTR lpServicesForOobe[NUM_OOBE_SERVICES] = { L"PlugPlay", L"AudioSrv" };
  269. UINT i;
  270. SC_LOG0(TRACE,
  271. "ScAutoStartServices: Is OOBE -- creating events\n");
  272. //
  273. // OOBE setup will wait on this event first. We set it
  274. // once PnP is done starting to wake up OOBE setup (which
  275. // will then prompt the user for the new machine name)
  276. //
  277. hPnPDone = CreateEvent(
  278. NULL, // Event Attributes
  279. TRUE, // ManualReset
  280. FALSE, // Initial State (not-signaled)
  281. SC_OOBE_PNP_DONE); // Name
  282. if (!hPnPDone)
  283. {
  284. dwError = GetLastError();
  285. SC_LOG1(ERROR,
  286. "ScAutoStartServices: Creation of SC_OOBE_PNP_DONE event failed %d\n",
  287. dwError);
  288. return dwError;
  289. }
  290. //
  291. // Once the machine name is set, OOBE setup will set this
  292. // event to tell us to finish auto-starting the services
  293. //
  294. hMachineNameDone = CreateEvent(
  295. NULL, // Event Attributes
  296. TRUE, // ManualReset
  297. FALSE, // Initial State (not-signaled)
  298. SC_OOBE_MACHINE_NAME_DONE); // Name
  299. if (!hMachineNameDone)
  300. {
  301. dwError = GetLastError();
  302. SC_LOG1(ERROR,
  303. "ScAutoStartServices: Creation of SC_OOBE_PNP_DONE event failed %d\n",
  304. dwError);
  305. CloseHandle(hPnPDone);
  306. return dwError;
  307. }
  308. SC_LOG0(TRACE,
  309. "ScAutoStartServices: Starting services used by OOBE\n");
  310. for (i = 0; i < NUM_OOBE_SERVICES; i++)
  311. {
  312. //
  313. // Since a computer name change may require PnP to be running,
  314. // start it and only it and wait until signalled to start the rest.
  315. // Grab the service list lock since ScGetNamedServiceRecord uses
  316. // the FOR_ALL_SERVICES macro, which expects it. Also start
  317. // AudioSrv, which is needed for audio for OOBE.
  318. //
  319. {
  320. CServiceListSharedLock LLock;
  321. dwError = ScGetNamedServiceRecord(lpServicesForOobe[i], &ServiceRecord);
  322. }
  323. if (dwError != NO_ERROR)
  324. {
  325. //
  326. // Ignore failure since ServiceRecord will now be NULL so
  327. // the call below will start all the auto-start services
  328. // instead of just PnP. The machine name will be wrong in
  329. // some of the services until the next reboot, but there's
  330. // nothing we can do about it at this point.
  331. //
  332. SC_LOG2(ERROR,
  333. "ScAutoStartServices: OOBE lookup of service %ws failed %d\n",
  334. lpServicesForOobe[i],
  335. dwError);
  336. }
  337. dwError = ScStartServiceAndDependencies(ServiceRecord, 0, NULL, TRUE);
  338. if (dwError != NO_ERROR)
  339. {
  340. //
  341. // Ignore failure -- it's possible PnP won't need to be
  342. // up and running (it's only necessary if the OEM setup
  343. // for the machine was done without a keyboard and PnP
  344. // is now needed to detect the hardware). Audio failure
  345. // is definitely non-fatal.
  346. //
  347. SC_LOG2(ERROR,
  348. "ScAutoStartServices: OOBE start of %ws failed %d\n",
  349. lpServicesForOobe[i],
  350. dwError);
  351. }
  352. }
  353. //
  354. // Drop the database lock since OOBE may invoke server-side PnP
  355. // installations and setupapi.dll will try to lock the database.
  356. // In addition, it may invoke 3rd-party class installers and we
  357. // have no idea what they may try to do with the lock.
  358. //
  359. ScUnlockDatabase(lpLock);
  360. //
  361. // Let setup proceed
  362. //
  363. if (! SetEvent(hPnPDone))
  364. {
  365. dwError = GetLastError();
  366. SC_LOG1(ERROR,
  367. "ScAutoStartServices: Failed to set event (hPnPDone) %d\n",
  368. dwError);
  369. }
  370. //
  371. // Wait for setup to let us proceed.
  372. //
  373. WaitForSingleObject(hMachineNameDone, INFINITE);
  374. dwError = NO_ERROR;
  375. //
  376. // Reacquire the database lock. Wait 10 minutes at most.
  377. //
  378. do
  379. {
  380. if (dwError != NO_ERROR)
  381. {
  382. Sleep(2000);
  383. }
  384. dwError = ScLockDatabase(TRUE, SERVICES_ACTIVE_DATABASEW, lpLock);
  385. dwTries++;
  386. }
  387. while (dwError != NO_ERROR && dwTries != 300);
  388. CloseHandle(hPnPDone);
  389. CloseHandle(hMachineNameDone);
  390. if (dwError != NO_ERROR)
  391. {
  392. SC_LOG1(ERROR,
  393. "ScAutoStartServices: Failed to reacquire database lock %d\n",
  394. dwError);
  395. return dwError;
  396. }
  397. #undef NUM_OOBE_SERVICES
  398. }
  399. //
  400. // Start services with start request flag set in group order
  401. //
  402. ScStartServiceAndDependencies(NULL, 0, NULL, FALSE);
  403. ScAutoStartInProgress = FALSE;
  404. return NO_ERROR;
  405. }
  406. DWORD
  407. ScStartServiceAndDependencies(
  408. IN LPSERVICE_RECORD ServiceToStart OPTIONAL,
  409. IN DWORD NumArgs,
  410. IN LPSTRING_PTRSW CmdArgs,
  411. IN BOOL fIsOOBE
  412. )
  413. /*++
  414. Routine Description:
  415. This function marks a group or a service to be started now before
  416. calling ScStartMarkedServices to start them.
  417. Arguments:
  418. ServiceToStart - Service to be started; or, NULL if autostarting
  419. services.
  420. NumArgs, CmdArgs - Arguments for the service to be started.
  421. Return Value:
  422. NO_ERROR if successful; otherwise, the return value from the first
  423. unsuccessful call to ScStartMarkedServices.
  424. --*/
  425. {
  426. DWORD status;
  427. DWORD ApiStatus = NO_ERROR;
  428. PLOAD_ORDER_GROUP Group;
  429. SC_RPC_LOCK Lock;
  430. BOOL databaseLocked = FALSE;
  431. //
  432. // Serialize start requests by allowing auto-starting of groups or
  433. // demand start of a service one at a time.
  434. //
  435. EnterCriticalSection(&ScServiceStartCriticalSection);
  436. //
  437. // Grab the SC Manager database lock.
  438. //
  439. if (!ScStillInitializing) {
  440. if ((status = ScLockDatabase(
  441. TRUE, // called internally
  442. SERVICES_ACTIVE_DATABASEW,
  443. &Lock
  444. )) != NO_ERROR) {
  445. LeaveCriticalSection(&ScServiceStartCriticalSection);
  446. return status;
  447. }
  448. databaseLocked = TRUE;
  449. }
  450. //
  451. // There is one (highly unlikely) condition in which we might need to
  452. // modify the group information here: if we call ScStartService and it
  453. // calls ScDeactivateSR on a service whose update flag is set (its
  454. // config was changed while it was running).
  455. // To prevent deadlocks, the grouplist lock is always acquired before
  456. // the service database lock, if both are needed. So we get an
  457. // exclusive lock on the grouplist here.
  458. //
  459. {
  460. CGroupListExclusiveLock GLock;
  461. //
  462. // Get a shared lock on the service list as we shall walk it several
  463. // times.
  464. //
  465. CServiceListSharedLock LLock;
  466. //
  467. // Get the exclusive database lock so that we can increment the
  468. // use count of the service being started as well as their dependencies
  469. // because otherwise they could go away if deleted.
  470. //
  471. {
  472. CServiceRecordExclusiveLock RLock;
  473. if (ARGUMENT_PRESENT(ServiceToStart)) {
  474. //
  475. // Demand starting a service.
  476. //
  477. //
  478. // We can never start a disabled service
  479. //
  480. if (ServiceToStart->StartType == SERVICE_DISABLED ||
  481. ! ScInHardwareProfile(ServiceToStart->ServiceName, 0)) {
  482. ApiStatus = ERROR_SERVICE_DISABLED;
  483. goto ReleaseLocks;
  484. }
  485. //
  486. // Cannot start a deleted service.
  487. //
  488. if (DELETE_FLAG_IS_SET(ServiceToStart)) {
  489. ApiStatus = ERROR_SERVICE_MARKED_FOR_DELETE;
  490. goto ReleaseLocks;
  491. }
  492. //
  493. // Get the current state of the service
  494. //
  495. if (ServiceToStart->ServiceStatus.dwServiceType & SERVICE_DRIVER) {
  496. (void) ScGetDriverStatus(ServiceToStart, NULL);
  497. }
  498. if (ServiceToStart->ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
  499. ApiStatus = ERROR_SERVICE_ALREADY_RUNNING;
  500. goto ReleaseLocks;
  501. }
  502. //
  503. // Set the current-start flag on the service and all of
  504. // its dependencies. Also increment their use counts so
  505. // that we know they won't go away, even when we release
  506. // the locks temporarily.
  507. //
  508. SC_LOG(DEPEND,"Setting start request for %ws and dependencies\n",
  509. ServiceToStart->ServiceName);
  510. SC_LOG(WHY, " Will start %ws because of an explicit start request\n",
  511. ServiceToStart->ServiceName);
  512. ScSetServiceStartRequest(ServiceToStart, TRUE);
  513. }
  514. else {
  515. //
  516. // Auto-starting services.
  517. //
  518. // If we are in GUI mode setup, we only start those auto-start
  519. // services that are allowed. Allowed services are listed
  520. // under HKLM\System\Setup\AllowStart as registry keys.
  521. // If the subkey with the same name as the service exits,
  522. // it means we allow it to be autostarted during GUI mode.
  523. //
  524. HKEY hkeyAllowStart = NULL;
  525. BOOL InSetup = SetupInProgress(NULL, NULL);
  526. if (InSetup)
  527. {
  528. status = ScRegOpenKeyExW(
  529. HKEY_LOCAL_MACHINE,
  530. REG_KEY_SETUP_ALLOW_START,
  531. REG_OPTION_NON_VOLATILE,
  532. KEY_READ,
  533. &hkeyAllowStart);
  534. if (NO_ERROR != status)
  535. {
  536. // This is not expected as the registry key is created
  537. // by hivesys.inf. We'll skip checking services in
  538. // this case.
  539. //
  540. hkeyAllowStart = NULL;
  541. }
  542. }
  543. // Set the CurrentStartRequest flag to TRUE for all services
  544. // of type AUTO_START that are enabled in this hardware profile,
  545. // and their dependencies.
  546. //
  547. SC_LOG0(DEPEND,"Setting start request for auto-started services and dependencies\n");
  548. FOR_SERVICES_THAT(Service, Service->StartType == SERVICE_AUTO_START &&
  549. ScInHardwareProfile(Service->ServiceName, 0))
  550. {
  551. BOOL AllowStart = TRUE;
  552. if (hkeyAllowStart)
  553. {
  554. HKEY hkey;
  555. ASSERT(InSetup);
  556. status = ScRegOpenKeyExW(
  557. hkeyAllowStart,
  558. Service->ServiceName,
  559. REG_OPTION_NON_VOLATILE,
  560. KEY_READ,
  561. &hkey);
  562. if (NO_ERROR == status)
  563. {
  564. // The service name exists and is therefore
  565. // allowed to start. Don't forget to close the
  566. // key.
  567. ScRegCloseKey(hkey);
  568. ASSERT(AllowStart);
  569. }
  570. else
  571. {
  572. AllowStart = FALSE;
  573. SC_LOG(WHY, " Will NOT start %ws because it's not "
  574. "allowed to run during system setup\n",
  575. Service->ServiceName);
  576. }
  577. }
  578. if (AllowStart)
  579. {
  580. SC_LOG(WHY, " Will start %ws because it's configured to autostart\n",
  581. Service->ServiceName);
  582. ScSetServiceStartRequest(Service, FALSE);
  583. }
  584. }
  585. if (hkeyAllowStart)
  586. {
  587. ScRegCloseKey(hkeyAllowStart);
  588. }
  589. }
  590. } // Release RLock
  591. //
  592. // Always start services in group order.
  593. //
  594. for (Group = ScGetOrderGroupList();
  595. Group != NULL;
  596. Group = Group->Next)
  597. {
  598. //
  599. // Start each group in load group order
  600. //
  601. if (ScMarkGroupStartNow(Group)) {
  602. SC_LOG(DEPEND,"------ Starting services in group \"%ws\" -----\n", Group->GroupName);
  603. BOOL WaitForGroup;
  604. if (ARGUMENT_PRESENT(ServiceToStart) &&
  605. ServiceToStart->MemberOfGroup == Group) {
  606. //
  607. // Don't have to wait for all marked members of the group
  608. // to finish starting because the service which is demand
  609. // started is polled by the UI.
  610. //
  611. WaitForGroup = FALSE;
  612. }
  613. else {
  614. //
  615. // Auto-starting (ServiceToStart == NULL) or demand-starting
  616. // a service that is not within this group. Wait for group
  617. // all marked members finish starting.
  618. //
  619. WaitForGroup = TRUE;
  620. }
  621. status = ScStartMarkedServices(
  622. ServiceToStart,
  623. NumArgs,
  624. CmdArgs,
  625. (WaitForGroup || fIsOOBE)
  626. );
  627. if (status != NO_ERROR && ApiStatus == NO_ERROR) {
  628. //
  629. // Save first error to be returned
  630. //
  631. ApiStatus = status;
  632. }
  633. }
  634. }
  635. //
  636. // Services that do not belong in any group are considered
  637. // in a group that starts last.
  638. //
  639. if (ScMarkGroupStartNow(NULL)) {
  640. SC_LOG0(DEPEND,"------ Starting services that aren't in ServiceGroupOrder -----\n");
  641. //
  642. // Wait only for auto-start services or for the service(s)
  643. // we explicitly demand-start during OOBE setup
  644. //
  645. status = ScStartMarkedServices(
  646. ServiceToStart,
  647. NumArgs,
  648. CmdArgs,
  649. (! ARGUMENT_PRESENT(ServiceToStart) || fIsOOBE)
  650. );
  651. if (status != NO_ERROR && ApiStatus == NO_ERROR) {
  652. //
  653. // Save first error to be returned
  654. //
  655. ApiStatus = status;
  656. }
  657. }
  658. SC_LOG(DEPEND,"------ Done %s-starting services -----\n",
  659. ARGUMENT_PRESENT(ServiceToStart) ? "demand" : "auto");
  660. //
  661. // Clear the CurrentStartRequest flags when done starting service(s).
  662. //
  663. {
  664. CServiceRecordExclusiveLock RLock;
  665. FOR_SERVICES_THAT(Service, CURRENTSTART_FLAG_IS_SET(Service))
  666. {
  667. CLEAR_CURRENTSTART_FLAG(Service);
  668. ScDecrementUseCountAndDelete(Service);
  669. }
  670. }
  671. } // Release LLock and GLock
  672. ReleaseLocks:
  673. //
  674. // Release the SC Manager database lock.
  675. //
  676. if (databaseLocked) {
  677. ScUnlockDatabase(&Lock);
  678. }
  679. LeaveCriticalSection(&ScServiceStartCriticalSection);
  680. return ApiStatus;
  681. }
  682. VOID
  683. ScSetServiceStartRequest(
  684. IN LPSERVICE_RECORD ServiceRecord,
  685. IN BOOL DemandStarting
  686. )
  687. /*++
  688. Routine Description:
  689. This function sets the CurrentStartRequest flag of the specified service
  690. to TRUE and recursively sets the flag of all the services this
  691. service depends on. It also initializes the StartState and StartError
  692. of the services that are about to be started.
  693. Arguments:
  694. ServiceRecord - Supplies a pointer to the service record of service
  695. to be started.
  696. DemandStarting - Supplies a flag that is set to TRUE if we are demand-
  697. starting a service, FALSE if we are auto-starting services.
  698. Return Value:
  699. None.
  700. Note:
  701. This function expects the caller to have held the exclusive service
  702. database lock. This function is called by ScStartServiceAndDependencies.
  703. --*/
  704. {
  705. SC_ASSERT(ScServiceListLock.Have());
  706. SC_ASSERT(ScServiceRecordLock.HaveExclusive());
  707. if (CURRENTSTART_FLAG_IS_SET(ServiceRecord)) {
  708. return;
  709. }
  710. //
  711. // Set the CurrentStartRequest to TRUE
  712. //
  713. SET_CURRENTSTART_FLAG(ServiceRecord);
  714. //
  715. // Update the StartState and StartError
  716. //
  717. if (ServiceRecord->StartType == SERVICE_DISABLED ||
  718. ! ScInHardwareProfile(ServiceRecord->ServiceName, 0)) {
  719. ServiceRecord->StartState = SC_START_FAIL;
  720. ServiceRecord->StartError = ERROR_SERVICE_DISABLED;
  721. }
  722. else if (DELETE_FLAG_IS_SET(ServiceRecord)) {
  723. ServiceRecord->StartState = SC_START_FAIL;
  724. ServiceRecord->StartError = ERROR_SERVICE_MARKED_FOR_DELETE;
  725. }
  726. else {
  727. if (ServiceRecord->ServiceStatus.dwServiceType & SERVICE_DRIVER) {
  728. (void) ScGetDriverStatus(ServiceRecord, NULL);
  729. }
  730. switch (ServiceRecord->ServiceStatus.dwCurrentState) {
  731. case SERVICE_STOPPED:
  732. if (DemandStarting) {
  733. //
  734. // Demand starting a service. We want to retry
  735. // eventhough we have failed once before.
  736. //
  737. ServiceRecord->StartState = SC_NEVER_STARTED;
  738. }
  739. else {
  740. //
  741. // Auto-starting bunch of services at boot. If
  742. // the service was ever started before and failed,
  743. // we don't want to start it again.
  744. //
  745. if (ServiceRecord->ServiceStatus.dwWin32ExitCode !=
  746. ERROR_SERVICE_NEVER_STARTED) {
  747. ServiceRecord->StartState = SC_START_FAIL;
  748. }
  749. else {
  750. ServiceRecord->StartState = SC_NEVER_STARTED;
  751. }
  752. }
  753. break;
  754. case SERVICE_START_PENDING:
  755. ServiceRecord->StartState = SC_START_PENDING;
  756. break;
  757. case SERVICE_STOP_PENDING:
  758. case SERVICE_PAUSED:
  759. case SERVICE_CONTINUE_PENDING:
  760. case SERVICE_PAUSE_PENDING:
  761. case SERVICE_RUNNING:
  762. ServiceRecord->StartState = SC_START_SUCCESS;
  763. break;
  764. default:
  765. SC_LOG1(
  766. ERROR,
  767. "ScSetServiceStartRequest: Unexpected dwCurrentState %0lx\n",
  768. ServiceRecord->ServiceStatus.dwCurrentState
  769. );
  770. SC_ASSERT(FALSE);
  771. ServiceRecord->StartState = SC_START_FAIL;
  772. break;
  773. }
  774. }
  775. //
  776. // Increment the reference count so that the dependency service
  777. // never goes away while we are in the process of starting them.
  778. //
  779. ServiceRecord->UseCount++;
  780. SC_LOG2(USECOUNT, "ScSetServiceStartRequest: " FORMAT_LPWSTR
  781. " increment USECOUNT=%lu\n", ServiceRecord->ServiceName, ServiceRecord->UseCount);
  782. SC_LOG2(DEPEND_DUMP, "CSR=TRUE for "
  783. FORMAT_LPWSTR " USECOUNT=%lu\n", ServiceRecord->ServiceName,
  784. ServiceRecord->UseCount);
  785. //
  786. // For each of this service's dependencies
  787. //
  788. for (LPDEPEND_RECORD Depend = ServiceRecord->StartDepend;
  789. Depend != NULL;
  790. Depend = Depend->Next)
  791. {
  792. if (Depend->DependType == TypeDependOnService) {
  793. if (CURRENTSTART_FLAG_IS_SET(Depend->DependService)) {
  794. //
  795. // CurrentStartRequest of a dependency service is already
  796. // set to TRUE. Just go on to next dependency.
  797. //
  798. SC_LOG2(WHY, " (Will start %ws because %ws depends on it too)\n",
  799. Depend->DependService->ServiceName, ServiceRecord->ServiceName);
  800. SC_LOG2(DEPEND_DUMP, "DependService " FORMAT_LPWSTR
  801. " CSR=TRUE already, USECOUNT=%lu\n",
  802. Depend->DependService->ServiceName,
  803. Depend->DependService->UseCount);
  804. }
  805. else {
  806. SC_LOG2(WHY, " Will start %ws because %ws depends on it\n",
  807. Depend->DependService->ServiceName, ServiceRecord->ServiceName);
  808. ScSetServiceStartRequest(Depend->DependService, DemandStarting);
  809. }
  810. }
  811. else if (Depend->DependType == TypeDependOnGroup) {
  812. //
  813. // This service has a dependency on a group.
  814. // For each service in that group
  815. //
  816. FOR_SERVICES_THAT(Service, BELONGS_TO(Service, Depend->DependGroup))
  817. {
  818. if (CURRENTSTART_FLAG_IS_SET(Service)) {
  819. //
  820. // CurrentStartRequest of a dependency service is
  821. // already set to TRUE. Just go on to next dependency.
  822. //
  823. SC_LOG3(WHY, " (Will start %ws because %ws depends on its group %ws too)\n",
  824. Service->ServiceName, ServiceRecord->ServiceName,
  825. Depend->DependGroup->GroupName);
  826. SC_LOG3(DEPEND_DUMP, "DependGroup " FORMAT_LPWSTR
  827. ", Service " FORMAT_LPWSTR
  828. " CSR=TRUE already, USECOUNT=%lu\n",
  829. Depend->DependGroup->GroupName,
  830. Service->ServiceName, Service->UseCount);
  831. }
  832. else {
  833. SC_LOG3(WHY, " Will start %ws because %ws depends on its group %ws\n",
  834. Service->ServiceName, ServiceRecord->ServiceName,
  835. Depend->DependGroup->GroupName);
  836. ScSetServiceStartRequest(
  837. Service,
  838. DemandStarting
  839. );
  840. }
  841. }
  842. }
  843. }
  844. #ifndef _CAIRO_
  845. //
  846. // We have now gone through all the dependencies that are listed. Now
  847. // Determine if this service needs to depend on NetLogon. If the service
  848. // runs in an account, it may require NetLogon.
  849. //
  850. ScCheckNetLogonDepend(ServiceRecord,DemandStarting);
  851. #endif // _CAIRO_
  852. }
  853. BOOL
  854. ScMarkGroupStartNow(
  855. IN LPLOAD_ORDER_GROUP Group
  856. )
  857. /*++
  858. Routine Description:
  859. This function go through all services that belong in the specified
  860. group and mark the services that have the CurrentStartRequest flag
  861. set to be started immediately.
  862. Arguments:
  863. Group - Supplies a pointer to the load order group to mark for
  864. start.
  865. Return Value:
  866. Returns TRUE if at least one member of the group is marked
  867. START_NOW or is START_PENDING. FALSE otherwise. This flag
  868. is to indicate whether ScStartMarkedServices should be called
  869. to handle starting a group.
  870. --*/
  871. {
  872. BOOL ReturnFlag = FALSE;
  873. //
  874. // Mark all the CurrentStartRequest (which includes all auto-start)
  875. // services to be started now
  876. //
  877. // A service is marked START_NOW if it is a member of the specified
  878. // group. If the specified group is NULL, mark all services that
  879. // do not belong to any group as well as services that belong to
  880. // standalone groups.
  881. //
  882. FOR_SERVICES_THAT(Service,
  883. ((Service->MemberOfGroup == Group) ||
  884. (Group == NULL && (Service->MemberOfGroup != NULL) &&
  885. (Service->MemberOfGroup->RefCount != MAXULONG) ))
  886. &&
  887. CURRENTSTART_FLAG_IS_SET(Service) )
  888. {
  889. if (Service->StartState == SC_NEVER_STARTED)
  890. {
  891. Service->StartState = SC_START_NOW;
  892. Service->StartError = NO_ERROR;
  893. }
  894. if (Service->StartState == SC_START_NOW ||
  895. Service->StartState == SC_START_PENDING)
  896. {
  897. ReturnFlag = TRUE;
  898. }
  899. }
  900. return ReturnFlag;
  901. }
  902. DWORD
  903. RI_ScGetCurrentGroupStateW(
  904. IN SC_RPC_HANDLE hSCManager,
  905. IN LPWSTR pszGroupName,
  906. OUT LPDWORD pdwCurrentState
  907. )
  908. /*++
  909. Routine Description:
  910. This is obsolete, but the RPC entry point still exists.
  911. --*/
  912. {
  913. return ERROR_NOT_SUPPORTED;
  914. }
  915. DWORD
  916. ScGetCurrentGroupState(
  917. LPLOAD_ORDER_GROUP Group
  918. )
  919. {
  920. BOOL OneStarted = FALSE;
  921. FOR_SERVICES_THAT(Service, BELONGS_TO(Service, Group))
  922. {
  923. switch (Service->StartState)
  924. {
  925. case SC_NEVER_STARTED:
  926. //
  927. // Ignore services that are disabled or marked for
  928. // deletion.
  929. // (This check is really needed only when this function is
  930. // called from RI_ScGetCurrentGroupState. When called
  931. // from ScDependenciesStarted, such services will already
  932. // have had their StartState set to SC_START_FAIL.)
  933. //
  934. if (Service->StartType == SERVICE_DISABLED ||
  935. DELETE_FLAG_IS_SET(Service) ||
  936. ! ScInHardwareProfile(Service->ServiceName, 0))
  937. {
  938. continue;
  939. }
  940. //
  941. // else fall through
  942. //
  943. case SC_START_NOW:
  944. case SC_START_PENDING:
  945. SC_LOG2(DEPEND, "Group " FORMAT_LPWSTR " NOT started "
  946. "because of Service " FORMAT_LPWSTR "\n",
  947. Group->GroupName, Service->ServiceName);
  948. return GROUP_NOT_STARTED;
  949. case SC_START_SUCCESS:
  950. OneStarted = TRUE;
  951. break; // out of switch, not out of loop
  952. }
  953. }
  954. if (OneStarted)
  955. {
  956. SC_LOG1(DEPEND, "Group " FORMAT_LPWSTR " ONE started\n",
  957. Group->GroupName);
  958. return GROUP_ONE_STARTED;
  959. }
  960. else
  961. {
  962. SC_LOG1(DEPEND, "Group " FORMAT_LPWSTR " FAILED to start\n",
  963. Group->GroupName);
  964. return GROUP_START_FAIL;
  965. }
  966. }
  967. DWORD
  968. ScStartMarkedServices(
  969. IN LPSERVICE_RECORD ServiceToStart OPTIONAL,
  970. IN DWORD NumArgs,
  971. IN LPSTRING_PTRSW CmdArgs,
  972. IN BOOL WaitForAll
  973. )
  974. /*++
  975. Routine Description:
  976. This function starts the services that are marked as SERVICE_START_NOW
  977. in the service record list. Once the service is running, or if the
  978. service failed to start, the SERVICE_START_NOW bit is removed.
  979. If a service marked as SERVICE_START_NOW depends on a service that is
  980. not marked, the dependency service will also be marked SERVICE_START_NOW.
  981. Arguments:
  982. ServiceToStart - Supplies a pointer to the service which is to be demand
  983. started via the StartService API. If this parameter is NULL, this
  984. routine is called by the service controller to auto-start services
  985. at boot.
  986. NumArgs - Supplies the number of command-line arguments for the demand
  987. started service. If ServiceToStart is NULL, this parameter is ignored.
  988. CmdArgs - Supplies an array of command arguments to the demand started
  989. service. If ServiceToStart is NULL, this parameter is ignored.
  990. WaitForAll - Supplies a flag which if TRUE tells this function to
  991. wait until all start-pending services that were marked START_NOW
  992. to get done.
  993. Return Value:
  994. Returns error if failure to reset the ScServiceChangeStateEvent.
  995. --*/
  996. {
  997. DWORD Error;
  998. BOOL AllStarted;
  999. BOOL ExistsBlockedService;
  1000. BOOL IsBadDependencies;
  1001. BOOL IsStartPending;
  1002. DWORD ServiceCurrentState;
  1003. #if DBG
  1004. DWORD LoopCount = 0;
  1005. #endif
  1006. //
  1007. // Reset ScServiceChangeStateEvent to non-signalled state
  1008. //
  1009. if (! ResetEvent(ScServiceChangeStateEvent)) {
  1010. Error = GetLastError();
  1011. //
  1012. // This is a serious error--we cannot proceed.
  1013. //
  1014. SC_LOG1(ERROR, "Error reseting ScServiceChangeStateEvent " FORMAT_DWORD
  1015. "\n", Error);
  1016. ScLogEvent(
  1017. NEVENT_CALL_TO_FUNCTION_FAILED,
  1018. SC_RESET_EVENT,
  1019. Error
  1020. );
  1021. return Error;
  1022. }
  1023. //
  1024. // Start all services that are marked
  1025. //
  1026. do { // while (! AllStarted)
  1027. AllStarted = TRUE;
  1028. IsStartPending = FALSE;
  1029. ExistsBlockedService = FALSE;
  1030. IsBadDependencies = FALSE;
  1031. SC_LOG1(DEPEND, "BIG LOOP COUNT " FORMAT_DWORD "\n", LoopCount++);
  1032. //
  1033. // Loop through every service which is currently in the database
  1034. //
  1035. FOR_ALL_SERVICES(Service)
  1036. {
  1037. //
  1038. // Check if the current service failed to start, and if we have
  1039. // to revert to last-known-good. Don't revert if demand start.
  1040. //
  1041. if (! ARGUMENT_PRESENT(ServiceToStart)) {
  1042. ScHandleServiceFailure(Service);
  1043. }
  1044. if (Service->StartState == SC_START_NOW) {
  1045. SC_LOG1(DEPEND, FORMAT_LPWSTR " is marked START NOW\n",
  1046. Service->ServiceName);
  1047. //
  1048. // Start the current service only if all its dependencies
  1049. // have started successfully.
  1050. //
  1051. if (ScDependenciesStarted(
  1052. Service,
  1053. &IsBadDependencies,
  1054. &AllStarted,
  1055. &ExistsBlockedService
  1056. )) {
  1057. //
  1058. // Start the service and save the start error code
  1059. //
  1060. SC_LOG1(DEPEND, "ScStartMarkedServices: Starting "
  1061. FORMAT_LPWSTR "\n", Service->ServiceName);
  1062. if (Service == ServiceToStart)
  1063. {
  1064. Service->StartError = ScStartService(
  1065. Service,
  1066. NumArgs,
  1067. CmdArgs
  1068. );
  1069. }
  1070. else
  1071. {
  1072. Service->StartError = ScStartService(
  1073. Service,
  1074. 0,
  1075. NULL
  1076. );
  1077. //
  1078. // We are starting a new service so remember to loop
  1079. // through again to process any service which are
  1080. // dependent on it. Don't have to set AllStarted
  1081. // to FALSE if this service is ServiceToStart because
  1082. // nothing is dependent on it since it is demand
  1083. // started.
  1084. //
  1085. AllStarted = FALSE;
  1086. }
  1087. if (Service->StartError == NO_ERROR ||
  1088. Service->StartError == ERROR_SERVICE_ALREADY_RUNNING)
  1089. {
  1090. //
  1091. // Get the state of the just started service
  1092. //
  1093. {
  1094. CServiceRecordSharedLock RLock;
  1095. ServiceCurrentState =
  1096. Service->ServiceStatus.dwCurrentState;
  1097. }
  1098. switch (ServiceCurrentState) {
  1099. case SERVICE_START_PENDING:
  1100. IsStartPending = TRUE;
  1101. Service->StartState = SC_START_PENDING;
  1102. break;
  1103. case SERVICE_STOP_PENDING:
  1104. case SERVICE_PAUSED:
  1105. case SERVICE_CONTINUE_PENDING:
  1106. case SERVICE_PAUSE_PENDING:
  1107. case SERVICE_RUNNING:
  1108. Service->StartState = SC_START_SUCCESS;
  1109. break;
  1110. case SERVICE_STOPPED:
  1111. Service->StartState = SC_START_FAIL;
  1112. break;
  1113. default:
  1114. SC_LOG1(ERROR, "Unexpected service state "
  1115. FORMAT_HEX_DWORD "\n",
  1116. ServiceCurrentState);
  1117. SC_ASSERT(FALSE);
  1118. Service->StartState = SC_START_FAIL;
  1119. }
  1120. }
  1121. else {
  1122. //
  1123. // Clear ERROR_SERVICE_NEVER_STARTED in the Win32ExitCode
  1124. // field if service failed to start.
  1125. //
  1126. {
  1127. CServiceRecordExclusiveLock RLock;
  1128. if (Service->ServiceStatus.dwWin32ExitCode ==
  1129. ERROR_SERVICE_NEVER_STARTED) {
  1130. Service->ServiceStatus.dwWin32ExitCode =
  1131. Service->StartError;
  1132. }
  1133. }
  1134. Service->StartState = SC_START_FAIL;
  1135. //
  1136. // For popup after user has logged on to indicate that some
  1137. // service started at boot has failed.
  1138. // We don't log the error if it is ERROR_IGNORE or if
  1139. // we tried to start a non-Safeboot service in Safeboot.
  1140. //
  1141. if (Service->ErrorControl != SERVICE_ERROR_IGNORE
  1142. &&
  1143. Service->StartError != ERROR_NOT_SAFEBOOT_SERVICE)
  1144. {
  1145. ScLogEvent(
  1146. NEVENT_SERVICE_START_FAILED,
  1147. Service->DisplayName,
  1148. Service->StartError
  1149. );
  1150. ScPopupStartFail = TRUE;
  1151. }
  1152. }
  1153. }
  1154. }
  1155. else if (Service->StartState == SC_START_PENDING) {
  1156. //
  1157. // We need to wait for this pending service to be completely
  1158. // started if:
  1159. // 1) We are auto-starting services in sequence;
  1160. // ServiceToStart == NULL
  1161. // 2) We are demand starting ServiceToStart and
  1162. // it depends on services that are currently
  1163. // start-pending
  1164. //
  1165. // We don't wait if the pending service is started by demand
  1166. // and is unrelated in the start sequence of ServiceToStart,
  1167. // or it is ServiceToStart itself.
  1168. //
  1169. if ((Service != ServiceToStart) &&
  1170. ScServiceToStartDependOn(ServiceToStart, Service))
  1171. {
  1172. SC_LOG3(DEPEND, FORMAT_LPWSTR " is still PENDING "
  1173. "(chkpt %lu, wait hint %lu ms)\n",
  1174. Service->ServiceName,
  1175. Service->ServiceStatus.dwCheckPoint,
  1176. Service->ServiceStatus.dwWaitHint);
  1177. //
  1178. // If a service makes some hokey state changes, it will be
  1179. // stuck in the SC_START_PENDING state, which means that we'll
  1180. // loop/wait forever. Correct things if the service is in a
  1181. // "confused" state. Note that this can happen for a service
  1182. // that goes from SERVICE_START_PENDING to anything other
  1183. // than SERVICE_RUNNING, SERVICE_STOPPED, or SERVICE_STOP_PENDING
  1184. // (and can then change to one of those three states without
  1185. // causing the state-change event to be set)
  1186. //
  1187. //
  1188. // Get the state of the pending service
  1189. //
  1190. {
  1191. CServiceRecordSharedLock RLock;
  1192. ServiceCurrentState = Service->ServiceStatus.dwCurrentState;
  1193. }
  1194. switch (ServiceCurrentState)
  1195. {
  1196. case SERVICE_START_PENDING:
  1197. IsStartPending = TRUE;
  1198. ExistsBlockedService = TRUE;
  1199. AllStarted = FALSE;
  1200. break;
  1201. case SERVICE_STOP_PENDING:
  1202. case SERVICE_PAUSED:
  1203. case SERVICE_CONTINUE_PENDING:
  1204. case SERVICE_PAUSE_PENDING:
  1205. case SERVICE_RUNNING:
  1206. Service->StartState = SC_START_SUCCESS;
  1207. break;
  1208. case SERVICE_STOPPED:
  1209. Service->StartState = SC_START_FAIL;
  1210. break;
  1211. default:
  1212. SC_LOG1(ERROR,
  1213. "Unexpected service state %x\n",
  1214. ServiceCurrentState);
  1215. SC_ASSERT(FALSE);
  1216. Service->StartState = SC_START_FAIL;
  1217. }
  1218. }
  1219. }
  1220. } // for every service
  1221. //
  1222. // Only wait for services to finish starting if:
  1223. // the services are auto-started at boot
  1224. // the services are required to be running before a service that
  1225. // is demand-started can run.
  1226. //
  1227. if (IsStartPending && (ExistsBlockedService || WaitForAll))
  1228. {
  1229. SC_LOG0(DEPEND, "About to wait on ScServiceChangeEvent\n");
  1230. //
  1231. // ScServiceChangeStateEvent is signalled by RSetServiceStatus whenever
  1232. // a service changes its state from SERVICE_START_PENDING to
  1233. // SERVICE_RUNNING or SERVICE_STOPPED.
  1234. //
  1235. Error = WaitForSingleObject(
  1236. ScServiceChangeStateEvent,
  1237. SERVICE_START_TIMEOUT
  1238. );
  1239. if (Error == WAIT_TIMEOUT)
  1240. {
  1241. //
  1242. // Go through all services and see if any one has hung
  1243. // while starting.
  1244. //
  1245. ScLookForHungServices();
  1246. }
  1247. else if (Error == 0)
  1248. {
  1249. //
  1250. // Reset ScServiceChangeStateEvent to non-signalled state
  1251. //
  1252. if (!ResetEvent(ScServiceChangeStateEvent))
  1253. {
  1254. Error = GetLastError();
  1255. //
  1256. // This is a serious error--we cannot proceed.
  1257. //
  1258. SC_LOG1(ERROR, "Error reseting ScServiceChangeStateEvent "
  1259. FORMAT_DWORD "\n", Error);
  1260. ScLogEvent(
  1261. NEVENT_CALL_TO_FUNCTION_FAILED,
  1262. SC_RESET_EVENT,
  1263. Error
  1264. );
  1265. return Error;
  1266. }
  1267. }
  1268. else if (Error == 0xffffffff)
  1269. {
  1270. //
  1271. // An error has occurred
  1272. //
  1273. SC_LOG1(ERROR,
  1274. "Wait for ScServiceChangeStateEvent returned %d\n",
  1275. GetLastError());
  1276. SC_ASSERT(FALSE);
  1277. }
  1278. }
  1279. else if ((AllStarted && ExistsBlockedService) || IsBadDependencies)
  1280. {
  1281. //
  1282. // Circular dependencies!
  1283. //
  1284. SC_LOG0(ERROR, "Detected circular dependencies!!\n");
  1285. SC_LOG3(ERROR,
  1286. "AllStarted=" FORMAT_DWORD
  1287. ", ExistsBlockedService=" FORMAT_DWORD
  1288. ", IsBadDependencies=" FORMAT_DWORD "\n",
  1289. (DWORD) AllStarted, (DWORD) ExistsBlockedService,
  1290. (DWORD) IsBadDependencies);
  1291. if (ARGUMENT_PRESENT(ServiceToStart))
  1292. {
  1293. SC_LOG1(ERROR, " Demand starting " FORMAT_LPWSTR "\n",
  1294. ServiceToStart->DisplayName);
  1295. ScLogEvent(
  1296. NEVENT_CIRCULAR_DEPENDENCY_DEMAND,
  1297. ServiceToStart->DisplayName
  1298. );
  1299. }
  1300. else
  1301. {
  1302. SC_LOG0(ERROR, " Auto-starting services\n");
  1303. ScLogEvent(NEVENT_CIRCULAR_DEPENDENCY_AUTO);
  1304. ScHandleBadDependencies();
  1305. }
  1306. return ERROR_CIRCULAR_DEPENDENCY;
  1307. }
  1308. }
  1309. while (! AllStarted);
  1310. return NO_ERROR;
  1311. }
  1312. VOID
  1313. ScHandleServiceFailure(
  1314. IN LPSERVICE_RECORD Service
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. This function checks to see if the specified service failed to start.
  1319. If so, it clears the SERVICE_START_NOW flag, and determine if we
  1320. have to revert to last-known-good.
  1321. Arguments:
  1322. Service - Supplies a pointer to the service record to examine if
  1323. the service failed to start.
  1324. Return Value:
  1325. None.
  1326. --*/
  1327. {
  1328. if (Service->StartState == SC_START_FAIL) {
  1329. //
  1330. // Revert to last-known-good only if service is auto-start and
  1331. // fail to start due to reasons other than failure to logon.
  1332. //
  1333. if ((Service->ErrorControl == SERVICE_ERROR_SEVERE ||
  1334. Service->ErrorControl == SERVICE_ERROR_CRITICAL) &&
  1335. CURRENTSTART_FLAG_IS_SET(Service) &&
  1336. Service->StartError != ERROR_SERVICE_LOGON_FAILED) {
  1337. SC_LOG1(DEPEND,
  1338. "ScHandleServiceFailure: "
  1339. "About to call ScRevertToLastKnownGood for " FORMAT_LPWSTR
  1340. "\n", Service->ServiceName);
  1341. (void) ScRevertToLastKnownGood();
  1342. }
  1343. }
  1344. }
  1345. BOOL
  1346. ScDependenciesStarted(
  1347. IN LPSERVICE_RECORD Service,
  1348. OUT BOOL *IsBadDependencies,
  1349. OUT BOOL *AllStarted,
  1350. OUT BOOL *ExistsBlockedService
  1351. )
  1352. /*++
  1353. Routine Description:
  1354. This function checks to see if the dependencies of the specified
  1355. service are all started. If any of the dependencies has failed to
  1356. start, the specified service will be marked as failed to start.
  1357. If any of the dependencies is not marked as starting now (because
  1358. they are demand-start services), they are marked to be started now.
  1359. Arguments:
  1360. Service - Supplies a pointer to the service which we want to check
  1361. the start dependencies.
  1362. IsBadDependencies - Receives the value of TRUE if the service we
  1363. depend on belongs in a group that starts after the group we
  1364. are in. Otherwise, FALSE is returned.
  1365. AllStarted - Receives the value of FALSE if we have marked
  1366. a service as failed to be started because its dependent
  1367. didn't start. This means that our job of starting all services is
  1368. not done and we have to loop through an additional time to resolve
  1369. the state of any service that is dependent on it.
  1370. ExistsBlockedService - Receives the value of TRUE if a dependent
  1371. is not started or not failed to start. This indicates that
  1372. the specified service is still blocked from starting.
  1373. Return Value:
  1374. TRUE - if all dependencies have already been started successfully.
  1375. FALSE - if there exists one dependency that has not started or failed
  1376. to start.
  1377. --*/
  1378. {
  1379. BOOL AllDependenciesStarted = TRUE;
  1380. LPDEPEND_RECORD DependEntry;
  1381. LPSERVICE_RECORD DependService;
  1382. LPLOAD_ORDER_GROUP DependGroup;
  1383. DWORD GroupState;
  1384. for (DependEntry = Service->StartDepend;
  1385. DependEntry != NULL;
  1386. DependEntry = DependEntry->Next)
  1387. {
  1388. switch (DependEntry->DependType)
  1389. {
  1390. case TypeDependOnUnresolved:
  1391. //
  1392. // Error with service setup because it depends on a group or
  1393. // service which does not exists
  1394. //
  1395. SC_LOG2(ERROR, FORMAT_LPWSTR " depends on non-existing " FORMAT_LPWSTR
  1396. "\n", Service->DisplayName,
  1397. DependEntry->DependUnresolved->Name);
  1398. if (Service->ErrorControl != SERVICE_ERROR_IGNORE)
  1399. {
  1400. ScLogEvent(
  1401. NEVENT_SERVICE_START_FAILED_NONE,
  1402. Service->DisplayName,
  1403. DependEntry->DependUnresolved->Name
  1404. );
  1405. }
  1406. ScCleanupStartFailure(Service, ERROR_SERVICE_DEPENDENCY_DELETED);
  1407. *AllStarted = FALSE;
  1408. return FALSE;
  1409. case TypeDependOnService:
  1410. //
  1411. // Depend on a service
  1412. //
  1413. DependService = DependEntry->DependService;
  1414. //
  1415. // If dependency service already failed to start, the current service
  1416. // is set as failed to start.
  1417. //
  1418. if (DependService->StartState == SC_START_FAIL)
  1419. {
  1420. DWORD dwError;
  1421. SC_LOG3(ERROR, FORMAT_LPWSTR " depends on " FORMAT_LPWSTR
  1422. " which failed to start because " FORMAT_DWORD "\n",
  1423. Service->DisplayName, DependService->DisplayName,
  1424. (DependService->StartError != NO_ERROR) ?
  1425. DependService->StartError :
  1426. DependService->ServiceStatus.dwWin32ExitCode);
  1427. if (Service->ErrorControl != SERVICE_ERROR_IGNORE
  1428. &&
  1429. DependService->StartError != ERROR_NOT_SAFEBOOT_SERVICE
  1430. &&
  1431. !SetupInProgress(NULL, NULL))
  1432. {
  1433. ScLogEvent(
  1434. NEVENT_SERVICE_START_FAILED_II,
  1435. Service->DisplayName,
  1436. DependService->DisplayName,
  1437. DependService->StartError != NO_ERROR ?
  1438. DependService->StartError : DependService->ServiceStatus.dwWin32ExitCode
  1439. );
  1440. }
  1441. dwError = ERROR_NOT_SAFEBOOT_SERVICE;
  1442. //
  1443. // Walk through the list of service dependencies and pick
  1444. // the more appropriate error code. Do this to avoid
  1445. // reporting ERROR_SERVICE_DEPENDENCY_FAIL on auto-start
  1446. // and ERROR_NOT_SAFEBOOT_SERVICE on demand-start for the
  1447. // same service.
  1448. //
  1449. for (DependEntry = Service->StartDepend;
  1450. DependEntry != NULL;
  1451. DependEntry = DependEntry->Next)
  1452. {
  1453. if (DependEntry->DependType == TypeDependOnService
  1454. &&
  1455. DependEntry->DependService->StartError
  1456. != ERROR_NOT_SAFEBOOT_SERVICE)
  1457. {
  1458. //
  1459. // There was a "real" start failure
  1460. //
  1461. dwError = ERROR_SERVICE_DEPENDENCY_FAIL;
  1462. break;
  1463. }
  1464. }
  1465. ScCleanupStartFailure(Service, dwError);
  1466. *AllStarted = FALSE;
  1467. return FALSE;
  1468. }
  1469. if (DependService->StartState == SC_NEVER_STARTED)
  1470. {
  1471. *IsBadDependencies = IsDependOnLaterGroup(
  1472. Service->MemberOfGroup,
  1473. DependService->MemberOfGroup,
  1474. TypeDependOnService
  1475. );
  1476. if (*IsBadDependencies) {
  1477. //
  1478. // Circular dependency!
  1479. //
  1480. SC_LOG1(ERROR, "Circular dependency! " FORMAT_LPWSTR
  1481. " depends on service in a group which starts later\n",
  1482. Service->DisplayName);
  1483. if (Service->ErrorControl != SERVICE_ERROR_IGNORE)
  1484. {
  1485. ScLogEvent(
  1486. NEVENT_DEPEND_ON_LATER_SERVICE,
  1487. Service->DisplayName);
  1488. }
  1489. ScCleanupStartFailure(Service, ERROR_CIRCULAR_DEPENDENCY);
  1490. return FALSE;
  1491. }
  1492. //
  1493. // No circular dependency. Mark the dependency service
  1494. // as START_NOW.
  1495. //
  1496. DependService->StartState = SC_START_NOW;
  1497. DependService->StartError = NO_ERROR;
  1498. *AllStarted = FALSE;
  1499. }
  1500. //
  1501. // Get the current state of the dependency service
  1502. //
  1503. if (DependService->StartState != SC_START_SUCCESS)
  1504. {
  1505. AllDependenciesStarted = FALSE;
  1506. if (DependService->StartState != SC_START_FAIL)
  1507. {
  1508. //
  1509. // The current service is still blocked.
  1510. //
  1511. *ExistsBlockedService = TRUE;
  1512. }
  1513. }
  1514. break;
  1515. case TypeDependOnGroup:
  1516. //
  1517. // Depend on a group
  1518. //
  1519. DependGroup = DependEntry->DependGroup;
  1520. GroupState = ScGetCurrentGroupState(DependGroup);
  1521. switch (GroupState)
  1522. {
  1523. case GROUP_START_FAIL:
  1524. SC_LOG2(ERROR, FORMAT_LPWSTR " depends on failed group "
  1525. FORMAT_LPWSTR "\n", Service->DisplayName,
  1526. DependGroup->GroupName);
  1527. if (Service->ErrorControl != SERVICE_ERROR_IGNORE
  1528. &&
  1529. !g_SafeBootEnabled
  1530. &&
  1531. !SetupInProgress(NULL, NULL))
  1532. {
  1533. ScLogEvent(
  1534. NEVENT_SERVICE_START_FAILED_GROUP,
  1535. Service->DisplayName,
  1536. DependGroup->GroupName
  1537. );
  1538. }
  1539. ScCleanupStartFailure(Service, ERROR_SERVICE_DEPENDENCY_FAIL);
  1540. *AllStarted = FALSE;
  1541. return FALSE;
  1542. case GROUP_NOT_STARTED:
  1543. *IsBadDependencies = IsDependOnLaterGroup(
  1544. Service->MemberOfGroup,
  1545. DependGroup,
  1546. TypeDependOnGroup
  1547. );
  1548. if (*IsBadDependencies) {
  1549. //
  1550. // Circular dependency!
  1551. //
  1552. SC_LOG1(ERROR, "Circular dependency! " FORMAT_LPWSTR
  1553. " depends on a group which starts later\n",
  1554. Service->DisplayName);
  1555. if (Service->ErrorControl != SERVICE_ERROR_IGNORE)
  1556. {
  1557. ScLogEvent(
  1558. NEVENT_DEPEND_ON_LATER_GROUP,
  1559. Service->DisplayName
  1560. );
  1561. }
  1562. ScCleanupStartFailure(Service, ERROR_CIRCULAR_DEPENDENCY);
  1563. return FALSE;
  1564. }
  1565. //
  1566. // No circular dependency. Mark the services in the
  1567. // dependency group to START_NOW.
  1568. //
  1569. {
  1570. FOR_SERVICES_THAT(Svc,
  1571. BELONGS_TO(Svc, DependGroup) &&
  1572. Svc->StartState == SC_NEVER_STARTED)
  1573. {
  1574. Svc->StartState = SC_START_NOW;
  1575. Svc->StartError = NO_ERROR;
  1576. }
  1577. }
  1578. AllDependenciesStarted = FALSE;
  1579. *ExistsBlockedService = TRUE;
  1580. break;
  1581. default:
  1582. //
  1583. // Otherwise group must be started. Nothing to do.
  1584. //
  1585. SC_ASSERT(GroupState == GROUP_ONE_STARTED);
  1586. break;
  1587. }
  1588. break;
  1589. }
  1590. }
  1591. return AllDependenciesStarted;
  1592. }
  1593. BOOL
  1594. IsDependOnLaterGroup(
  1595. IN LPLOAD_ORDER_GROUP ServiceGroup,
  1596. IN LPLOAD_ORDER_GROUP DependOnGroup,
  1597. IN DEPEND_TYPE DependType
  1598. )
  1599. {
  1600. LPLOAD_ORDER_GROUP Group;
  1601. switch (DependType)
  1602. {
  1603. case TypeDependOnService:
  1604. if (ServiceGroup == DependOnGroup) {
  1605. //
  1606. // It is OK for a service to depend on another service
  1607. // in the same group.
  1608. //
  1609. return FALSE;
  1610. }
  1611. break;
  1612. case TypeDependOnGroup:
  1613. if (IS_SUBGROUP(ServiceGroup, DependOnGroup)) {
  1614. //
  1615. // It is circular dependency if a service depends on the
  1616. // group it itself belongs to
  1617. //
  1618. return TRUE;
  1619. }
  1620. break;
  1621. default:
  1622. SC_LOG(ERROR, "IsDependOnLaterGroup: got invalid DependType %lu\n",
  1623. DependType);
  1624. SC_ASSERT(FALSE);
  1625. return FALSE;
  1626. }
  1627. if (ServiceGroup == NULL ||
  1628. ServiceGroup->RefCount != MAXULONG ||
  1629. DependOnGroup == NULL ||
  1630. DependOnGroup->RefCount != MAXULONG) {
  1631. //
  1632. // Service we are starting belongs to a standalone group,
  1633. // or service or group we depend on is standalone.
  1634. //
  1635. return FALSE;
  1636. }
  1637. //
  1638. // Both the service's group and the depended on group are in the
  1639. // load order group list.
  1640. // The depended on group must not occur after the service's group.
  1641. // TDI GROUP SPECIAL: Also, if the depended on group is the TDI
  1642. // group, then there is an implicit dependency on the PNP_TDI group,
  1643. // so that must not occur after the service's group either.
  1644. //
  1645. for (Group = ServiceGroup->Next;
  1646. Group != NULL;
  1647. Group = Group->Next)
  1648. {
  1649. if (IS_SUBGROUP(Group, DependOnGroup)) {
  1650. return TRUE;
  1651. }
  1652. }
  1653. return FALSE;
  1654. }
  1655. VOID
  1656. ScCleanupStartFailure(
  1657. LPSERVICE_RECORD Service,
  1658. DWORD StartError
  1659. )
  1660. {
  1661. Service->StartState = SC_START_FAIL;
  1662. Service->StartError = StartError;
  1663. //
  1664. // Clear ERROR_SERVICE_NEVER_STARTED in the Win32ExitCode field if
  1665. // service failed to start.
  1666. //
  1667. CServiceRecordExclusiveLock RLock;
  1668. if (Service->ServiceStatus.dwWin32ExitCode ==
  1669. ERROR_SERVICE_NEVER_STARTED) {
  1670. Service->ServiceStatus.dwWin32ExitCode = StartError;
  1671. }
  1672. //
  1673. // For popup after user has logged on to indicate that some
  1674. // service started at boot has failed.
  1675. //
  1676. if (Service->ErrorControl != SERVICE_ERROR_IGNORE) {
  1677. ScPopupStartFail = TRUE;
  1678. }
  1679. }
  1680. VOID
  1681. ScLookForHungServices(
  1682. VOID
  1683. )
  1684. /*++
  1685. Routine Description:
  1686. This function loops through all services and queries the status
  1687. of each service that is start pending. It waits for the service to
  1688. show signs of progress in starting by waiting for the wait-hint
  1689. amount of time (in millisecs), and if the service is still start
  1690. pending and checkpoint has not incremented, the service's exitcode
  1691. is set to ERROR_SERVICE_START_HANG.
  1692. Arguments:
  1693. None.
  1694. Return Value:
  1695. None.
  1696. --*/
  1697. {
  1698. DWORD status;
  1699. SERVICE_STATUS CurrentServiceStatus;
  1700. STATUS_UNION ServiceStatus;
  1701. DWORD OldCheckPoint;
  1702. FOR_SERVICES_THAT(Service, Service->StartState == SC_START_PENDING)
  1703. {
  1704. ServiceStatus.Regular = &CurrentServiceStatus;
  1705. status = ScQueryServiceStatus(
  1706. Service,
  1707. ServiceStatus,
  1708. FALSE
  1709. );
  1710. if ((status == NO_ERROR) &&
  1711. (CurrentServiceStatus.dwCurrentState == SERVICE_START_PENDING)) {
  1712. #define SC_POLL_FACTOR 10
  1713. #define SC_MAX_SLEEP_TIME 10000
  1714. DWORD SleepTime = 1;
  1715. DWORD i;
  1716. DWORD NumIterations;
  1717. OldCheckPoint = CurrentServiceStatus.dwCheckPoint;
  1718. //
  1719. // Set up for the loop where we will poll the service status.
  1720. // The maximum sleep time during this polling operation will
  1721. // be 10 seconds.
  1722. //
  1723. //
  1724. // If the wait hint is greater than 100 seconds, then
  1725. // we want to modify the number of iterations through the
  1726. // loop so that we only sleep for the MAX_SLEEP_TIME.
  1727. //
  1728. // If the wait hint is less than that, then we change the
  1729. // sleep time to be less than 10 seconds, so that we go
  1730. // through the loop a max of 10 times.
  1731. //
  1732. if (CurrentServiceStatus.dwWaitHint > 100000) {
  1733. NumIterations = CurrentServiceStatus.dwWaitHint / SC_MAX_SLEEP_TIME;
  1734. SleepTime = SC_MAX_SLEEP_TIME;
  1735. }
  1736. else {
  1737. NumIterations = SC_POLL_FACTOR;
  1738. if (CurrentServiceStatus.dwWaitHint > SC_POLL_FACTOR) {
  1739. SleepTime = CurrentServiceStatus.dwWaitHint / SC_POLL_FACTOR;
  1740. }
  1741. }
  1742. for (i = 0; i < NumIterations; i++) {
  1743. //
  1744. // Wait a while for the checkpoint to increment, or
  1745. // service to be out of start-pending state.
  1746. //
  1747. Sleep(SleepTime);
  1748. status = ScQueryServiceStatus(
  1749. Service,
  1750. ServiceStatus,
  1751. FALSE
  1752. );
  1753. if (status == NO_ERROR) {
  1754. if (CurrentServiceStatus.dwCurrentState != SERVICE_START_PENDING ||
  1755. (CurrentServiceStatus.dwCurrentState == SERVICE_START_PENDING &&
  1756. OldCheckPoint < CurrentServiceStatus.dwCheckPoint)) {
  1757. goto NextService;
  1758. }
  1759. }
  1760. SC_LOG2(DEPEND, " Wait %ld on %ws for response\n", i + 1,
  1761. Service->ServiceName);
  1762. }
  1763. if ((status == NO_ERROR) &&
  1764. (CurrentServiceStatus.dwCurrentState == SERVICE_START_PENDING) &&
  1765. (OldCheckPoint == CurrentServiceStatus.dwCheckPoint)) {
  1766. SC_LOG2(ERROR, "%ws hung on starting (wait hint %lu ms)\n",
  1767. Service->ServiceName,
  1768. CurrentServiceStatus.dwWaitHint);
  1769. if (Service->ErrorControl != SERVICE_ERROR_IGNORE)
  1770. {
  1771. ScLogEvent(
  1772. NEVENT_SERVICE_START_HUNG,
  1773. Service->DisplayName
  1774. );
  1775. }
  1776. ScCleanupStartFailure(Service, ERROR_SERVICE_START_HANG);
  1777. }
  1778. }
  1779. if (status != NO_ERROR) {
  1780. SC_LOG2(ERROR, "ScLookForHungService: ScQueryServiceStatus "
  1781. FORMAT_LPWSTR " failed " FORMAT_DWORD "\n",
  1782. Service->ServiceName, status);
  1783. Service->StartState = SC_START_FAIL;
  1784. Service->StartError = ERROR_GEN_FAILURE;
  1785. }
  1786. NextService:
  1787. ;
  1788. }
  1789. }
  1790. VOID
  1791. ScHandleBadDependencies(
  1792. VOID
  1793. )
  1794. /*++
  1795. Routine Description:
  1796. This function is called when a circular dependency is detected.
  1797. Arguments:
  1798. None.
  1799. Return Value:
  1800. None.
  1801. --*/
  1802. {
  1803. FOR_SERVICES_THAT(Service,
  1804. (Service->StartState == SC_START_NOW) &&
  1805. (Service->ErrorControl == SERVICE_ERROR_SEVERE ||
  1806. Service->ErrorControl == SERVICE_ERROR_CRITICAL) )
  1807. {
  1808. SC_LOG1(ERROR, "ScHandleBadDependencies: "
  1809. "About to call ScRevertToLastKnownGood for "
  1810. FORMAT_LPWSTR "\n", Service->DisplayName);
  1811. ScLogEvent(
  1812. NEVENT_SEVERE_SERVICE_FAILED,
  1813. Service->DisplayName
  1814. );
  1815. ScRevertToLastKnownGood();
  1816. }
  1817. }
  1818. BOOL
  1819. ScServiceToStartDependOn(
  1820. LPSERVICE_RECORD ServiceToStart OPTIONAL,
  1821. LPSERVICE_RECORD StartPendingService
  1822. )
  1823. /*++
  1824. Routine Description:
  1825. This function is called by ScStartMarkedServices (BIG LOOP) to determine
  1826. if we have to wait for a pending service to complete.
  1827. If ServiceToStart == NULL, we are auto-starting service and we always
  1828. want to wait.
  1829. If ServiceToStart is not NULL, we are demand starting a service.
  1830. We have to wait if ServiceToStart depends on the StartPendingService.
  1831. Arguments:
  1832. ServiceToStart - Supplies the service record pointer of the service
  1833. being demand started.
  1834. StartPendingService - Supplies the service record pointer of the
  1835. service that is currently start pending.
  1836. Return Value:
  1837. TRUE - If ServiceToStart depends on StartPendingService or
  1838. ServiceToStart == NULL.
  1839. FALSE - Otherwise.
  1840. --*/
  1841. {
  1842. if (! ARGUMENT_PRESENT(ServiceToStart)) {
  1843. return TRUE;
  1844. }
  1845. if (ServiceToStart->StartState == SC_START_FAIL) {
  1846. return FALSE;
  1847. }
  1848. if (CURRENTSTART_FLAG_IS_SET(StartPendingService)) {
  1849. SC_LOG2(DEPEND_DUMP, "Service %ws directly/indirectly depends on pending service %ws\n",
  1850. ServiceToStart->ServiceName,
  1851. StartPendingService->ServiceName);
  1852. return TRUE;
  1853. }
  1854. SC_LOG(DEPEND_DUMP, "ScServiceToStartDependOn: Won't wait for pending "
  1855. FORMAT_LPWSTR "\n", StartPendingService->ServiceName);
  1856. return FALSE;
  1857. }
  1858. VOID
  1859. ScNotifyChangeState(
  1860. VOID
  1861. )
  1862. /*++
  1863. Routine Description:
  1864. This function is called by RSetServiceStatus which a service state
  1865. changes from start-pending to running or stopped. This will
  1866. notify the thread processing start dependencies that we can
  1867. proceed with starting up services that depend on the one that
  1868. called RSetServiceStatus.
  1869. Arguments:
  1870. None.
  1871. Return Value:
  1872. None.
  1873. --*/
  1874. {
  1875. if (! SetEvent(ScServiceChangeStateEvent)) {
  1876. SC_LOG1(ERROR, "ScNotifyChangeState: SetEvent error " FORMAT_DWORD "\n",
  1877. GetLastError());
  1878. SC_ASSERT(FALSE);
  1879. }
  1880. }
  1881. BOOL
  1882. ScDependentsStopped(
  1883. IN LPSERVICE_RECORD ServiceToStop
  1884. )
  1885. /*++
  1886. Routine Description:
  1887. This function checks to see if any service which depends on the
  1888. specified service is active. If so, it returns FALSE, otherwise
  1889. if no service depends on the specified service, or all services
  1890. which depend on the specified service is stopped, it returns
  1891. TRUE.
  1892. A service which is not in SERVICE_STOPPED is considered active.
  1893. Arguments:
  1894. ServiceToStop - Supplies a pointer to the service to see if other
  1895. active services depend on it.
  1896. Return Value:
  1897. TRUE - if all services which depend on ServiceToStop are stopped,
  1898. or there are no services which depend on ServiceToStop.
  1899. FALSE - if one or more of the services which depend on ServiceToStop
  1900. is active.
  1901. Note:
  1902. The database lock must be acquired with share access before calling
  1903. this routine.
  1904. --*/
  1905. {
  1906. SC_ASSERT(ScServiceRecordLock.Have());
  1907. LPDEPEND_RECORD StopDepend;
  1908. for (StopDepend = ServiceToStop->StopDepend;
  1909. StopDepend != NULL;
  1910. StopDepend = StopDepend->Next)
  1911. {
  1912. if (StopDepend->DependService->ServiceStatus.dwCurrentState
  1913. != SERVICE_STOPPED) {
  1914. SC_LOG1(DEPEND, FORMAT_LPWSTR " is still ACTIVE\n",
  1915. StopDepend->DependService->ServiceName);
  1916. return FALSE;
  1917. }
  1918. SC_LOG1(DEPEND, FORMAT_LPWSTR " is STOPPED\n",
  1919. StopDepend->DependService->ServiceName);
  1920. }
  1921. return TRUE;
  1922. }
  1923. VOID
  1924. ScEnumDependents(
  1925. IN LPSERVICE_RECORD ServiceRecord,
  1926. IN LPENUM_SERVICE_STATUS_WOW64 EnumBuffer,
  1927. IN DWORD RequestedState,
  1928. IN OUT LPDWORD EntriesRead,
  1929. IN OUT LPDWORD BytesNeeded,
  1930. IN OUT LPENUM_SERVICE_STATUS_WOW64 *EnumRecord,
  1931. IN OUT LPWSTR *EndOfVariableData,
  1932. IN OUT LPDWORD Status
  1933. )
  1934. /*++
  1935. Routine Description:
  1936. This function enumerates the stop depend list of the specified
  1937. service in the order which the dependents should be stopped.
  1938. Arguments:
  1939. ServiceRecord - Supplies a pointer to the service whose dependents
  1940. are to be enumerated.
  1941. EnumBuffer - Supplies a pointer to the first byte of the enum
  1942. buffer we are writing to. This is for duplicate entry checking.
  1943. RequestedState - Supplies one or the bitwise or of SERVICE_ACTIVE
  1944. and SERVICE_INACTIVE.
  1945. BytesNeeded - Supplies a pointer to a variable to receive the
  1946. running sum of bytes needed to enumerate all the entries.
  1947. EnumRecord - Supplies a pointer into the next location in the
  1948. output buffer to receive the next entry. The pointer is
  1949. updated on return.
  1950. EndOfVariableData - Supplies a pointer past the last available
  1951. byte in the output buffer so that variable length data
  1952. can be written from the end of the buffer. This pointer is
  1953. updated on return.
  1954. Status - Receives ERROR_MORE_DATA if dependent services does not
  1955. entirely fit in the output buffer. It should be initialized
  1956. to NO_ERROR this function is called.
  1957. Return Value:
  1958. None.
  1959. Note:
  1960. The database lock must be acquired with share access before calling
  1961. this routine.
  1962. --*/
  1963. {
  1964. SC_ASSERT(ScServiceRecordLock.Have());
  1965. LPDEPEND_RECORD StopDepend;
  1966. for (StopDepend = ServiceRecord->StopDepend;
  1967. StopDepend != NULL;
  1968. StopDepend = StopDepend->Next)
  1969. {
  1970. if (StopDepend->DependService->StopDepend != NULL) {
  1971. //
  1972. // Stop dependent also have other services that depends on
  1973. // it. Recursively call this routine to enumerate its
  1974. // dependents.
  1975. //
  1976. ScEnumDependents(
  1977. StopDepend->DependService,
  1978. EnumBuffer,
  1979. RequestedState,
  1980. EntriesRead,
  1981. BytesNeeded,
  1982. EnumRecord,
  1983. EndOfVariableData,
  1984. Status
  1985. );
  1986. }
  1987. if (
  1988. ((StopDepend->DependService->ServiceStatus.dwCurrentState
  1989. != SERVICE_STOPPED) &&
  1990. (RequestedState & SERVICE_ACTIVE))
  1991. ||
  1992. ((StopDepend->DependService->ServiceStatus.dwCurrentState
  1993. == SERVICE_STOPPED) &&
  1994. (RequestedState & SERVICE_INACTIVE))
  1995. ) {
  1996. SC_LOG1(DEPEND, "Enumerating dependent " FORMAT_LPWSTR "\n",
  1997. StopDepend->DependService->ServiceName);
  1998. if (! ScFoundDuplicateDependent(
  1999. StopDepend->DependService->ServiceName,
  2000. EnumBuffer,
  2001. *EnumRecord
  2002. )) {
  2003. *BytesNeeded += (sizeof(ENUM_SERVICE_STATUS_WOW64) +
  2004. (DWORD) WCSSIZE(StopDepend->DependService->ServiceName) +
  2005. (DWORD) WCSSIZE(StopDepend->DependService->DisplayName));
  2006. if (*Status == NO_ERROR) {
  2007. if (((DWORD_PTR) *EnumRecord + sizeof(ENUM_SERVICE_STATUS_WOW64)) >=
  2008. (DWORD_PTR) *EndOfVariableData) {
  2009. *Status = ERROR_MORE_DATA;
  2010. }
  2011. else {
  2012. //
  2013. // Write the entry into output buffer
  2014. //
  2015. memcpy(
  2016. (PVOID) &((*EnumRecord)->ServiceStatus),
  2017. (PVOID) &(StopDepend->DependService->ServiceStatus),
  2018. sizeof(SERVICE_STATUS)
  2019. );
  2020. //
  2021. // Copy the ServiceName string data
  2022. //
  2023. if (! ScCopyStringToBufferW(
  2024. StopDepend->DependService->ServiceName,
  2025. (DWORD) wcslen(StopDepend->DependService->ServiceName),
  2026. (LPWSTR) (*EnumRecord + 1),
  2027. EndOfVariableData,
  2028. (LPWSTR *) &((*EnumRecord)->dwServiceNameOffset),
  2029. (LPBYTE) EnumBuffer))
  2030. {
  2031. *Status = ERROR_MORE_DATA;
  2032. }
  2033. //
  2034. // Copy the DisplayName string data
  2035. //
  2036. if (! ScCopyStringToBufferW(
  2037. StopDepend->DependService->DisplayName,
  2038. (DWORD) wcslen(StopDepend->DependService->DisplayName),
  2039. (LPWSTR) ((*EnumRecord) + 1),
  2040. EndOfVariableData,
  2041. (LPWSTR *) &((*EnumRecord)->dwDisplayNameOffset),
  2042. (LPBYTE) EnumBuffer))
  2043. {
  2044. *Status = ERROR_MORE_DATA;
  2045. }
  2046. }
  2047. if (*Status == NO_ERROR) {
  2048. (*EnumRecord)++;
  2049. (*EntriesRead)++;
  2050. SC_LOG0(DEPEND, " Written into buffer successfully\n");
  2051. }
  2052. else {
  2053. SC_LOG0(DEPEND, " Failed to fit into buffer\n");
  2054. }
  2055. } // *Status is still NO_ERROR
  2056. } // non-duplicate entry
  2057. }
  2058. }
  2059. }
  2060. BOOL
  2061. ScFoundDuplicateDependent(
  2062. IN LPWSTR ServiceName,
  2063. IN LPENUM_SERVICE_STATUS_WOW64 EnumBuffer,
  2064. IN LPENUM_SERVICE_STATUS_WOW64 BufferEnd
  2065. )
  2066. /*++
  2067. Routine Description:
  2068. This function looks at service entries written to EnumBuffer for
  2069. any service names that matches the specified ServiceName.
  2070. Arguments:
  2071. ServiceName - Supplies the name of the service to look for.
  2072. EnumBuffer - Supplies a pointer to the buffer to look for matching
  2073. service name.
  2074. BufferEnd - Supplies a pointer to the end of buffer.
  2075. Return Value:
  2076. TRUE - if found a matching service name.
  2077. FALSE - no matching service name found.
  2078. --*/
  2079. {
  2080. LPENUM_SERVICE_STATUS_WOW64 EnumEntry;
  2081. for (EnumEntry = EnumBuffer;
  2082. EnumEntry < BufferEnd;
  2083. EnumEntry++)
  2084. {
  2085. if (_wcsicmp((LPWSTR) ((LPBYTE) EnumEntry + EnumEntry->dwServiceNameOffset),
  2086. ServiceName) == 0)
  2087. {
  2088. return TRUE;
  2089. }
  2090. }
  2091. return FALSE;
  2092. }
  2093. #ifndef _CAIRO_
  2094. VOID
  2095. ScCheckNetLogonDepend(
  2096. LPSERVICE_RECORD ServiceRecord,
  2097. BOOL DemandStarting
  2098. )
  2099. /*++
  2100. Routine Description:
  2101. If the current service is running in a remote account or if we are
  2102. running on an Advanced Server (NtProductLanManNt), then this routine
  2103. makes a (soft) dependency on Netlogon. This dependency is not stored
  2104. in the registry.
  2105. Note that all services with account names that are UPNs will require
  2106. the dependency on Netlogon.
  2107. Arguments:
  2108. ServiceRecord - Pointer to the service record that is to be checked.
  2109. DemandStarting - boolean that indicates if we are demand starting or
  2110. auto starting.
  2111. Return Value:
  2112. none - If something fails within this function, we will just press on
  2113. since there isn't much we can do about it.
  2114. --*/
  2115. {
  2116. DWORD status;
  2117. HKEY ServiceNameKey;
  2118. LPWSTR DomainName;
  2119. BOOL bRemoteAccount=TRUE;
  2120. LPSERVICE_RECORD pNetLogonSR;
  2121. //
  2122. // Open the service name key.
  2123. //
  2124. status = ScOpenServiceConfigKey(
  2125. ServiceRecord->ServiceName,
  2126. KEY_READ,
  2127. FALSE, // Create if missing
  2128. &ServiceNameKey
  2129. );
  2130. if (status != NO_ERROR)
  2131. {
  2132. return;
  2133. }
  2134. //
  2135. // Read the account name from the registry.
  2136. //
  2137. status = ScReadStartName(
  2138. ServiceNameKey,
  2139. &DomainName
  2140. );
  2141. if (status != NO_ERROR || DomainName == NULL)
  2142. {
  2143. ScRegCloseKey(ServiceNameKey);
  2144. return;
  2145. }
  2146. ScRegCloseKey(ServiceNameKey);
  2147. if (_wcsicmp(DomainName, SC_LOCAL_SYSTEM_USER_NAME) == 0)
  2148. {
  2149. //
  2150. // LocalSystem account, we don't need netlogon.
  2151. //
  2152. SC_LOG1(TRACE,"ScCheckNetLogonDepend: %ws Service is LocalSystem!\n",
  2153. ServiceRecord->ServiceName);
  2154. LocalFree(DomainName);
  2155. return;
  2156. }
  2157. else if (wcsncmp(DomainName, L".\\", 2) == 0)
  2158. {
  2159. bRemoteAccount = FALSE;
  2160. SC_LOG1(TRACE,"ScCheckNetLogonDepend: %ws Service has a local domain name\n",
  2161. ServiceRecord->ServiceName);
  2162. }
  2163. else
  2164. {
  2165. //
  2166. // Check for local-only accounts (domain name of NT AUTHORITY). Note
  2167. // that the domain name may be quoted.
  2168. //
  2169. LPWSTR lpTempDomain = DomainName;
  2170. if (*lpTempDomain == '"')
  2171. {
  2172. lpTempDomain++;
  2173. }
  2174. if (_wcsnicmp(lpTempDomain,
  2175. SC_LOCAL_NTAUTH_NAME,
  2176. sizeof(SC_LOCAL_NTAUTH_NAME) / sizeof (WCHAR) - 1) == 0)
  2177. {
  2178. SC_LOG1(TRACE,
  2179. "ScCheckNetLogonDepend: %ws service is LocalService/NetworkService\n",
  2180. ServiceRecord->ServiceName);
  2181. LocalFree(DomainName);
  2182. return;
  2183. }
  2184. }
  2185. LocalFree(DomainName);
  2186. //
  2187. // We know if it runs in a remote account or not.
  2188. // Now we should check the product type. If it is an
  2189. // advanced server, or runs in an remote account, then
  2190. // we need to start NetLogon.
  2191. //
  2192. if ((ScGlobalProductType == NtProductLanManNt) || (bRemoteAccount)) {
  2193. //
  2194. // Get the service record for NetLogon.
  2195. //
  2196. status = ScGetNamedServiceRecord(L"NetLogon", &pNetLogonSR);
  2197. if (status != NO_ERROR) {
  2198. return;
  2199. }
  2200. //
  2201. // If it is already marked to start, then we don't
  2202. // have to do anything right now. If it isn't then
  2203. // we should SetServiceStartRequest and create a
  2204. // dependency.
  2205. //
  2206. if (CURRENTSTART_FLAG_IS_SET(pNetLogonSR)) {
  2207. //
  2208. // CurrentStartRequest of a dependency service is already
  2209. // set to TRUE. Just go on to next dependency.
  2210. //
  2211. SC_LOG2(DEPEND_DUMP, "DependService " FORMAT_LPWSTR
  2212. " CSR=TRUE already, USECOUNT=%lu\n",
  2213. pNetLogonSR->ServiceName,
  2214. pNetLogonSR->UseCount);
  2215. }
  2216. else {
  2217. LPDEPEND_RECORD pDependRecord;
  2218. SC_LOG(WHY, " Will start NetLogon because %ws runs in a remote account, or this is a server\n",
  2219. ServiceRecord->ServiceName);
  2220. ScSetServiceStartRequest(pNetLogonSR,DemandStarting);
  2221. //
  2222. // Add the dependency to the service record and mark it as
  2223. // temporary.
  2224. //
  2225. status = ScCreateDependRecord(TRUE,ServiceRecord,&pDependRecord);
  2226. if (status != NO_ERROR) {
  2227. return;
  2228. }
  2229. pDependRecord->DependType = TypeDependOnService;
  2230. pDependRecord->DependService = pNetLogonSR;
  2231. }
  2232. }
  2233. return;
  2234. }
  2235. #endif // _CAIRO_
  2236. BOOL
  2237. ScInHardwareProfile(
  2238. IN LPCWSTR ServiceName,
  2239. IN ULONG GetDeviceListFlags
  2240. )
  2241. /*++
  2242. Routine Description:
  2243. This function checks whether a specified service is enabled in the
  2244. current hardware profile.
  2245. Arguments:
  2246. Service - Specifies the service of interest.
  2247. GetDeviceListFlags - Specifies any special flags to be passed to
  2248. PNP_GetDeviceList. The CM_GETIDLIST_DONOTGENERATE
  2249. flag indicates that a legacy device instance should
  2250. not be generated for the service.
  2251. Return Value:
  2252. TRUE - if the service is enabled in the current hardware profile, or
  2253. if this cannot be determined.
  2254. FALSE - if the service is disabled in the current hardware profile.
  2255. --*/
  2256. {
  2257. CONFIGRET Status;
  2258. BOOL RetStatus;
  2259. WCHAR Buffer[200]; // default buffer on stack
  2260. WCHAR * pBuffer = Buffer;
  2261. ULONG cchLen;
  2262. LPCWSTR pDeviceID;
  2263. //
  2264. // Allocate a buffer for the list of device instances associated with
  2265. // this service
  2266. //
  2267. Status = PNP_GetDeviceListSize(
  2268. NULL, // hBinding
  2269. ServiceName, // pszFilter
  2270. &cchLen, // list length in wchars
  2271. CM_GETIDLIST_FILTER_SERVICE); // filter is a service name
  2272. if (Status != CR_SUCCESS)
  2273. {
  2274. SC_LOG2(WARNING, "PNP_GetDeviceListSize failed %#lx for service %ws\n",
  2275. Status, ServiceName);
  2276. return TRUE;
  2277. }
  2278. if (cchLen > LENGTH(Buffer))
  2279. {
  2280. SC_LOG2(DEPEND, "PNP_GetDeviceListSize wants a %lu-character buffer for service %ws\n",
  2281. cchLen, ServiceName);
  2282. pBuffer = (WCHAR *) LocalAlloc(0, cchLen * sizeof(WCHAR));
  2283. if (pBuffer == NULL)
  2284. {
  2285. SC_LOG(ERROR, "Couldn't allocate buffer for device list, error %lu\n",
  2286. GetLastError());
  2287. return TRUE;
  2288. }
  2289. }
  2290. else
  2291. {
  2292. cchLen = LENGTH(Buffer);
  2293. }
  2294. //
  2295. // Initialize parameters for PNP_GetDeviceList, the same way as is
  2296. // normally done in the client side of the API
  2297. //
  2298. pBuffer[0] = L'\0';
  2299. //
  2300. // Get the list of device instances that are associated with this service
  2301. //
  2302. // (For legacy services, the PNP manager makes up an artificial device
  2303. // instance; but for PNP-aware services, we could get an empty device list.)
  2304. //
  2305. Status = PNP_GetDeviceList(
  2306. NULL, // binding handle
  2307. ServiceName, // pszFilter
  2308. pBuffer, // buffer for device list
  2309. &cchLen, // buffer length in wchars
  2310. CM_GETIDLIST_FILTER_SERVICE | // filter is a service name
  2311. GetDeviceListFlags // OR with passed in flag
  2312. );
  2313. if (Status != CR_SUCCESS)
  2314. {
  2315. SC_LOG2(ERROR, "PNP_GetDeviceList failed %#lx for service %ws\n",
  2316. Status, ServiceName);
  2317. RetStatus = TRUE;
  2318. goto CleanExit;
  2319. }
  2320. //
  2321. // Get each device instance's config flags. The service is enabled in
  2322. // the current hardware profile if at least one of its devices is enabled.
  2323. //
  2324. for (pDeviceID = pBuffer;
  2325. pDeviceID[0] != L'\0';
  2326. pDeviceID += wcslen(pDeviceID) + 1)
  2327. {
  2328. ULONG ConfigFlags;
  2329. Status = PNP_HwProfFlags(
  2330. NULL, // binding handle
  2331. PNP_GET_HWPROFFLAGS, // action: get, not set
  2332. pDeviceID,
  2333. 0, // which profile: current one
  2334. &ConfigFlags,
  2335. NULL,
  2336. NULL,
  2337. 0,
  2338. 0 // flags, MBZ
  2339. );
  2340. if (Status == CR_SUCCESS)
  2341. {
  2342. if (!(ConfigFlags & (CSCONFIGFLAG_DISABLED |
  2343. CSCONFIGFLAG_DO_NOT_CREATE)))
  2344. {
  2345. //
  2346. // The device is enabled, so the service is enabled
  2347. //
  2348. RetStatus = TRUE;
  2349. goto CleanExit;
  2350. }
  2351. }
  2352. else
  2353. {
  2354. SC_LOG2(ERROR, "PNP_HwProfFlags failed %#lx for device %ws\n",
  2355. Status, pDeviceID);
  2356. }
  2357. }
  2358. RetStatus = FALSE;
  2359. SC_LOG(DEPEND, "The %ws service has no enabled device instances\n"
  2360. " in this hardware profile. Attempts to start\n"
  2361. " it will result in ERROR_SERVICE_DISABLED.\n",
  2362. ServiceName);
  2363. CleanExit:
  2364. if (pBuffer != Buffer)
  2365. {
  2366. LocalFree(pBuffer);
  2367. }
  2368. return RetStatus;
  2369. }