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.

1058 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996.
  5. //
  6. // clsid.cxx
  7. //
  8. // Classes for managing CLSID and APPID registry settings.
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "act.hxx"
  12. #include <catalog.h>
  13. #include <ole2com.h>
  14. #include "registry.hxx"
  15. // The domain name to use if no domain name is specified in the RunAs key.
  16. // We use . instead of the local machine name because the local machine name
  17. // does not work if we are on a Domain Controller, . works in all cases.
  18. WCHAR *gpwszLocalMachineDomain = L".";
  19. extern "C"
  20. {
  21. HANDLE
  22. GetCurrentUserTokenW(
  23. WCHAR Winsta[],
  24. DWORD DesiredAccess
  25. );
  26. };
  27. //+-------------------------------------------------------------------------
  28. //
  29. // LookupClsidData
  30. //
  31. // Loads the registry configuration for the given CLSID. Option can be any
  32. // of the LOAD_* values defined in clsid.hxx, or 0 for no special handling.
  33. //
  34. //--------------------------------------------------------------------------
  35. HRESULT
  36. LookupClsidData(
  37. IN GUID & Clsid,
  38. IN IComClassInfo* pComClassInfo,
  39. IN CToken * pToken,
  40. IN DWORD Option,
  41. IN OUT CClsidData **ppClsidData
  42. )
  43. {
  44. HRESULT hr;
  45. if ( ! *ppClsidData )
  46. *ppClsidData = new CClsidData( Clsid, pToken, pComClassInfo );
  47. if ( ! *ppClsidData )
  48. return (E_OUTOFMEMORY);
  49. hr = (*ppClsidData)->Load( Option );
  50. if ( hr != S_OK )
  51. {
  52. delete *ppClsidData;
  53. *ppClsidData = 0;
  54. }
  55. else
  56. {
  57. // In case of Treat As
  58. Clsid = *(*ppClsidData)->ClsidGuid();
  59. }
  60. return (hr);
  61. }
  62. //+-------------------------------------------------------------------------
  63. //
  64. // LookupAppidData
  65. //
  66. // Loads the registry configuration for the given APPID.
  67. //
  68. //--------------------------------------------------------------------------
  69. HRESULT
  70. LookupAppidData(
  71. IN GUID & AppidGuid,
  72. IN CToken * pToken,
  73. IN DWORD Option,
  74. OUT CAppidData ** ppAppidData
  75. )
  76. {
  77. HRESULT hr = S_OK;
  78. WCHAR wszAppid[GUIDSTR_MAX];
  79. wStringFromGUID2( AppidGuid, wszAppid, sizeof(wszAppid) );
  80. *ppAppidData = new CAppidData( wszAppid, pToken );
  81. if ( ! *ppAppidData )
  82. hr = E_OUTOFMEMORY;
  83. else
  84. hr = (*ppAppidData)->Load( Option );
  85. return (hr);
  86. }
  87. //
  88. // CClsidData
  89. //
  90. CClsidData::CClsidData(
  91. IN GUID & Clsid,
  92. IN CToken * pToken,
  93. IN IComClassInfo* pComClassInfo
  94. )
  95. {
  96. if ( pToken )
  97. pToken->AddRef();
  98. _pToken = pToken;
  99. _Clsid = Clsid;
  100. _pAppid = NULL;
  101. _ServerType = SERVERTYPE_NONE;
  102. _DllThreadModel = SINGLE_THREADED;
  103. _pwszServer = NULL;
  104. _pIComCI = pComClassInfo;
  105. if (pComClassInfo)
  106. {
  107. pComClassInfo->AddRef();
  108. pComClassInfo->Lock();
  109. }
  110. _pIClassCI = NULL;
  111. _pICPI = NULL;
  112. _pwszDarwinId = NULL;
  113. _pwszDllSurrogate = NULL;
  114. _hSaferLevel = NULL;
  115. _dwAcceptableCtx = 0;
  116. _bIsInprocClass = FALSE;
  117. memset(_wszClsid, 0, sizeof(_wszClsid));
  118. }
  119. CClsidData::~CClsidData()
  120. {
  121. Purge();
  122. #ifndef _CHICAGO_
  123. if ( _pToken )
  124. _pToken->Release();
  125. _pToken = 0;
  126. #endif
  127. if ( _pIComCI != NULL )
  128. {
  129. _pIComCI->Unlock();
  130. _pIComCI->Release();
  131. }
  132. if ( _pIClassCI != NULL )
  133. _pIClassCI->Release();
  134. if ( _pICPI != NULL )
  135. _pICPI->Release();
  136. }
  137. //-------------------------------------------------------------------------
  138. //
  139. // CClsidData::Load
  140. //
  141. // Forces a load of all registry keys and values for this clsid and its
  142. // associated APPID.
  143. //
  144. //-------------------------------------------------------------------------
  145. HRESULT
  146. CClsidData::Load(
  147. IN DWORD Option
  148. )
  149. {
  150. HRESULT hr = E_FAIL;
  151. LocalServerType lsType = LocalServerType32;
  152. ProcessType pType = ProcessTypeNormal;
  153. ThreadingModel tModel = SingleThreaded;
  154. DWORD dwAcceptableClsCtx = 0;
  155. IComServices *pServices = NULL;
  156. IComClassInfo2 *pIComCI2 = NULL;
  157. //
  158. // Catalog cruft
  159. //
  160. hr = InitializeCatalogIfNecessary();
  161. if ( FAILED(hr) )
  162. {
  163. goto cleanup;
  164. }
  165. if ( _pIComCI == NULL )
  166. {
  167. if ( _pToken )
  168. {
  169. // Ok, here's the deal.
  170. // First we need to make sure we've exhausted all of the LocalServer
  171. // options on the machine before turning to a remote server option,
  172. // because the classinfo will always say yes to remote server.
  173. hr = gpCatalogSCM->GetClassInfo ( CLSCTX_LOCAL_SERVER,
  174. _pToken,
  175. _Clsid,
  176. IID_IComClassInfo,
  177. (void**) &_pIComCI );
  178. if ( _pIComCI == NULL || hr != S_OK )
  179. {
  180. // Exhaustive search for localserver failed, or we just want
  181. // the first thing we find. Just do a normal search.
  182. // REVIEW: Will the do the right thing for 32bit CLSID?
  183. // What about Darwin?
  184. hr = gpCatalogSCM->GetClassInfo ( 0,
  185. _pToken,
  186. _Clsid,
  187. IID_IComClassInfo,
  188. (void**) &_pIComCI );
  189. }
  190. }
  191. else
  192. {
  193. hr = gpCatalog->GetClassInfo ( _Clsid,
  194. IID_IComClassInfo,
  195. (void**) &_pIComCI );
  196. }
  197. if ( _pIComCI == NULL || hr != S_OK )
  198. {
  199. hr = REGDB_E_CLASSNOTREG;
  200. goto cleanup;
  201. }
  202. _pIComCI->Lock();
  203. }
  204. hr = _pIComCI->QueryInterface(IID_IComClassInfo2, (void **)&pIComCI2);
  205. if(SUCCEEDED(hr))
  206. {
  207. BOOL bClassEnabled;
  208. pIComCI2->IsEnabled(&bClassEnabled);
  209. pIComCI2->Release();
  210. if(bClassEnabled == FALSE)
  211. {
  212. hr = CO_E_CLASS_DISABLED;
  213. goto cleanup;
  214. }
  215. }
  216. // Treat As possible so read clsid
  217. GUID *pguid;
  218. hr = _pIComCI->GetConfiguredClsid(&pguid);
  219. _Clsid = *pguid;
  220. wStringFromGUID2(_Clsid, _wszClsid, sizeof(_wszClsid));
  221. if ( _pIClassCI == NULL )
  222. {
  223. hr = _pIComCI->QueryInterface (IID_IClassClassicInfo, (void**) &_pIClassCI );
  224. if ( _pIClassCI == NULL || hr != S_OK )
  225. {
  226. hr = REGDB_E_CLASSNOTREG;
  227. goto cleanup;
  228. }
  229. }
  230. if ( _pICPI == NULL )
  231. {
  232. hr = _pIClassCI->GetProcess ( IID_IComProcessInfo, (void**) &_pICPI );
  233. if ( hr != S_OK && _pICPI != NULL )
  234. {
  235. _pICPI->Release();
  236. _pICPI = NULL;
  237. }
  238. hr = S_OK;
  239. }
  240. Purge();
  241. //
  242. // Load Surrogate command line
  243. hr = _pIClassCI->GetSurrogateCommandLine(&_pwszDllSurrogate);
  244. if ( hr != S_OK )
  245. {
  246. // GetSurrogateCommandLine can fail for two reasons: 1) out-of-memory;
  247. // or 2) the class is not configured to run as a surrogate. It is
  248. // somewhat difficult to tell at this point which is which. Therefore,
  249. // we don't let a failure here doesn't stop us; instead we check further
  250. // below for the case where we are supposedly a surrogate but don't have
  251. // a surrogate cmd line.
  252. _pwszDllSurrogate = NULL;
  253. hr = S_OK;
  254. }
  255. //
  256. // Load APPID settings before other non-Darwin CLSID settings.
  257. //
  258. if ( _pICPI != NULL )
  259. {
  260. GUID* pGuidProcessId;
  261. WCHAR wszAppid[GUIDSTR_MAX];
  262. hr = _pICPI->GetProcessId (&pGuidProcessId);
  263. if ( hr != S_OK )
  264. {
  265. hr = REGDB_E_CLASSNOTREG;
  266. goto cleanup;
  267. }
  268. wStringFromGUID2( *pGuidProcessId, wszAppid, sizeof(wszAppid) );
  269. #ifndef _CHICAGO_
  270. _pAppid = new CAppidData( wszAppid, _pToken );
  271. #else
  272. _pAppid = new CAppidData( wszAppid, NULL );
  273. #endif
  274. if ( _pAppid == NULL )
  275. {
  276. hr = E_OUTOFMEMORY;
  277. }
  278. else
  279. {
  280. hr = _pAppid->Load( _pICPI );
  281. }
  282. if ( hr != S_OK )
  283. {
  284. goto cleanup;
  285. }
  286. hr = _pICPI->GetProcessType (&pType);
  287. if ( hr != S_OK )
  288. {
  289. pType = ProcessTypeNormal;
  290. hr = S_OK;
  291. }
  292. }
  293. //
  294. // See if we can find a LocalServer
  295. //
  296. hr = _pIClassCI->GetLocalServerType (&lsType);
  297. if ( hr != S_OK )
  298. {
  299. hr = S_OK;
  300. }
  301. else if ( (pType != ProcessTypeService) &&
  302. (pType != ProcessTypeComPlusService) )
  303. {
  304. if ( lsType == LocalServerType16 )
  305. {
  306. _ServerType = SERVERTYPE_EXE16;
  307. }
  308. else
  309. {
  310. _ServerType = SERVERTYPE_EXE32;
  311. }
  312. hr = _pIClassCI->GetModulePath(CLSCTX_LOCAL_SERVER, &_pwszServer);
  313. if ( hr != S_OK )
  314. {
  315. hr = REGDB_E_CLASSNOTREG;
  316. goto cleanup;
  317. }
  318. else
  319. {
  320. pType = ProcessTypeNormal;
  321. }
  322. }
  323. //
  324. // Set up process type information
  325. //
  326. // Determine the acceptable context of creation
  327. hr = _pIComCI->GetClassContext((CLSCTX)(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER),
  328. (CLSCTX*) &dwAcceptableClsCtx);
  329. if ( SUCCEEDED(hr) )
  330. {
  331. if ( !dwAcceptableClsCtx )
  332. {
  333. if (Option == LOAD_APPID)
  334. {
  335. _bIsInprocClass = TRUE;
  336. }
  337. else
  338. {
  339. hr = REGDB_E_CLASSNOTREG;
  340. }
  341. }
  342. }
  343. if ( FAILED(hr) )
  344. goto cleanup;
  345. // Set the acceptable context of creation
  346. _dwAcceptableCtx = dwAcceptableClsCtx;
  347. switch ( pType )
  348. {
  349. case ProcessTypeNormal:
  350. break;
  351. case ProcessTypeService:
  352. _ServerType = SERVERTYPE_SERVICE;
  353. break;
  354. case ProcessTypeComPlusService:
  355. _ServerType = SERVERTYPE_COMPLUS_SVC;
  356. break;
  357. case ProcessTypeComPlus:
  358. //See if services configured, else normal dllhost
  359. if (_pICPI->QueryInterface(IID_IComServices,
  360. (void**) &pServices) == S_OK )
  361. {
  362. _ServerType = SERVERTYPE_COMPLUS;
  363. pServices->Release();
  364. }
  365. else
  366. _ServerType = SERVERTYPE_DLLHOST;
  367. break;
  368. case ProcessTypeLegacySurrogate:
  369. _ServerType = SERVERTYPE_SURROGATE;
  370. hr = _pIClassCI->GetModulePath(CLSCTX_INPROC_SERVER, &_pwszServer);
  371. if ( hr != S_OK )
  372. {
  373. hr = REGDB_E_CLASSNOTREG;
  374. goto cleanup;
  375. }
  376. break;
  377. default:
  378. hr = REGDB_E_CLASSNOTREG;
  379. goto cleanup;
  380. break;
  381. }
  382. //
  383. // Other process info
  384. //
  385. if ( S_OK != _pIClassCI->GetThreadingModel (&tModel) )
  386. {
  387. hr = REGDB_E_BADTHREADINGMODEL;
  388. }
  389. else
  390. {
  391. switch ( tModel )
  392. {
  393. case ApartmentThreaded:
  394. _DllThreadModel = APT_THREADED;
  395. break;
  396. case FreeThreaded:
  397. _DllThreadModel = FREE_THREADED;
  398. break;
  399. case SingleThreaded:
  400. default:
  401. _DllThreadModel = SINGLE_THREADED;
  402. break;
  403. case BothThreaded:
  404. case NeutralThreaded:
  405. _DllThreadModel = BOTH_THREADED;
  406. break;
  407. }
  408. }
  409. //
  410. // Safer Level.
  411. //
  412. hr = CalculateSaferLevel();
  413. cleanup:
  414. if ( _ServerType == SERVERTYPE_SURROGATE ||
  415. _ServerType == SERVERTYPE_COMPLUS ||
  416. _ServerType == SERVERTYPE_DLLHOST)
  417. {
  418. if (!_pwszDllSurrogate)
  419. {
  420. // we're supposed to be a surrogate, but don't have a cmd line for such
  421. if (SUCCEEDED(hr))
  422. hr = E_OUTOFMEMORY;
  423. }
  424. }
  425. if ( FAILED(hr) )
  426. {
  427. Purge();
  428. if ( _pIComCI != NULL )
  429. {
  430. _pIComCI->Unlock();
  431. _pIComCI->Release();
  432. _pIComCI = NULL;
  433. }
  434. if ( _pIClassCI != NULL )
  435. {
  436. _pIClassCI->Release();
  437. _pIClassCI = NULL;
  438. }
  439. if ( _pICPI != NULL )
  440. {
  441. _pICPI->Release();
  442. _pICPI = NULL;
  443. }
  444. }
  445. return (hr);
  446. }
  447. //-------------------------------------------------------------------------
  448. //
  449. // CClsidData::Purge
  450. //
  451. // Frees and clears all member data except for clsid registry key and
  452. // Darwin ID values.
  453. //
  454. //-------------------------------------------------------------------------
  455. void
  456. CClsidData::Purge()
  457. {
  458. if ( _pAppid )
  459. {
  460. delete _pAppid;
  461. }
  462. _pAppid = NULL;
  463. _ServerType = SERVERTYPE_NONE;
  464. _DllThreadModel = SINGLE_THREADED;
  465. _pwszServer = NULL;
  466. _pwszDarwinId = NULL;
  467. _pwszDllSurrogate = NULL;
  468. if (_hSaferLevel)
  469. {
  470. SaferCloseLevel(_hSaferLevel);
  471. _hSaferLevel = NULL;
  472. }
  473. }
  474. //-------------------------------------------------------------------------
  475. //
  476. // CClsidData::CalculateSaferLevel
  477. //
  478. // Determine (and open) the safer level for this CLSID. The decision
  479. // process is as follows:
  480. //
  481. // - If a SAFER level is configured on the application, use that.
  482. // - Otherwise, if automatic enforcement is ON:
  483. // - If we can get a SAFER level from the file, use that.
  484. // - Otherwise, if there's a default SAFER level, use that.
  485. // - Otherwise, don't use SAFER.
  486. // - Otherwise, don't use SAFER.
  487. //
  488. //-------------------------------------------------------------------------
  489. HRESULT
  490. CClsidData::CalculateSaferLevel()
  491. {
  492. HRESULT hr = S_OK;
  493. //
  494. // One has already been calculated, return it.
  495. //
  496. if (_hSaferLevel)
  497. {
  498. return S_OK;
  499. }
  500. //
  501. // Get the configured safer level...
  502. //
  503. if (_pAppid)
  504. {
  505. DWORD dwSaferLevel;
  506. // GetSaferLevel returns TRUE if we have a configured safer level....
  507. BOOL fSaferConfigured = _pAppid->GetSaferLevel(&dwSaferLevel);
  508. if (fSaferConfigured)
  509. {
  510. if (!SaferCreateLevel(SAFER_SCOPEID_MACHINE,
  511. dwSaferLevel,
  512. SAFER_LEVEL_OPEN,
  513. &_hSaferLevel,
  514. NULL))
  515. {
  516. _hSaferLevel = NULL;
  517. hr = HRESULT_FROM_WIN32(GetLastError());
  518. }
  519. else
  520. {
  521. hr = S_OK;
  522. }
  523. }
  524. }
  525. return hr;
  526. }
  527. //
  528. // CAppidData
  529. //
  530. CAppidData::CAppidData(
  531. IN WCHAR * pwszAppid,
  532. IN CToken * pToken
  533. )
  534. {
  535. ASSERT( lstrlenW( pwszAppid ) == GUIDSTR_MAX - 1 );
  536. lstrcpyW( _wszAppid, pwszAppid );
  537. BOOL bGuidConv = wGUIDFromString(_wszAppid,&_GuidAppid);
  538. Win4Assert(bGuidConv && "AppID is not a well-formed GUID");
  539. #ifndef _CHICAGO_
  540. if ( pToken )
  541. pToken->AddRef();
  542. _pToken = pToken;
  543. #endif
  544. _bActivateAtStorage = FALSE;
  545. #ifndef _CHICAGO_
  546. _pwszService = 0;
  547. _pwszServiceParameters = 0;
  548. _pwszRunAsUser = 0;
  549. _pwszRunAsDomain = 0;
  550. _pLaunchPermission = 0;
  551. #endif
  552. _pwszRemoteServerNames = 0;
  553. _bComPlusProcess = FALSE;
  554. _pICPI = NULL;
  555. _dwSaferLevel = 0;
  556. _fSaferLevelValid = FALSE;
  557. }
  558. CAppidData::~CAppidData()
  559. {
  560. Purge();
  561. #ifndef _CHICAGO_
  562. if ( _pToken )
  563. _pToken->Release();
  564. #endif
  565. if ( _pICPI != NULL )
  566. _pICPI->Release();
  567. }
  568. //-------------------------------------------------------------------------
  569. //
  570. // CAppidData::Load
  571. //
  572. // Reads all named value settings for this APPID.
  573. //
  574. //-------------------------------------------------------------------------
  575. HRESULT
  576. CAppidData::Load( IN DWORD Option )
  577. {
  578. HRESULT hr;
  579. IComProcessInfo *pICPI = NULL;
  580. hr = InitializeCatalogIfNecessary();
  581. if (FAILED(hr))
  582. return hr;
  583. //
  584. // Ok, if we don't already have a IComProcesssInfo object, and somebody
  585. // has passed an Option in to us, then we will get a special IComProcessInfo
  586. // based on the option passed in.
  587. //
  588. if ((_pICPI == NULL) && (Option))
  589. {
  590. //BUGBUG: Either pull out the if or pull out the assert.
  591. ASSERT(_pToken && "Asked for a special ICPI without a token!");
  592. if (_pToken)
  593. {
  594. hr = gpCatalogSCM->GetProcessInfo(Option,
  595. _pToken,
  596. _GuidAppid,
  597. IID_IComProcessInfo,
  598. (void **)&pICPI);
  599. }
  600. if (( hr != S_OK ) || ( pICPI == NULL ))
  601. return REGDB_E_CLASSNOTREG;
  602. }
  603. return Load ( pICPI );
  604. }
  605. HRESULT
  606. CAppidData::Load( IN IComProcessInfo *pICPI )
  607. {
  608. HRESULT hr;
  609. IComProcessInfo2 *pICPI2 = NULL;
  610. ProcessType pType = ProcessTypeNormal;
  611. WCHAR* pwszTmpValue = NULL;
  612. WCHAR* pwszRunAsDomain = NULL;
  613. int len = 0;
  614. DWORD dwJunk;
  615. hr = InitializeCatalogIfNecessary();
  616. if ( FAILED(hr) )
  617. {
  618. goto cleanup;
  619. }
  620. if ( _pICPI == NULL )
  621. {
  622. if ( pICPI != NULL )
  623. {
  624. _pICPI = pICPI;
  625. _pICPI->AddRef();
  626. }
  627. #ifndef _CHICAGO_
  628. else if ( _pToken )
  629. hr = gpCatalogSCM->GetProcessInfo (0,
  630. _pToken,
  631. _GuidAppid,
  632. IID_IComProcessInfo,
  633. (void**) &_pICPI );
  634. else
  635. #endif // _CHICAGO_
  636. hr = gpCatalog->GetProcessInfo ( _GuidAppid,
  637. IID_IComProcessInfo,
  638. (void**) &_pICPI );
  639. if ( _pICPI == NULL || hr != S_OK )
  640. {
  641. hr = REGDB_E_CLASSNOTREG;
  642. goto cleanup;
  643. }
  644. }
  645. //
  646. // ActivateAtStorage
  647. //
  648. hr = _pICPI->GetActivateAtStorage (&_bActivateAtStorage);
  649. if ( hr != S_OK )
  650. {
  651. _bActivateAtStorage = FALSE;
  652. hr = S_OK;
  653. }
  654. //
  655. // ProcessType
  656. //
  657. hr = _pICPI->GetProcessType (&pType);
  658. if ( hr != S_OK )
  659. {
  660. pType = ProcessTypeNormal;
  661. hr = S_OK;
  662. }
  663. //
  664. // ComPlus?
  665. //
  666. // NOTE!!!!:: This is true for normal dllhost.exe regardless of
  667. // whether they are really complus or not. We won't
  668. // distinguish this in here in AppidData but in
  669. // ClsidData
  670. _bComPlusProcess = pType == ProcessTypeComPlus;
  671. //
  672. // RemoteServerName
  673. //
  674. hr = _pICPI->GetRemoteServerName (&_pwszRemoteServerNames);
  675. if ( hr != S_OK )
  676. {
  677. _pwszRemoteServerNames = NULL;
  678. hr = S_OK;
  679. }
  680. //
  681. // LaunchPermision
  682. //
  683. hr = _pICPI->GetLaunchPermission ( (void**) &_pLaunchPermission, &dwJunk );
  684. if ( hr != S_OK )
  685. {
  686. _pLaunchPermission = NULL;
  687. hr = S_OK;
  688. }
  689. //
  690. // LocalService and ServiceParameters
  691. //
  692. hr = _pICPI->GetServiceName (&_pwszService);
  693. if ( hr != S_OK )
  694. {
  695. _pwszService = NULL;
  696. hr = S_OK;
  697. }
  698. hr = _pICPI->GetServiceParameters (&_pwszServiceParameters);
  699. if ( hr != S_OK )
  700. {
  701. _pwszServiceParameters = NULL;
  702. hr = S_OK;
  703. }
  704. //
  705. // RunAs
  706. //
  707. hr = _pICPI->GetRunAsUser (&pwszTmpValue);
  708. if ( hr != S_OK )
  709. {
  710. _pwszRunAsUser = NULL;
  711. _pwszRunAsDomain = NULL;
  712. hr = S_OK;
  713. }
  714. else
  715. {
  716. len = lstrlenW(pwszTmpValue)+1;
  717. _pwszRunAsUser = new WCHAR[len];
  718. if (!_pwszRunAsUser)
  719. {
  720. hr = E_OUTOFMEMORY;
  721. goto cleanup;
  722. }
  723. lstrcpyW(_pwszRunAsUser, pwszTmpValue);
  724. pwszTmpValue = _pwszRunAsUser;
  725. while ( *pwszTmpValue && *pwszTmpValue != L'\\' )
  726. pwszTmpValue++;
  727. if ( ! *pwszTmpValue )
  728. {
  729. // user name, no domain name, use the machine name
  730. _pwszRunAsDomain = gpwszLocalMachineDomain;
  731. }
  732. else
  733. {
  734. // domain\user
  735. Win4Assert( L'\\' == *pwszTmpValue );
  736. *pwszTmpValue = 0;
  737. _pwszRunAsDomain = _pwszRunAsUser;
  738. _pwszRunAsUser = pwszTmpValue + 1;
  739. if ( ! *_pwszRunAsUser )
  740. {
  741. hr = E_FAIL;
  742. goto cleanup;
  743. }
  744. }
  745. }
  746. //
  747. // Safer trust level.
  748. //
  749. hr = _pICPI->QueryInterface(IID_IComProcessInfo2, (void **)&pICPI2);
  750. if (SUCCEEDED(hr))
  751. {
  752. hr = pICPI2->GetSaferTrustLevel(&_dwSaferLevel);
  753. pICPI2->Release();
  754. }
  755. // If we couldn't get a configured trust level, make
  756. // sure we remember that.
  757. if (FAILED(hr))
  758. {
  759. _fSaferLevelValid = FALSE;
  760. hr = S_OK;
  761. }
  762. else
  763. {
  764. _fSaferLevelValid = TRUE;
  765. }
  766. cleanup:
  767. if ( FAILED(hr) )
  768. {
  769. Purge();
  770. if ( _pICPI != NULL )
  771. {
  772. _pICPI->Release();
  773. _pICPI = NULL;
  774. }
  775. }
  776. return (hr);
  777. }
  778. //-------------------------------------------------------------------------
  779. //
  780. // CAppidData::Purge
  781. //
  782. // Frees and clears all named value settings for this APPID.
  783. //
  784. //-------------------------------------------------------------------------
  785. void
  786. CAppidData::Purge()
  787. {
  788. _pwszService = 0;
  789. _pwszServiceParameters = 0;
  790. _pLaunchPermission = 0;
  791. // This is too tricky, so it goes. If we've assigned RunAsDomain
  792. // the address of the global local machine name, then the buffer
  793. // we allocated is pointed at by _pwszRunAsUser. Otherwise, it's
  794. // pointed at by _pwszRunAsDomain ('cause if both user and domain
  795. // are in the string, domain is first).
  796. if ( _pwszRunAsUser != NULL )
  797. {
  798. if ( _pwszRunAsDomain == gpwszLocalMachineDomain )
  799. {
  800. delete [] _pwszRunAsUser;
  801. }
  802. else
  803. {
  804. delete [] _pwszRunAsDomain;
  805. }
  806. }
  807. _pwszRunAsUser = 0;
  808. _pwszRunAsDomain = 0;
  809. _fSaferLevelValid = FALSE;
  810. _dwSaferLevel = 0;
  811. _pwszRemoteServerNames = 0;
  812. _bActivateAtStorage = 0;
  813. }
  814. BOOL
  815. CAppidData::CertifyServer(
  816. CProcess * pProcess
  817. )
  818. {
  819. PSID pRequiredSid = NULL;
  820. HANDLE hToken = 0;
  821. BOOL bStatus;
  822. if ( _pwszService )
  823. {
  824. SERVICE_STATUS ServiceStatus;
  825. SC_HANDLE hService;
  826. ASSERT(g_hServiceController);
  827. hService = OpenService( g_hServiceController,
  828. _pwszService,
  829. GENERIC_READ );
  830. if ( ! hService )
  831. return (FALSE);
  832. bStatus = QueryServiceStatus( hService, &ServiceStatus );
  833. if ( bStatus )
  834. {
  835. if ( (ServiceStatus.dwCurrentState == SERVICE_STOPPED) ||
  836. (ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING) )
  837. bStatus = FALSE;
  838. }
  839. CloseServiceHandle(hService);
  840. return (bStatus);
  841. }
  842. if ( ( ! _pwszRunAsUser ) && ( ! IsInteractiveUser() ) )
  843. return (TRUE);
  844. if ( IsInteractiveUser() )
  845. {
  846. ULONG ulSessionId = pProcess->GetToken()->GetSessionId();
  847. if ( ulSessionId )
  848. {
  849. hToken = GetShellProcessToken( ulSessionId );
  850. }
  851. else
  852. {
  853. // hToken = GetShellProcessToken();
  854. hToken = GetCurrentUserTokenW(L"WinSta0", TOKEN_ALL_ACCESS);
  855. }
  856. }
  857. else
  858. hToken = GetRunAsToken( 0, // CLSCTX isn't always available here
  859. _wszAppid,
  860. _pwszRunAsDomain,
  861. _pwszRunAsUser );
  862. if (hToken)
  863. {
  864. DWORD dwSaferLevel;
  865. if (GetSaferLevel(&dwSaferLevel))
  866. {
  867. //
  868. // If a safer level is configured, then the person being launched
  869. // must have the same safer restrictions as we expected put on them.
  870. //
  871. SAFER_LEVEL_HANDLE hSaferLevel = NULL;
  872. HANDLE hSaferToken = NULL;
  873. bStatus = SaferCreateLevel(SAFER_SCOPEID_MACHINE,
  874. dwSaferLevel,
  875. SAFER_LEVEL_OPEN,
  876. &hSaferLevel,
  877. NULL);
  878. if (bStatus)
  879. {
  880. bStatus = SaferComputeTokenFromLevel(hSaferLevel,
  881. hToken,
  882. &hSaferToken,
  883. 0,
  884. NULL);
  885. SaferCloseLevel(hSaferLevel);
  886. }
  887. if (bStatus)
  888. {
  889. NtClose(hToken);
  890. hToken = hSaferToken;
  891. }
  892. }
  893. else
  894. bStatus = TRUE;
  895. if (bStatus)
  896. {
  897. if (S_OK != pProcess->GetToken()->MatchToken(hToken, TRUE))
  898. bStatus = FALSE;
  899. }
  900. }
  901. else
  902. bStatus = FALSE;
  903. if ( hToken )
  904. NtClose( hToken );
  905. return (bStatus);
  906. }