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.

675 lines
17 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. HRESULT GetCategoryProperty (HANDLE hADs,
  22. ADS_SEARCH_HANDLE hSearchHandle,
  23. CATEGORYINFO *pcategoryinfo,
  24. LCID lcid)
  25. {
  26. HRESULT hr = S_OK;
  27. WCHAR *szName = NULL;
  28. LPOLESTR *pdesc = NULL;
  29. ULONG i, cdesc = 0;
  30. ADS_SEARCH_COLUMN column;
  31. hr = ADSIGetColumn(hADs, hSearchHandle, CATEGORYCATID, &column);
  32. RETURN_ON_FAILURE(hr);
  33. hr = UnpackGUIDFrom(column, &(pcategoryinfo->catid));
  34. RETURN_ON_FAILURE(hr);
  35. ADSIFreeColumn(hADs, &column);
  36. hr = ADSIGetColumn(hADs, hSearchHandle, LOCALEDESCRIPTION, &column);
  37. RETURN_ON_FAILURE(hr);
  38. UnpackStrArrAllocFrom(column, &pdesc, &cdesc);
  39. pcategoryinfo->lcid = lcid;
  40. hr = GetCategoryLocaleDesc(pdesc, cdesc, &(pcategoryinfo->lcid),
  41. (pcategoryinfo->szDescription));
  42. ADSIFreeColumn(hADs, &column);
  43. for (i = 0; i < cdesc; i++)
  44. CoTaskMemFree(pdesc[i]);
  45. CoTaskMemFree(pdesc);
  46. if (FAILED(hr))
  47. *(pcategoryinfo->szDescription) = L'\0';
  48. return S_OK;
  49. }
  50. //----------------------------------------------
  51. // IEnumCATEGORYINFO:
  52. // IUnknown methods
  53. HRESULT CSCEnumCategories::QueryInterface(REFIID riid, void** ppObject)
  54. {
  55. *ppObject = NULL; //gd
  56. if ((riid==IID_IUnknown) || (riid==IID_IEnumCATEGORYINFO))
  57. {
  58. *ppObject=(IUnknown *)(IEnumCATEGORYINFO*) this;
  59. }
  60. else
  61. {
  62. return E_NOINTERFACE;
  63. }
  64. AddRef();
  65. return S_OK;
  66. }
  67. ULONG CSCEnumCategories::AddRef()
  68. {
  69. InterlockedIncrement((long*) &m_dwRefCount);
  70. return m_dwRefCount;
  71. }
  72. ULONG CSCEnumCategories::Release()
  73. {
  74. ULONG dwRefCount;
  75. if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
  76. {
  77. delete this;
  78. return 0;
  79. }
  80. return dwRefCount;
  81. }
  82. // IEnumCATEGORYINFO methods
  83. //--------------------------------------------------------------------
  84. // Next:
  85. // celt: Number of elements to be fetched.
  86. // rgelt: Buffer to return the elements.
  87. // pceltFetched: ptr to Number of elements actually fetched.
  88. // Takes care of that being NULL.
  89. // Uses OLE DS interfaces to get the next enumerators.
  90. //--------------------------------------------------------------------
  91. HRESULT CSCEnumCategories::Next(ULONG celt, CATEGORYINFO *rgelt, ULONG *pceltFetched)
  92. {
  93. HRESULT hr = S_OK;
  94. ULONG dwCount = 0, cElems = 0;
  95. if ((celt > 1) && (!pceltFetched))
  96. return E_INVALIDARG;
  97. if (pceltFetched)
  98. (*pceltFetched) = 0;
  99. if (celt < 0)
  100. return E_INVALIDARG;
  101. if (!IsValidPtrOut(rgelt, sizeof(CATEGORYINFO)*celt))
  102. return E_INVALIDARG;
  103. for ((dwCount) = 0; (dwCount) < celt;)
  104. {
  105. if ((!m_dwPosition) && (!cElems))
  106. hr = ADSIGetFirstRow(m_hADs, m_hADsSearchHandle);
  107. else
  108. hr = ADSIGetNextRow(m_hADs, m_hADsSearchHandle);
  109. cElems++;
  110. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  111. break;
  112. hr = GetCategoryProperty(m_hADs, m_hADsSearchHandle, &(rgelt[dwCount]), m_lcid);
  113. if (FAILED(hr))
  114. continue;
  115. (dwCount)++;
  116. }
  117. m_dwPosition += dwCount;
  118. if (pceltFetched)
  119. (*pceltFetched) = dwCount;
  120. if (dwCount == celt)
  121. return S_OK;
  122. return S_FALSE;
  123. }
  124. //---------------------------------------------------
  125. // skip:
  126. // skips elements.
  127. // celt Number of elements to skip.
  128. //---------------------------------------------------
  129. HRESULT CSCEnumCategories::Skip(ULONG celt)
  130. {
  131. CATEGORYINFO *dummy = NULL;
  132. ULONG got = 0;
  133. HRESULT hr = S_OK;
  134. dummy = new CATEGORYINFO[celt];
  135. if (!dummy)
  136. return E_OUTOFMEMORY;
  137. hr = Next(celt, dummy, &got);
  138. delete dummy;
  139. return hr;
  140. }
  141. //---------------------------------------------------
  142. // Reset:
  143. // Resets the pointer.
  144. //---------------------------------------------------
  145. HRESULT CSCEnumCategories::Reset(void)
  146. {
  147. HRESULT hr = S_OK;
  148. WCHAR szfilter[_MAX_PATH];
  149. m_dwPosition = 0;
  150. if (m_hADsSearchHandle)
  151. {
  152. ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle);
  153. m_hADsSearchHandle = NULL;
  154. }
  155. wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CATEGORY);
  156. hr = ADSIExecuteSearch(m_hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &m_hADsSearchHandle);
  157. return RemapErrorCode(hr, m_szCategoryName);
  158. }
  159. //--------------------------------------------------------------
  160. // Clone:
  161. // returns another interface which points to the same data.
  162. // ppenum: enumerator
  163. //--------------------------------------------------------------
  164. HRESULT CSCEnumCategories::Clone(IEnumCATEGORYINFO **ppenum)
  165. {
  166. CSCEnumCategories* pClone=NULL;
  167. if (!IsValidPtrOut(ppenum, sizeof(IEnumCATEGORYINFO *))) {
  168. return E_INVALIDARG;
  169. }
  170. pClone=new CSCEnumCategories();
  171. if (!pClone)
  172. {
  173. return E_OUTOFMEMORY;
  174. }
  175. if (FAILED(pClone->Initialize(m_szCategoryName, m_lcid)))
  176. {
  177. delete pClone;
  178. return E_UNEXPECTED;
  179. }
  180. pClone->Skip(m_dwPosition);
  181. if (SUCCEEDED(pClone->QueryInterface(IID_IEnumCATEGORYINFO, (void**) ppenum)))
  182. {
  183. return S_OK;
  184. }
  185. delete pClone;
  186. return E_UNEXPECTED;
  187. }
  188. CSCEnumCategories::CSCEnumCategories()
  189. {
  190. m_dwRefCount=0;
  191. m_hADs = NULL;
  192. m_hADsSearchHandle = NULL;
  193. wcscpy(m_szCategoryName, L"");
  194. m_lcid = 0;
  195. m_dwPosition = 0;
  196. }
  197. // clone will go over the wire again.
  198. // reference counting will be good.
  199. HRESULT CSCEnumCategories::Initialize(WCHAR *szCategoryName, LCID lcid)
  200. {
  201. HRESULT hr = S_OK;
  202. WCHAR szfilter[_MAX_PATH];
  203. ADS_SEARCHPREF_INFO SearchPrefs[2];
  204. // set the search preference.
  205. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  206. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  207. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  208. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  209. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  210. SearchPrefs[1].vValue.Integer = 20;
  211. wcscpy(m_szCategoryName, szCategoryName);
  212. hr = ADSIOpenDSObject(m_szCategoryName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  213. &m_hADs);
  214. RETURN_ON_FAILURE(hr);
  215. hr = ADSISetSearchPreference(m_hADs, SearchPrefs, 2);
  216. RETURN_ON_FAILURE(hr);
  217. wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CATEGORY);
  218. hr = ADSIExecuteSearch(m_hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &m_hADsSearchHandle);
  219. RETURN_ON_FAILURE(hr);
  220. m_lcid = lcid;
  221. return S_OK;
  222. } /* EnumCategories */
  223. CSCEnumCategories::~CSCEnumCategories()
  224. {
  225. if (m_hADs)
  226. ADSICloseDSObject(m_hADs);
  227. if (m_hADsSearchHandle)
  228. ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle);
  229. }
  230. // CSCEnumCategoriesOfClass:
  231. // IUnknown methods
  232. HRESULT CSCEnumCategoriesOfClass::QueryInterface(REFIID riid, void** ppObject)
  233. {
  234. if ((riid==IID_IUnknown) || (riid==IID_IEnumCATID))
  235. {
  236. *ppObject=(IEnumCATID*) this;
  237. }
  238. else
  239. {
  240. return E_NOINTERFACE;
  241. }
  242. AddRef();
  243. return S_OK;
  244. }
  245. ULONG CSCEnumCategoriesOfClass::AddRef()
  246. {
  247. InterlockedIncrement((long*) &m_dwRefCount);
  248. return m_dwRefCount;
  249. }
  250. ULONG CSCEnumCategoriesOfClass::Release()
  251. {
  252. ULONG dwRefCount;
  253. if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
  254. {
  255. delete this;
  256. return 0;
  257. }
  258. return dwRefCount;
  259. }
  260. // IEnumCATID methods
  261. HRESULT CSCEnumCategoriesOfClass::Next(ULONG celt, GUID *rgelt, ULONG *pceltFetched)
  262. {
  263. ULONG dwCount;
  264. if ((celt > 1) && (!pceltFetched))
  265. return E_INVALIDARG;
  266. if (pceltFetched)
  267. (*pceltFetched) = 0;
  268. if (celt < 0)
  269. return E_INVALIDARG;
  270. if (!IsValidPtrOut(rgelt, sizeof(GUID)*celt))
  271. return E_INVALIDARG;
  272. for ( (dwCount) = 0; (((dwCount) < celt) && (m_dwPosition < m_cCatid));
  273. (dwCount)++, m_dwPosition++)
  274. rgelt[(dwCount)] = m_catid[m_dwPosition];
  275. if (pceltFetched)
  276. (*pceltFetched) = dwCount;
  277. if (dwCount == celt)
  278. return S_OK;
  279. return S_FALSE;
  280. }
  281. HRESULT CSCEnumCategoriesOfClass::Skip(ULONG celt)
  282. {
  283. if (m_cCatid >= (celt + m_dwPosition)) {
  284. m_dwPosition += celt;
  285. return S_OK;
  286. }
  287. m_dwPosition = m_cCatid;
  288. return S_FALSE;
  289. }
  290. HRESULT CSCEnumCategoriesOfClass::Reset(void)
  291. {
  292. m_dwPosition = 0;
  293. return S_OK;
  294. }
  295. HRESULT CSCEnumCategoriesOfClass::Clone(IEnumGUID **ppenum)
  296. {
  297. HRESULT hr = S_OK;
  298. CSCEnumCategoriesOfClass *pEnumClone = NULL;
  299. if (!IsValidPtrOut(ppenum, sizeof(IEnumGUID *)))
  300. return E_POINTER;
  301. pEnumClone = new CSCEnumCategoriesOfClass;
  302. if (pEnumClone == NULL)
  303. return E_OUTOFMEMORY;
  304. pEnumClone->Initialize(m_catid, m_cCatid);
  305. pEnumClone->m_dwPosition = m_dwPosition;
  306. if (SUCCEEDED(hr = pEnumClone->QueryInterface(IID_IEnumCATID, (void**) ppenum)))
  307. return S_OK;
  308. delete pEnumClone;
  309. return hr;
  310. }
  311. CSCEnumCategoriesOfClass::CSCEnumCategoriesOfClass()
  312. {
  313. m_dwRefCount=0;
  314. m_dwPosition = 0;
  315. m_catid = NULL;
  316. }
  317. HRESULT CSCEnumCategoriesOfClass::Initialize(CATID catid[], ULONG cCatid)
  318. {
  319. ULONG i;
  320. m_catid = new CATID[cCatid];
  321. if ((cCatid) && (!m_catid))
  322. return E_OUTOFMEMORY;
  323. m_cCatid = cCatid;
  324. for (i = 0; i < cCatid; i++)
  325. m_catid[i] = catid[i];
  326. m_dwPosition = 0;
  327. return S_OK;
  328. }
  329. CSCEnumCategoriesOfClass::~CSCEnumCategoriesOfClass()
  330. {
  331. if (m_catid)
  332. delete m_catid;
  333. }
  334. // CEnumClassesOfCategories:
  335. // IUnknown methods
  336. HRESULT CSCEnumClassesOfCategories::QueryInterface(REFIID riid, void** ppObject)
  337. {
  338. if (riid==IID_IUnknown || riid==IID_IEnumCLSID)
  339. {
  340. *ppObject=(IEnumCLSID*) this;
  341. }
  342. else
  343. {
  344. return E_NOINTERFACE;
  345. }
  346. AddRef();
  347. return S_OK;
  348. }
  349. ULONG CSCEnumClassesOfCategories::AddRef()
  350. {
  351. InterlockedIncrement((long*) &m_dwRefCount);
  352. return m_dwRefCount;
  353. }
  354. ULONG CSCEnumClassesOfCategories::Release()
  355. {
  356. ULONG dwRefCount;
  357. if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
  358. {
  359. delete this;
  360. return 0;
  361. }
  362. return dwRefCount;
  363. }
  364. // IEnumGUID methods
  365. HRESULT CSCEnumClassesOfCategories::Next(ULONG celt, GUID *rgelt, ULONG *pceltFetched)
  366. {
  367. ULONG i, dwCount=0;
  368. HRESULT hr = S_OK;
  369. CLSID clsid;
  370. WCHAR * szClsid = NULL;
  371. DWORD cElems = 0;
  372. ADS_SEARCH_COLUMN column;
  373. if ((celt > 1) && (!pceltFetched))
  374. return E_INVALIDARG;
  375. if (pceltFetched)
  376. (*pceltFetched) = 0;
  377. if ((celt < 0) || (!IsValidPtrOut(rgelt, sizeof(GUID)*celt)))
  378. return E_INVALIDARG;
  379. for ((dwCount) = 0; (dwCount) < celt;)
  380. {
  381. if ((!m_dwPosition) && (!cElems))
  382. hr = ADSIGetFirstRow(m_hADs, m_hADsSearchHandle);
  383. else
  384. hr = ADSIGetNextRow(m_hADs, m_hADsSearchHandle);
  385. cElems++;
  386. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  387. {
  388. if (pceltFetched)
  389. *pceltFetched = dwCount;
  390. return S_FALSE;
  391. }
  392. hr = ADSIGetColumn(m_hADs, m_hADsSearchHandle, CLASSCLSID, &column);
  393. if (FAILED(hr))
  394. {
  395. if (pceltFetched)
  396. *pceltFetched = dwCount;
  397. return S_FALSE;
  398. }
  399. UnpackStrFrom(column, &szClsid);
  400. GUIDFromString(szClsid, &clsid);
  401. if ((ImplSatisfied(m_cImplemented, m_rgcatidImpl, m_hADs, m_hADsSearchHandle) == S_OK) &&
  402. (ReqSatisfied(m_cRequired, m_rgcatidReq, m_hADs, m_hADsSearchHandle) == S_OK))
  403. {
  404. rgelt[dwCount] = clsid;
  405. (dwCount)++;
  406. }
  407. }
  408. m_dwPosition += dwCount;
  409. if (pceltFetched)
  410. *pceltFetched = dwCount;
  411. return S_OK;
  412. }
  413. HRESULT CSCEnumClassesOfCategories::Skip(ULONG celt)
  414. {
  415. CLSID *dummyclasses=NULL;
  416. ULONG celtFetched=0;
  417. HRESULT hr=S_OK;
  418. dummyclasses = new CLSID[celt];
  419. hr = Next(celt, dummyclasses, &celtFetched);
  420. delete dummyclasses;
  421. return hr;
  422. }
  423. HRESULT CSCEnumClassesOfCategories::Reset()
  424. {
  425. LPOLESTR AttrNames[] = {CLASSCLSID, IMPL_CATEGORIES, REQ_CATEGORIES};
  426. DWORD cAttrs = 3;
  427. WCHAR szfilter[_MAX_PATH];
  428. HRESULT hr = S_OK;
  429. m_dwPosition = 0;
  430. if (m_hADsSearchHandle)
  431. {
  432. ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle);
  433. m_hADsSearchHandle = NULL;
  434. }
  435. wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CLASS);
  436. hr = ADSIExecuteSearch(m_hADs, szfilter, AttrNames, cAttrs, &m_hADsSearchHandle);
  437. return RemapErrorCode(hr, m_szClassName);
  438. }
  439. HRESULT CSCEnumClassesOfCategories::Clone(IEnumGUID **ppenum)
  440. {
  441. HRESULT hr=S_OK;
  442. CSCEnumClassesOfCategories *pEnumClone=NULL;
  443. if (!ppenum)
  444. return E_INVALIDARG;
  445. pEnumClone = new CSCEnumClassesOfCategories;
  446. if (!pEnumClone)
  447. return E_OUTOFMEMORY;
  448. hr = pEnumClone->Initialize(m_cRequired, m_rgcatidReq,
  449. m_cImplemented, m_rgcatidImpl,
  450. m_szClassName);
  451. if (FAILED(hr))
  452. {
  453. delete pEnumClone;
  454. return hr;
  455. }
  456. pEnumClone->Skip(m_dwPosition);
  457. hr = pEnumClone->QueryInterface(IID_IEnumCLSID, (void **)ppenum);
  458. if (FAILED(hr))
  459. {
  460. delete pEnumClone;
  461. }
  462. return hr;
  463. }
  464. CSCEnumClassesOfCategories::CSCEnumClassesOfCategories()
  465. {
  466. m_dwRefCount = 0;
  467. m_rgcatidReq = NULL;
  468. m_rgcatidImpl = NULL;
  469. wcscpy(m_szClassName,L"");
  470. m_dwPosition = 0;
  471. m_hADs = NULL;
  472. m_hADsSearchHandle = NULL;
  473. }
  474. HRESULT CSCEnumClassesOfCategories::Initialize(ULONG cRequired, CATID rgcatidReq[],
  475. ULONG cImplemented, CATID rgcatidImpl[],
  476. WCHAR *szClassName)
  477. {
  478. ULONG i;
  479. HRESULT hr = S_OK;
  480. ADS_SEARCHPREF_INFO SearchPrefs[2];
  481. LPOLESTR AttrNames[] = {CLASSCLSID, IMPL_CATEGORIES, REQ_CATEGORIES};
  482. DWORD cAttrs = 3;
  483. WCHAR szfilter[_MAX_PATH];
  484. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  485. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  486. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  487. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  488. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  489. SearchPrefs[1].vValue.Integer = 20;
  490. wcscpy(m_szClassName, szClassName);
  491. hr = ADSIOpenDSObject(m_szClassName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  492. &m_hADs);
  493. ERROR_ON_FAILURE(hr);
  494. hr = ADSISetSearchPreference(m_hADs, SearchPrefs, 2);
  495. ERROR_ON_FAILURE(hr);
  496. wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CLASS);
  497. hr = ADSIExecuteSearch(m_hADs, szfilter, AttrNames, cAttrs, &m_hADsSearchHandle);
  498. ERROR_ON_FAILURE(hr);
  499. m_cRequired = cRequired;
  500. if (cRequired != -1)
  501. {
  502. m_rgcatidReq = new CATID[cRequired];
  503. if (!m_rgcatidReq) {
  504. hr = E_OUTOFMEMORY;
  505. ERROR_ON_FAILURE(hr);
  506. }
  507. for (i = 0; i < m_cRequired; i++)
  508. m_rgcatidReq[i] = rgcatidReq[i];
  509. }
  510. m_cImplemented = cImplemented;
  511. if (cImplemented != -1)
  512. {
  513. m_rgcatidImpl = new CATID[cImplemented];
  514. if (!m_rgcatidImpl) {
  515. hr = E_OUTOFMEMORY;
  516. ERROR_ON_FAILURE(hr);
  517. }
  518. for (i = 0; i < m_cImplemented; i++)
  519. m_rgcatidImpl[i] = rgcatidImpl[i];
  520. }
  521. Error_Cleanup:
  522. return RemapErrorCode(hr, m_szClassName);
  523. }
  524. CSCEnumClassesOfCategories::~CSCEnumClassesOfCategories()
  525. {
  526. if (m_rgcatidReq)
  527. delete m_rgcatidReq;
  528. if (m_rgcatidImpl)
  529. delete m_rgcatidImpl;
  530. if (m_hADsSearchHandle)
  531. ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle);
  532. if (m_hADs)
  533. ADSICloseDSObject(m_hADs);
  534. }