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.

1622 lines
44 KiB

  1. //
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // Author: DebiM
  7. // Date: January 97
  8. // Revision History:
  9. // Made Changes for reimplementation with adsldpc interfaces.
  10. // UShaji, Mar 1998
  11. //
  12. // Class Access Implementation
  13. //
  14. // This source file contains implementations for IClassAccess
  15. // interface on CAppContainer object.
  16. //
  17. // It uses ADs interfaces (over LDAP) to talk to an LDAP
  18. // provider such as NTDS.
  19. //
  20. //---------------------------------------------------------------------
  21. //
  22. #include "cstore.hxx"
  23. CBindingList BindingCache;
  24. //
  25. // Critical Section for All Global Objects.
  26. //
  27. extern CRITICAL_SECTION ClassStoreBindList;
  28. HRESULT
  29. UsnGet(ADS_ATTR_INFO Attr, CSUSN *pUsn);
  30. long CompareUsn(CSUSN *pUsn1, CSUSN *pUsn2)
  31. {
  32. return CompareFileTime((FILETIME *)pUsn1, (FILETIME *)pUsn2);
  33. }
  34. void GetExpiredTime( FILETIME* pftCurrentTime, FILETIME* pftExpiredTime )
  35. {
  36. //
  37. // Add the cache interval time to determine
  38. // the time this will expire
  39. //
  40. LARGE_INTEGER liTime;
  41. //
  42. // First copy the filetime to a large integer so
  43. // we can perform arithmetic
  44. //
  45. liTime.LowPart = pftCurrentTime->dwLowDateTime;
  46. liTime.HighPart = pftCurrentTime->dwHighDateTime;
  47. //
  48. // The compiler can perform 64 bit math -- use this
  49. // to perform the arithmetic for calculating the
  50. // time at which cache entries will expire
  51. //
  52. liTime.QuadPart += CACHE_PURGE_TIME_FILETIME_INTERVAL;
  53. //
  54. // Now copy the information back to the caller's structure
  55. //
  56. pftExpiredTime->dwLowDateTime = liTime.LowPart;
  57. pftExpiredTime->dwHighDateTime = liTime.HighPart;
  58. }
  59. BOOL IsExpired(
  60. FILETIME* pftCurrentTime,
  61. FILETIME* pftExpiredTime)
  62. {
  63. SYSTEMTIME SystemTimeCurrent;
  64. SYSTEMTIME SystemTimeExpiration;
  65. BOOL bRetrievedTime;
  66. bRetrievedTime = FileTimeToSystemTime(
  67. pftCurrentTime,
  68. &SystemTimeCurrent);
  69. bRetrievedTime &= FileTimeToSystemTime(
  70. pftExpiredTime,
  71. &SystemTimeExpiration);
  72. if ( bRetrievedTime )
  73. {
  74. CSDBGPrint((
  75. DM_VERBOSE,
  76. IDS_CSTORE_CACHE_EXPIRE,
  77. L"Current Time",
  78. SystemTimeCurrent.wMonth,
  79. SystemTimeCurrent.wDay,
  80. SystemTimeCurrent.wYear,
  81. SystemTimeCurrent.wHour,
  82. SystemTimeCurrent.wMinute,
  83. SystemTimeCurrent.wSecond));
  84. CSDBGPrint((
  85. DM_VERBOSE,
  86. IDS_CSTORE_CACHE_EXPIRE,
  87. L"Expire Time",
  88. SystemTimeExpiration.wMonth,
  89. SystemTimeExpiration.wDay,
  90. SystemTimeExpiration.wYear,
  91. SystemTimeExpiration.wHour,
  92. SystemTimeExpiration.wMinute,
  93. SystemTimeExpiration.wSecond));
  94. }
  95. //
  96. // Compare the current time to the expiration time
  97. //
  98. LONG CompareResult;
  99. CompareResult = CompareFileTime(
  100. pftCurrentTime,
  101. pftExpiredTime);
  102. //
  103. // If the current time is later than the expired time,
  104. // then we have expired
  105. //
  106. if ( CompareResult > 0 )
  107. {
  108. return TRUE;
  109. }
  110. return FALSE;
  111. }
  112. //
  113. // CAppContainer implementation
  114. //
  115. CAppContainer::CAppContainer()
  116. {
  117. m_fOpen = FALSE;
  118. m_ADsContainer = NULL;
  119. m_ADsPackageContainer = NULL;
  120. m_szPackageName = NULL;
  121. memset (&m_PolicyId, 0, sizeof(GUID));
  122. m_KnownMissingClsidCache.sz = 0;
  123. m_KnownMissingClsidCache.start = 0;
  124. m_KnownMissingClsidCache.end = 0;
  125. m_uRefs = 1;
  126. m_szGpoPath = NULL;
  127. m_pRsopToken = NULL;
  128. }
  129. //
  130. // CAppContainer implementation
  131. //
  132. /*----------------------------------------------------------------------*
  133. CAppContainer Constructor:
  134. Parameters:
  135. [in] szStoreName: The Class Store Name without 'ADCS:' moniker
  136. [out] phr The Error Code returned.
  137. Remarks: Tries to Bind to Base Class Store Container, get the version
  138. Number and Packages and Classes container underneath.
  139. Initializes members corresp. to their Names
  140. Return Codes:
  141. Success S_OK
  142. Failures CS_E_INVALID_VERSION
  143. Look at RemapErrorCodes
  144. *----------------------------------------------------------------------*/
  145. CAppContainer::CAppContainer(CServerContext* pServerContext,
  146. LPOLESTR szStoreName,
  147. PRSOPTOKEN pRsopToken,
  148. HRESULT* phr)
  149. {
  150. LPOLESTR pszName = NULL;
  151. DWORD dwStoreVersion = 0;
  152. LPOLESTR AttrNames[] = {STOREVERSION, POLICYDN};
  153. DWORD posn = 0, cgot = 0;
  154. ADS_SEARCHPREF_INFO SearchPrefs[3];
  155. ADS_ATTR_INFO * pAttrsGot = NULL;
  156. m_szGpoPath = NULL;
  157. m_pRsopToken = pRsopToken;
  158. *phr = S_OK;
  159. if ( pServerContext )
  160. {
  161. *phr = m_ServerContext.Initialize( pServerContext );
  162. if ( FAILED(*phr) )
  163. {
  164. return;
  165. }
  166. }
  167. // set the search preference for the search Handle
  168. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  169. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  170. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  171. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  172. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  173. SearchPrefs[1].vValue.Integer = SEARCHPAGESIZE;
  174. SearchPrefs[2].dwSearchPref = ADS_SEARCHPREF_SECURITY_MASK;
  175. SearchPrefs[2].vValue.dwType = ADSTYPE_INTEGER;
  176. SearchPrefs[2].vValue.Integer =
  177. OWNER_SECURITY_INFORMATION |
  178. GROUP_SECURITY_INFORMATION |
  179. DACL_SECURITY_INFORMATION;
  180. memset (&m_PolicyId, 0, sizeof(GUID));
  181. m_fOpen = FALSE;
  182. m_ADsContainer = NULL;
  183. m_ADsPackageContainer = NULL;
  184. m_szPackageName = NULL;
  185. memset (&m_PolicyId, 0, sizeof(GUID));
  186. m_KnownMissingClsidCache.sz = 0;
  187. m_KnownMissingClsidCache.start = 0;
  188. m_KnownMissingClsidCache.end = 0;
  189. m_uRefs = 1;
  190. //
  191. // For every interface pointer, we create a separate session
  192. //
  193. // Bind to a Class Store Container Object
  194. // Cache the interface pointer
  195. //
  196. *phr = StringCchCopy (m_szContainerName, _MAX_PATH, szStoreName);
  197. ERROR_ON_FAILURE(*phr);
  198. *phr = DSServerOpenDSObject( &m_ServerContext, m_szContainerName, GetDsFlags(),
  199. &m_ADsContainer);
  200. ERROR_ON_FAILURE(*phr);
  201. //
  202. // Check the Schema Version of this container
  203. //
  204. *phr = ADSIGetObjectAttributes(m_ADsContainer, AttrNames, 2, &pAttrsGot, &cgot);
  205. if ((SUCCEEDED(*phr)) && (cgot))
  206. {
  207. posn = GetPropertyFromAttr(pAttrsGot, cgot, STOREVERSION);
  208. dwStoreVersion = 0;
  209. if (posn < cgot)
  210. {
  211. //
  212. // Ensure that we validate the type of the data return by the ds --
  213. // if the type is not valid (most often this occurs because adsi
  214. // could not create a schema cache on the local machine), we
  215. // will assume it to be invalid. The version number will be
  216. // initialized to 0, which is invalid, and we will abort.
  217. //
  218. if ( ADSTYPE_INTEGER == pAttrsGot[posn].dwADsType )
  219. {
  220. UnpackDWFrom(pAttrsGot[posn], &dwStoreVersion);
  221. }
  222. }
  223. if (dwStoreVersion != SCHEMA_VERSION_NUMBER)
  224. {
  225. *phr = CS_E_INVALID_VERSION;
  226. }
  227. if (SUCCEEDED(*phr))
  228. {
  229. LPOLESTR szPolicyPath = NULL;
  230. posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYDN);
  231. if (posn < cgot)
  232. {
  233. LPOLESTR szParentPath = NULL, szPolicyGuid = NULL;
  234. UnpackStrFrom(pAttrsGot[posn], &szPolicyPath);
  235. //
  236. BuildADsParentPath(szPolicyPath, &szParentPath, &szPolicyGuid);
  237. if (szParentPath)
  238. FreeADsMem(szParentPath);
  239. if (szPolicyGuid)
  240. {
  241. if (wcslen(szPolicyGuid) == 41)
  242. {
  243. // valid GUID
  244. GUIDFromString(&szPolicyGuid[4], &m_PolicyId);
  245. }
  246. FreeADsMem(szPolicyGuid);
  247. }
  248. }
  249. }
  250. }
  251. else
  252. {
  253. if (SUCCEEDED(*phr))
  254. {
  255. *phr = CS_E_INVALID_VERSION;
  256. }
  257. }
  258. if (pAttrsGot)
  259. FreeADsMem(pAttrsGot);
  260. ERROR_ON_FAILURE(*phr);
  261. //
  262. // Bind to the Package container Object
  263. // Cache the interface pointer
  264. //
  265. BuildADsPathFromParent(m_szContainerName, PACKAGECONTAINERNAME, &m_szPackageName);
  266. m_ADsPackageContainer = NULL;
  267. *phr = DSServerOpenDSObject( &m_ServerContext, m_szPackageName, GetDsFlags(),
  268. &m_ADsPackageContainer);
  269. ERROR_ON_FAILURE(*phr);
  270. *phr = ADSISetSearchPreference(m_ADsPackageContainer, SearchPrefs, 3);
  271. ERROR_ON_FAILURE(*phr);
  272. m_fOpen = TRUE;
  273. m_uRefs = 1;
  274. m_szGpoPath = AllocGpoPathFromClassStorePath( m_szContainerName );
  275. if ( ! m_szGpoPath )
  276. {
  277. *phr = E_OUTOFMEMORY;
  278. }
  279. Error_Cleanup:
  280. *phr = RemapErrorCode(*phr, m_szContainerName);
  281. return;
  282. }
  283. /*----------------------------------------------------------------------*
  284. CAppContainer Destructor:
  285. Parameters:
  286. None
  287. Function:
  288. Destroys CAppContainer object.
  289. Remarks:
  290. Frees all the members.
  291. Return Codes
  292. *----------------------------------------------------------------------*/
  293. CAppContainer::~CAppContainer(void)
  294. {
  295. UINT i;
  296. if (m_fOpen)
  297. {
  298. m_fOpen = FALSE;
  299. }
  300. if (m_ADsPackageContainer)
  301. {
  302. ADSICloseDSObject(m_ADsPackageContainer);
  303. m_ADsPackageContainer = NULL;
  304. FreeADsMem(m_szPackageName);
  305. }
  306. if (m_ADsContainer)
  307. {
  308. ADSICloseDSObject(m_ADsContainer);
  309. m_ADsContainer = NULL;
  310. }
  311. if (m_szGpoPath)
  312. {
  313. CsMemFree(m_szGpoPath);
  314. }
  315. }
  316. //
  317. // Constructor for App Container Class factory
  318. //
  319. unsigned long gulcappcon = 0;
  320. CAppContainerCF::CAppContainerCF()
  321. {
  322. m_uRefs = 1;
  323. InterlockedIncrement((long *) &gulcappcon );
  324. }
  325. //
  326. // Destructor
  327. //
  328. CAppContainerCF::~CAppContainerCF()
  329. {
  330. //
  331. // Cleanup the cache
  332. //
  333. InterlockedDecrement((long *) &gulcappcon );
  334. }
  335. HRESULT __stdcall CAppContainerCF::QueryInterface(REFIID riid, void * * ppvObject)
  336. {
  337. IUnknown *pUnkTemp = NULL;
  338. SCODE sc = S_OK;
  339. if( IsEqualIID( IID_IUnknown, riid ) )
  340. {
  341. pUnkTemp = (IUnknown *)(ITypeLib *)this;
  342. }
  343. else if( IsEqualIID( IID_IClassFactory, riid ) )
  344. {
  345. pUnkTemp = (IUnknown *)(IClassFactory *)this;
  346. }
  347. else if( IsEqualIID( IID_IParseDisplayName, riid ) )
  348. {
  349. pUnkTemp = (IUnknown *)(IParseDisplayName *)this;
  350. }
  351. else
  352. {
  353. sc = (E_NOINTERFACE);
  354. }
  355. if((pUnkTemp != NULL) && (SUCCEEDED(sc)))
  356. {
  357. *ppvObject = (void * )pUnkTemp;
  358. pUnkTemp->AddRef();
  359. }
  360. return(sc);
  361. }
  362. ULONG __stdcall CAppContainerCF::AddRef()
  363. {
  364. InterlockedIncrement(( long * )&m_uRefs );
  365. return m_uRefs;
  366. }
  367. ULONG __stdcall CAppContainerCF::Release()
  368. {
  369. unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs);
  370. unsigned long cRef = m_uRefs;
  371. // 0 is the only valid value to check
  372. if (uTmp == 0)
  373. {
  374. delete this;
  375. }
  376. return(cRef);
  377. }
  378. //
  379. // IClassFactory Overide
  380. //
  381. HRESULT __stdcall CAppContainerCF::CreateInstance(IUnknown * pUnkOuter, REFIID riid,
  382. void ** ppvObject)
  383. {
  384. CAppContainer * pIUnk = NULL;
  385. SCODE sc = S_OK;
  386. if( pUnkOuter == NULL )
  387. {
  388. if( (pIUnk = new CAppContainer()) != NULL)
  389. {
  390. sc = pIUnk->QueryInterface( riid , ppvObject );
  391. if(FAILED(sc))
  392. {
  393. sc = E_UNEXPECTED;
  394. }
  395. pIUnk->Release();
  396. }
  397. else
  398. sc = E_OUTOFMEMORY;
  399. }
  400. else
  401. {
  402. return E_INVALIDARG;
  403. }
  404. return (sc);
  405. }
  406. //---------------------------------------------------------------
  407. //
  408. // Function: CreateConnectedInstance
  409. //
  410. // Synopsis: Returns IClassAccess Pointer, given a class store
  411. // path.
  412. //
  413. // Arguments:
  414. // [in]
  415. // pszPath Class Store Path without the leading ADCS:
  416. //
  417. // pUserSid
  418. // Sid under which the calling thread is running.
  419. // fCache
  420. // Boolean that decides whether to use a cached pointer or
  421. // not.
  422. // [out]
  423. // ppvObject
  424. // IClassAccess Interface pointer
  425. //
  426. // Returns:
  427. // S_OK, E_NOINTERFACE, E_OUTOFMEMORY, CS_E_XXX
  428. //
  429. // if (fCache)
  430. // Looks in the cache to see if we have already tried to bind to the same
  431. // ClassStore Path under the same SID. If it finds it, then we just QI for
  432. // IClassAccess and return. o/w create a new class store pointer and caches it.
  433. // else
  434. // Just binds to a new ClassStore and returns.
  435. //----------------------------------------------------------------
  436. HRESULT __stdcall
  437. CAppContainerCF::CreateConnectedInstance(
  438. CServerContext* pServerContext,
  439. LPOLESTR pszPath,
  440. PSID pUserSid,
  441. PRSOPTOKEN pRsopToken,
  442. BOOL fCache,
  443. void ** ppvObject)
  444. {
  445. CAppContainer * pIUnk = NULL;
  446. SCODE sc = S_OK;
  447. HRESULT hr = S_OK;
  448. BOOL fFound = FALSE;
  449. FILETIME ftCurrentTime;
  450. IClassAccess* pNewClassAccess = NULL;
  451. CBinding* pBinding;
  452. //
  453. // See if we have an existing connection in the cache
  454. //
  455. if (fCache)
  456. {
  457. GetSystemTimeAsFileTime( &ftCurrentTime );
  458. BindingCache.Lock();
  459. pBinding = BindingCache.Find(
  460. pServerContext,
  461. &ftCurrentTime,
  462. pszPath,
  463. pUserSid);
  464. if ( pBinding )
  465. {
  466. if ( FAILED( pBinding->Hr ) )
  467. {
  468. sc = pBinding->Hr;
  469. }
  470. else
  471. {
  472. sc = pBinding->pIClassAccess->
  473. QueryInterface( IID_IClassAccess, ppvObject );
  474. }
  475. }
  476. BindingCache.Unlock();
  477. }
  478. if ( fCache && pBinding )
  479. {
  480. return sc;
  481. }
  482. //
  483. // Couldn't find anything in the cache -- we will have to create a new connection
  484. //
  485. //
  486. // If this is called in the context of policy, ipsec policy may not be enabled.
  487. // Therefore, our communications with the directory would not be secure.
  488. // We will pass TRUE for the secure channel argument of the CAppContainer
  489. // constructor since this code path is exercised during policy and we
  490. // want to ensure security.
  491. //
  492. //
  493. // Note that this object has a refcount of 1 when created
  494. //
  495. if ((pIUnk = new CAppContainer( pServerContext, pszPath, pRsopToken, &sc)) != NULL)
  496. {
  497. if (SUCCEEDED(sc))
  498. {
  499. sc = pIUnk->QueryInterface( IID_IClassAccess, (LPVOID*) &pNewClassAccess );
  500. }
  501. else
  502. {
  503. CSDBGPrint((DM_WARNING,
  504. IDS_CSTORE_BIND_FAIL,
  505. pszPath,
  506. sc));
  507. }
  508. pIUnk->Release();
  509. }
  510. else
  511. {
  512. return E_OUTOFMEMORY;
  513. }
  514. //
  515. // Store the result in the cache -- create a binding
  516. // descriptor so we can cache it
  517. //
  518. CBinding* pNewBinding;
  519. if (fCache)
  520. {
  521. //
  522. // Should not cache situations out of network failures
  523. // For now we are only caching successes OR CS does not exist cases
  524. //
  525. if ((sc == S_OK) || (sc == CS_E_OBJECT_NOTFOUND))
  526. {
  527. HRESULT hrBinding;
  528. hrBinding = E_OUTOFMEMORY;
  529. pNewBinding = new CBinding(
  530. pServerContext,
  531. pszPath,
  532. pUserSid,
  533. pNewClassAccess,
  534. sc,
  535. &hrBinding);
  536. if ( FAILED( hrBinding ) )
  537. {
  538. sc = hrBinding;
  539. fCache = FALSE;
  540. }
  541. }
  542. else
  543. {
  544. fCache = FALSE;
  545. }
  546. }
  547. //
  548. // We have the binding descriptor, now cache it
  549. //
  550. if ( fCache )
  551. {
  552. CBinding* pBindingAdded;
  553. BindingCache.Lock();
  554. //
  555. // Attempt to add the binding -- if one already
  556. // exists, it will destroy the one we pass in and
  557. // use the existing binding
  558. //
  559. pBindingAdded = BindingCache.AddBinding(
  560. &ftCurrentTime,
  561. pNewBinding);
  562. sc = pBindingAdded->Hr;
  563. if ( SUCCEEDED(sc) )
  564. {
  565. sc = pBindingAdded->pIClassAccess->
  566. QueryInterface( IID_IClassAccess, ppvObject );
  567. }
  568. BindingCache.Unlock();
  569. }
  570. else
  571. {
  572. if ( SUCCEEDED(sc) )
  573. {
  574. pNewClassAccess->AddRef();
  575. *ppvObject = pNewClassAccess;
  576. }
  577. }
  578. if ( pNewClassAccess )
  579. {
  580. pNewClassAccess->Release();
  581. }
  582. return (sc);
  583. }
  584. HRESULT __stdcall CAppContainerCF::LockServer(BOOL fLock)
  585. {
  586. if(fLock)
  587. { InterlockedIncrement((long *) &gulcappcon ); }
  588. else
  589. { InterlockedDecrement((long *) &gulcappcon ); }
  590. return(S_OK);
  591. }
  592. //
  593. // IUnknown methods for CAppContainer
  594. //
  595. //
  596. HRESULT __stdcall CAppContainer::QueryInterface(REFIID riid, void * * ppvObject)
  597. {
  598. IUnknown *pUnkTemp = NULL;
  599. SCODE sc = S_OK;
  600. if( IsEqualIID( IID_IUnknown, riid ) )
  601. {
  602. pUnkTemp = (IUnknown *)(IClassAccess *)this;
  603. }
  604. else if( IsEqualIID( IID_IClassAccess, riid ) )
  605. {
  606. pUnkTemp = (IUnknown *)(IClassAccess *)this;
  607. }
  608. /*
  609. else if( IsEqualIID( IID_IClassRefresh, riid ) )
  610. {
  611. pUnkTemp = (IUnknown *)(IClassRefresh *)this;
  612. }
  613. else if( IsEqualIID( IID_ICatInformation, riid ) )
  614. {
  615. pUnkTemp = (IUnknown *)(ICatInformation *)this;
  616. }
  617. */
  618. else
  619. {
  620. sc = (E_NOINTERFACE);
  621. }
  622. if((pUnkTemp != NULL) && (SUCCEEDED(sc)))
  623. {
  624. *ppvObject = (void * )pUnkTemp;
  625. pUnkTemp->AddRef();
  626. }
  627. return(sc);
  628. }
  629. ULONG __stdcall CAppContainer::AddRef()
  630. {
  631. InterlockedIncrement(( long * )&m_uRefs );
  632. return m_uRefs;
  633. }
  634. ULONG __stdcall CAppContainer::Release()
  635. {
  636. unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs);
  637. unsigned long cRef = m_uRefs;
  638. if (uTmp == 0)
  639. {
  640. delete this;
  641. }
  642. return(cRef);
  643. }
  644. /*----------------------------------------------------------------------*
  645. GetPackageDetails:
  646. Parameters:
  647. [in] pszPackageName: The Package Name
  648. [out] pPackageDetail Package Detail Structure.
  649. Functionality:
  650. Returns the PackageDetail corresp. to a Package given
  651. by pszPackageName.
  652. Remarks:
  653. It constructs the Full Package Name
  654. and calls GetPackageDetail
  655. Return Codes:
  656. Success S_OK
  657. Failures Look at RemapErrorCodes
  658. *----------------------------------------------------------------------*/
  659. // This is not being called currently by anybody and hence is still using PackageId.
  660. HRESULT CAppContainer::GetPackageDetails (
  661. LPOLESTR pszPackageId,
  662. PACKAGEDETAIL *pPackageDetail)
  663. {
  664. HRESULT hr = S_OK;
  665. HANDLE hADs = NULL;
  666. WCHAR * szFullName = NULL, szRDN[_MAX_PATH];
  667. ADS_ATTR_INFO * pAttr = NULL;
  668. DWORD cgot;
  669. if ((!pszPackageId))
  670. return E_INVALIDARG;
  671. hr = StringCchPrintf(szRDN, _MAX_PATH, L"CN=%s", pszPackageId);
  672. ERROR_ON_FAILURE(hr);
  673. CSDBGPrint((DM_WARNING,
  674. IDS_CSTORE_PKG_DETAILS,
  675. szRDN));
  676. BuildADsPathFromParent(m_szPackageName, szRDN, &szFullName);
  677. //
  678. // We do not enforce packet integrity options here because
  679. // this is only called in the context of the admin tool and we
  680. // can rely on ipsec to have executed at that point
  681. //
  682. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(), &hADs);
  683. ERROR_ON_FAILURE(hr);
  684. hr = GetPackageDetail (hADs, NULL, pPackageDetail);
  685. ADSICloseDSObject(hADs);
  686. if (pAttr)
  687. FreeADsMem(pAttr);
  688. if (szFullName)
  689. FreeADsMem(szFullName);
  690. Error_Cleanup:
  691. return RemapErrorCode(hr, m_szContainerName);
  692. }
  693. /*----------------------------------------------------------------------*
  694. EnumPackages
  695. Parameters:
  696. [in] pszPackageName Substring match for a package name
  697. [in] pCategory Package Category.
  698. [in] pLastUsn Last modification time.
  699. [in] dwAppFlags Set the following bits to select specific ones
  700. Published Only APPINFO_PUBLISHED
  701. Assigned Only APPINFO_ASSIGNED
  702. Msi Only APPINFO_MSI
  703. Visible APPINFO_VISIBLE
  704. Auto-Install APPINFO_AUTOINSTALL
  705. All Locale APPINFO_ALLLOCALE
  706. All Platform APPINFO_ALLPLATFORM
  707. [out] ppIEnumPackage Returns the Enumerator
  708. Functionality
  709. Obtains an enumerator for packages in the app container.
  710. Remarks:
  711. *----------------------------------------------------------------------*/
  712. HRESULT CAppContainer::EnumPackages (
  713. LPOLESTR pszPackageName,
  714. GUID *pCategory,
  715. ULONGLONG *pLastUsn,
  716. DWORD dwQuerySpec, // AppType options
  717. IEnumPackage **ppIEnumPackage
  718. )
  719. {
  720. const DWORD dwMaxStrLen = 1000;
  721. HRESULT hr = S_OK;
  722. CEnumPackage *pEnum = NULL;
  723. WCHAR szLdapFilter[dwMaxStrLen];
  724. WCHAR szLdapFilterFinal[1500];
  725. UINT len = 0;
  726. UINT fFilters = 0;
  727. CSPLATFORM *pPlatform = NULL, Platform;
  728. DWORD dwAppFlags;
  729. //
  730. // Validate
  731. //
  732. switch ( dwQuerySpec )
  733. {
  734. case APPQUERY_ALL:
  735. case APPQUERY_ADMINISTRATIVE:
  736. case APPQUERY_POLICY:
  737. case APPQUERY_USERDISPLAY:
  738. case APPQUERY_RSOP_LOGGING:
  739. case APPQUERY_RSOP_ARP:
  740. break;
  741. default:
  742. return E_INVALIDARG;
  743. }
  744. *ppIEnumPackage = NULL;
  745. pEnum = new CEnumPackage( &m_ServerContext, m_PolicyId, NULL, m_szContainerName, m_pRsopToken );
  746. if(NULL == pEnum)
  747. return E_OUTOFMEMORY;
  748. //
  749. // Set client side filters
  750. //
  751. dwAppFlags = ClientSideFilterFromQuerySpec( dwQuerySpec, NULL != m_pRsopToken );
  752. //
  753. // Create a LDAP Search Filter based on input params
  754. //
  755. // Count Filters
  756. if (pszPackageName && (*pszPackageName))
  757. fFilters++;
  758. if ((pLastUsn) && (*pLastUsn))
  759. fFilters++;
  760. if (pCategory)
  761. fFilters++;
  762. if (fFilters == 0)
  763. {
  764. // No Conditionals
  765. hr = StringCchPrintf (szLdapFilter,
  766. dwMaxStrLen,
  767. L"(%s=%s)", OBJECTCLASS, CLASS_CS_PACKAGE);
  768. ERROR_ON_FAILURE(hr);
  769. len = wcslen (szLdapFilter);
  770. }
  771. else
  772. {
  773. if (fFilters > 1)
  774. {
  775. hr = StringCchPrintf (szLdapFilter, dwMaxStrLen, L"(&");
  776. ERROR_ON_FAILURE(hr);
  777. len = wcslen (szLdapFilter);
  778. }
  779. else
  780. len = 0;
  781. if (pszPackageName)
  782. {
  783. //
  784. // Validate
  785. //
  786. if (*pszPackageName)
  787. {
  788. hr = StringCchPrintf (&szLdapFilter[len],
  789. dwMaxStrLen - len,
  790. L"(%s=*%s*)",
  791. PACKAGENAME,
  792. pszPackageName);
  793. ERROR_ON_FAILURE(hr);
  794. len = wcslen (szLdapFilter);
  795. }
  796. }
  797. if ((pLastUsn) && (*pLastUsn))
  798. {
  799. SYSTEMTIME SystemTime;
  800. FileTimeToSystemTime(
  801. (CONST FILETIME *) pLastUsn,
  802. &SystemTime);
  803. hr = StringCchPrintf (&szLdapFilter[len],
  804. dwMaxStrLen - len,
  805. L"(%s>=%04d%02d%02d%02d%02d%02d)",
  806. PKGUSN,
  807. SystemTime.wYear,
  808. SystemTime.wMonth,
  809. SystemTime.wDay,
  810. SystemTime.wHour,
  811. SystemTime.wMinute,
  812. SystemTime.wSecond+1);
  813. ERROR_ON_FAILURE(hr);
  814. len = wcslen (szLdapFilter);
  815. }
  816. if (pCategory)
  817. {
  818. STRINGGUID szCat;
  819. StringFromGUID (*pCategory, szCat);
  820. hr = StringCchPrintf (&szLdapFilter[len],
  821. dwMaxStrLen - len,
  822. L"(%s=%s)",
  823. PKGCATEGORYLIST,
  824. szCat);
  825. ERROR_ON_FAILURE(hr);
  826. len = wcslen (szLdapFilter);
  827. }
  828. if (fFilters > 1)
  829. {
  830. if (dwMaxStrLen - len < 2)
  831. {
  832. hr = STRSAFE_E_INSUFFICIENT_BUFFER;
  833. ERROR_ON_FAILURE(hr);
  834. }
  835. szLdapFilter[len] = L')';
  836. szLdapFilter[++len] = NULL;
  837. }
  838. }
  839. //
  840. // Finish setting the server side filter
  841. // based on the query type
  842. //
  843. ServerSideFilterFromQuerySpec(
  844. dwQuerySpec,
  845. NULL != m_pRsopToken,
  846. szLdapFilter,
  847. szLdapFilterFinal,
  848. sizeof(szLdapFilterFinal)/sizeof(szLdapFilterFinal[0]));
  849. CSDBGPrint((DM_WARNING,
  850. IDS_CSTORE_ENUMPACKAGE,
  851. szLdapFilterFinal,
  852. dwAppFlags));
  853. //
  854. // Check all local/platform flags
  855. //
  856. if (!(dwAppFlags & APPFILTER_REQUIRE_THIS_PLATFORM))
  857. {
  858. pPlatform = NULL;
  859. }
  860. else
  861. {
  862. pPlatform = &Platform;
  863. GetDefaultPlatform(pPlatform);
  864. }
  865. if (pLastUsn)
  866. {
  867. //
  868. // Find the current store USN and return it
  869. //
  870. LPOLESTR AttrName = STOREUSN;
  871. ADS_ATTR_INFO * pAttr = NULL;
  872. DWORD cgot = 0;
  873. hr = ADSIGetObjectAttributes(m_ADsContainer, &AttrName, 1, &pAttr, &cgot);
  874. if ((SUCCEEDED(hr)) && (cgot))
  875. {
  876. UsnGet(*pAttr, (CSUSN *)pLastUsn);
  877. if (pAttr)
  878. FreeADsMem(pAttr);
  879. }
  880. }
  881. hr = pEnum->Initialize(m_szPackageName, szLdapFilterFinal, dwQuerySpec, NULL != m_pRsopToken, pPlatform);
  882. ERROR_ON_FAILURE(hr);
  883. hr = pEnum->QueryInterface(IID_IEnumPackage,(void**) ppIEnumPackage);
  884. ERROR_ON_FAILURE(hr);
  885. return S_OK;
  886. Error_Cleanup:
  887. if (pEnum)
  888. delete pEnum;
  889. *ppIEnumPackage = NULL;
  890. return RemapErrorCode(hr, m_szContainerName);
  891. }
  892. // choosing the best package that can be returned after returning from the DS
  893. DWORD CAppContainer::ChooseBestFit(PACKAGEDISPINFO *PackageInfo, UINT *rgPriority, DWORD cRowsFetched)
  894. {
  895. DWORD i=0, k=0, j = 0, temp = 0;
  896. DWORD index[10];
  897. // initialising the indices
  898. for (i = 0; (i < cRowsFetched); i++)
  899. index[i] = i;
  900. // sort the index based on priority and time stamp
  901. for (i = 0; (i < (cRowsFetched-1)); i++)
  902. {
  903. DWORD Pri = rgPriority[i];
  904. k = i;
  905. // max element's index is in k
  906. for (j=(i+1); (j < cRowsFetched); ++j)
  907. {
  908. // order first by weight and then by time stamp.
  909. if ((rgPriority[index[j]] > Pri) ||
  910. ((rgPriority[index[j]] == Pri) &&
  911. (CompareUsn((FILETIME *)&PackageInfo[index[j]].Usn, (FILETIME *)&PackageInfo[index[k]].Usn) == 1)))
  912. {
  913. Pri = rgPriority[index[j]];
  914. k = j;
  915. }
  916. }
  917. if (k != i)
  918. {
  919. temp = index[k];
  920. index[k] = index[i];
  921. index[i] = temp;
  922. }
  923. }
  924. DWORD dwPackage;
  925. DWORD dwBestPackage;
  926. dwBestPackage = 0;
  927. //
  928. // Now the packages are sorted in order from highest precedence to lowest.
  929. // We will now check for upgrades for each package
  930. //
  931. for (dwPackage = 0; (dwPackage < cRowsFetched); dwPackage++)
  932. {
  933. DWORD dwPossibleUpgrader;
  934. PACKAGEDISPINFO* pBestPackage;
  935. pBestPackage = PackageInfo+index[dwBestPackage];
  936. CSDBGPrint((DM_WARNING,
  937. IDS_CSTORE_BESTFIT,
  938. pBestPackage->pszPackageName));
  939. //
  940. // Now search for someone that upgrades the current choice -- look at all packages
  941. // after the current one since we've already determined that the packages before
  942. // this one got upgraded (otherwise we wouldn't be here).
  943. //
  944. for (dwPossibleUpgrader = dwPackage + 1; dwPossibleUpgrader < cRowsFetched; dwPossibleUpgrader ++)
  945. {
  946. PACKAGEDISPINFO* pUpgraderCandidate;
  947. //
  948. // Obviously, we don't need to check the current choice
  949. // to see if it upgrades itself, so skip it
  950. //
  951. if (dwPossibleUpgrader == dwBestPackage)
  952. {
  953. continue;
  954. }
  955. pUpgraderCandidate = PackageInfo + index[dwPossibleUpgrader];
  956. //
  957. // See if the upgrader candidate has any upgrades, if not, keep looking
  958. //
  959. if (0 == pUpgraderCandidate->cUpgrades)
  960. {
  961. continue;
  962. }
  963. //
  964. // Now we have to see if any of those upgrades apply to the package we have
  965. // currently selected as the best
  966. //
  967. DWORD dwUpgrade;
  968. BOOL fFoundUpgrade;
  969. fFoundUpgrade = FALSE;
  970. for (dwUpgrade = 0; dwUpgrade < pUpgraderCandidate->cUpgrades; dwUpgrade++)
  971. {
  972. DWORD dwValidUpgradeMask;
  973. dwValidUpgradeMask = UPGFLG_Uninstall |
  974. UPGFLG_NoUninstall |
  975. UPGFLG_Enforced;
  976. //
  977. // If this is a valid upgrade
  978. //
  979. if (pUpgraderCandidate->prgUpgradeInfoList[dwUpgrade].Flag & dwValidUpgradeMask)
  980. {
  981. //
  982. // Does it upgrade the package we think is best at this point? We only
  983. // consider upgrades in this container, as we no longer allow upgrades from lower
  984. // precedence class stores -- the caller who iterates through each container from
  985. // highest precedence to lowest will simply choose the app from the first container in which
  986. // we have a match.
  987. //
  988. // We use memcmp to compare guids to see if the best choice package's guid is listed
  989. // as being upgraded by this upgrade candidate
  990. //
  991. if (memcmp(&((pUpgraderCandidate->prgUpgradeInfoList)[dwUpgrade].PackageGuid),
  992. &(pBestPackage->PackageGuid), sizeof(GUID) == 0))
  993. {
  994. //
  995. // We have a match -- reset the current best choice to the upgrade candidate
  996. //
  997. dwBestPackage = dwPossibleUpgrader;
  998. //
  999. // another package upgrades this -- no need to look any further, so we quit
  1000. //
  1001. CSDBGPrint((DM_WARNING,
  1002. IDS_CSTORE_BESTFITSKIP,
  1003. pBestPackage->pszPackageName,
  1004. pUpgraderCandidate->pszPackageName));
  1005. break;
  1006. }
  1007. }
  1008. }
  1009. //
  1010. // If we found an upgrade in the list above, we can stop abort the search for an upgrade now --
  1011. // if we found another, it would just be a lower precedence app since we're iterating from highest to lowest,
  1012. // and we want the highest predecence app that upgrades the currently chosen best app
  1013. //
  1014. if (fFoundUpgrade)
  1015. {
  1016. break;
  1017. }
  1018. }
  1019. }
  1020. DWORD dwChoice;
  1021. dwChoice = index[dwBestPackage];
  1022. CSDBGPrint((DM_WARNING,
  1023. IDS_CSTORE_BESTFIT_END,
  1024. PackageInfo[dwChoice].pszPackageName));
  1025. return dwChoice;
  1026. }
  1027. //
  1028. // CAppContainer::GetAppInfo
  1029. // -----------------------------
  1030. //
  1031. //
  1032. //
  1033. // Synopsis: This is the most common access point to the Class Store.
  1034. // It receives a CLSID and a QUERYCONTEXT.
  1035. // It looks up the Class Store container for a matching set
  1036. // of packages with in the context of the QUERYCONTEXT.
  1037. //
  1038. // QUERYCONTEXT includes
  1039. // Execution Context
  1040. // Locale Id
  1041. // Platform/OS
  1042. //
  1043. // If i finds an app that matches the requirements, it returns
  1044. // an PACKAGEDISPINFO structure containing installation details.
  1045. //
  1046. // Arguments: [in] clsid
  1047. // [in] pQryContext
  1048. // [out] pPackageInfo
  1049. //
  1050. // Returns: CS_E_PACKAGE_NOTFOUND
  1051. // S_OK
  1052. //
  1053. //
  1054. //
  1055. HRESULT STDMETHODCALLTYPE
  1056. CAppContainer::GetAppInfo(
  1057. uCLSSPEC * pclsspec, // Class Spec (GUID/Ext/MIME)
  1058. QUERYCONTEXT * pQryContext, // Query Attributes
  1059. PACKAGEDISPINFO * pPackageInfo
  1060. )
  1061. //
  1062. // This is the most common method to access the Class Store.
  1063. // It queries the class store for implementations for a specific
  1064. // Class Id, or File Ext, or ProgID.
  1065. //
  1066. // If a matching implementation is available (for the object type,
  1067. // client architecture, locale and class context) then the installation
  1068. // parameters of the package is returned.
  1069. {
  1070. const DWORD dwMaxStrLen = 1000;
  1071. GUID clsid;
  1072. WCHAR szfilterbuf[dwMaxStrLen];
  1073. WCHAR* szfilter = szfilterbuf;
  1074. WCHAR* szNameFilter;
  1075. STRINGGUID szClsid;
  1076. UINT i, iClsid = 0;
  1077. ULONG cRead;
  1078. HRESULT hr;
  1079. ULONG cSize = _MAX_PATH;
  1080. BOOL fFound = FALSE;
  1081. PLATFORMINFO PlatformInfo;
  1082. LPOLESTR pFileExt = NULL;
  1083. BOOL OnDemandInstallOnly = TRUE;
  1084. WCHAR FileExtLower [10];
  1085. FILETIME ftCurrentTime;
  1086. szNameFilter = NULL;
  1087. memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
  1088. if (!m_fOpen)
  1089. return E_FAIL;
  1090. //
  1091. // Check if the TypeSpec is MIMEType
  1092. // then map it to a CLSID
  1093. //
  1094. switch (pclsspec->tyspec)
  1095. {
  1096. case TYSPEC_CLSID:
  1097. if (IsNullGuid(pclsspec->tagged_union.clsid))
  1098. return E_INVALIDARG;
  1099. //
  1100. // Check against known missing ones
  1101. //
  1102. hr = S_OK;
  1103. EnterCriticalSection (&ClassStoreBindList);
  1104. //
  1105. // Retrieve the current time so we can determine
  1106. // if cache entries are expired
  1107. //
  1108. GetSystemTimeAsFileTime( &ftCurrentTime );
  1109. for (iClsid=m_KnownMissingClsidCache.start; (iClsid != m_KnownMissingClsidCache.end);
  1110. iClsid = (iClsid+1)%(CLSIDCACHESIZE))
  1111. {
  1112. if ( IsExpired( &ftCurrentTime, &(m_KnownMissingClsidCache.ElemArr[iClsid].Time) ) )
  1113. {
  1114. // all the prev. elems must have expired.
  1115. // delete this element
  1116. m_KnownMissingClsidCache.start = (m_KnownMissingClsidCache.start+1)%CLSIDCACHESIZE;
  1117. m_KnownMissingClsidCache.sz--;
  1118. CSDBGPrint((DM_WARNING,
  1119. IDS_CSTORE_CLASS_PURGE));
  1120. // iClsid will be moved automatically.
  1121. continue;
  1122. }
  1123. if ((IsEqualGUID(pclsspec->tagged_union.clsid,
  1124. m_KnownMissingClsidCache.ElemArr[iClsid].Clsid)) &&
  1125. ((pQryContext->dwContext) == m_KnownMissingClsidCache.ElemArr[iClsid].Ctx))
  1126. {
  1127. CSDBGPrint((DM_WARNING,
  1128. IDS_CSTORE_CLASS_HIT));
  1129. hr = CS_E_PACKAGE_NOTFOUND;
  1130. break;
  1131. }
  1132. }
  1133. LeaveCriticalSection (&ClassStoreBindList);
  1134. if (hr == CS_E_PACKAGE_NOTFOUND)
  1135. return hr;
  1136. StringFromGUID (pclsspec->tagged_union.clsid, szClsid);
  1137. hr = StringCchPrintf (szfilter, dwMaxStrLen, L"(%s=%s*)", PKGCLSIDLIST, szClsid);
  1138. if (FAILED(hr))
  1139. {
  1140. return hr;
  1141. }
  1142. break;
  1143. case TYSPEC_FILEEXT:
  1144. if ((pclsspec->tagged_union.pFileExt == NULL) ||
  1145. (*(pclsspec->tagged_union.pFileExt) == NULL))
  1146. return E_INVALIDARG;
  1147. if (wcslen(pclsspec->tagged_union.pFileExt) > 9)
  1148. return E_INVALIDARG;
  1149. hr = StringCbCopy (&FileExtLower[0], sizeof(FileExtLower), pclsspec->tagged_union.pFileExt);
  1150. if (FAILED(hr))
  1151. {
  1152. return hr;
  1153. }
  1154. _wcslwr (&FileExtLower[0]);
  1155. hr = StringCchPrintf (szfilter,
  1156. dwMaxStrLen,
  1157. L"(%s=%s*)",
  1158. PKGFILEEXTNLIST, &FileExtLower[0]);
  1159. if (FAILED(hr))
  1160. {
  1161. return hr;
  1162. }
  1163. pFileExt = &FileExtLower[0];
  1164. break;
  1165. case TYSPEC_PROGID:
  1166. if ((pclsspec->tagged_union.pProgId == NULL) ||
  1167. (*(pclsspec->tagged_union.pProgId) == NULL))
  1168. return E_INVALIDARG;
  1169. hr = StringCchPrintf (szfilter,
  1170. dwMaxStrLen,
  1171. L"(%s=%s)", PKGPROGIDLIST, pclsspec->tagged_union.pProgId);
  1172. if (FAILED(hr))
  1173. {
  1174. return hr;
  1175. }
  1176. break;
  1177. case TYSPEC_PACKAGENAME:
  1178. //
  1179. // Validate package name
  1180. //
  1181. if ((pclsspec->tagged_union.ByName.pPackageName == NULL) ||
  1182. (*(pclsspec->tagged_union.ByName.pPackageName) == NULL))
  1183. return E_INVALIDARG;
  1184. //
  1185. // The search filter syntax requires that the package name is
  1186. // properly escaped, so we retrieve such a filter below
  1187. //
  1188. hr = GetEscapedNameFilter( pclsspec->tagged_union.ByName.pPackageName, &szNameFilter );
  1189. if ( FAILED(hr) )
  1190. {
  1191. return hr;
  1192. }
  1193. szfilter = szNameFilter;
  1194. OnDemandInstallOnly = FALSE;
  1195. break;
  1196. case TYSPEC_OBJECTID:
  1197. //
  1198. // Validate object id
  1199. //
  1200. if (IsNullGuid(pclsspec->tagged_union.ByObjectId.ObjectId))
  1201. return E_INVALIDARG;
  1202. LPWSTR EncodedGuid;
  1203. EncodedGuid = NULL;
  1204. hr = ADsEncodeBinaryData((PBYTE)&pclsspec->tagged_union.ByObjectId.ObjectId, sizeof(GUID), &EncodedGuid);
  1205. hr = StringCchPrintf(szfilter, dwMaxStrLen, L"(%s=%s)", OBJECTGUID, EncodedGuid);
  1206. FreeADsMem(EncodedGuid);
  1207. OnDemandInstallOnly = FALSE;
  1208. if (FAILED(hr))
  1209. {
  1210. return hr;
  1211. }
  1212. break;
  1213. default:
  1214. return E_NOTIMPL;
  1215. }
  1216. //
  1217. //
  1218. ULONG cRowsFetched;
  1219. PACKAGEDISPINFO PackageInfo[10];
  1220. UINT rgPriority [10];
  1221. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  1222. hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, pszInstallInfoAttrNames, cInstallInfoAttr, &hADsSearchHandle);
  1223. CSDBGPrint((DM_WARNING,
  1224. IDS_CSTORE_MERGEAPPINFO,
  1225. szfilter));
  1226. ERROR_ON_FAILURE(hr);
  1227. //
  1228. // We obtain the 10 best matches
  1229. //
  1230. hr = FetchInstallData(
  1231. m_ADsPackageContainer,
  1232. hADsSearchHandle,
  1233. pQryContext,
  1234. pclsspec,
  1235. pFileExt,
  1236. 10,
  1237. &cRowsFetched,
  1238. &PackageInfo[0],
  1239. &rgPriority[0],
  1240. OnDemandInstallOnly,
  1241. &m_PolicyId,
  1242. m_szGpoPath
  1243. );
  1244. CSDBGPrint((DM_WARNING,
  1245. IDS_CSTORE_ONDEMAND,
  1246. cRowsFetched,
  1247. hr));
  1248. if (cRowsFetched == 0)
  1249. {
  1250. hr = CS_E_OBJECT_NOTFOUND;
  1251. //
  1252. // If CLSID was passed cache the miss
  1253. //
  1254. if (pclsspec->tyspec == TYSPEC_CLSID)
  1255. {
  1256. EnterCriticalSection (&ClassStoreBindList);
  1257. if (m_KnownMissingClsidCache.sz < (CLSIDCACHESIZE-1))
  1258. {
  1259. memcpy (&m_KnownMissingClsidCache.ElemArr[m_KnownMissingClsidCache.end].Clsid,
  1260. &(pclsspec->tagged_union.clsid), sizeof(GUID));
  1261. m_KnownMissingClsidCache.ElemArr[m_KnownMissingClsidCache.end].Ctx
  1262. = pQryContext->dwContext;
  1263. //
  1264. // Set the time member to the current time -- this is retrieved
  1265. // above for all clsid queries
  1266. //
  1267. GetExpiredTime( &ftCurrentTime,
  1268. &(m_KnownMissingClsidCache.ElemArr[m_KnownMissingClsidCache.end].Time) );
  1269. m_KnownMissingClsidCache.sz++;
  1270. m_KnownMissingClsidCache.end = (m_KnownMissingClsidCache.end+1) % CLSIDCACHESIZE;
  1271. }
  1272. LeaveCriticalSection (&ClassStoreBindList);
  1273. }
  1274. }
  1275. else
  1276. {
  1277. DWORD dwChoice = 0;
  1278. if (cRowsFetched > 1)
  1279. {
  1280. dwChoice = ChooseBestFit(PackageInfo, rgPriority, cRowsFetched);
  1281. }
  1282. memcpy (pPackageInfo, &PackageInfo[dwChoice], sizeof(PACKAGEDISPINFO));
  1283. memset (&PackageInfo[dwChoice], NULL, sizeof(PACKAGEDISPINFO));
  1284. // Clean up all allocations
  1285. for (i=0; i < cRowsFetched; i++)
  1286. {
  1287. ReleasePackageInfo(&PackageInfo[i]);
  1288. }
  1289. }
  1290. if (hADsSearchHandle)
  1291. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  1292. //
  1293. // fill in PolicyID
  1294. //
  1295. if (SUCCEEDED(hr))
  1296. {
  1297. memcpy (&(pPackageInfo->GpoId), &m_PolicyId, sizeof(GUID));
  1298. }
  1299. Error_Cleanup:
  1300. if ( szNameFilter )
  1301. {
  1302. CsMemFree( szNameFilter );
  1303. }
  1304. CSDBGPrint((DM_WARNING,
  1305. IDS_CSTORE_APPINFO_END,
  1306. hr));
  1307. return RemapErrorCode(hr, m_szContainerName);
  1308. }
  1309.