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.

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