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.

1127 lines
34 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: launch.cxx
  7. //
  8. // Contents:
  9. //
  10. // History: ?-??-?? ??? Created
  11. // 6-17-99 a-sergiv Added event log filtering
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "act.hxx"
  15. #include <winbasep.h> // For CreateProcessInternalW
  16. extern "C" {
  17. #include <execsrv.h>
  18. }
  19. #include "execclt.hxx"
  20. const ULONG MAX_SERVICE_ARGS = 16;
  21. const WCHAR REGEVENT_PREFIX[] = L"RPCSS_REGEVENT:";
  22. const DWORD REGEVENT_PREFIX_STRLEN = sizeof(REGEVENT_PREFIX) / sizeof(WCHAR) - 1;
  23. const WCHAR INITEVENT_PREFIX[] = L"RPCSS_INITEVENT:";
  24. const DWORD INITEVENT_PREFIX_STRLEN = sizeof(INITEVENT_PREFIX) / sizeof(WCHAR) - 1;
  25. HRESULT
  26. CClsidData::GetAAASaferToken(
  27. IN CToken *pClientToken,
  28. OUT HANDLE *pTokenOut
  29. )
  30. /*++
  31. Routine Description:
  32. Get the token that will be used in an Activate As Activator
  33. launch. This token is the more restricted of the incoming
  34. token and the configured safer level.
  35. Arguments:
  36. pClientToken - token of the user doing the activation
  37. pTokenOut - out parameter that will recieve the handle to use
  38. in the activation.
  39. Return Value:
  40. S_OK: Everything went fine. The caller owns a reference on
  41. pTokenOut and must close it.
  42. S_FALSE: Everything went fine. The caller does not own a
  43. reference on pToken out and does not need to close it.
  44. Anything else: An error occured.
  45. --*/
  46. {
  47. HANDLE hSaferToken = NULL;
  48. HRESULT hr = S_OK;
  49. BOOL bStatus = TRUE;
  50. *pTokenOut = NULL;
  51. ASSERT(SaferLevel() && "Called GetAAASaferToken with SAFER disabled!");
  52. if (!SaferLevel()) return E_UNEXPECTED;
  53. // Get the safer token for this configuration.
  54. bStatus = SaferComputeTokenFromLevel(SaferLevel(),
  55. pClientToken->GetToken(),
  56. &hSaferToken,
  57. 0,
  58. NULL);
  59. if (bStatus)
  60. {
  61. hr = pClientToken->CompareSaferLevels(hSaferToken);
  62. if (hr == S_OK)
  63. {
  64. CloseHandle(hSaferToken);
  65. hSaferToken = pClientToken->GetToken();
  66. // Shared reference, return S_FALSE.
  67. hr = S_FALSE;
  68. }
  69. else
  70. {
  71. hr = S_OK;
  72. }
  73. }
  74. else
  75. {
  76. hr = HRESULT_FROM_WIN32(GetLastError());
  77. }
  78. *pTokenOut = hSaferToken;
  79. return hr;
  80. }
  81. HRESULT
  82. CClsidData::LaunchActivatorServer(
  83. IN CToken * pClientToken,
  84. IN WCHAR * pEnvBlock,
  85. IN DWORD EnvBlockLength,
  86. IN BOOL fIsRemoteActivation,
  87. IN BOOL fClientImpersonating,
  88. IN WCHAR* pwszWinstaDesktop,
  89. IN DWORD clsctx,
  90. OUT HANDLE * phProcess,
  91. OUT DWORD * pdwProcessId
  92. )
  93. {
  94. WCHAR * pwszCommandLine;
  95. WCHAR * pFinalEnvBlock;
  96. STARTUPINFO StartupInfo;
  97. PROCESS_INFORMATION ProcessInfo;
  98. SECURITY_ATTRIBUTES saProcess;
  99. PSECURITY_DESCRIPTOR psdNewProcessSD;
  100. HRESULT hr;
  101. DWORD CreateFlags;
  102. BOOL bStatus = FALSE;
  103. ULONG SessionId = 0;
  104. HANDLE hSaferToken = NULL;
  105. BOOL bCloseSaferToken = TRUE;
  106. *phProcess = NULL;
  107. *pdwProcessId = 0;
  108. if ( ! pClientToken )
  109. return (E_ACCESSDENIED);
  110. pFinalEnvBlock = NULL;
  111. StartupInfo.cb = sizeof(StartupInfo);
  112. StartupInfo.lpReserved = NULL;
  113. // Choose desktop for new server:
  114. // client remote -> system chooses desktop
  115. // client local, not impersonating -> we pick client's desktop
  116. // client local, impersonating -> system chooses desktop
  117. StartupInfo.lpDesktop = (fIsRemoteActivation || fClientImpersonating) ? L"" : pwszWinstaDesktop;
  118. StartupInfo.lpTitle = (SERVERTYPE_SURROGATE == _ServerType) ? NULL : _pwszServer;
  119. StartupInfo.dwX = 40;
  120. StartupInfo.dwY = 40;
  121. StartupInfo.dwXSize = 80;
  122. StartupInfo.dwYSize = 40;
  123. StartupInfo.dwFlags = 0;
  124. StartupInfo.wShowWindow = SW_SHOWNORMAL;
  125. StartupInfo.cbReserved2 = 0;
  126. StartupInfo.lpReserved2 = NULL;
  127. ProcessInfo.hThread = 0;
  128. ProcessInfo.hProcess = 0;
  129. ProcessInfo.dwProcessId = 0;
  130. hr = GetLaunchCommandLine( &pwszCommandLine );
  131. if ( hr != S_OK )
  132. return (hr);
  133. if ( pEnvBlock )
  134. {
  135. hr = AddAppPathsToEnv( pEnvBlock, EnvBlockLength, &pFinalEnvBlock );
  136. if ( hr != S_OK )
  137. {
  138. PrivMemFree( pwszCommandLine );
  139. return (hr);
  140. }
  141. }
  142. CreateFlags = CREATE_NEW_CONSOLE;
  143. if ( pFinalEnvBlock )
  144. CreateFlags |= CREATE_UNICODE_ENVIRONMENT;
  145. CAccessInfo AccessInfo( pClientToken->GetSid() );
  146. //
  147. // Apply configured safer restrictions to the token we're using to launch.
  148. // SAFER might not be enabled at all, in which case we don't need to do this.
  149. //
  150. if ( gbSAFERAAAChecksEnabled && SaferLevel() )
  151. {
  152. hr = GetAAASaferToken( pClientToken, &hSaferToken );
  153. if ( FAILED(hr) ) goto LaunchServerEnd;
  154. if ( hr == S_FALSE )
  155. {
  156. // GetAAASaferToken has returned a shared reference
  157. // to pClientToken.
  158. bCloseSaferToken = FALSE;
  159. hr = S_OK;
  160. }
  161. else
  162. bCloseSaferToken = TRUE;
  163. }
  164. else
  165. {
  166. hSaferToken = pClientToken->GetToken();
  167. bCloseSaferToken = FALSE;
  168. }
  169. //
  170. // This should never fail here, but if it did that would be a really,
  171. // really bad security breach, so check it anyway.
  172. //
  173. if ( ! ImpersonateLoggedOnUser( hSaferToken ) )
  174. {
  175. hr = E_ACCESSDENIED;
  176. goto LaunchServerEnd;
  177. }
  178. //
  179. // Initialize process security info (SDs). We need both SIDs to
  180. // do this, so here is the 1st time we can. We Delete the SD right
  181. // after the CreateProcess call, no matter what happens.
  182. //
  183. psdNewProcessSD = AccessInfo.IdentifyAccess(
  184. FALSE,
  185. PROCESS_ALL_ACCESS,
  186. PROCESS_SET_INFORMATION | // Allow primary token to be set
  187. PROCESS_TERMINATE | SYNCHRONIZE // Allow screen-saver control
  188. );
  189. if ( ! psdNewProcessSD )
  190. {
  191. RevertToSelf();
  192. hr = E_OUTOFMEMORY;
  193. goto LaunchServerEnd;
  194. }
  195. saProcess.nLength = sizeof(SECURITY_ATTRIBUTES);
  196. saProcess.lpSecurityDescriptor = psdNewProcessSD;
  197. saProcess.bInheritHandle = FALSE;
  198. SessionId = fIsRemoteActivation ? 0 : pClientToken->GetSessionId();
  199. if( SessionId != 0 ) {
  200. //
  201. // We must send the request to the remote WinStation
  202. // of the requestor
  203. //
  204. // NOTE: The current WinStationCreateProcessW() does not use
  205. // the supplied security descriptor, but creates the
  206. // process under the account of the logged on user.
  207. //
  208. // We do not stuff the security descriptor, so clear the suspend flag
  209. #if DBGX
  210. CairoleDebugOut((DEB_TRACE, "SCM: Sending CreateProcess to SessionId %d\n",SessionId));
  211. #endif
  212. // Non-zero sessions have only one winstation/desktop which is
  213. // the default one. We will ignore the winstation/desktop passed
  214. // in and use the default one.
  215. // review: Figure this out TarunA 05/07/99
  216. //StartupInfo.lpDesktop = L"WinSta0\\Default";
  217. // jsimmons 4/6/00 -- note that if the client was impersonating, then we won't
  218. // launch the server under the correct identity. More work needed to determine
  219. // if we can fully support this.
  220. //
  221. // Stop impersonating before doing the WinStationCreateProcess.
  222. // The remote winstation exec thread will launch the app under
  223. // the users context. We must not be impersonating because this
  224. // call only lets SYSTEM request the remote execute.
  225. //
  226. RevertToSelf();
  227. HANDLE hDuplicate = NULL;
  228. // We need to pass in the SAFER blessed token to TS so that the
  229. // server can use that token
  230. // TS code will call CreateProcessAsUser, so we need to get a primary token
  231. if (DuplicateTokenForSessionUse(hSaferToken, &hDuplicate))
  232. {
  233. if (bCloseSaferToken)
  234. {
  235. CloseHandle(hSaferToken);
  236. }
  237. hSaferToken = hDuplicate;
  238. bCloseSaferToken = TRUE;
  239. bStatus = CreateRemoteSessionProcess(
  240. SessionId,
  241. hSaferToken,
  242. FALSE, // Run as Logged on USER
  243. ServerExecutable(), // application name
  244. pwszCommandLine, // command line
  245. &saProcess, // process sec attributes
  246. NULL, // default thread sec attributes
  247. // (this was &saThread, but isn't needed)
  248. FALSE, // dont inherit handles
  249. CreateFlags, // creation flags
  250. pFinalEnvBlock, // use same enviroment block as the client
  251. NULL, // use same directory
  252. &StartupInfo, // startup info
  253. &ProcessInfo // proc info returned
  254. );
  255. }
  256. }
  257. else
  258. {
  259. HANDLE hPrimary = NULL;
  260. if (DuplicateTokenAsPrimary(hSaferToken, pClientToken->GetSid(), &hPrimary))
  261. {
  262. if (bCloseSaferToken)
  263. {
  264. CloseHandle(hSaferToken);
  265. }
  266. hSaferToken = hPrimary;
  267. bCloseSaferToken = TRUE;
  268. //
  269. // Do the exec while impersonating so the file access gets ACL
  270. // checked correctly.
  271. //
  272. //
  273. bStatus = CreateProcessAsUser(
  274. hSaferToken,
  275. ServerExecutable(),
  276. pwszCommandLine,
  277. &saProcess,
  278. NULL,
  279. FALSE,
  280. CreateFlags,
  281. pFinalEnvBlock,
  282. NULL,
  283. &StartupInfo,
  284. &ProcessInfo);
  285. }
  286. RevertToSelf();
  287. }
  288. if ( ! bStatus )
  289. {
  290. hr = HRESULT_FROM_WIN32( GetLastError() );
  291. LogServerStartError( &_Clsid, clsctx, pClientToken, pwszCommandLine );
  292. goto LaunchServerEnd;
  293. }
  294. LaunchServerEnd:
  295. if ( pFinalEnvBlock && pFinalEnvBlock != pEnvBlock )
  296. PrivMemFree( pFinalEnvBlock );
  297. if ( ProcessInfo.hThread )
  298. CloseHandle( ProcessInfo.hThread );
  299. if ( ProcessInfo.hProcess && ! bStatus )
  300. {
  301. CloseHandle( ProcessInfo.hProcess );
  302. ProcessInfo.hProcess = 0;
  303. }
  304. if ( hSaferToken && bCloseSaferToken )
  305. {
  306. CloseHandle( hSaferToken );
  307. }
  308. *phProcess = ProcessInfo.hProcess;
  309. *pdwProcessId = ProcessInfo.dwProcessId;
  310. PrivMemFree( pwszCommandLine );
  311. return (hr);
  312. }
  313. //+-------------------------------------------------------------------------
  314. //
  315. // LaunchRunAsServer
  316. //
  317. //--------------------------------------------------------------------------
  318. HRESULT
  319. CClsidData::LaunchRunAsServer(
  320. IN CToken * pClientToken,
  321. IN BOOL fIsRemoteActivation,
  322. IN ActivationPropertiesIn *pActIn,
  323. IN DWORD clsctx,
  324. OUT HANDLE * phProcess,
  325. OUT DWORD * pdwProcessId,
  326. OUT void** ppvRunAsHandle
  327. )
  328. {
  329. WCHAR * pwszCommandLine;
  330. STARTUPINFO StartupInfo;
  331. PROCESS_INFORMATION ProcessInfo = {0};
  332. HANDLE hToken;
  333. SECURITY_ATTRIBUTES saProcess;
  334. PSECURITY_DESCRIPTOR psdNewProcessSD;
  335. PSID psidUserSid;
  336. HRESULT hr;
  337. BOOL bStatus = FALSE;
  338. ULONG ulSessionId;
  339. BOOL bFromRunAsCache = FALSE;
  340. hr = GetLaunchCommandLine( &pwszCommandLine );
  341. if ( hr != S_OK )
  342. return (hr);
  343. *phProcess = NULL;
  344. *pdwProcessId = 0;
  345. hToken = NULL;
  346. bStatus = FALSE;
  347. StartupInfo.cb = sizeof(STARTUPINFO);
  348. StartupInfo.lpReserved = NULL;
  349. StartupInfo.lpDesktop = NULL;
  350. StartupInfo.lpTitle = (SERVERTYPE_SURROGATE == _ServerType) ? NULL : _pwszServer;
  351. StartupInfo.dwFlags = 0;
  352. StartupInfo.cbReserved2 = 0;
  353. StartupInfo.lpReserved2 = NULL;
  354. ulSessionId = 0;
  355. if( IsInteractiveUser() )
  356. {
  357. if (!fIsRemoteActivation)
  358. {
  359. // This code seems to be saying, "if the client is local then I
  360. // should always be able to impersonate him". Which is true under
  361. // normal circumstances, but we have seen a case (stress machine
  362. // shutdowns) where the client is local but came in un-authenticated.
  363. if (!pClientToken)
  364. return E_ACCESSDENIED;
  365. if ( !ImpersonateLoggedOnUser( pClientToken->GetToken() ) )
  366. {
  367. PrivMemFree(pwszCommandLine);
  368. return E_ACCESSDENIED;
  369. }
  370. RevertToSelf();
  371. }
  372. ASSERT(pActIn);
  373. LONG lSessIdTemp;
  374. // Query for incoming session
  375. GetSessionIDFromActParams(pActIn, &lSessIdTemp);
  376. if (lSessIdTemp != INVALID_SESSION_ID)
  377. {
  378. ulSessionId = lSessIdTemp;
  379. }
  380. // Right now force all complus to
  381. // session 0. Session based activation
  382. // is still ill defined for complus
  383. // servers.
  384. if (_ServerType == SERVERTYPE_COMPLUS)
  385. {
  386. ulSessionId = 0;
  387. }
  388. hToken = GetUserTokenForSession(ulSessionId);
  389. }
  390. else
  391. {
  392. hToken = GetRunAsToken( clsctx,
  393. AppidString(),
  394. RunAsDomain(),
  395. RunAsUser(),
  396. TRUE);
  397. if (hToken)
  398. {
  399. hr = RunAsGetTokenElem(&hToken,
  400. ppvRunAsHandle);
  401. if (SUCCEEDED(hr))
  402. bFromRunAsCache = TRUE;
  403. else
  404. {
  405. ASSERT((*ppvRunAsHandle == NULL) && "RunAsGetTokenElem failed but *ppvRunAsHandle is non-NULL");
  406. PrivMemFree( pwszCommandLine );
  407. CloseHandle(hToken);
  408. return hr;
  409. }
  410. }
  411. }
  412. if ( ! hToken )
  413. {
  414. PrivMemFree( pwszCommandLine );
  415. return (CO_E_RUNAS_LOGON_FAILURE);
  416. }
  417. psdNewProcessSD = 0;
  418. psidUserSid = GetUserSid(hToken);
  419. CAccessInfo AccessInfo(psidUserSid);
  420. // We have to get past the CAccessInfo before we can use a goto.
  421. if ( psidUserSid )
  422. {
  423. psdNewProcessSD = AccessInfo.IdentifyAccess(
  424. FALSE,
  425. PROCESS_ALL_ACCESS,
  426. PROCESS_SET_INFORMATION | // Allow primary token to be set
  427. PROCESS_TERMINATE | SYNCHRONIZE // Allow screen-saver control
  428. );
  429. }
  430. if ( ! psdNewProcessSD )
  431. {
  432. hr = E_OUTOFMEMORY;
  433. goto LaunchRunAsServerEnd;
  434. }
  435. saProcess.nLength = sizeof(SECURITY_ATTRIBUTES);
  436. saProcess.lpSecurityDescriptor = psdNewProcessSD;
  437. saProcess.bInheritHandle = FALSE;
  438. {
  439. //
  440. // Get the environment block of the user
  441. //
  442. LPVOID lpEnvBlock = NULL;
  443. bStatus = CreateEnvironmentBlock(&lpEnvBlock, hToken, FALSE);
  444. HANDLE hSaferToken = NULL;
  445. if(bStatus && SaferLevel())
  446. {
  447. bStatus = SaferComputeTokenFromLevel(SaferLevel(),
  448. hToken,
  449. &hSaferToken,
  450. 0,
  451. NULL);
  452. }
  453. else
  454. {
  455. hSaferToken = hToken;
  456. }
  457. if (bStatus && (ulSessionId != 0))
  458. {
  459. bStatus = SetTokenInformation(hSaferToken,
  460. TokenSessionId,
  461. &ulSessionId,
  462. sizeof(ulSessionId));
  463. }
  464. if(bStatus)
  465. {
  466. //
  467. // This allows the process create to work with paths to remote machines.
  468. //
  469. (void) ImpersonateLoggedOnUser( hSaferToken );
  470. bStatus = CreateProcessAsUser(hSaferToken,
  471. ServerExecutable(),
  472. pwszCommandLine,
  473. &saProcess,
  474. NULL,
  475. FALSE,
  476. CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
  477. lpEnvBlock,
  478. NULL,
  479. &StartupInfo,
  480. &ProcessInfo);
  481. (void) RevertToSelf();
  482. }
  483. //
  484. // Free the environment block buffer
  485. //
  486. if (lpEnvBlock)
  487. DestroyEnvironmentBlock(lpEnvBlock);
  488. if (hSaferToken && SaferLevel())
  489. CloseHandle(hSaferToken);
  490. }
  491. if ( ! bStatus )
  492. {
  493. hr = HRESULT_FROM_WIN32( GetLastError() );
  494. LogRunAsServerStartError(
  495. &_Clsid,
  496. clsctx,
  497. pClientToken,
  498. pwszCommandLine,
  499. RunAsUser(),
  500. RunAsDomain() );
  501. goto LaunchRunAsServerEnd;
  502. }
  503. *phProcess = ProcessInfo.hProcess;
  504. *pdwProcessId = ProcessInfo.dwProcessId;
  505. NtClose( ProcessInfo.hThread );
  506. LaunchRunAsServerEnd:
  507. if ( hToken )
  508. {
  509. NtClose( hToken );
  510. }
  511. if ( psidUserSid )
  512. {
  513. PrivMemFree(psidUserSid);
  514. }
  515. PrivMemFree( pwszCommandLine );
  516. if (!bFromRunAsCache)
  517. *ppvRunAsHandle = NULL;
  518. else
  519. if (!SUCCEEDED(hr))
  520. {
  521. RunAsRelease(*ppvRunAsHandle);
  522. *ppvRunAsHandle = NULL;
  523. }
  524. return (hr);
  525. }
  526. //+-------------------------------------------------------------------------
  527. //
  528. // Member: LaunchService
  529. //
  530. //--------------------------------------------------------------------------
  531. HRESULT
  532. CClsidData::LaunchService(
  533. IN CToken * pClientToken,
  534. IN DWORD clsctx,
  535. OUT SC_HANDLE * phService
  536. )
  537. {
  538. WCHAR *pwszArgs = NULL;
  539. ULONG cArgs = 0;
  540. WCHAR *apwszArgs[MAX_SERVICE_ARGS];
  541. BOOL bStatus;
  542. HRESULT hr;
  543. ASSERT(g_hServiceController);
  544. *phService = OpenService( g_hServiceController,
  545. _pAppid->Service(),
  546. GENERIC_EXECUTE | GENERIC_READ );
  547. if ( ! *phService )
  548. return (HRESULT_FROM_WIN32( GetLastError() ));
  549. // Formulate the arguments (if any)
  550. if ( ServiceArgs() )
  551. {
  552. UINT k = 0;
  553. // Make a copy of the service arguments
  554. pwszArgs = (WCHAR *) PrivMemAlloc(
  555. (lstrlenW(ServiceArgs()) + 1) * sizeof(WCHAR));
  556. if ( pwszArgs == NULL )
  557. {
  558. CloseServiceHandle(*phService);
  559. *phService = 0;
  560. return (E_OUTOFMEMORY);
  561. }
  562. lstrcpyW(pwszArgs, ServiceArgs());
  563. // Scan the arguments
  564. do
  565. {
  566. // Scan to the next non-whitespace character
  567. while ( pwszArgs[k] &&
  568. (pwszArgs[k] == L' ' ||
  569. pwszArgs[k] == L'\t') )
  570. {
  571. k++;
  572. }
  573. // Store the next argument
  574. if ( pwszArgs[k] )
  575. {
  576. apwszArgs[cArgs++] = &pwszArgs[k];
  577. }
  578. // Scan to the next whitespace char
  579. while ( pwszArgs[k] &&
  580. pwszArgs[k] != L' ' &&
  581. pwszArgs[k] != L'\t' )
  582. {
  583. k++;
  584. }
  585. // Null terminate the previous argument
  586. if ( pwszArgs[k] )
  587. {
  588. pwszArgs[k++] = L'\0';
  589. }
  590. } while ( pwszArgs[k] );
  591. }
  592. bStatus = StartService( *phService,
  593. cArgs,
  594. cArgs > 0 ? (LPCTSTR *) apwszArgs : NULL);
  595. PrivMemFree(pwszArgs);
  596. if ( bStatus )
  597. return (S_OK);
  598. DWORD dwErr = GetLastError();
  599. hr = HRESULT_FROM_WIN32( dwErr );
  600. if ( dwErr == ERROR_SERVICE_ALREADY_RUNNING )
  601. return (hr);
  602. CairoleDebugOut((DEB_ERROR,
  603. "StartService %ws failed, error = %#x\n",_pAppid->Service(),GetLastError()));
  604. CloseServiceHandle(*phService);
  605. *phService = 0;
  606. LogServiceStartError(
  607. &_Clsid,
  608. clsctx,
  609. pClientToken,
  610. _pAppid->Service(),
  611. ServiceArgs(),
  612. dwErr );
  613. return (hr);
  614. }
  615. //+-------------------------------------------------------------------------
  616. //
  617. // LaunchAllowed
  618. //
  619. //--------------------------------------------------------------------------
  620. BOOL
  621. CClsidData::LaunchAllowed(
  622. IN CToken * pClientToken,
  623. IN DWORD clsctx
  624. )
  625. {
  626. BOOL bStatus;
  627. ASSERT(pClientToken);
  628. #if DBG
  629. WCHAR wszUser[MAX_PATH];
  630. ULONG cchSize = MAX_PATH;
  631. pClientToken->Impersonate();
  632. GetUserName( wszUser, &cchSize );
  633. pClientToken->Revert();
  634. CairoleDebugOut((DEB_TRACE, "RPCSS : CClsidData::LaunchAllowed on %ws\n", wszUser));
  635. #endif
  636. if ( LaunchPermission() )
  637. bStatus = CheckForAccess( pClientToken, LaunchPermission() );
  638. else
  639. {
  640. CSecDescriptor* pSD = GetDefaultLaunchPermissions();
  641. if (pSD)
  642. {
  643. bStatus = CheckForAccess( pClientToken, pSD->GetSD() );
  644. pSD->DecRefCount();
  645. }
  646. else
  647. bStatus = FALSE;
  648. }
  649. if ( ! bStatus )
  650. {
  651. LogLaunchAccessFailed(
  652. &_Clsid,
  653. clsctx,
  654. pClientToken,
  655. 0 == LaunchPermission() );
  656. }
  657. return (bStatus);
  658. }
  659. HRESULT
  660. CClsidData::GetLaunchCommandLine(
  661. OUT WCHAR ** ppwszCommandLine
  662. )
  663. {
  664. DWORD AllocBytes;
  665. *ppwszCommandLine = 0;
  666. if ( (SERVERTYPE_EXE16 == _ServerType) || (SERVERTYPE_EXE32 == _ServerType) )
  667. {
  668. AllocBytes = ( 1 + lstrlenW( L"-Embedding" ) +
  669. 1 + lstrlenW( _pwszServer ) ) * sizeof(WCHAR);
  670. *ppwszCommandLine = (WCHAR *) PrivMemAlloc( AllocBytes );
  671. if ( *ppwszCommandLine != NULL )
  672. {
  673. lstrcpyW( *ppwszCommandLine, _pwszServer );
  674. lstrcatW( *ppwszCommandLine, L" -Embedding" );
  675. }
  676. }
  677. else
  678. {
  679. ASSERT( SERVERTYPE_SURROGATE == _ServerType
  680. || SERVERTYPE_COMPLUS == _ServerType
  681. || SERVERTYPE_DLLHOST == _ServerType );
  682. AllocBytes = ( 1 + lstrlenW( DllSurrogate() ) ) * sizeof(WCHAR);
  683. *ppwszCommandLine = (WCHAR *) PrivMemAlloc( AllocBytes );
  684. if ( *ppwszCommandLine != NULL )
  685. {
  686. lstrcpyW( *ppwszCommandLine, DllSurrogate() );
  687. }
  688. }
  689. return (*ppwszCommandLine ? S_OK : E_OUTOFMEMORY);
  690. }
  691. CNamedObject*
  692. CClsidData::ServerLaunchMutex()
  693. {
  694. WCHAR* pwszPath = NULL;
  695. WCHAR* pszPathBuf = NULL;
  696. if ( SERVERTYPE_SURROGATE == _ServerType )
  697. {
  698. pwszPath = DllSurrogate();
  699. // Will never be called any more, ever
  700. if ( ! pwszPath || ! *pwszPath )
  701. {
  702. ASSERT(_pAppid);
  703. pwszPath = _pAppid->AppidString();
  704. //pwszPath = L"dllhost.exe";
  705. }
  706. }
  707. else if ( DllHostOrComPlusProcess() )
  708. {
  709. ASSERT(_pAppid);
  710. pwszPath = _pAppid->AppidString();
  711. //pwszPath = L"dllhost.exe";
  712. }
  713. else
  714. {
  715. pwszPath = Server();
  716. // Need to use the base .exe part of the file path here,
  717. // there are tests that move the registration of their
  718. // server from one dir to another and we need to handle
  719. // this while concurrent activations are happening.
  720. LPWSTR pszBaseExeName = NULL;
  721. // First see how much of a buffer we need
  722. DWORD dwRet = GetFullPathName(pwszPath,
  723. 0,
  724. NULL,
  725. NULL);
  726. ASSERT(dwRet != 0);
  727. pszPathBuf = (WCHAR*)PrivMemAlloc(dwRet * sizeof(WCHAR));
  728. if (!pszPathBuf)
  729. return NULL;
  730. dwRet = GetFullPathName(pwszPath,
  731. dwRet,
  732. pszPathBuf,
  733. &pszBaseExeName);
  734. if ((dwRet == 0) || !pszBaseExeName)
  735. {
  736. ASSERT(!"Unexpected failure from GetFullPathName");
  737. PrivMemFree(pszPathBuf);
  738. return NULL;
  739. }
  740. // Use the base exe name for the event name
  741. pwszPath = pszBaseExeName;
  742. }
  743. if ( !pwszPath )
  744. {
  745. ASSERT(0);
  746. PrivMemFree(pszPathBuf);
  747. return (NULL);
  748. }
  749. CNamedObject* pObject =
  750. gpNamedObjectTable->GetNamedObject(pwszPath, CNamedObject::MUTEX);
  751. PrivMemFree(pszPathBuf);
  752. if (pObject)
  753. {
  754. WaitForSingleObject(pObject->Handle(), INFINITE);
  755. }
  756. return pObject;
  757. }
  758. //
  759. // CClsidData::ServerRegisterEvent
  760. //
  761. // Returns a handle to the appropriate register
  762. // event for the server in question.
  763. //
  764. CNamedObject*
  765. CClsidData::ServerRegisterEvent()
  766. {
  767. if ( DllHostOrComPlusProcess() )
  768. {
  769. // For dllhost\com+ surrogates, we delegate to the appid
  770. ASSERT(_pAppid);
  771. return _pAppid->ServerRegisterEvent();
  772. }
  773. // Prefix the string with a special string; objects with guid
  774. // names are just a touch too common for me to feel comfortable
  775. // otherwise.
  776. WCHAR wszEventName[GUIDSTR_MAX + sizeof(REGEVENT_PREFIX)];
  777. memcpy(wszEventName, REGEVENT_PREFIX, sizeof(REGEVENT_PREFIX));
  778. memcpy(wszEventName + REGEVENT_PREFIX_STRLEN, _wszClsid, sizeof(_wszClsid));
  779. return gpNamedObjectTable->GetNamedObject(wszEventName, CNamedObject::EVENT);
  780. }
  781. //
  782. // CClsidData::ServerInitializedEvent
  783. //
  784. // Returns a handle to the appropriate register
  785. // event for the server in question. This event is
  786. // signaled when initialization is finished.
  787. //
  788. CNamedObject*
  789. CAppidData::ServerInitializedEvent()
  790. {
  791. // Prefix the string with a special string; objects with guid
  792. // names are just a touch too common for me to feel comfortable
  793. // otherwise.
  794. WCHAR wszEventName[GUIDSTR_MAX + sizeof(INITEVENT_PREFIX)];
  795. memcpy(wszEventName, INITEVENT_PREFIX, sizeof(INITEVENT_PREFIX));
  796. memcpy(wszEventName + INITEVENT_PREFIX_STRLEN, _wszAppid, sizeof(_wszAppid));
  797. return gpNamedObjectTable->GetNamedObject(wszEventName, CNamedObject::EVENT);
  798. }
  799. //
  800. // CClsidData::ServerInitializedEvent
  801. //
  802. // Returns a handle to the appropriate register
  803. // event for the server in question. This event is
  804. // signaled when initialization is finished.
  805. //
  806. // NOTE: The non-DllHost path is currently not used here.
  807. //
  808. CNamedObject*
  809. CClsidData::ServerInitializedEvent()
  810. {
  811. if ( DllHostOrComPlusProcess() )
  812. {
  813. // For dllhost\com+ surrogates, we delegate to the appid
  814. ASSERT(_pAppid);
  815. return _pAppid->ServerInitializedEvent();
  816. }
  817. // Prefix the string with a special string; objects with guid
  818. // names are just a touch too common for me to feel comfortable
  819. // otherwise.
  820. WCHAR wszEventName[GUIDSTR_MAX + sizeof(INITEVENT_PREFIX)];
  821. memcpy(wszEventName, INITEVENT_PREFIX, sizeof(INITEVENT_PREFIX));
  822. memcpy(wszEventName + INITEVENT_PREFIX_STRLEN, _wszClsid, sizeof(_wszClsid));
  823. return gpNamedObjectTable->GetNamedObject(wszEventName, CNamedObject::EVENT);
  824. }
  825. //
  826. // CAppidData::ServerRegisterEvent
  827. //
  828. // Returns a handle to the appropriate register
  829. // event for the server in question.
  830. //
  831. CNamedObject*
  832. CAppidData::ServerRegisterEvent()
  833. {
  834. // Prefix the string with a special string; objects with guid
  835. // names are just a touch too common for me to feel comfortable
  836. // otherwise.
  837. WCHAR wszEventName[GUIDSTR_MAX + sizeof(REGEVENT_PREFIX)];
  838. memcpy(wszEventName, REGEVENT_PREFIX, sizeof(REGEVENT_PREFIX));
  839. memcpy(wszEventName + REGEVENT_PREFIX_STRLEN, _wszAppid, sizeof(_wszAppid));
  840. return gpNamedObjectTable->GetNamedObject(wszEventName, CNamedObject::EVENT);
  841. }
  842. //+-------------------------------------------------------------------------
  843. //
  844. // CClsidData::AddAppPathsToEnv
  845. //
  846. // Constructs a new environment block with an exe's AppPath value from the
  847. // registry appended to the Path environment variable. Simply returns the
  848. // given environment block if the clsid's server is not a 32 bit exe or if
  849. // no AppPath is found for the exe.
  850. //
  851. //--------------------------------------------------------------------------
  852. HRESULT
  853. CClsidData::AddAppPathsToEnv(
  854. IN WCHAR * pEnvBlock,
  855. IN DWORD EnvBlockLength,
  856. OUT WCHAR ** ppFinalEnvBlock
  857. )
  858. {
  859. HKEY hAppKey;
  860. WCHAR * pwszExe;
  861. WCHAR * pwszExeEnd;
  862. WCHAR * pwszAppPath;
  863. WCHAR * pPath;
  864. WCHAR * pNewEnvBlock;
  865. WCHAR wszStr[8];
  866. WCHAR wszKeyName[APP_PATH_LEN+MAX_PATH];
  867. DWORD AppPathLength;
  868. DWORD EnvFragLength;
  869. DWORD Status;
  870. BOOL bFoundPath;
  871. pwszAppPath = 0;
  872. pNewEnvBlock = 0;
  873. *ppFinalEnvBlock = pEnvBlock;
  874. if ( _ServerType != SERVERTYPE_EXE32 )
  875. return (S_OK);
  876. //
  877. // Find the exe name by looking for the first .exe sub string which
  878. // is followed by a space or null. Only servers registered with a
  879. // .exe binary are supported. Otherwise the parsing is ambiguous since
  880. // the LocalServer32 can contain paths with spaces as well as optional
  881. // arguments.
  882. //
  883. if ( ! FindExeComponent( _pwszServer, L" ", &pwszExe, &pwszExeEnd ) )
  884. return (S_OK);
  885. //
  886. // pwszExe points to the beginning of the binary name
  887. // pwszExeEnd points to one char past the end of the binary name
  888. //
  889. memcpy( wszKeyName, APP_PATH, APP_PATH_LEN * sizeof(WCHAR) );
  890. memcpy( &wszKeyName[APP_PATH_LEN], pwszExe, (ULONG) (pwszExeEnd - pwszExe) * sizeof(WCHAR) );
  891. wszKeyName[APP_PATH_LEN + (pwszExeEnd - pwszExe)] = 0;
  892. Status = RegOpenKeyEx(
  893. HKEY_LOCAL_MACHINE,
  894. wszKeyName,
  895. 0,
  896. KEY_READ,
  897. &hAppKey );
  898. if ( ERROR_SUCCESS == Status )
  899. {
  900. Status = ReadStringValue( hAppKey, L"Path", &pwszAppPath );
  901. RegCloseKey( hAppKey );
  902. }
  903. if ( Status != ERROR_SUCCESS )
  904. return (S_OK);
  905. AppPathLength = lstrlenW(pwszAppPath);
  906. // New env block size includes space for a new ';' separator in the path.
  907. pNewEnvBlock = (WCHAR *) PrivMemAlloc( (EnvBlockLength + 1 + AppPathLength) * sizeof(WCHAR) );
  908. if ( ! pNewEnvBlock )
  909. {
  910. PrivMemFree( pwszAppPath );
  911. return (E_OUTOFMEMORY);
  912. }
  913. pPath = pEnvBlock;
  914. bFoundPath = FALSE;
  915. for ( ; *pPath; )
  916. {
  917. memcpy( wszStr, pPath, 5 * sizeof(WCHAR) );
  918. wszStr[5] = 0;
  919. pPath += lstrlenW( pPath ) + 1;
  920. if ( lstrcmpiW( wszStr, L"Path=" ) == 0 )
  921. {
  922. bFoundPath = TRUE;
  923. break;
  924. }
  925. }
  926. if ( bFoundPath )
  927. {
  928. pPath--;
  929. EnvFragLength = (ULONG) (pPath - pEnvBlock);
  930. memcpy( pNewEnvBlock,
  931. pEnvBlock,
  932. EnvFragLength * sizeof(WCHAR) );
  933. pNewEnvBlock[EnvFragLength] = L';';
  934. memcpy( &pNewEnvBlock[EnvFragLength + 1],
  935. pwszAppPath,
  936. AppPathLength * sizeof(WCHAR) );
  937. memcpy( &pNewEnvBlock[EnvFragLength + 1 + AppPathLength],
  938. pPath,
  939. (EnvBlockLength - EnvFragLength) * sizeof(WCHAR) );
  940. *ppFinalEnvBlock = pNewEnvBlock;
  941. }
  942. else
  943. {
  944. PrivMemFree( pNewEnvBlock );
  945. }
  946. PrivMemFree( pwszAppPath );
  947. return (S_OK);
  948. }