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.

1100 lines
32 KiB

  1. //
  2. // Author: DebiM
  3. // Date: January 97
  4. // Revision History:
  5. // Made Changes for reimplementation with adsldpc interfaces.
  6. // UShaji, Mar 1998
  7. //
  8. // Class Access Implementation
  9. //
  10. // This source file contains implementations for IClassAccess
  11. // interface on CAppContainer object.
  12. //
  13. // It uses ADs interfaces (over LDAP) to talk to an LDAP
  14. // provider such as NTDS.
  15. //
  16. //---------------------------------------------------------------------
  17. //
  18. #include "cstore.hxx"
  19. void
  20. GetDefaultPlatform(CSPLATFORM *pPlatform);
  21. HRESULT
  22. UsnGet(ADS_ATTR_INFO Attr, CSUSN *pUsn);
  23. extern CRITICAL_SECTION ClassStoreBindList;
  24. long CompareUsn(CSUSN *pUsn1, CSUSN *pUsn2)
  25. {
  26. return CompareFileTime((FILETIME *)pUsn1, (FILETIME *)pUsn2);
  27. }
  28. //
  29. // CAppContainer implementation
  30. //
  31. CAppContainer::CAppContainer()
  32. {
  33. m_fOpen = FALSE;
  34. m_ADsContainer = NULL;
  35. m_ADsPackageContainer = NULL;
  36. m_szPackageName = NULL;
  37. m_szClassName = NULL;
  38. m_szPolicyName = NULL;
  39. memset (&m_PolicyId, 0, sizeof(GUID));
  40. m_KnownMissingClsidCache.sz = 0;
  41. m_KnownMissingClsidCache.start = 0;
  42. m_KnownMissingClsidCache.end = 0;
  43. m_uRefs = 1;
  44. }
  45. //
  46. // CAppContainer implementation
  47. //
  48. /*----------------------------------------------------------------------*
  49. CAppContainer Constructor:
  50. Parameters:
  51. [in] szStoreName: The Class Store Name without 'ADCS:' moniker
  52. [out] phr The Error Code returned.
  53. Remarks: Tries to Bind to Base Class Store Container, get the version
  54. Number and Packages and Classes container underneath.
  55. Initializes members corresp. to their Names
  56. Return Codes:
  57. Success S_OK
  58. Failures CS_E_INVALID_VERSION
  59. Look at RemapErrorCodes
  60. *----------------------------------------------------------------------*/
  61. CAppContainer::CAppContainer(LPOLESTR szStoreName,
  62. HRESULT *phr)
  63. {
  64. LPOLESTR pszName = NULL;
  65. DWORD dwStoreVersion = 0;
  66. LPOLESTR AttrNames[] = {STOREVERSION, POLICYDN, POLICYNAME};
  67. DWORD posn = 0, cgot = 0;
  68. ADS_SEARCHPREF_INFO SearchPrefs[2];
  69. ADS_ATTR_INFO * pAttrsGot = NULL;
  70. *phr = S_OK;
  71. // set the search preference for the search Handle
  72. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  73. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  74. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  75. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  76. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  77. SearchPrefs[1].vValue.Integer = 20;
  78. m_szPolicyName = NULL;
  79. memset (&m_PolicyId, 0, sizeof(GUID));
  80. m_fOpen = FALSE;
  81. m_ADsContainer = NULL;
  82. m_ADsPackageContainer = NULL;
  83. m_szPackageName = NULL;
  84. m_szClassName = NULL;
  85. m_szPolicyName = NULL;
  86. memset (&m_PolicyId, 0, sizeof(GUID));
  87. m_KnownMissingClsidCache.sz = 0;
  88. m_KnownMissingClsidCache.start = 0;
  89. m_KnownMissingClsidCache.end = 0;
  90. m_uRefs = 1;
  91. //
  92. // For every interface pointer, we create a separate session
  93. //
  94. // Bind to a Class Store Container Object
  95. // Cache the interface pointer
  96. //
  97. wcscpy (m_szContainerName, szStoreName);
  98. *phr = ADSIOpenDSObject(m_szContainerName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  99. &m_ADsContainer);
  100. ERROR_ON_FAILURE(*phr);
  101. //
  102. // Check the Schema Version of this container
  103. //
  104. *phr = ADSIGetObjectAttributes(m_ADsContainer, AttrNames, 3, &pAttrsGot, &cgot);
  105. if ((SUCCEEDED(*phr)) && (cgot))
  106. {
  107. posn = GetPropertyFromAttr(pAttrsGot, cgot, STOREVERSION);
  108. dwStoreVersion = 0;
  109. if (posn < cgot)
  110. {
  111. UnpackDWFrom(pAttrsGot[posn], &dwStoreVersion);
  112. }
  113. if (dwStoreVersion != SCHEMA_VERSION_NUMBER)
  114. {
  115. CSDBGPrint((L"CS: .. Wrong Version of Class Container:%s",
  116. m_szContainerName));
  117. *phr = CS_E_INVALID_VERSION;
  118. }
  119. if (SUCCEEDED(*phr))
  120. {
  121. LPOLESTR szPolicyPath = NULL, szPolicyName = NULL;
  122. posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYDN);
  123. if (posn < cgot)
  124. {
  125. LPOLESTR szParentPath = NULL, szPolicyGuid = NULL;
  126. UnpackStrFrom(pAttrsGot[posn], &szPolicyPath);
  127. //
  128. BuildADsParentPath(szPolicyPath, &szParentPath, &szPolicyGuid);
  129. if (szParentPath)
  130. FreeADsMem(szParentPath);
  131. if (szPolicyGuid)
  132. {
  133. if (wcslen(szPolicyGuid) == 41)
  134. {
  135. // valid GUID
  136. GUIDFromString(&szPolicyGuid[4], &m_PolicyId);
  137. }
  138. FreeADsMem(szPolicyGuid);
  139. }
  140. }
  141. posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYNAME);
  142. if (posn < cgot)
  143. {
  144. UnpackStrAllocFrom(pAttrsGot[posn], &m_szPolicyName);
  145. }
  146. }
  147. }
  148. else
  149. {
  150. if (SUCCEEDED(*phr))
  151. {
  152. CSDBGPrint((L"CS: .. Wrong Version of Class Container:%s",
  153. m_szContainerName));
  154. *phr = CS_E_INVALID_VERSION;
  155. }
  156. }
  157. if (pAttrsGot)
  158. FreeADsMem(pAttrsGot);
  159. ERROR_ON_FAILURE(*phr);
  160. m_szClassName = NULL;
  161. BuildADsPathFromParent(m_szContainerName, CLASSCONTAINERNAME, &m_szClassName);
  162. //
  163. // Bind to the Package container Object
  164. // Cache the interface pointer
  165. //
  166. BuildADsPathFromParent(m_szContainerName, PACKAGECONTAINERNAME, &m_szPackageName);
  167. m_ADsPackageContainer = NULL;
  168. *phr = ADSIOpenDSObject(m_szPackageName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  169. &m_ADsPackageContainer);
  170. ERROR_ON_FAILURE(*phr);
  171. CSDBGPrint((L"PackageContainer handle 0x%x", m_ADsPackageContainer));
  172. *phr = ADSISetSearchPreference(m_ADsPackageContainer, SearchPrefs, 2);
  173. ERROR_ON_FAILURE(*phr);
  174. m_fOpen = TRUE;
  175. CSDBGPrint((L".. Connected to Class Container:%s",
  176. m_szContainerName));
  177. m_uRefs = 1;
  178. Error_Cleanup:
  179. *phr = RemapErrorCode(*phr, m_szContainerName);
  180. return;
  181. }
  182. /*----------------------------------------------------------------------*
  183. CAppContainer Destructor:
  184. Parameters:
  185. None
  186. Function:
  187. Destroys CAppContainer object.
  188. Remarks:
  189. Frees all the members.
  190. Return Codes
  191. *----------------------------------------------------------------------*/
  192. CAppContainer::~CAppContainer(void)
  193. {
  194. UINT i;
  195. if (m_fOpen)
  196. {
  197. m_fOpen = FALSE;
  198. }
  199. if (m_szClassName)
  200. {
  201. FreeADsMem(m_szClassName);
  202. }
  203. if (m_ADsPackageContainer)
  204. {
  205. ADSICloseDSObject(m_ADsPackageContainer);
  206. m_ADsPackageContainer = NULL;
  207. FreeADsMem(m_szPackageName);
  208. }
  209. if (m_ADsContainer)
  210. {
  211. ADSICloseDSObject(m_ADsContainer);
  212. m_ADsContainer = NULL;
  213. }
  214. if (m_szPolicyName)
  215. {
  216. CoTaskMemFree(m_szPolicyName);
  217. }
  218. }
  219. /*----------------------------------------------------------------------*
  220. GetPackageDetails:
  221. Parameters:
  222. [in] pszPackageName: The Package Name
  223. [out] pPackageDetail Package Detail Structure.
  224. Functionality:
  225. Returns the PackageDetail corresp. to a Package given
  226. by pszPackageName.
  227. Remarks:
  228. It constructs the Full Package Name
  229. and calls GetPackageDetail
  230. Return Codes:
  231. Success S_OK
  232. Failures Look at RemapErrorCodes
  233. *----------------------------------------------------------------------*/
  234. // This is not being called currently by anybody and hence is still using PackageId.
  235. HRESULT CAppContainer::GetPackageDetails (
  236. LPOLESTR pszPackageId,
  237. PACKAGEDETAIL *pPackageDetail)
  238. {
  239. HRESULT hr = S_OK;
  240. HANDLE hADs = NULL;
  241. WCHAR * szFullName = NULL, szRDN[_MAX_PATH];
  242. ADS_ATTR_INFO * pAttr = NULL;
  243. DWORD cgot;
  244. if ((!pszPackageId) || IsBadStringPtr(pszPackageId, _MAX_PATH))
  245. return E_INVALIDARG;
  246. wsprintf(szRDN, L"CN=%s", pszPackageId);
  247. CSDBGPrint((L"GetPackageDetails called for %s", szRDN));
  248. BuildADsPathFromParent(m_szPackageName, szRDN, &szFullName);
  249. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs);
  250. ERROR_ON_FAILURE(hr);
  251. hr = GetPackageDetail (hADs, m_szClassName, pPackageDetail);
  252. ADSICloseDSObject(hADs);
  253. if (pAttr)
  254. FreeADsMem(pAttr);
  255. if (szFullName)
  256. FreeADsMem(szFullName);
  257. Error_Cleanup:
  258. return RemapErrorCode(hr, m_szContainerName);
  259. }
  260. /*----------------------------------------------------------------------*
  261. EnumPackages
  262. Parameters:
  263. [in] pszPackageName Substring match for a package name
  264. [in] pCategory Package Category.
  265. [in] pLastUsn Last modification time.
  266. [in] dwAppFlags Set the following bits to select specific ones
  267. Published Only APPINFO_PUBLISHED
  268. Assigned Only APPINFO_ASSIGNED
  269. Msi Only APPINFO_MSI
  270. Visible APPINFO_VISIBLE
  271. Auto-Install APPINFO_AUTOINSTALL
  272. All Locale APPINFO_ALLLOCALE
  273. All Platform APPINFO_ALLPLATFORM
  274. [out] ppIEnumPackage Returns the Enumerator
  275. Functionality
  276. Obtains an enumerator for packages in the app container.
  277. Remarks:
  278. *----------------------------------------------------------------------*/
  279. HRESULT CAppContainer::EnumPackages (
  280. LPOLESTR pszPackageName,
  281. GUID *pCategory,
  282. ULONGLONG *pLastUsn,
  283. DWORD dwAppFlags, // AppType options
  284. IEnumPackage **ppIEnumPackage
  285. )
  286. {
  287. HRESULT hr = S_OK;
  288. CEnumPackage *pEnum = NULL;
  289. WCHAR szLdapFilter [2000];
  290. UINT len = 0;
  291. UINT fFilters = 0;
  292. CSPLATFORM *pPlatform = NULL, Platform;
  293. //
  294. // Validate
  295. //
  296. if (!IsValidPtrOut(ppIEnumPackage, sizeof(IEnumPackage *)))
  297. return E_INVALIDARG;
  298. if (pszPackageName && (IsBadStringPtr(pszPackageName, _MAX_PATH)))
  299. return E_INVALIDARG;
  300. if (pCategory && !IsValidReadPtrIn(pCategory, sizeof(GUID)))
  301. return E_INVALIDARG;
  302. *ppIEnumPackage = NULL;
  303. //pEnum = new CEnumPackage;
  304. pEnum = new CEnumPackage(m_PolicyId, m_szPolicyName);
  305. if(NULL == pEnum)
  306. return E_OUTOFMEMORY;
  307. //
  308. // Create a LDAP Search Filter based on input params
  309. //
  310. // Count Filters
  311. if (pszPackageName && (*pszPackageName))
  312. fFilters++;
  313. if ((pLastUsn) && (*pLastUsn))
  314. fFilters++;
  315. if (pCategory)
  316. fFilters++;
  317. if (dwAppFlags & APPINFO_ASSIGNED)
  318. fFilters++;
  319. if (fFilters == 0)
  320. {
  321. // No Conditionals
  322. wsprintf (szLdapFilter,
  323. L"(%s=%s)", OBJECTCLASS, CLASS_CS_PACKAGE);
  324. len = wcslen (szLdapFilter);
  325. }
  326. else
  327. {
  328. if (fFilters > 1)
  329. {
  330. wsprintf (szLdapFilter, L"(&");
  331. len = wcslen (szLdapFilter);
  332. }
  333. else
  334. len = 0;
  335. if (pszPackageName)
  336. {
  337. //
  338. // Validate
  339. //
  340. if (IsBadStringPtr(pszPackageName, _MAX_PATH))
  341. return E_INVALIDARG;
  342. if (*pszPackageName)
  343. {
  344. wsprintf (&szLdapFilter[len],
  345. L"(%s=*%s*)",
  346. PACKAGENAME,
  347. pszPackageName);
  348. len = wcslen (szLdapFilter);
  349. }
  350. }
  351. if ((pLastUsn) && (*pLastUsn))
  352. {
  353. //
  354. // Validate
  355. //
  356. SYSTEMTIME SystemTime;
  357. if (!IsValidReadPtrIn(pLastUsn, sizeof(ULONGLONG)))
  358. return E_INVALIDARG;
  359. FileTimeToSystemTime(
  360. (CONST FILETIME *) pLastUsn,
  361. &SystemTime);
  362. wsprintf (&szLdapFilter[len],
  363. L"(%s>=%04d%02d%02d%02d%02d%02d)",
  364. PKGUSN,
  365. SystemTime.wYear,
  366. SystemTime.wMonth,
  367. SystemTime.wDay,
  368. SystemTime.wHour,
  369. SystemTime.wMinute,
  370. SystemTime.wSecond+1);
  371. len = wcslen (szLdapFilter);
  372. }
  373. if (pCategory)
  374. {
  375. //
  376. // Validate
  377. //
  378. STRINGGUID szCat;
  379. if (!IsValidReadPtrIn(pCategory, sizeof(GUID)))
  380. return E_INVALIDARG;
  381. StringFromGUID (*pCategory, szCat);
  382. wsprintf (&szLdapFilter[len],
  383. L"(%s=%s)",
  384. PKGCATEGORYLIST,
  385. szCat);
  386. len = wcslen (szLdapFilter);
  387. }
  388. if (dwAppFlags & APPINFO_ASSIGNED)
  389. // if only Assigned Packages are in demand
  390. {
  391. wsprintf (&szLdapFilter[len],
  392. L"(%s>=%d)",
  393. PACKAGEFLAGS,
  394. (ACTFLG_Assigned));
  395. len = wcslen (szLdapFilter);
  396. }
  397. if (fFilters > 1)
  398. {
  399. szLdapFilter[len] = L')';
  400. szLdapFilter[++len] = NULL;
  401. }
  402. }
  403. CSDBGPrint((L"EnumPackage Called:: Search filter created is %s, Appflags = %d", szLdapFilter, dwAppFlags));
  404. //
  405. // Check all local/platform flags
  406. //
  407. if (dwAppFlags & APPINFO_ALLPLATFORM)
  408. {
  409. pPlatform = NULL;
  410. }
  411. else
  412. {
  413. pPlatform = &Platform;
  414. GetDefaultPlatform(pPlatform);
  415. }
  416. if (pLastUsn)
  417. {
  418. //
  419. // Find the current store USN and return it
  420. //
  421. LPOLESTR AttrName = STOREUSN;
  422. ADS_ATTR_INFO * pAttr = NULL;
  423. DWORD cgot = 0;
  424. hr = ADSIGetObjectAttributes(m_ADsContainer, &AttrName, 1, &pAttr, &cgot);
  425. if ((SUCCEEDED(hr)) && (cgot))
  426. {
  427. UsnGet(*pAttr, (CSUSN *)pLastUsn);
  428. if (pAttr)
  429. FreeADsMem(pAttr);
  430. }
  431. }
  432. hr = pEnum->Initialize(m_szPackageName, szLdapFilter, dwAppFlags, pPlatform);
  433. ERROR_ON_FAILURE(hr);
  434. hr = pEnum->QueryInterface(IID_IEnumPackage,(void**) ppIEnumPackage);
  435. ERROR_ON_FAILURE(hr);
  436. return S_OK;
  437. Error_Cleanup:
  438. if (pEnum)
  439. delete pEnum;
  440. *ppIEnumPackage = NULL;
  441. return RemapErrorCode(hr, m_szContainerName);
  442. }
  443. DWORD GetTime()
  444. {
  445. return (GetTickCount()/1000);
  446. }
  447. BOOL IsExpired(DWORD dwCurrentTime, DWORD Time, DWORD Tolerance)
  448. {
  449. if (Time > dwCurrentTime)
  450. return TRUE;
  451. if ((Time+Tolerance) < dwCurrentTime)
  452. return TRUE;
  453. return FALSE;
  454. }
  455. // choosing the best package that can be returned after returning from the DS
  456. DWORD CAppContainer::ChooseBestFit(PACKAGEDISPINFO *PackageInfo, UINT *rgPriority, DWORD cRowsFetched)
  457. {
  458. DWORD i=0, k=0, j = 0, temp = 0;
  459. DWORD index[10];
  460. CSDBGPrint((L"Entering ChooseBestFit"));
  461. // initialising the indices
  462. for (i = 0; (i < cRowsFetched); i++)
  463. index[i] = i;
  464. // sort the index based on priority and time stamp
  465. for (i = 0; (i < (cRowsFetched-1)); i++)
  466. {
  467. DWORD Pri = rgPriority[i];
  468. k = i;
  469. // max element's index is in k
  470. for (j=(i+1); (j < cRowsFetched); ++j)
  471. {
  472. // order first by weight and then by time stamp.
  473. if ((rgPriority[index[j]] > Pri) ||
  474. ((rgPriority[index[j]] == Pri) &&
  475. (CompareUsn((FILETIME *)&PackageInfo[index[j]].Usn, (FILETIME *)&PackageInfo[index[k]].Usn) == 1)))
  476. {
  477. Pri = rgPriority[index[j]];
  478. k = j;
  479. }
  480. }
  481. if (k != i)
  482. {
  483. temp = index[k];
  484. index[k] = index[i];
  485. index[i] = temp;
  486. }
  487. }
  488. DWORD dwPackage;
  489. DWORD dwBestPackage;
  490. dwBestPackage = 0;
  491. //
  492. // Now the packages are sorted in order from highest precedence to lowest.
  493. // We will now check for upgrades for each package
  494. //
  495. for (dwPackage = 0; (dwPackage < cRowsFetched); dwPackage++)
  496. {
  497. DWORD dwPossibleUpgrader;
  498. PACKAGEDISPINFO* pBestPackage;
  499. pBestPackage = PackageInfo+index[dwBestPackage];
  500. CSDBGPrint((L"Processing Package %s", pBestPackage->pszPackageName));
  501. //
  502. // Now search for someone that upgrades the current choice -- look at all packages
  503. // after the current one since we've already determined that the packages before
  504. // this one got upgraded (otherwise we wouldn't be here).
  505. //
  506. for (dwPossibleUpgrader = dwPackage + 1; dwPossibleUpgrader < cRowsFetched; dwPossibleUpgrader ++)
  507. {
  508. PACKAGEDISPINFO* pUpgraderCandidate;
  509. //
  510. // Obviously, we don't need to check the current choice
  511. // to see if it upgrades itself, so skip it
  512. //
  513. if (dwPossibleUpgrader == dwBestPackage)
  514. {
  515. continue;
  516. }
  517. pUpgraderCandidate = PackageInfo + index[dwPossibleUpgrader];
  518. //
  519. // See if the upgrader candidate has any upgrades, if not, keep looking
  520. //
  521. if (0 == pUpgraderCandidate->cUpgrades)
  522. {
  523. continue;
  524. }
  525. //
  526. // Now we have to see if any of those upgrades apply to the package we have
  527. // currently selected as the best
  528. //
  529. DWORD dwUpgrade;
  530. BOOL fFoundUpgrade;
  531. fFoundUpgrade = FALSE;
  532. for (dwUpgrade = 0; dwUpgrade < pUpgraderCandidate->cUpgrades; dwUpgrade++)
  533. {
  534. DWORD dwValidUpgradeMask;
  535. dwValidUpgradeMask = UPGFLG_Uninstall |
  536. UPGFLG_NoUninstall |
  537. UPGFLG_Enforced;
  538. //
  539. // If this is a valid upgrade
  540. //
  541. if (pUpgraderCandidate->prgUpgradeInfoList[dwUpgrade].Flag & dwValidUpgradeMask)
  542. {
  543. //
  544. // Does it upgrade the package we think is best at this point? We only
  545. // consider upgrades in this container, as we no longer allow upgrades from lower
  546. // precedence class stores -- the caller who iterates through each container from
  547. // highest precedence to lowest will simply choose the app from the first container in which
  548. // we have a match.
  549. //
  550. // We use memcmp to compare guids to see if the best choice package's guid is listed
  551. // as being upgraded by this upgrade candidate
  552. //
  553. if (memcmp(&((pUpgraderCandidate->prgUpgradeInfoList)[dwUpgrade].PackageGuid),
  554. &(pBestPackage->PackageGuid), sizeof(GUID) == 0))
  555. {
  556. //
  557. // We have a match -- reset the current best choice to the upgrade candidate
  558. //
  559. dwBestPackage = dwPossibleUpgrader;
  560. //
  561. // another package upgrades this -- no need to look any further, so we quit
  562. //
  563. CSDBGPrint((L"Ignoring Package %s because it is getting upgraded in the same store", pBestPackage->pszPackageName));
  564. break;
  565. }
  566. }
  567. }
  568. //
  569. // If we found an upgrade in the list above, we can stop abort the search for an upgrade now --
  570. // if we found another, it would just be a lower precedence app since we're iterating from highest to lowest,
  571. // and we want the highest predecence app that upgrades the currently chosen best app
  572. //
  573. if (fFoundUpgrade)
  574. {
  575. break;
  576. }
  577. }
  578. }
  579. DWORD dwChoice;
  580. dwChoice = index[dwBestPackage];
  581. CSDBGPrint((L"Selecting Package %s as the Best Fit", PackageInfo[dwChoice].pszPackageName));
  582. return dwChoice;
  583. }
  584. //
  585. // CAppContainer::GetAppInfo
  586. // -----------------------------
  587. //
  588. //
  589. //
  590. // Synopsis: This is the most common access point to the Class Store.
  591. // It receives a CLSID and a QUERYCONTEXT.
  592. // It looks up the Class Store container for a matching set
  593. // of packages with in the context of the QUERYCONTEXT.
  594. //
  595. // QUERYCONTEXT includes
  596. // Execution Context
  597. // Locale Id
  598. // Platform/OS
  599. //
  600. // If i finds an app that matches the requirements, it returns
  601. // an PACKAGEDISPINFO structure containing installation details.
  602. //
  603. // Arguments: [in] clsid
  604. // [in] pQryContext
  605. // [out] pPackageInfo
  606. //
  607. // Returns: CS_E_PACKAGE_NOTFOUND
  608. // S_OK
  609. //
  610. //
  611. //
  612. HRESULT STDMETHODCALLTYPE
  613. CAppContainer::GetAppInfo(
  614. uCLSSPEC * pclsspec, // Class Spec (GUID/Ext/MIME)
  615. QUERYCONTEXT * pQryContext, // Query Attributes
  616. PACKAGEDISPINFO * pPackageInfo
  617. )
  618. //
  619. // This is the most common method to access the Class Store.
  620. // It queries the class store for implementations for a specific
  621. // Class Id, or File Ext, or ProgID.
  622. //
  623. // If a matching implementation is available (for the object type,
  624. // client architecture, locale and class context) then the installation
  625. // parameters of the package is returned.
  626. {
  627. GUID clsid;
  628. WCHAR szfilter[1000];
  629. STRINGGUID szClsid;
  630. UINT i, iClsid = 0;
  631. ULONG cRead;
  632. HRESULT hr;
  633. ULONG cSize = _MAX_PATH;
  634. BOOL fFound = FALSE;
  635. PLATFORMINFO PlatformInfo;
  636. LPOLESTR pFileExt = NULL;
  637. BOOL OnDemandInstallOnly = TRUE;
  638. WCHAR FileExtLower [10];
  639. DWORD dwCurrentTime = GetTime();
  640. memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
  641. if (!m_fOpen)
  642. return E_FAIL;
  643. //
  644. // Check if the TypeSpec is MIMEType
  645. // then map it to a CLSID
  646. //
  647. if (pclsspec->tyspec == TYSPEC_MIMETYPE)
  648. {
  649. //
  650. // BUGBUG.
  651. // Considering removal of MimeType support from Class Store
  652. // Till it is decided the code is OUT.
  653. return E_NOTIMPL;
  654. /*
  655. if (IsBadStringPtr(pclsspec->tagged_union.pMimeType, _MAX_PATH))
  656. return E_INVALIDARG;
  657. if ((pclsspec->tagged_union.pMimeType == NULL) ||
  658. (*(pclsspec->tagged_union.pMimeType) == NULL))
  659. return E_INVALIDARG;
  660. wsprintf (szfilter,
  661. L"<%s>;(%s=%s);name",
  662. m_szClassName, MIMETYPES, pclsspec->tagged_union.pMimeType);
  663. */
  664. }
  665. switch (pclsspec->tyspec)
  666. {
  667. case TYSPEC_TYPELIB: // leaving it here.
  668. if (IsNullGuid(pclsspec->tagged_union.typelibID))
  669. return E_INVALIDARG;
  670. StringFromGUID (pclsspec->tagged_union.typelibID, szClsid);
  671. wsprintf (szfilter,
  672. L"(%s=%s)", PKGTLBIDLIST, szClsid);
  673. break;
  674. case TYSPEC_IID:
  675. if (IsNullGuid(pclsspec->tagged_union.iid))
  676. return E_INVALIDARG;
  677. StringFromGUID (pclsspec->tagged_union.iid, szClsid);
  678. wsprintf (szfilter,
  679. L"(%s=%s)", PKGIIDLIST, szClsid);
  680. break;
  681. case TYSPEC_CLSID:
  682. if (IsNullGuid(pclsspec->tagged_union.clsid))
  683. return E_INVALIDARG;
  684. //
  685. // Check against known missing ones
  686. //
  687. hr = S_OK;
  688. EnterCriticalSection (&ClassStoreBindList);
  689. for (iClsid=m_KnownMissingClsidCache.start; (iClsid != m_KnownMissingClsidCache.end);
  690. iClsid = (iClsid+1)%(CLSIDCACHESIZE))
  691. {
  692. if (IsExpired(dwCurrentTime, m_KnownMissingClsidCache.ElemArr[iClsid].Time, CACHE_PURGE_TIME))
  693. {
  694. // all the prev. elems must have expired.
  695. // delete this element
  696. m_KnownMissingClsidCache.start = (m_KnownMissingClsidCache.start+1)%CLSIDCACHESIZE;
  697. m_KnownMissingClsidCache.sz--;
  698. CSDBGPrint((L"Expiring element in CLSID Cache"));
  699. // iClsid will be moved automatically.
  700. continue;
  701. }
  702. if ((IsEqualGUID(pclsspec->tagged_union.clsid,
  703. m_KnownMissingClsidCache.ElemArr[iClsid].Clsid)) &&
  704. ((pQryContext->dwContext) == m_KnownMissingClsidCache.ElemArr[iClsid].Ctx))
  705. {
  706. CSDBGPrint((L"Clsid Found in MISSING Cache"));
  707. hr = CS_E_PACKAGE_NOTFOUND;
  708. break;
  709. }
  710. }
  711. LeaveCriticalSection (&ClassStoreBindList);
  712. if (hr == CS_E_PACKAGE_NOTFOUND)
  713. return hr;
  714. StringFromGUID (pclsspec->tagged_union.clsid, szClsid);
  715. wsprintf (szfilter, L"(%s=%s*)", PKGCLSIDLIST, szClsid);
  716. break;
  717. case TYSPEC_FILEEXT:
  718. if (IsBadStringPtr(pclsspec->tagged_union.pFileExt, _MAX_PATH))
  719. return E_INVALIDARG;
  720. if ((pclsspec->tagged_union.pFileExt == NULL) ||
  721. (*(pclsspec->tagged_union.pFileExt) == NULL))
  722. return E_INVALIDARG;
  723. if (wcslen(pclsspec->tagged_union.pFileExt) > 9)
  724. return E_INVALIDARG;
  725. wcscpy (&FileExtLower[0], pclsspec->tagged_union.pFileExt);
  726. _wcslwr (&FileExtLower[0]);
  727. wsprintf (szfilter,
  728. L"(%s=%s*)",
  729. PKGFILEEXTNLIST, &FileExtLower[0]);
  730. pFileExt = &FileExtLower[0];
  731. break;
  732. case TYSPEC_PROGID:
  733. if (IsBadStringPtr(pclsspec->tagged_union.pProgId, _MAX_PATH))
  734. return E_INVALIDARG;
  735. if ((pclsspec->tagged_union.pProgId == NULL) ||
  736. (*(pclsspec->tagged_union.pProgId) == NULL))
  737. return E_INVALIDARG;
  738. wsprintf (szfilter,
  739. L"(%s=%s)", PKGPROGIDLIST, pclsspec->tagged_union.pProgId);
  740. break;
  741. case TYSPEC_PACKAGENAME:
  742. //
  743. // Validate package name
  744. //
  745. if (IsBadStringPtr(pclsspec->tagged_union.ByName.pPackageName, _MAX_PATH))
  746. return E_INVALIDARG;
  747. if ((pclsspec->tagged_union.ByName.pPackageName == NULL) ||
  748. (*(pclsspec->tagged_union.ByName.pPackageName) == NULL))
  749. return E_INVALIDARG;
  750. wsprintf (szfilter, L"(%s=%s)", PACKAGENAME, pclsspec->tagged_union.ByName.pPackageName);
  751. OnDemandInstallOnly = FALSE;
  752. break;
  753. case TYSPEC_SCRIPTNAME:
  754. //
  755. // Validate script name
  756. //
  757. if (IsBadStringPtr(pclsspec->tagged_union.ByScript.pScriptName, _MAX_PATH))
  758. return E_INVALIDARG;
  759. if ((pclsspec->tagged_union.ByScript.pScriptName == NULL) ||
  760. (*(pclsspec->tagged_union.ByScript.pScriptName) == NULL))
  761. return E_INVALIDARG;
  762. wsprintf (szfilter, L"(%s=*%s*)", SCRIPTPATH, pclsspec->tagged_union.ByScript.pScriptName);
  763. OnDemandInstallOnly = FALSE;
  764. break;
  765. default:
  766. return E_NOTIMPL;
  767. }
  768. //
  769. //
  770. ULONG cRowsFetched;
  771. PACKAGEDISPINFO PackageInfo[10];
  772. UINT rgPriority [10];
  773. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  774. CSDBGPrint((L"PackageContainer handle 0x%x", m_ADsPackageContainer));
  775. hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, pszInstallInfoAttrNames, cInstallInfoAttr, &hADsSearchHandle);
  776. CSDBGPrint((L"CAppContainer::GetAppInfo search filter %s", szfilter));
  777. ERROR_ON_FAILURE(hr);
  778. //
  779. // BUGBUG. Currently limited to 10.
  780. // Must put a loop to retry more in future.
  781. //
  782. hr = FetchInstallData(m_ADsPackageContainer,
  783. hADsSearchHandle,
  784. pQryContext,
  785. pclsspec,
  786. pFileExt,
  787. 10,
  788. &cRowsFetched,
  789. &PackageInfo[0],
  790. &rgPriority[0],
  791. OnDemandInstallOnly
  792. );
  793. CSDBGPrint((L"CAppContainer::FetchInstallData returned 0x%x", hr));
  794. CSDBGPrint((L"CAppContainer::FetchInstallData returned %d Packages", cRowsFetched));
  795. if (cRowsFetched == 0)
  796. {
  797. hr = CS_E_OBJECT_NOTFOUND;
  798. //
  799. // If CLSID was passed cache the miss
  800. //
  801. if (pclsspec->tyspec == TYSPEC_CLSID)
  802. {
  803. EnterCriticalSection (&ClassStoreBindList);
  804. if (m_KnownMissingClsidCache.sz < (CLSIDCACHESIZE-1))
  805. {
  806. memcpy (&m_KnownMissingClsidCache.ElemArr[m_KnownMissingClsidCache.end].Clsid,
  807. &(pclsspec->tagged_union.clsid), sizeof(GUID));
  808. m_KnownMissingClsidCache.ElemArr[m_KnownMissingClsidCache.end].Ctx
  809. = pQryContext->dwContext;
  810. m_KnownMissingClsidCache.ElemArr[m_KnownMissingClsidCache.end].Time
  811. = dwCurrentTime;
  812. m_KnownMissingClsidCache.sz++;
  813. m_KnownMissingClsidCache.end = (m_KnownMissingClsidCache.end+1) % CLSIDCACHESIZE;
  814. CSDBGPrint((L"Adding Element to the clsid cache"));
  815. }
  816. LeaveCriticalSection (&ClassStoreBindList);
  817. }
  818. }
  819. else
  820. {
  821. DWORD dwChoice = 0;
  822. if (cRowsFetched > 1)
  823. {
  824. dwChoice = ChooseBestFit(PackageInfo, rgPriority, cRowsFetched);
  825. }
  826. memcpy (pPackageInfo, &PackageInfo[dwChoice], sizeof(PACKAGEDISPINFO));
  827. memset (&PackageInfo[dwChoice], NULL, sizeof(PACKAGEDISPINFO));
  828. // Clean up all allocations
  829. for (i=0; i < cRowsFetched; i++)
  830. {
  831. ReleasePackageInfo(&PackageInfo[i]);
  832. }
  833. }
  834. if (hADsSearchHandle)
  835. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  836. //
  837. // fill in PolicyID and Name
  838. //
  839. if (SUCCEEDED(hr))
  840. {
  841. memcpy (&(pPackageInfo->GpoId), &m_PolicyId, sizeof(GUID));
  842. if (m_szPolicyName && (*m_szPolicyName))
  843. {
  844. pPackageInfo->pszPolicyName = (LPOLESTR) CoTaskMemAlloc(sizeof(WCHAR) * (1+wcslen(m_szPolicyName)));
  845. if (pPackageInfo->pszPolicyName)
  846. wcscpy (pPackageInfo->pszPolicyName, m_szPolicyName);
  847. else {
  848. ReleasePackageInfo(pPackageInfo);
  849. memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
  850. return E_OUTOFMEMORY;
  851. }
  852. }
  853. }
  854. Error_Cleanup:
  855. CSDBGPrint((L"CAppContainer::GetAppInfo returning 0x%x", RemapErrorCode(hr, m_szContainerName)));
  856. return RemapErrorCode(hr, m_szContainerName);
  857. }