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.

1590 lines
48 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. start.cxx
  5. Abstract:
  6. Contains functions that are required for starting a service.
  7. RStartServiceW
  8. StartImage
  9. InitStartImage
  10. ScInitStartupInfo
  11. EndStartImage
  12. ScAllowInteractiveServices
  13. Author:
  14. Dan Lafferty (danl) 20-Jan-1992
  15. Environment:
  16. User Mode - Calls Win32 and NT native APIs.
  17. Revision History:
  18. 13-Mar-199 jschwart
  19. Use CreateProcessAsUserW for non-LocalSystem services
  20. 06-Apr-1998 jschwart
  21. Change check for Security Process connection -- check to see if
  22. the service being started runs in the process, not if it's NetLogon.
  23. Also clean up WesW from 12-Dec-1997
  24. 10-Mar-1998 jschwart
  25. Allow services to receive control messages for Plug-and-Play events
  26. 12-Dec-1997 WesW
  27. Added support for safe boot
  28. 22-Oct-1997 jschwart
  29. Enable 12-Apr-1995 change for non-_CAIRO_.
  30. 08-Jan-1997 AnirudhS
  31. Fixed miscellaneous synchronization bugs found by new locking
  32. scheme.
  33. 09-Dec-1996 AnirudhS
  34. Added ScInitStartupInfo and ScAllowInteractiveServices, also used
  35. by crash.cxx
  36. 01-Mar-1996 AnirudhS
  37. ScStartImage: Notify the PNP manager when a service is started.
  38. 12-Apr-1995 AnirudhS
  39. Allow services that run under accounts other than LocalSystem to
  40. share processes too.
  41. (_CAIRO_ only)
  42. 21-Feb-1995 AnirudhS
  43. Since CreateProcess now handles quoted exe pathnames, removed the
  44. (buggy) code that had been added to parse them, including
  45. ScParseImagePath.
  46. 08-Sep-1994 Danl
  47. ScLogonAndStartImage: Close the Duplicate token when we are done
  48. with it. This allows logoff notification when the service process
  49. exits.
  50. 30-Aug-1994 Danl
  51. ScParseImagePath: Added this function to look for quotes around the
  52. pathname. The Quotes may be necessary if the path contains a space
  53. character.
  54. 18-Mar-1994 Danl
  55. ScLogonAndStartImage: When starting a service in an account, we now
  56. Impersonate using a duplicate of the token for the service, prior
  57. to calling CreateProcess. This allows us to load executables
  58. whose binaries reside on a remote server.
  59. 20-Oct-1993 Danl
  60. ScStartService: If the NetLogon Service isn't in our database yet,
  61. then we want to check to see if the service to be started is
  62. NetLogon. If it is then we need to init our connection with the
  63. Security Process.
  64. 17-Feb-1993 danl
  65. Must release the database lock around the CreateProcess call so
  66. that dll init routines can call OpenService.
  67. 12-Feb-1993 danl
  68. Move the incrementing of the Service UseCount to
  69. ScActivateServiceRecord. This is because if we fail beyond this
  70. point, we call ScRemoveService to cleanup - but that assumes the
  71. UseCount has already been incremented one for the service itself.
  72. 25-Apr-1992 ritaw
  73. Changed ScStartImage to ScLogonAndStartImage
  74. 20-Jan-1992 danl
  75. created
  76. --*/
  77. //
  78. // Includes
  79. //
  80. #include "precomp.hxx"
  81. extern "C" {
  82. #include <winuserp.h> // STARTF_DESKTOPINHERIT
  83. #include <cfgmgr32.h> // PNP manager functions
  84. #include <pnp.h> // PNP manager functions, server side
  85. #include <cfgmgrp.h> // PNP manager functions, server side, internal
  86. #include <userenv.h> // UnloadUserProfile
  87. }
  88. #include <stdlib.h> // wide character c runtimes.
  89. #include <tstr.h> // Unicode string macros
  90. #include <scconfig.h> // ScGetImageFileName
  91. #include <control.h>
  92. #include <scseclib.h> // ScCreateAndSetSD
  93. #include <svcslib.h> // SvcStartLocalDispatcher
  94. #include <valid.h> // MAX_SERVICE_NAME_LENGTH
  95. #include "depend.h" // ScStartMarkedServices
  96. #include "driver.h" // ScLoadDeviceDriver
  97. #include "account.h" // ScLogonService
  98. #include "start.h" // ScStartService
  99. //
  100. // STATIC DATA
  101. //
  102. CRITICAL_SECTION ScStartImageCriticalSection;
  103. const LPWSTR pszInteractiveDesktop=L"WinSta0\\Default";
  104. //
  105. // LOCAL FUNCTIONS
  106. //
  107. DWORD
  108. ScLogonAndStartImage(
  109. IN LPSERVICE_RECORD ServiceRecord,
  110. IN LPWSTR ImageName,
  111. OUT LPIMAGE_RECORD *ImageRecordPtr
  112. );
  113. VOID
  114. ScProcessHandleIsSignaled(
  115. PVOID pContext,
  116. BOOLEAN fWaitStatus
  117. );
  118. BOOL
  119. ScEqualAccountName(
  120. IN LPWSTR Account1,
  121. IN LPWSTR Account2
  122. );
  123. DWORD
  124. RStartServiceW(
  125. IN SC_RPC_HANDLE hService,
  126. IN DWORD NumArgs,
  127. IN LPSTRING_PTRSW CmdArgs
  128. )
  129. /*++
  130. Routine Description:
  131. This function begins the execution of a service.
  132. Arguments:
  133. hService - A handle which is a pointer to a service handle structure.
  134. dwNumServiceArgs - This indicates the number of argument vectors.
  135. lpServiceArgVectors - This is a pointer to an array of string pointers.
  136. Return Value:
  137. NO_ERROR - The operation was completely successful.
  138. ERROR_ACCESS_DENIED - The specified handle was not opened with
  139. SERVICE_START access.
  140. ERROR_INVALID_HANDLE - The specified handle was invalid.
  141. ERROR_SERVICE_WAS_STARTED - An instance of the service is already running.
  142. ERROR_SERVICE_REQUEST_TIMEOUT - The service did not respond to the start
  143. request in a timely fashion.
  144. ERROR_SERVICE_NO_THREAD - A thread could not be created for the Win32
  145. service.
  146. ERROR_PATH_NOT_FOUND - The image file name could not be found in
  147. the configuration database (registry), or the image file name
  148. failed in a unicode/ansi conversion.
  149. --*/
  150. {
  151. DWORD status;
  152. DWORD i;
  153. LPWSTR *CmdArray;
  154. LPSERVICE_RECORD serviceRecord;
  155. if (ScShutdownInProgress) {
  156. return(ERROR_SHUTDOWN_IN_PROGRESS);
  157. }
  158. //
  159. // Check the handle.
  160. //
  161. if (!ScIsValidServiceHandle(hService))
  162. {
  163. return ERROR_INVALID_HANDLE;
  164. }
  165. //
  166. // Validate the CmdArgs
  167. //
  168. if (NumArgs != 0)
  169. {
  170. if (CmdArgs == NULL)
  171. {
  172. SC_LOG0(ERROR, "RStartServiceW: NULL CmdArgs with non-zero NumArgs!\n");
  173. return ERROR_INVALID_PARAMETER;
  174. }
  175. CmdArray = (LPWSTR *) CmdArgs;
  176. for (i = 0; i < NumArgs; i++)
  177. {
  178. if (CmdArray[i] == NULL)
  179. {
  180. SC_LOG1(ERROR, "RStartServiceW: CmdArray[%d] NULL!\n", i);
  181. return ERROR_INVALID_PARAMETER;
  182. }
  183. }
  184. }
  185. //
  186. // Was the handle opened with SERVICE_START access?
  187. //
  188. if (! RtlAreAllAccessesGranted(
  189. ((LPSC_HANDLE_STRUCT)hService)->AccessGranted,
  190. SERVICE_START
  191. )) {
  192. return(ERROR_ACCESS_DENIED);
  193. }
  194. //
  195. // A word about Locks....
  196. // We don't bother to get locks here because (1) We know the service
  197. // record cannot go away because we have an open handle to it,
  198. // (2) For these checks, we don't care if state changes after we
  199. // check them.
  200. //
  201. // (ScStartServiceAndDependencies also performs these checks; they are
  202. // repeated here so we can fail quickly in these 2 cases.)
  203. //
  204. serviceRecord =
  205. ((LPSC_HANDLE_STRUCT)hService)->Type.ScServiceObject.ServiceRecord;
  206. //
  207. // We can never start a disabled service
  208. //
  209. if (serviceRecord->StartType == SERVICE_DISABLED) {
  210. return ERROR_SERVICE_DISABLED;
  211. }
  212. //
  213. // Cannot start a deleted service.
  214. //
  215. if (DELETE_FLAG_IS_SET(serviceRecord)) {
  216. return ERROR_SERVICE_MARKED_FOR_DELETE;
  217. }
  218. status = ScStartServiceAndDependencies(serviceRecord, NumArgs, CmdArgs, FALSE);
  219. if (status == NO_ERROR)
  220. {
  221. if (serviceRecord->StartError == NO_ERROR)
  222. {
  223. //
  224. // Log successful service start. 0 is for a start "control"
  225. // since there's actually no such SERVICE_CONTROL_* constant.
  226. //
  227. ScLogControlEvent(NEVENT_SERVICE_CONTROL_SUCCESS,
  228. serviceRecord->DisplayName,
  229. 0);
  230. }
  231. return serviceRecord->StartError;
  232. }
  233. else
  234. {
  235. //
  236. // Start failure was logged by ScStartServiceAndDependencies
  237. //
  238. return status;
  239. }
  240. }
  241. DWORD
  242. ScStartService(
  243. IN LPSERVICE_RECORD ServiceRecord,
  244. IN DWORD NumArgs,
  245. IN LPSTRING_PTRSW CmdArgs
  246. )
  247. /*++
  248. Routine Description:
  249. This function starts a service. This code is split from the RStartServiceW
  250. so that the service controller internal code can bypass RPC and security
  251. checking when auto-starting services and their dependencies.
  252. Arguments:
  253. ServiceRecord - This is a pointer to the service record.
  254. NumArgs - This indicates the number of argument vectors.
  255. CmdArgs - This is a pointer to an array of string pointers.
  256. Return Value:
  257. NO_ERROR - The operation was completely successful.
  258. ERROR_ACCESS_DENIED - The specified handle was not opened with
  259. SERVICE_START access.
  260. ERROR_INVALID_HANDLE - The specified handle was invalid.
  261. ERROR_SERVICE_WAS_STARTED - An instance of the service is already running.
  262. ERROR_SERVICE_REQUEST_TIMEOUT - The service did not respond to the start
  263. request in a timely fashion.
  264. ERROR_SERVICE_NO_THREAD - A thread could not be created for the Win32
  265. service.
  266. ERROR_PATH_NOT_FOUND - The image file name could not be found in
  267. the configuration database (registry), or the image file name
  268. failed in a Unicode/Ansi conversion.
  269. ERROR_NOT_SAFEBOOT_SERVICE - This service isn't startable during Safeboot.
  270. --*/
  271. {
  272. DWORD status;
  273. LPWSTR ImageName = NULL;
  274. LPIMAGE_RECORD ImageRecord = NULL;
  275. LPWSTR serviceName;
  276. LPWSTR displayName;
  277. HANDLE pipeHandle;
  278. DWORD startControl;
  279. //
  280. // Check for Safeboot
  281. //
  282. if (g_dwSafebootLen != 0 && g_SafeBootEnabled != SAFEBOOT_DSREPAIR) {
  283. HKEY hKeySafeBoot;
  284. //
  285. // If this ever fails, g_szSafebootKey must be made larger
  286. //
  287. SC_ASSERT(g_dwSafebootLen + wcslen(ServiceRecord->ServiceName)
  288. < SAFEBOOT_KEY_LENGTH + MAX_SERVICE_NAME_LENGTH + 50 + 1);
  289. wcscpy(g_szSafebootKey + g_dwSafebootLen, ServiceRecord->ServiceName);
  290. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  291. g_szSafebootKey,
  292. 0,
  293. KEY_READ,
  294. &hKeySafeBoot);
  295. if (status != NO_ERROR) {
  296. SC_LOG1(ERROR, "SAFEBOOT: service skipped = %ws\n",
  297. ServiceRecord->ServiceName);
  298. return ERROR_NOT_SAFEBOOT_SERVICE;
  299. }
  300. RegCloseKey(hKeySafeBoot);
  301. }
  302. // NOTE: Only one thread at a time should be in this part of the code.
  303. // This prevents two images from getting started as could happen if
  304. // two threads get the Image Record at virtually the same time. In
  305. // this case, they might both decide to start the same image.
  306. //
  307. // We need to do this before the check for the CurrentState. Otherwise,
  308. // two threads could race down to start the same service, and they
  309. // would both attempt to start it. We would end up with either
  310. // two service images running, or two threads of the same service
  311. // running in a single image.
  312. //
  313. EnterCriticalSection(&ScStartImageCriticalSection);
  314. SC_LOG0(LOCKS,"RStartServiceW: Entering StartImage Critical Section.....\n");
  315. //
  316. // We need to gain exclusive access to the database so that we may
  317. // Read the database and make decisions based on its content.
  318. //
  319. {
  320. CServiceRecordExclusiveLock RLock;
  321. #ifdef TIMING_TEST
  322. DbgPrint("[SC_TIMING] Start Next Service TickCount for\t%ws\t%d\n",
  323. ServiceRecord->ServiceName, GetTickCount());
  324. #endif // TIMING_TEST
  325. //
  326. // Check to see if the service is already running.
  327. //
  328. if (ServiceRecord->ServiceStatus.dwCurrentState != SERVICE_STOPPED){
  329. SC_LOG(LOCKS,"RStartServiceW: Leaving StartImage Critical Section....\n",0);
  330. LeaveCriticalSection(&ScStartImageCriticalSection);
  331. return(ERROR_SERVICE_ALREADY_RUNNING);
  332. }
  333. //
  334. // If we are loading a driver, load it and return.
  335. // WARNING: ScLoadDeviceDriver releases and reacquires the RecordLock.
  336. //
  337. if (ServiceRecord->ServiceStatus.dwServiceType & SERVICE_DRIVER) {
  338. status = ScLoadDeviceDriver(ServiceRecord);
  339. LeaveCriticalSection(&ScStartImageCriticalSection);
  340. return(status);
  341. }
  342. //
  343. // Get the image record information out of the configuration database.
  344. //
  345. status = ScGetImageFileName(ServiceRecord->ServiceName, &ImageName);
  346. if (status != NO_ERROR) {
  347. SC_LOG(ERROR,"GetImageFileName failed rc = %d\n",status);
  348. SC_LOG(LOCKS,"RStartServiceW: Leaving StartImage Critical Section....\n",0);
  349. LeaveCriticalSection(&ScStartImageCriticalSection);
  350. return status;
  351. }
  352. if (ImageName == NULL) {
  353. SC_LOG0(ERROR,"GetImageFileName returned a NULL pointer\n");
  354. SC_LOG(LOCKS,"RStartServiceW: Leaving StartImage Critical Section....\n",0);
  355. LeaveCriticalSection(&ScStartImageCriticalSection);
  356. return ERROR_PATH_NOT_FOUND;
  357. }
  358. //
  359. // If the LSA hasn't been started yet, see if this service runs
  360. // inside of it and if so, initialize it.
  361. //
  362. // Even if ScInitSecurityProcess fails, we will set the global
  363. // flag since we will not attempt to connect again.
  364. //
  365. if (!ScConnectedToSecProc)
  366. {
  367. if (_wcsicmp(ScGlobalSecurityExePath, ImageName) == 0)
  368. {
  369. if (!ScInitSecurityProcess(ServiceRecord))
  370. {
  371. SC_LOG0(ERROR, "ScInitSecurityProcess Failed\n");
  372. }
  373. ScConnectedToSecProc = TRUE;
  374. }
  375. }
  376. //
  377. // Make the service record active.
  378. // Because the service effectively has a handle to itself, the
  379. // UseCount gets incremented inside ScActivateServiceRecord() when
  380. // called with a NULL ImageRecord pointer.
  381. //
  382. // We need to do this here because when we get to ScLogonAndStartImage,
  383. // we have to release the database lock around the CreateProcess call.
  384. // Since we open ourselves up to DeleteService and Control Service calls,
  385. // We need to increment the use count, and set the START_PENDING status
  386. // here.
  387. //
  388. ScActivateServiceRecord(ServiceRecord, NULL);
  389. //
  390. // Is the image file for that service already running?
  391. // If not, call StartImage.
  392. //
  393. // If the Image Record was NOT found in the database OR if the service
  394. // wants to share a process and there is no shareable version of the
  395. // Image Record, then start the image file.
  396. //
  397. if (ServiceRecord->ServiceStatus.dwServiceType & SERVICE_WIN32_SHARE_PROCESS) {
  398. ScGetNamedImageRecord(ImageName,&ImageRecord);
  399. }
  400. // CODEWORK - may not need to release the lock here in all cases.
  401. } // Release RLock
  402. if (ImageRecord != NULL)
  403. {
  404. //
  405. // The service is configured to share its process with other services,
  406. // and the image for the service is already running. So we don't need
  407. // to start a new instance of the image.
  408. //
  409. // We do need to check that the account for the service is the same
  410. // as the one that the image was started under, and that the password
  411. // is valid.
  412. //
  413. LPWSTR AccountName = NULL;
  414. status = ScLookupServiceAccount(
  415. ServiceRecord->ServiceName,
  416. &AccountName
  417. );
  418. if (status == NO_ERROR)
  419. {
  420. if (!ScEqualAccountName(AccountName, ImageRecord->AccountName))
  421. {
  422. status = ERROR_DIFFERENT_SERVICE_ACCOUNT;
  423. SC_LOG3(ERROR,
  424. "Can't start %ws service in account %ws because "
  425. "image is already running under account %ws\n",
  426. ServiceRecord->ServiceName,
  427. AccountName,
  428. ImageRecord->AccountName
  429. );
  430. }
  431. }
  432. //
  433. // If the account is not LocalSystem, validate the password by
  434. // logging on the service
  435. //
  436. if (status == NO_ERROR && AccountName != NULL)
  437. {
  438. HANDLE ServiceToken = NULL;
  439. PSID ServiceSid = NULL;
  440. status = ScLogonService(
  441. ServiceRecord->ServiceName,
  442. AccountName,
  443. &ServiceToken,
  444. NULL, // Don't need to load the user profile again
  445. &ServiceSid);
  446. if (status == NO_ERROR)
  447. {
  448. CloseHandle(ServiceToken);
  449. LocalFree(ServiceSid);
  450. }
  451. LocalFree(AccountName);
  452. }
  453. }
  454. else
  455. {
  456. //
  457. // Start a new instance of the image
  458. //
  459. SC_LOG(TRACE,"Start: calling StartImage\n",0);
  460. status = ScLogonAndStartImage(
  461. ServiceRecord,
  462. ImageName,
  463. &ImageRecord
  464. );
  465. if (status != NO_ERROR) {
  466. SC_LOG(TRACE,"Start: StartImage failed!\n",0);
  467. }
  468. }
  469. LocalFree( ImageName );
  470. if (status != NO_ERROR) {
  471. //
  472. // Deactivate the service record.
  473. //
  474. CServiceRecordExclusiveLock RLock;
  475. (void)ScDeactivateServiceRecord(ServiceRecord);
  476. SC_LOG(LOCKS,"RStartServiceW: Leaving StartImage Critical Section........\n",0);
  477. LeaveCriticalSection(&ScStartImageCriticalSection);
  478. return(status);
  479. }
  480. //
  481. // Before leaving the StartImage critical section, we need to gain
  482. // exclusive access to the database so that we may add the image record
  483. // pointer to the service record. (ActivateServiceRecord).
  484. //
  485. {
  486. CServiceRecordExclusiveLock RLock;
  487. //
  488. // By the time we get here, the Service Process will already be
  489. // running and ready to accept its first control request.
  490. //
  491. //
  492. // Add the ImageRecord Information to the active service record.
  493. //
  494. // Note that, as soon as we activate the service record and release
  495. // the lock, we open ourselves up to receiving control requests.
  496. // However, ScActivateServiceRecord sets the ControlsAccepted field
  497. // to 0, so that the service cannot accept any controls. Thus, until
  498. // the service actually sends its own status, the service controller
  499. // will reject any controls other than INTERROGATE.
  500. //
  501. // Because the service effectively has a handle to itself, the
  502. // UseCount gets incremented inside ScActivateServiceRecord().
  503. //
  504. ScActivateServiceRecord(ServiceRecord,ImageRecord);
  505. pipeHandle = ServiceRecord->ImageRecord->PipeHandle;
  506. serviceName = ServiceRecord->ServiceName;
  507. displayName = ServiceRecord->DisplayName;
  508. }
  509. SC_LOG(LOCKS,"RStartServiceW: Leaving StartImage Critical Section........\n",0);
  510. LeaveCriticalSection(&ScStartImageCriticalSection);
  511. //
  512. // Start the Service
  513. //
  514. if (ServiceRecord->ServiceStatus.dwServiceType & SERVICE_WIN32_OWN_PROCESS) {
  515. startControl = SERVICE_CONTROL_START_OWN;
  516. }
  517. else {
  518. startControl = SERVICE_CONTROL_START_SHARE;
  519. }
  520. CONTROL_ARGS ControlArgs;
  521. ControlArgs.CmdArgs = (LPWSTR *)CmdArgs;
  522. status = ScSendControl (
  523. serviceName, // ServiceName
  524. displayName, // DisplayName
  525. pipeHandle, // pipeHandle
  526. startControl, // Opcode
  527. &ControlArgs, // Union holding command-line args
  528. NumArgs, // NumArgs
  529. NULL); // Ignore handler return value
  530. if (status != NO_ERROR) {
  531. //
  532. // If an error occured, remove the service by de-activating the
  533. // service record and terminating the service process if it is
  534. // the only one running in the process.
  535. //
  536. SC_LOG2(ERROR,"Start: SendControl to %ws service failed! status=%ld\n",
  537. serviceName, status);
  538. //
  539. // NOTE: Because ScRemoveService will expect the use count
  540. // to already be incremented (for the service's own handle),
  541. // it is necessary to increment that use count prior to
  542. // removing it.
  543. //
  544. ScRemoveService(ServiceRecord);
  545. }
  546. else
  547. {
  548. //
  549. // Notify the PNP manager that the service was started.
  550. // The PNP manager uses this information to resolve ambiguities in
  551. // reconfiguration scenarios where there could temporarily be more
  552. // than one controlling service for a device. It remembers the last
  553. // service started for each device, and marks it as the "active"
  554. // service for the device in the registry.
  555. // We don't need to do this for drivers, because NtLoadDriver itself
  556. // notifies the PNP manager.
  557. //
  558. CONFIGRET PnpStatus = PNP_SetActiveService(
  559. NULL, // hBinding
  560. serviceName, // pszService
  561. PNP_SERVICE_STARTED // ulFlags
  562. );
  563. if (PnpStatus != CR_SUCCESS)
  564. {
  565. SC_LOG2(ERROR, "PNP_SetActiveService failed %#lx for service %ws\n",
  566. PnpStatus, serviceName);
  567. }
  568. }
  569. return status;
  570. }
  571. /****************************************************************************/
  572. DWORD
  573. ScLogonAndStartImage(
  574. IN LPSERVICE_RECORD ServiceRecord,
  575. IN LPWSTR ImageName,
  576. OUT LPIMAGE_RECORD *ImageRecordPtr
  577. )
  578. /*++
  579. Routine Description:
  580. This function is called when the first service in an instance of an
  581. image needs to be started.
  582. This function creates a pipe instance for control messages and invokes
  583. the executable image. It then waits for the new process to connect
  584. to the control data pipe. An image Record is created with the
  585. above information by calling CreateImageRecord.
  586. Arguments:
  587. ImageName - This is the name of the image file that is to be started.
  588. This is expected to be a fully qualified path name.
  589. ImageRecordPtr - This is a location where the pointer to the new
  590. Image Record is returned.
  591. Return Value:
  592. NO_ERROR - The operation was successful. It any other return value
  593. is returned, a pipe instance will not be created, a process will
  594. not be started, and an image record will not be created.
  595. ERROR_NOT_ENOUGH_MEMORY - Unable to allocate buffer for the image record.
  596. other - Any error returned by the following could be returned:
  597. CreateNamedPipe
  598. ConnectNamedPipe
  599. CreateProcess
  600. ScCreateControlInstance
  601. ScLogonService
  602. Note:
  603. LOCKS:
  604. The Database Lock is not held when this function is called.
  605. CODEWORK: This function badly needs to use C++ destructors for safe
  606. cleanup in error conditions.
  607. --*/
  608. {
  609. PROCESS_INFORMATION processInfo = { 0, 0, 0, 0 };
  610. DWORD servicePID;
  611. DWORD dwServiceID;
  612. HANDLE pipeHandle = NULL;
  613. DWORD status;
  614. BOOL runningInThisProcess = FALSE;
  615. HANDLE ServiceToken = NULL;
  616. HANDLE ProfileHandle = NULL;
  617. LPWSTR AccountName = NULL;
  618. DWORD ImageFlags = 0;
  619. PSID ServiceSid = LocalSystemSid;
  620. LPVOID Environment = NULL;
  621. BOOL fLoadedEnv = FALSE;
  622. BOOL fUseRtlDestroyEnv = FALSE;
  623. SC_ASSERT(! ScServiceRecordLock.Have());
  624. //
  625. // IMPORTANT:
  626. // Only one thread at a time should be allowed to execute this
  627. // code.
  628. //
  629. //
  630. // Lookup the account that the service is to be started under.
  631. // An AccountName of NULL means the LocalSystem account.
  632. //
  633. status = ScLookupServiceAccount(
  634. ServiceRecord->ServiceName,
  635. &AccountName
  636. );
  637. if (status != NO_ERROR) {
  638. return status;
  639. }
  640. //
  641. // get the environment for the target service account
  642. //
  643. if ( AccountName != NULL ) {
  644. //*******************************************************************
  645. // Service has a specific Account associated with it
  646. //*******************************************************************
  647. //
  648. // Get service token, to be assigned into the service process,
  649. // by logging on the service
  650. //
  651. status = ScLogonService(
  652. ServiceRecord->ServiceName,
  653. AccountName,
  654. &ServiceToken,
  655. &ProfileHandle,
  656. &ServiceSid
  657. );
  658. if (status != NO_ERROR) {
  659. LocalFree(AccountName);
  660. return status;
  661. }
  662. //
  663. // Get the environment for this user.
  664. //
  665. fLoadedEnv = CreateEnvironmentBlock(&Environment,
  666. ServiceToken,
  667. FALSE);
  668. }
  669. else {
  670. //*******************************************************************
  671. // Service to run with the LocalSystem account
  672. //*******************************************************************
  673. NTSTATUS ntstatus;
  674. ntstatus = RtlCreateEnvironment( TRUE, // clone environment
  675. &Environment);
  676. if ( NT_SUCCESS( ntstatus )) {
  677. fLoadedEnv = TRUE;
  678. fUseRtlDestroyEnv = TRUE;
  679. }
  680. else
  681. {
  682. SC_LOG(ERROR,
  683. "ScLogonAndStartImage: RtlCreateEnvironment FAILED %08X\n",
  684. ntstatus);
  685. }
  686. #if 0
  687. //
  688. // we need LocalSystem's token to get its environment. If a Service
  689. // that runs with LocalSystem is under cluster service control, then
  690. // there is still a possibility that LocalSystem's environment needs
  691. // to be merged with a cluster specified environment.
  692. //
  693. ServiceToken = g_hProcessToken;
  694. #endif
  695. }
  696. if (fLoadedEnv) {
  697. //
  698. // See if the Service has additional environment variables that
  699. // need to be merged into the user's environment.
  700. //
  701. status = ScMergeEnvironments(ServiceRecord->ServiceName, &Environment);
  702. if (status != NO_ERROR) {
  703. if ( status != ERROR_FILE_NOT_FOUND ) {
  704. SC_LOG(ERROR,
  705. "ScLogonAndStartImage: ScMergeEnvironments FAILED %d\n",
  706. status);
  707. goto ExitAccountError;
  708. }
  709. //
  710. // If there is no environment to be merged, continue using
  711. // just the standard environment.
  712. //
  713. status = NO_ERROR;
  714. }
  715. }
  716. else {
  717. SC_LOG(ERROR,
  718. "ScLogonAndStartImage: CreateEnvironmentBlock FAILED %d\n",
  719. GetLastError());
  720. Environment = NULL;
  721. }
  722. #if 0
  723. //
  724. // if the Service is running as LocalSystem, then clear the "reference" to
  725. // the SCM's process token. The rest of this code path and its called
  726. // functions assume that if the token handle is NULL, then the Service is
  727. // running in the context of LocalSystem.
  728. //
  729. if ( ServiceToken == g_hProcessToken ) {
  730. ServiceToken = NULL;
  731. }
  732. #endif
  733. if (AccountName != NULL) {
  734. //*******************************************************************
  735. // Start Service in an Account
  736. //*******************************************************************
  737. //
  738. // A token can be created via service logon, if the service
  739. // account name is not LocalSystem. Assign this token into
  740. // the service process.
  741. //
  742. NTSTATUS ntstatus;
  743. SECURITY_ATTRIBUTES SaProcess;
  744. PSECURITY_DESCRIPTOR SecurityDescriptor;
  745. #define SC_PROCESSSD_ACECOUNT 2
  746. SC_ACE_DATA AceData[SC_PROCESSSD_ACECOUNT] = {
  747. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  748. PROCESS_ALL_ACCESS,
  749. 0},
  750. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  751. PROCESS_SET_INFORMATION |
  752. PROCESS_TERMINATE |
  753. SYNCHRONIZE,
  754. &LocalSystemSid}
  755. };
  756. //
  757. // Fill pointer in AceData structure with ServiceSid we just
  758. // got back.
  759. //
  760. AceData[0].Sid = &ServiceSid;
  761. //
  762. // Create a security descriptor for the process we are about
  763. // to create
  764. //
  765. ntstatus = ScCreateAndSetSD(
  766. AceData, // AceData
  767. SC_PROCESSSD_ACECOUNT, // AceCount
  768. NULL, // OwnerSid (optional)
  769. NULL, // GroupSid (optional)
  770. &SecurityDescriptor // pNewDescriptor
  771. );
  772. #undef SC_PROCESSSD_ACECOUNT
  773. if (! NT_SUCCESS(ntstatus)) {
  774. SC_LOG1(ERROR, "ScCreateAndSetSD failed " FORMAT_NTSTATUS
  775. "\n", ntstatus);
  776. status = RtlNtStatusToDosError(ntstatus);
  777. goto ExitAccountError;
  778. }
  779. //
  780. // Initialize process security info
  781. //
  782. SaProcess.nLength = sizeof(SECURITY_ATTRIBUTES);
  783. SaProcess.lpSecurityDescriptor = SecurityDescriptor;
  784. SaProcess.bInheritHandle = FALSE;
  785. //
  786. // Set the flags that prevent the service from interacting
  787. // with the desktop
  788. //
  789. STARTUPINFOW StartupInfo;
  790. ScInitStartupInfo(&StartupInfo, FALSE);
  791. //
  792. // Impersonate the user so we don't give access to
  793. // EXEs that have been locked down for the account.
  794. //
  795. if (!ImpersonateLoggedOnUser(ServiceToken))
  796. {
  797. status = GetLastError();
  798. SC_LOG1(ERROR,
  799. "ScLogonAndStartImage: ImpersonateLoggedOnUser failed %d\n",
  800. status);
  801. RtlDeleteSecurityObject(&SecurityDescriptor);
  802. goto ExitAccountError;
  803. }
  804. //
  805. // Create the process in suspended mode to set the token
  806. // into the process.
  807. //
  808. // Note: If someone tries to start a service in a user account
  809. // with an image name of services.exe, a second instance of
  810. // services.exe will start, but will exit because it won't be
  811. // able to open the start event with write access (see
  812. // ScGetStartEvent).
  813. //
  814. if (!CreateProcessAsUserW (
  815. ServiceToken, // Token representing logged-on user
  816. NULL, // Fully qualified image name
  817. ImageName, // Command Line
  818. &SaProcess, // Process Attributes
  819. NULL, // Thread Attributes
  820. FALSE, // Inherit Handles
  821. DETACHED_PROCESS |
  822. CREATE_UNICODE_ENVIRONMENT |
  823. CREATE_SUSPENDED, // Creation Flags
  824. Environment, // Pointer to Environment block
  825. NULL, // Pointer to Current Directory
  826. &StartupInfo, // Startup Info
  827. &processInfo)) // ProcessInformation
  828. {
  829. status = GetLastError();
  830. }
  831. //
  832. // Stop impersonating
  833. //
  834. RevertToSelf();
  835. RtlDeleteSecurityObject(&SecurityDescriptor);
  836. if (status != NO_ERROR) {
  837. SC_LOG2(ERROR,
  838. "LogonAndStartImage: CreateProcessAsUser %ws failed " FORMAT_DWORD "\n",
  839. ImageName, status);
  840. goto ExitAccountError;
  841. }
  842. SC_LOG1(ACCOUNT, "LogonAndStartImage: Service " FORMAT_LPWSTR
  843. " was spawned to run in an account\n", ServiceRecord->ServiceName);
  844. //*******************************************************************
  845. // End of Service In Account Stuff.
  846. //*******************************************************************
  847. }
  848. else
  849. {
  850. //-----------------------------------------------
  851. // Service to run with the LocalSystem account.
  852. //-----------------------------------------------
  853. BOOL bInteractive = FALSE;
  854. if (_wcsicmp(ImageName, ScGlobalThisExePath) == 0)
  855. {
  856. processInfo.hProcess = NULL;
  857. processInfo.dwProcessId = GetCurrentProcessId();
  858. runningInThisProcess = TRUE;
  859. }
  860. else
  861. {
  862. //
  863. // The service is to run in some other image.
  864. //
  865. // If the service is to run interactively, check the flag in the
  866. // registry to see if this system is to allow interactive services.
  867. //
  868. if (ServiceRecord->ServiceStatus.dwServiceType & SERVICE_INTERACTIVE_PROCESS) {
  869. bInteractive = ScAllowInteractiveServices();
  870. if (!bInteractive)
  871. {
  872. //
  873. // Write an event to indicate that an interactive service
  874. // was started, but the system is configured to not allow
  875. // services to be interactive.
  876. //
  877. ScLogEvent(NEVENT_SERVICE_NOT_INTERACTIVE,
  878. ServiceRecord->DisplayName);
  879. }
  880. }
  881. //
  882. // If the process is to be interactive, set the appropriate flags.
  883. //
  884. STARTUPINFOW StartupInfo;
  885. ScInitStartupInfo(&StartupInfo, bInteractive);
  886. //
  887. // Spawn the Image Process
  888. //
  889. SC_LOG0(TRACE,"LogonAndStartImage: about to spawn a Service Process\n");
  890. if (!CreateProcessW (
  891. NULL, // Fully qualified image name
  892. ImageName, // Command Line
  893. NULL, // Process Attributes
  894. NULL, // Thread Attributes
  895. FALSE, // Inherit Handles
  896. DETACHED_PROCESS |
  897. CREATE_UNICODE_ENVIRONMENT |
  898. CREATE_SUSPENDED, // Creation Flags
  899. Environment, // Pointer to Environment block
  900. NULL, // Pointer to Current Directory
  901. &StartupInfo, // Startup Info
  902. &processInfo)) // ProcessInformation
  903. {
  904. status = GetLastError();
  905. SC_LOG2(ERROR,
  906. "LogonAndStartImage: CreateProcess %ws failed %d \n",
  907. ImageName,
  908. status);
  909. goto ExitAccountError;
  910. }
  911. SC_LOG1(ACCOUNT, "LogonAndStartImage: Service " FORMAT_LPWSTR
  912. " was spawned to run as LocalSystem\n", ServiceRecord->ServiceName);
  913. }
  914. //-----------------------------------------------
  915. // End of LocalSystem account stuff
  916. //-----------------------------------------------
  917. }
  918. //
  919. // Create an instance of the control pipe. If a malicious process
  920. // has already created a pipe by this name, the CreateNamedPipe
  921. // call in ScCreateControlInstance will return ERROR_ACCESS_DENIED.
  922. // Since that error should never come back otherwise, keep trying
  923. // new pipe names until we stop getting that error.
  924. //
  925. do
  926. {
  927. //
  928. // Write the service's ID to the registry
  929. //
  930. status = ScWriteCurrentServiceValue(&dwServiceID);
  931. if (status != NO_ERROR)
  932. {
  933. goto ExitAccountError;
  934. }
  935. status = ScCreateControlInstance(&pipeHandle,
  936. dwServiceID,
  937. ServiceSid);
  938. }
  939. while (status == ERROR_ACCESS_DENIED);
  940. if (status != NO_ERROR)
  941. {
  942. SC_LOG(ERROR,"LogonAndStartImage: CreateControlInstance Failure\n",0);
  943. goto ExitAccountError;
  944. }
  945. if (runningInThisProcess)
  946. {
  947. //
  948. // The service is to run in this image (services.exe).
  949. // Since this is the first service to be started in this image,
  950. // we need to start the local dispatcher.
  951. //
  952. status = SvcStartLocalDispatcher();
  953. if (status != NO_ERROR)
  954. {
  955. SC_LOG1(ERROR,
  956. "LogonAndStartImage: SvcStartLocalDispatcher failed %d",
  957. status);
  958. goto ExitAccountError;
  959. }
  960. }
  961. else
  962. {
  963. //
  964. // Let the suspended process run.
  965. //
  966. ResumeThread(processInfo.hThread);
  967. }
  968. status = ScWaitForConnect(pipeHandle,
  969. processInfo.hProcess,
  970. ServiceRecord->DisplayName,
  971. &servicePID);
  972. if (status != NO_ERROR)
  973. {
  974. SC_LOG0(ERROR,
  975. "LogonAndStartImage: Failed to connect to pipe - Terminating the Process...\n");
  976. goto ExitAccountError;
  977. }
  978. //
  979. // The client managed to connect on the correct PID-named pipe, so
  980. // the PID it's reporting should be the same as what we think it is.
  981. // Note that a mismatch is OK if the service is being run under the
  982. // debugger, though it may be due to a random EXE in the same account
  983. // as the service calling StartServiceCtrlDispatcher to see if it's
  984. // being launched as a service or as an app (yes, this has actually
  985. // happened). As a result, log a warning and update the PID we're
  986. // about to put in the service record with the actual PID of the
  987. // service process.
  988. //
  989. if (processInfo.dwProcessId != servicePID)
  990. {
  991. SC_LOG2(ERROR,
  992. "LogonAndStartImage: PID mismatch - started process %d, process %d connected\n",
  993. processInfo.dwProcessId,
  994. servicePID);
  995. ScLogEvent(NEVENT_SERVICE_DIFFERENT_PID_CONNECTED,
  996. ServiceRecord->DisplayName,
  997. processInfo.dwProcessId,
  998. servicePID);
  999. processInfo.dwProcessId = servicePID;
  1000. }
  1001. //
  1002. // If it's a shared-process service, put this information into the Image Record
  1003. //
  1004. if (ServiceRecord->ServiceStatus.dwServiceType & SERVICE_WIN32_SHARE_PROCESS)
  1005. {
  1006. ImageFlags |= CANSHARE_FLAG;
  1007. }
  1008. status = ScCreateImageRecord (
  1009. ImageRecordPtr,
  1010. ImageName,
  1011. AccountName,
  1012. processInfo.dwProcessId,
  1013. pipeHandle,
  1014. processInfo.hProcess,
  1015. ServiceToken,
  1016. ProfileHandle,
  1017. ImageFlags);
  1018. if (status != NO_ERROR) {
  1019. SC_LOG0(ERROR,
  1020. "LogonAndStartImage: Failed to create imageRecord - Terminating the Process...\n");
  1021. goto ExitAccountError;
  1022. }
  1023. //
  1024. // If the dispatcher is running in this process, then we want to
  1025. // increment the service count an extra time so that the dispatcher
  1026. // never goes away. Also, we don't really have a process handle for
  1027. // the watcher to wait on.
  1028. // It could wait on the ThreadHandle, but handling that when it becomes
  1029. // signaled becomes a special case. So we won't try that.
  1030. //
  1031. if (runningInThisProcess)
  1032. {
  1033. (*ImageRecordPtr)->ServiceCount = 1;
  1034. (*ImageRecordPtr)->ImageFlags |= IS_SYSTEM_SERVICE;
  1035. }
  1036. else
  1037. {
  1038. HANDLE hWaitObject = NULL;
  1039. NTSTATUS ntStatus;
  1040. CloseHandle(processInfo.hThread);
  1041. //
  1042. // Add the process handle as a handle to wait on.
  1043. // Retain the WaitObject handle for when we shut down
  1044. // the process because all the services stopped.
  1045. //
  1046. ntStatus = RtlRegisterWait(&hWaitObject,
  1047. processInfo.hProcess,
  1048. ScProcessHandleIsSignaled,
  1049. processInfo.hProcess,
  1050. INFINITE, // Infinite
  1051. WT_EXECUTEONLYONCE);
  1052. if (!NT_SUCCESS(ntStatus))
  1053. {
  1054. //
  1055. // Work item registration failed
  1056. //
  1057. SC_LOG1(ERROR,
  1058. "ScLogonAndStartImage: RtlRegisterWait failed 0x%x\n",
  1059. ntStatus);
  1060. }
  1061. (*ImageRecordPtr)->ObjectWaitHandle = hWaitObject;
  1062. }
  1063. if (ServiceSid != LocalSystemSid)
  1064. {
  1065. LocalFree(ServiceSid);
  1066. }
  1067. if ( fLoadedEnv ) {
  1068. if ( fUseRtlDestroyEnv ) {
  1069. RtlDestroyEnvironment( Environment );
  1070. }
  1071. else
  1072. {
  1073. DestroyEnvironmentBlock( Environment );
  1074. }
  1075. }
  1076. LocalFree(AccountName);
  1077. return(NO_ERROR);
  1078. ExitAccountError:
  1079. if (pipeHandle != NULL) {
  1080. CloseHandle(pipeHandle);
  1081. }
  1082. if (ServiceSid != LocalSystemSid) {
  1083. LocalFree(ServiceSid);
  1084. }
  1085. UnloadUserProfile(ServiceToken, ProfileHandle);
  1086. if ( ServiceToken != NULL ) {
  1087. CloseHandle(ServiceToken);
  1088. }
  1089. if (processInfo.hProcess)
  1090. {
  1091. TerminateProcess(processInfo.hProcess, 0);
  1092. CloseHandle(processInfo.hProcess);
  1093. CloseHandle(processInfo.hThread);
  1094. }
  1095. if ( fLoadedEnv ) {
  1096. if ( fUseRtlDestroyEnv ) {
  1097. RtlDestroyEnvironment( Environment );
  1098. }
  1099. else
  1100. {
  1101. DestroyEnvironmentBlock( Environment );
  1102. }
  1103. }
  1104. LocalFree(AccountName);
  1105. return status;
  1106. }
  1107. BOOL
  1108. ScEqualAccountName(
  1109. IN LPWSTR Account1,
  1110. IN LPWSTR Account2
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. This function compares two account names, either of which may be NULL,
  1115. for equality.
  1116. Arguments:
  1117. Account1, Account2 - account names to be compared
  1118. Return Value:
  1119. TRUE - names are equal
  1120. FALSE - names are not equal
  1121. --*/
  1122. {
  1123. if (Account1 == NULL && Account2 == NULL)
  1124. {
  1125. return TRUE;
  1126. }
  1127. if (Account1 == NULL || Account2 == NULL)
  1128. {
  1129. return FALSE;
  1130. }
  1131. return (_wcsicmp(Account1, Account2) == 0);
  1132. }
  1133. VOID
  1134. ScInitStartImage(
  1135. VOID
  1136. )
  1137. /*++
  1138. Routine Description:
  1139. This function initializes the Critical Section that protects
  1140. entry into the ScStartImage Routine.
  1141. Arguments:
  1142. none
  1143. Return Value:
  1144. none
  1145. --*/
  1146. {
  1147. InitializeCriticalSection(&ScStartImageCriticalSection);
  1148. }
  1149. VOID
  1150. ScInitStartupInfo(
  1151. OUT LPSTARTUPINFOW StartupInfo,
  1152. IN BOOL bInteractive
  1153. )
  1154. /*++
  1155. Routine Description:
  1156. Arguments:
  1157. none
  1158. Return Value:
  1159. none
  1160. --*/
  1161. {
  1162. static const STARTUPINFOW ScStartupInfo =
  1163. {
  1164. sizeof(STARTUPINFOW), // size
  1165. NULL, // lpReserved
  1166. NULL, // DeskTop
  1167. NULL, // Title
  1168. 0, // X (position)
  1169. 0, // Y (position)
  1170. 0, // XSize (dimension)
  1171. 0, // YSize (dimension)
  1172. 0, // XCountChars
  1173. 0, // YCountChars
  1174. 0, // FillAttributes
  1175. STARTF_FORCEOFFFEEDBACK,
  1176. // Flags - should be STARTF_TASKNOTCLOSABLE
  1177. SW_HIDE, // ShowWindow
  1178. 0L, // cbReserved
  1179. NULL, // lpReserved
  1180. NULL, // hStdInput
  1181. NULL, // hStdOutput
  1182. NULL // hStdError
  1183. };
  1184. RtlCopyMemory(StartupInfo, &ScStartupInfo, sizeof(ScStartupInfo));
  1185. if (bInteractive)
  1186. {
  1187. StartupInfo->dwFlags |= STARTF_DESKTOPINHERIT;
  1188. StartupInfo->lpDesktop = pszInteractiveDesktop;
  1189. }
  1190. }
  1191. VOID
  1192. ScProcessHandleIsSignaled(
  1193. PVOID pContext,
  1194. BOOLEAN fWaitStatus
  1195. )
  1196. /*++
  1197. Routine Description:
  1198. Arguments:
  1199. pContext - This is the process handle.
  1200. fWaitStatus - This is the status from the wait on the process handle.
  1201. TRUE means the wait timed out, FALSE means it was signaled
  1202. Return Value:
  1203. --*/
  1204. {
  1205. if (fWaitStatus == TRUE)
  1206. {
  1207. //
  1208. // This should never happen -- it indicates a bug in the thread pool code
  1209. // since we registered an infinite wait and are getting called on a timeout
  1210. //
  1211. SC_LOG0(ERROR,
  1212. "ScProcessCleanup received bad WaitStatus\n");
  1213. SC_ASSERT(FALSE);
  1214. return;
  1215. }
  1216. SC_ASSERT(fWaitStatus == FALSE);
  1217. SC_LOG1(THREADS, "Process Handle is signaled 0x%lx\n", pContext);
  1218. ScNotifyChangeState();
  1219. ScProcessCleanup((HANDLE) pContext);
  1220. }
  1221. BOOL
  1222. ScAllowInteractiveServices(
  1223. VOID
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. Check the flag in the registry to see if this system is to allow
  1228. interactive services.
  1229. REG KEY = HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\-
  1230. Windows\NoInteractiveServices.
  1231. Arguments:
  1232. Return Value:
  1233. --*/
  1234. {
  1235. HKEY WindowsKey=NULL;
  1236. DWORD NoInteractiveFlag=0;
  1237. BOOL bServicesInteractive = TRUE;
  1238. DWORD status = ScRegOpenKeyExW(
  1239. HKEY_LOCAL_MACHINE,
  1240. CONTROL_WINDOWS_KEY_W,
  1241. REG_OPTION_NON_VOLATILE, // options
  1242. KEY_READ, // desired access
  1243. &WindowsKey
  1244. );
  1245. if (status != ERROR_SUCCESS)
  1246. {
  1247. SC_LOG1(TRACE,
  1248. "ScAllowInteractiveServices: ScRegOpenKeyExW of Control\\Windows failed "
  1249. FORMAT_LONG "\n",
  1250. status);
  1251. }
  1252. else
  1253. {
  1254. status = ScReadNoInteractiveFlag(WindowsKey,&NoInteractiveFlag);
  1255. if ((status == ERROR_SUCCESS) && (NoInteractiveFlag != 0))
  1256. {
  1257. bServicesInteractive = FALSE;
  1258. }
  1259. ScRegCloseKey(WindowsKey);
  1260. }
  1261. return bServicesInteractive;
  1262. }