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.

679 lines
16 KiB

  1. //
  2. // Author: ushaji
  3. // Date: December 1996
  4. //
  5. //
  6. // Providing support for Component Categories in Class Store
  7. //
  8. // This source file contains implementations for Enumerator Interfaces.
  9. //
  10. // Refer Doc "Design for Support of File Types and Component Categories
  11. // in Class Store" ? (or may be Class Store Schema). Most of these uses
  12. // OLE DB interfaces within the interfaces.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "cstore.hxx"
  16. //
  17. // Private defines
  18. //
  19. #define MAX_ADS_FILTERS 10
  20. #define MAX_ADS_ENUM 100
  21. // BUGBUG:: Should this go to common
  22. HRESULT
  23. EnumCsObject(
  24. IADsContainer * pADsContainer,
  25. LPWSTR * lppPathNames,
  26. DWORD dwPathNames,
  27. IEnumVARIANT ** ppEnumVariant
  28. )
  29. {
  30. ULONG cElementFetched = 0L;
  31. VARIANT VarFilter;
  32. HRESULT hr;
  33. DWORD dwObjects = 0, dwEnumCount = 0, i = 0;
  34. BOOL fContinue = TRUE;
  35. if (dwPathNames)
  36. {
  37. VariantInit(&VarFilter);
  38. hr = BuildVarArrayStr(
  39. lppPathNames,
  40. dwPathNames,
  41. &VarFilter
  42. );
  43. RETURN_ON_FAILURE(hr);
  44. hr = pADsContainer->put_Filter(VarFilter);
  45. RETURN_ON_FAILURE(hr);
  46. VariantClear(&VarFilter);
  47. }
  48. hr = ADsBuildEnumerator(
  49. pADsContainer,
  50. ppEnumVariant
  51. );
  52. return hr;
  53. }
  54. HRESULT
  55. GetNextEnum(
  56. IEnumVARIANT * pEnum,
  57. IADs **ppADs
  58. )
  59. {
  60. HRESULT hr;
  61. VARIANT VariantArray[MAX_ADS_ENUM];
  62. IDispatch *pDispatch = NULL;
  63. hr = ADsEnumerateNext(
  64. pEnum,
  65. 1,
  66. VariantArray,
  67. NULL
  68. );
  69. if (hr == S_FALSE)
  70. return hr;
  71. RETURN_ON_FAILURE(hr);
  72. pDispatch = VariantArray[0].pdispVal;
  73. memset(VariantArray, 0, sizeof(VARIANT)*MAX_ADS_ENUM);
  74. hr = pDispatch->QueryInterface(IID_IADs, (void **) ppADs) ;
  75. pDispatch->Release();
  76. return(S_OK);
  77. }
  78. HRESULT GetCategoryProperty (IADs *pADs,
  79. CATEGORYINFO *pcategoryinfo, LCID lcid)
  80. {
  81. HRESULT hr = S_OK;
  82. WCHAR szName[_MAX_PATH];
  83. LPOLESTR *pdesc = NULL;
  84. ULONG i, cdesc;
  85. hr = GetPropertyGuid(pADs, CATEGORYCATID, &(pcategoryinfo->catid));
  86. RETURN_ON_FAILURE(hr);
  87. hr = GetPropertyListAlloc(pADs, LOCALEDESCRIPTION, &cdesc, &pdesc);
  88. RETURN_ON_FAILURE(hr);
  89. pcategoryinfo->lcid = lcid;
  90. hr = GetCategoryLocaleDesc(pdesc, cdesc, &(pcategoryinfo->lcid),
  91. (pcategoryinfo->szDescription));
  92. for (i = 0; i < cdesc; i++)
  93. CoTaskMemFree(pdesc[i]);
  94. CoTaskMemFree(pdesc);
  95. if (FAILED(hr))
  96. *(pcategoryinfo->szDescription) = L'\0';
  97. return S_OK;
  98. }
  99. //----------------------------------------------
  100. // IEnumCATEGORYINFO:
  101. // IUnknown methods
  102. HRESULT CSCEnumCategories::QueryInterface(REFIID riid, void** ppObject)
  103. {
  104. *ppObject = NULL; //gd
  105. if ((riid==IID_IUnknown) || (riid==IID_IEnumCATEGORYINFO))
  106. {
  107. *ppObject=(IUnknown *)(IEnumCATEGORYINFO*) this;
  108. }
  109. else
  110. {
  111. return E_NOINTERFACE;
  112. }
  113. AddRef();
  114. return S_OK;
  115. }
  116. ULONG CSCEnumCategories::AddRef()
  117. {
  118. InterlockedIncrement((long*) &m_dwRefCount);
  119. return m_dwRefCount;
  120. }
  121. ULONG CSCEnumCategories::Release()
  122. {
  123. ULONG dwRefCount;
  124. if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
  125. {
  126. delete this;
  127. return 0;
  128. }
  129. return dwRefCount;
  130. }
  131. // IEnumCATEGORYINFO methods
  132. //--------------------------------------------------------------------
  133. // Next:
  134. // celt: Number of elements to be fetched.
  135. // rgelt: Buffer to return the elements.
  136. // pceltFetched: ptr to Number of elements actually fetched.
  137. // Takes care of that being NULL.
  138. // Uses OLE DS interfaces to get the next enumerators.
  139. //--------------------------------------------------------------------
  140. HRESULT CSCEnumCategories::Next(ULONG celt, CATEGORYINFO *rgelt, ULONG *pceltFetched)
  141. {
  142. HRESULT hr = S_OK;
  143. IADs *pCatADs = NULL;
  144. ULONG dwCount;
  145. if ((celt > 1) && (!pceltFetched))
  146. return E_INVALIDARG;
  147. if (pceltFetched)
  148. (*pceltFetched) = 0;
  149. if (m_pEnumVariant == NULL)
  150. return E_UNEXPECTED;
  151. if (celt < 0)
  152. return E_INVALIDARG;
  153. if (!IsValidPtrOut(rgelt, sizeof(CATEGORYINFO)*celt)) {
  154. return E_INVALIDARG;
  155. }
  156. for ((dwCount) = 0; (dwCount) < celt;) {
  157. hr = GetNextEnum(m_pEnumVariant, &pCatADs);
  158. if ((FAILED(hr)) || (hr == S_FALSE))
  159. break;
  160. hr = GetCategoryProperty(pCatADs, &(rgelt[dwCount]), m_lcid);
  161. pCatADs->Release();
  162. if (FAILED(hr))
  163. continue;
  164. (dwCount)++;
  165. }
  166. m_dwPosition += dwCount;
  167. if (pceltFetched)
  168. (*pceltFetched) = dwCount;
  169. return hr;
  170. }
  171. //---------------------------------------------------
  172. // skip:
  173. // skips elements.
  174. // celt Number of elements to skip.
  175. //---------------------------------------------------
  176. HRESULT CSCEnumCategories::Skip(ULONG celt)
  177. {
  178. CATEGORYINFO *dummy;
  179. ULONG got;
  180. HRESULT hr;
  181. dummy = new CATEGORYINFO[celt];
  182. if (!dummy)
  183. return E_OUTOFMEMORY;
  184. if (m_pEnumVariant == NULL)
  185. {
  186. delete dummy;
  187. return E_UNEXPECTED;
  188. }
  189. hr = Next(celt, dummy, &got);
  190. delete dummy;
  191. return hr;
  192. }
  193. //---------------------------------------------------
  194. // Reset:
  195. // Resets the pointer.
  196. //---------------------------------------------------
  197. HRESULT CSCEnumCategories::Reset(void)
  198. {
  199. LPOLESTR pszPathNames [2];
  200. HRESULT hr;
  201. pszPathNames [0] = CLASS_CS_CATEGORY;
  202. if (m_pEnumVariant == NULL)
  203. return E_UNEXPECTED;
  204. m_pEnumVariant->Release();
  205. hr = EnumCsObject(m_ADsCategoryContainer, &pszPathNames[0],
  206. 0, &m_pEnumVariant);
  207. m_dwPosition = 0;
  208. return hr;
  209. }
  210. //--------------------------------------------------------------
  211. // Clone:
  212. // returns another interface which points to the same data.
  213. // ppenum: enumerator
  214. //------------------------------------------------------------
  215. ////////////////////////////////////////////////////////////////////
  216. HRESULT CSCEnumCategories::Clone(IEnumCATEGORYINFO **ppenum)
  217. {
  218. CSCEnumCategories* pClone=NULL;
  219. if (!IsValidPtrOut(ppenum, sizeof(IEnumCATEGORYINFO *))) {
  220. return E_INVALIDARG;
  221. }
  222. pClone=new CSCEnumCategories();
  223. if (!pClone)
  224. {
  225. return E_OUTOFMEMORY;
  226. }
  227. if (FAILED(pClone->Initialize(m_ADsCategoryContainer, m_lcid)))
  228. {
  229. delete pClone;
  230. return E_UNEXPECTED;
  231. }
  232. pClone->Skip(m_dwPosition);
  233. if (SUCCEEDED(pClone->QueryInterface(IID_IEnumCATEGORYINFO, (void**) ppenum)))
  234. {
  235. return S_OK;
  236. }
  237. delete pClone;
  238. return E_UNEXPECTED;
  239. }
  240. CSCEnumCategories::CSCEnumCategories()
  241. {
  242. m_dwRefCount=0;
  243. m_pEnumVariant = NULL;
  244. m_ADsCategoryContainer = NULL;
  245. m_lcid=0;
  246. m_dwPosition = 0;
  247. }
  248. HRESULT CSCEnumCategories::Initialize(IADsContainer *ADsCategoryContainer, LCID lcid)
  249. {
  250. LPOLESTR pszPathNames [2];
  251. HRESULT hr;
  252. pszPathNames [0] = CLASS_CS_CATEGORY;
  253. m_ADsCategoryContainer = ADsCategoryContainer;
  254. m_ADsCategoryContainer->AddRef();
  255. hr = EnumCsObject(m_ADsCategoryContainer, &pszPathNames[0], 0, &m_pEnumVariant);
  256. RETURN_ON_FAILURE(hr);
  257. m_lcid = lcid;
  258. return S_OK;
  259. } /* EnumCategories */
  260. CSCEnumCategories::~CSCEnumCategories()
  261. {
  262. if (m_ADsCategoryContainer)
  263. m_ADsCategoryContainer->Release();
  264. if (m_pEnumVariant)
  265. m_pEnumVariant->Release();
  266. }
  267. // CSCEnumCategoriesOfClass:
  268. // IUnknown methods
  269. HRESULT CSCEnumCategoriesOfClass::QueryInterface(REFIID riid, void** ppObject)
  270. {
  271. if ((riid==IID_IUnknown) || (riid==IID_IEnumCATID))
  272. {
  273. *ppObject=(IEnumCATID*) this;
  274. }
  275. else
  276. {
  277. return E_NOINTERFACE;
  278. }
  279. AddRef();
  280. return S_OK;
  281. }
  282. ULONG CSCEnumCategoriesOfClass::AddRef()
  283. {
  284. InterlockedIncrement((long*) &m_dwRefCount);
  285. return m_dwRefCount;
  286. }
  287. ULONG CSCEnumCategoriesOfClass::Release()
  288. {
  289. ULONG dwRefCount;
  290. if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
  291. {
  292. delete this;
  293. return 0;
  294. }
  295. return dwRefCount;
  296. }
  297. // IEnumCATID methods
  298. HRESULT CSCEnumCategoriesOfClass::Next(ULONG celt, GUID *rgelt, ULONG *pceltFetched)
  299. {
  300. ULONG dwCount;
  301. if ((celt > 1) && (!pceltFetched))
  302. return E_INVALIDARG;
  303. if (pceltFetched)
  304. (*pceltFetched) = 0;
  305. if (celt < 0)
  306. return E_INVALIDARG;
  307. if (!IsValidPtrOut(rgelt, sizeof(GUID)*celt))
  308. return E_INVALIDARG;
  309. for ( (dwCount) = 0; (((dwCount) < celt) && (m_dwPosition < m_cCatid));
  310. (dwCount)++, m_dwPosition++)
  311. rgelt[(dwCount)] = m_catid[m_dwPosition];
  312. if (pceltFetched)
  313. (*pceltFetched) = dwCount;
  314. if (dwCount == celt)
  315. return S_OK;
  316. return S_FALSE;
  317. }
  318. HRESULT CSCEnumCategoriesOfClass::Skip(ULONG celt)
  319. {
  320. if (m_cCatid >= (celt + m_dwPosition)) {
  321. m_dwPosition += celt;
  322. return S_OK;
  323. }
  324. m_dwPosition = m_cCatid;
  325. return S_FALSE;
  326. }
  327. HRESULT CSCEnumCategoriesOfClass::Reset(void)
  328. {
  329. m_dwPosition = 0;
  330. return S_OK;
  331. }
  332. HRESULT CSCEnumCategoriesOfClass::Clone(IEnumGUID **ppenum)
  333. {
  334. HRESULT hr = S_OK;
  335. CSCEnumCategoriesOfClass *pEnumClone = NULL;
  336. if (!IsValidPtrOut(ppenum, sizeof(IEnumGUID *)))
  337. return E_POINTER;
  338. pEnumClone = new CSCEnumCategoriesOfClass;
  339. if (pEnumClone == NULL)
  340. return E_OUTOFMEMORY;
  341. pEnumClone->Initialize(m_catid, m_cCatid);
  342. pEnumClone->m_dwPosition = m_dwPosition;
  343. if (SUCCEEDED(hr = pEnumClone->QueryInterface(IID_IEnumCATID, (void**) ppenum)))
  344. return S_OK;
  345. delete pEnumClone;
  346. return hr;
  347. }
  348. CSCEnumCategoriesOfClass::CSCEnumCategoriesOfClass()
  349. {
  350. m_dwRefCount=0;
  351. m_dwPosition = 0;
  352. m_catid = NULL;
  353. }
  354. HRESULT CSCEnumCategoriesOfClass::Initialize(CATID catid[], ULONG cCatid)
  355. {
  356. ULONG i;
  357. m_catid = new CATID[cCatid];
  358. if (!m_catid)
  359. return E_OUTOFMEMORY;
  360. m_cCatid = cCatid;
  361. for (i = 0; i < cCatid; i++)
  362. m_catid[i] = catid[i];
  363. m_dwPosition = 0;
  364. return S_OK;
  365. }
  366. CSCEnumCategoriesOfClass::~CSCEnumCategoriesOfClass()
  367. {
  368. if (m_catid)
  369. delete m_catid;
  370. }
  371. // CEnumClassesOfCategories:
  372. // IUnknown methods
  373. HRESULT CSCEnumClassesOfCategories::QueryInterface(REFIID riid, void** ppObject)
  374. {
  375. if (riid==IID_IUnknown || riid==IID_IEnumCLSID)
  376. {
  377. *ppObject=(IEnumCLSID*) this;
  378. }
  379. else
  380. {
  381. return E_NOINTERFACE;
  382. }
  383. AddRef();
  384. return S_OK;
  385. }
  386. ULONG CSCEnumClassesOfCategories::AddRef()
  387. {
  388. InterlockedIncrement((long*) &m_dwRefCount);
  389. return m_dwRefCount;
  390. }
  391. ULONG CSCEnumClassesOfCategories::Release()
  392. {
  393. ULONG dwRefCount;
  394. if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
  395. {
  396. delete this;
  397. return 0;
  398. }
  399. return dwRefCount;
  400. }
  401. // IEnumGUID methods
  402. HRESULT CSCEnumClassesOfCategories::Next(ULONG celt, GUID *rgelt, ULONG *pceltFetched)
  403. {
  404. ULONG cRead;
  405. ULONG i, dwCount, cgot;
  406. HRESULT hr;
  407. CLSID clsid;
  408. IADs *pclsid;
  409. WCHAR szClsid[_MAX_PATH];
  410. if ((celt > 1) && (!pceltFetched))
  411. return E_INVALIDARG;
  412. if (pceltFetched)
  413. (*pceltFetched) = 0;
  414. if ((celt < 0) || (!IsValidPtrOut(rgelt, sizeof(GUID)*celt)))
  415. return E_INVALIDARG;
  416. for ((dwCount) = 0; (dwCount) < celt;) {
  417. hr = GetNextEnum(m_pEnumVariant, &pclsid);
  418. if ((FAILED(hr)) || (hr == S_FALSE))
  419. {
  420. if (pceltFetched)
  421. *pceltFetched = dwCount;
  422. return S_FALSE;
  423. }
  424. hr = GetProperty (pclsid, CLASSCLSID, szClsid);
  425. pclsid->Release();
  426. if (FAILED(hr)) {
  427. if (pceltFetched)
  428. *pceltFetched = dwCount;
  429. return S_FALSE;
  430. }
  431. GUIDFromString(szClsid, &clsid);
  432. if ((ImplSatisfied(clsid, m_cImplemented, m_rgcatidImpl, m_pICatInfo) == S_OK) &&
  433. (ReqSatisfied(clsid, m_cRequired, m_rgcatidReq, m_pICatInfo) == S_OK))
  434. {
  435. rgelt[dwCount] = clsid;
  436. (dwCount)++;
  437. }
  438. }
  439. m_dwPosition += dwCount;
  440. if (pceltFetched)
  441. *pceltFetched = dwCount;
  442. return S_OK;
  443. }
  444. HRESULT CSCEnumClassesOfCategories::Skip(ULONG celt)
  445. {
  446. CLSID *dummyclasses;
  447. ULONG celtFetched;
  448. HRESULT hr;
  449. dummyclasses = new CLSID[celt];
  450. hr = Next(celt, dummyclasses, &celtFetched);
  451. delete dummyclasses;
  452. return hr;
  453. }
  454. HRESULT CSCEnumClassesOfCategories::Reset()
  455. {
  456. LPOLESTR pszPathNames [2];
  457. HRESULT hr;
  458. pszPathNames [0] = CLASS_CS_CLASS;
  459. if (m_pEnumVariant == NULL)
  460. return E_UNEXPECTED;
  461. m_pEnumVariant->Release();
  462. hr = EnumCsObject(m_ADsClassContainer, &pszPathNames[0],
  463. 0, &m_pEnumVariant);
  464. m_dwPosition = 0;
  465. return hr;
  466. }
  467. HRESULT CSCEnumClassesOfCategories::Clone(IEnumGUID **ppenum)
  468. {
  469. HRESULT hr;
  470. CSCEnumClassesOfCategories *pEnumClone;
  471. if (!ppenum)
  472. return E_INVALIDARG;
  473. pEnumClone = new CSCEnumClassesOfCategories;
  474. if (!pEnumClone)
  475. return E_OUTOFMEMORY;
  476. hr = pEnumClone->Initialize(m_cRequired, m_rgcatidReq,
  477. m_cImplemented, m_rgcatidImpl,
  478. m_ADsClassContainer,
  479. m_pICatInfo);
  480. if (FAILED(hr))
  481. {
  482. delete pEnumClone;
  483. return hr;
  484. }
  485. pEnumClone->Skip(m_dwPosition);
  486. hr = pEnumClone->QueryInterface(IID_IEnumCLSID, (void **)ppenum);
  487. if (FAILED(hr))
  488. {
  489. delete pEnumClone;
  490. }
  491. return hr;
  492. }
  493. CSCEnumClassesOfCategories::CSCEnumClassesOfCategories()
  494. {
  495. m_dwRefCount = 0;
  496. m_rgcatidReq = NULL;
  497. m_rgcatidImpl = NULL;
  498. m_pICatInfo = NULL;
  499. m_ADsClassContainer = NULL;
  500. m_pEnumVariant = NULL;
  501. m_dwPosition = 0;
  502. }
  503. HRESULT CSCEnumClassesOfCategories::Initialize(ULONG cRequired, CATID rgcatidReq[],
  504. ULONG cImplemented, CATID rgcatidImpl[],
  505. IADsContainer *ADsClassContainer,
  506. ICatInformation *pICatInfo)
  507. {
  508. ULONG i;
  509. HRESULT hr;
  510. LPOLESTR pszPathNames [2];
  511. pszPathNames [0] = CLASS_CS_CLASS;
  512. m_ADsClassContainer = ADsClassContainer;
  513. m_ADsClassContainer->AddRef();
  514. hr = EnumCsObject(m_ADsClassContainer, &pszPathNames[0], 0, &m_pEnumVariant);
  515. RETURN_ON_FAILURE(hr);
  516. m_pICatInfo = pICatInfo;
  517. RETURN_ON_FAILURE(m_pICatInfo->AddRef());
  518. m_cRequired = cRequired;
  519. if (cRequired != -1)
  520. {
  521. m_rgcatidReq = new CATID[cRequired];
  522. if (!m_rgcatidReq)
  523. return E_OUTOFMEMORY;
  524. for (i = 0; i < m_cRequired; i++)
  525. m_rgcatidReq[i] = rgcatidReq[i];
  526. }
  527. m_cImplemented = cImplemented;
  528. if (cImplemented != -1)
  529. {
  530. m_rgcatidImpl = new CATID[cImplemented];
  531. if (!m_rgcatidImpl)
  532. return E_OUTOFMEMORY;
  533. for (i = 0; i < m_cImplemented; i++)
  534. m_rgcatidImpl[i] = rgcatidImpl[i];
  535. }
  536. return S_OK;
  537. }
  538. CSCEnumClassesOfCategories::~CSCEnumClassesOfCategories()
  539. {
  540. if (m_rgcatidReq)
  541. delete m_rgcatidReq;
  542. if (m_rgcatidImpl)
  543. delete m_rgcatidImpl;
  544. if (m_pICatInfo)
  545. m_pICatInfo->Release();
  546. if (m_ADsClassContainer)
  547. m_ADsClassContainer->Release();
  548. if (m_pEnumVariant)
  549. m_pEnumVariant->Release();
  550. }
  551.