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.

463 lines
14 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 ICatInformation interfaces. �
  9. //
  10. // Refer Doc "Design for Support of File Types and Component Categories
  11. // in Class Store" ? (or may be Class Store Schema)
  12. //
  13. #include "cstore.hxx"
  14. //---------------------------------------------------------------
  15. // EnumCategories:
  16. // returns the enumerator to enumerate categories.
  17. // lcid: locale id.
  18. // ppenumcategoryinfo: Enumerator that is returned.
  19. //
  20. // ppEnumCategoryInfo value is undefined if an error occurs
  21. // I am assuming that except in rare conditions all the application in a
  22. // particular environment will have the same lcid.
  23. //---------------------------------------------------------------
  24. HRESULT __stdcall CClassContainer::EnumCategories(LCID lcid, IEnumCATEGORYINFO **ppenumCategoryInfo)
  25. {
  26. VARIANT *pVarFilter = NULL;
  27. HRESULT hr;
  28. CSCEnumCategories *pEnum;
  29. if (!m_fOpen)
  30. return E_FAIL;
  31. if (!IsValidPtrOut(this, sizeof(*this)))
  32. return E_ACCESSDENIED;
  33. if (!IsValidPtrOut(ppenumCategoryInfo, sizeof(IEnumCATEGORYINFO *)))
  34. return E_INVALIDARG;
  35. *ppenumCategoryInfo=NULL;
  36. pEnum=new CSCEnumCategories;
  37. if(NULL == pEnum)
  38. return E_OUTOFMEMORY;
  39. hr = pEnum->Initialize(m_ADsCategoryContainer, lcid);
  40. if (FAILED(hr))
  41. {
  42. delete pEnum;
  43. return hr;
  44. }
  45. hr = pEnum->QueryInterface(IID_IEnumCATEGORYINFO,(void**) ppenumCategoryInfo);
  46. if (FAILED(hr))
  47. {
  48. delete pEnum;
  49. return hr;
  50. }
  51. return S_OK;
  52. } /* EnumCategories */
  53. //---------------------------------------------------------------
  54. // GetCategoryDesc:
  55. // returns the description of a given category.
  56. // rcatid: category id.
  57. // lcid: locale id.
  58. // ppszDesc pointer to the description string to be returned.
  59. // Allocated by the function. to be freed by client.
  60. //--------------------------------------------------------------------------
  61. HRESULT __stdcall CClassContainer::GetCategoryDesc(REFCATID rcatid, LCID lcid, LPOLESTR *ppszDesc)
  62. {
  63. STRINGGUID guidstr;
  64. ULONG cdesc, i;
  65. LPOLESTR *localedesc;
  66. IADs *pADs;
  67. HRESULT hr;
  68. if (!IsValidPtrOut(ppszDesc, sizeof(LPOLESTR)))
  69. return E_INVALIDARG;
  70. if (IsNullGuid(rcatid))
  71. return E_INVALIDARG;
  72. if (!IsValidPtrOut(this, sizeof(*this)))
  73. return E_ACCESSDENIED;
  74. RdnFromGUID(rcatid, guidstr);
  75. hr = m_ADsCategoryContainer->GetObject(NULL, guidstr, (IDispatch **)&pADs);
  76. if (FAILED(hr))
  77. return CAT_E_CATIDNOEXIST;
  78. hr = GetPropertyListAlloc(pADs, LOCALEDESCRIPTION, &cdesc, &localedesc);
  79. if (hr == E_OUTOFMEMORY)
  80. return hr;
  81. if (FAILED(hr))
  82. return CAT_E_NODESCRIPTION;
  83. *ppszDesc = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR)*128);
  84. if (!(*ppszDesc))
  85. return E_OUTOFMEMORY;
  86. GetCategoryLocaleDesc(localedesc, cdesc, &lcid, *ppszDesc);
  87. for (i = 0; i < cdesc; i++)
  88. CoTaskMemFree(localedesc[i]);
  89. CoTaskMemFree(localedesc);
  90. pADs->Release();
  91. return S_OK;
  92. } /* GetCategoryDesc */
  93. //---------------------------------------------------------------
  94. // EnumClassesOfCategories:
  95. // returns the enumerator for classes that implements given catids and
  96. // requires some given catids.
  97. //
  98. // cImplemented number of implemented categories.
  99. // (0 is error and -1 is ignore implemented.
  100. // rgcatidImpl list of implemented categories.
  101. // should be NULL in the two cases mentioned above.
  102. //
  103. // cRequired: number of required categories.
  104. // (0 is requiring nothing and -1 is ignore required.
  105. // rgcatidReq list of required categories.
  106. // should be NULL in the two cases mentioned above.
  107. //
  108. // ppenumClsid the enumerator of class ids.
  109. //--------------------------------------------------------------------------
  110. HRESULT __stdcall CClassContainer::EnumClassesOfCategories(ULONG cImplemented, CATID rgcatidImpl[],
  111. ULONG cRequired, CATID rgcatidReq[],
  112. IEnumGUID **ppenumClsid)
  113. {
  114. ULONG i;
  115. CSCEnumClassesOfCategories *penumclasses;
  116. HRESULT hr;
  117. Data *pData;
  118. if (!IsValidPtrOut(ppenumClsid, sizeof(IEnumGUID *)))
  119. return E_INVALIDARG;
  120. if ((rgcatidImpl == NULL) && (cImplemented != 0) && (cImplemented != -1))
  121. return E_INVALIDARG;
  122. if ((rgcatidReq == NULL) && (cRequired != 0) && (cRequired != -1))
  123. return E_INVALIDARG;
  124. if ((cImplemented == -1) && (rgcatidImpl != NULL))
  125. return E_POINTER;
  126. if ((cRequired == -1) && (rgcatidReq != NULL))
  127. return E_POINTER;
  128. if (cImplemented == 0)
  129. return E_INVALIDARG;
  130. if ((rgcatidImpl) && (!IsValidReadPtrIn(rgcatidImpl, sizeof(CATID)*cImplemented)))
  131. {
  132. return E_INVALIDARG;
  133. }
  134. if ((rgcatidReq) && (!IsValidReadPtrIn(rgcatidReq, sizeof(CATID)*cRequired)))
  135. {
  136. return E_INVALIDARG;
  137. }
  138. if (!IsValidPtrOut(this, sizeof(*this)))
  139. return E_ACCESSDENIED;
  140. penumclasses = new CSCEnumClassesOfCategories;
  141. if (!penumclasses)
  142. {
  143. return E_OUTOFMEMORY;
  144. }
  145. hr = penumclasses->Initialize(cRequired, rgcatidReq, cImplemented, rgcatidImpl,
  146. m_ADsClassContainer, (ICatInformation *)this);
  147. if (FAILED(hr))
  148. {
  149. delete penumclasses;
  150. return hr;
  151. }
  152. hr = penumclasses->QueryInterface(IID_IEnumCLSID, (void **)ppenumClsid);
  153. if (FAILED(hr))
  154. {
  155. delete penumclasses;
  156. return hr;
  157. }
  158. return hr;
  159. } /* EnumClassesOfCategories */
  160. //---------------------------------------------------------------
  161. // EnumReqCategoriesOfClass:
  162. // see below EnumCategoriesofClass
  163. //
  164. //---------------------------------------------------------------
  165. HRESULT CClassContainer::EnumReqCategoriesOfClass(REFCLSID rclsid, IEnumGUID **ppenumCatid)
  166. {
  167. if (!IsValidReadPtrIn(this, sizeof(*this)))
  168. return E_ACCESSDENIED;
  169. if (IsNullGuid(rclsid))
  170. return E_INVALIDARG;
  171. if (!IsValidPtrOut(ppenumCatid, sizeof(IEnumGUID *)))
  172. return E_INVALIDARG;
  173. return EnumCategoriesOfClass(rclsid, REQ_CATEGORIES, ppenumCatid);
  174. } /* EnumReqClassesOfCategories */
  175. //---------------------------------------------------------------
  176. // EnumImplCategoriesOfClass:
  177. // see below EnumCategoriesofClass
  178. //
  179. //---------------------------------------------------------------
  180. HRESULT CClassContainer::EnumImplCategoriesOfClass(REFCLSID rclsid, IEnumGUID **ppenumCatid)
  181. {
  182. if (!IsValidReadPtrIn(this, sizeof(*this)))
  183. return E_ACCESSDENIED;
  184. if (IsNullGuid(rclsid))
  185. return E_INVALIDARG;
  186. if (!IsValidPtrOut(ppenumCatid, sizeof(IEnumGUID *)))
  187. return E_INVALIDARG;
  188. return EnumCategoriesOfClass(rclsid, IMPL_CATEGORIES, ppenumCatid);
  189. } /* EnumimplClassesOfCategories */
  190. //---------------------------------------------------------------
  191. // EnumCategoriesOfClass:
  192. // returns the enumerator for the implemented or required
  193. // rclsid: the class id.
  194. // impl_or_req the type of category to enumerated.
  195. // ppenumcatid the enumerator that is returned.
  196. // Prefetches all the catids and then enumerates them.
  197. //---------------------------------------------------------------
  198. HRESULT CClassContainer::EnumCategoriesOfClass(REFCLSID rclsid, BSTR impl_or_req,
  199. IEnumGUID **ppenumCatid)
  200. {
  201. STRINGGUID szName;
  202. IADs *pADs = NULL;
  203. ULONG i;
  204. ULONG cCatid;
  205. CATID *Catid = NULL;
  206. CSCEnumCategoriesOfClass *pEnumCatid;
  207. HRESULT hr = S_OK;
  208. if (!m_fOpen)
  209. return E_FAIL;
  210. // Get the ADs interface corresponding to the clsid that is mentioned.
  211. RdnFromGUID(rclsid, szName);
  212. hr = m_ADsClassContainer->GetObject(NULL,
  213. szName,
  214. (IDispatch **)&pADs
  215. );
  216. RETURN_ON_FAILURE(hr);
  217. hr = GetPropertyListAllocGuid(pADs, impl_or_req, &cCatid, &Catid);
  218. pADs->Release();
  219. RETURN_ON_FAILURE(hr);
  220. pEnumCatid = new CSCEnumCategoriesOfClass;
  221. if (!pEnumCatid)
  222. {
  223. if (Catid)
  224. CoTaskMemFree(Catid);
  225. return E_OUTOFMEMORY;
  226. }
  227. hr = pEnumCatid->Initialize(Catid, cCatid);
  228. if (Catid)
  229. CoTaskMemFree(Catid);
  230. if (FAILED(hr)) {
  231. delete pEnumCatid;
  232. return hr;
  233. }
  234. return pEnumCatid->QueryInterface(IID_IEnumCATID, (void **)ppenumCatid);
  235. }
  236. //---------------------------------------------------------------
  237. // IsClassOfCategories:
  238. // similar to EnumClassesOfCategories but returns S_OK/S_FALSE for the
  239. // clsid rclsid. Finds the first class that implements these categories
  240. // and is of this clsid and checks its required.
  241. //---------------------------------------------------------------
  242. HRESULT __stdcall CClassContainer::IsClassOfCategories(REFCLSID rclsid, ULONG cImplemented,
  243. CATID __RPC_FAR rgcatidImpl[ ],
  244. ULONG cRequired, CATID __RPC_FAR rgcatidReq[ ])
  245. {
  246. ULONG cRead, i;
  247. Data *pData;
  248. HRESULT hr, hr1;
  249. if (IsNullGuid(rclsid))
  250. return E_INVALIDARG;
  251. if (!IsValidPtrOut(this, sizeof(*this)))
  252. return E_ACCESSDENIED;
  253. if (cImplemented == 0)
  254. return E_INVALIDARG;
  255. if ((rgcatidImpl == NULL) && (cImplemented != 0) && (cImplemented != -1))
  256. return E_INVALIDARG;
  257. if ((rgcatidReq == NULL) && (cRequired != 0) && (cRequired != -1))
  258. return E_INVALIDARG;
  259. if ((cImplemented == -1) && (rgcatidImpl != NULL))
  260. return E_POINTER;
  261. if ((cRequired == -1) && (rgcatidReq != NULL))
  262. return E_POINTER;
  263. if ((rgcatidImpl) && (!IsValidReadPtrIn(rgcatidImpl, sizeof(CATID)*cImplemented)))
  264. {
  265. return E_INVALIDARG;
  266. }
  267. if ((rgcatidReq) && (!IsValidReadPtrIn(rgcatidReq, sizeof(CATID)*cRequired)))
  268. {
  269. return E_INVALIDARG;
  270. }
  271. hr = ImplSatisfied(rclsid, cImplemented, rgcatidImpl, this);
  272. RETURN_ON_FAILURE(hr);
  273. if (hr == S_OK)
  274. {
  275. hr = ReqSatisfied(rclsid, cRequired, rgcatidReq, this);
  276. RETURN_ON_FAILURE(hr);
  277. }
  278. if (hr != S_OK)
  279. return S_FALSE;
  280. return S_OK;
  281. } /* IsClassOfCategories */
  282. //--------------------------------------------------------------------------------
  283. // ReqSatisfied:
  284. // Returns S_OK/S_FALSE depending on whether the clsid satisfies the required
  285. // condition for the clsid.
  286. // clsid: Class ID of the class.
  287. // cAvailReq: Number of Available required classes.
  288. // AvailReq: Avail required classes.
  289. // calls the enumerator and sees whether there is any required class not present in
  290. // the available list. returns S_OK if cAvailReq = -1.
  291. //--------------------------------------------------------------------------------
  292. HRESULT ReqSatisfied(CLSID clsid, ULONG cAvailReq, CATID *AvailReq,
  293. ICatInformation *pICatInfo)
  294. {
  295. IEnumGUID *pIEnumCatid;
  296. ULONG got, i;
  297. CATID catid;
  298. HRESULT hr;
  299. if (cAvailReq == -1)
  300. return S_OK;
  301. hr = pICatInfo->EnumReqCategoriesOfClass(clsid, &pIEnumCatid);
  302. if (FAILED(hr)) {
  303. return hr;
  304. }
  305. for (;;) {
  306. hr = pIEnumCatid->Next(1, &catid, &got);
  307. if (FAILED(hr)) {
  308. hr = S_FALSE;
  309. break;
  310. }
  311. if (!got) {
  312. hr = S_OK;
  313. break;
  314. }
  315. /// check if the required categories are available
  316. for (i = 0; i < cAvailReq; i++)
  317. if (IsEqualGUID(catid, AvailReq[i]))
  318. break;
  319. if (i == cAvailReq) {
  320. hr = S_FALSE;
  321. break;
  322. }
  323. }
  324. pIEnumCatid->Release();
  325. return hr;
  326. }
  327. //--------------------------------------------------------------------------------
  328. // Implements:
  329. // Returns S_OK/S_FALSE depending on whether the clsid satisfies the required
  330. // condition for the clsid.
  331. // clsid: Class ID of the class.
  332. // cImplemented: Number of Implemented categories.
  333. // ImplementedList: Implemented Categories.
  334. // calls the enumerator and sees whether there is any required class not present in
  335. // the available list. returns S_OK if cImplemented = -1.
  336. //--------------------------------------------------------------------------------
  337. // BUGBUG:: This should return error when the enumerator return errors.
  338. HRESULT ImplSatisfied(CLSID clsid, ULONG cImplemented, CATID *ImplementedList,
  339. ICatInformation *pICatInfo)
  340. {
  341. IEnumGUID *pIEnumCatid;
  342. ULONG got, i;
  343. CATID catid;
  344. HRESULT hr;
  345. if (cImplemented == -1)
  346. return S_OK;
  347. hr = pICatInfo->EnumImplCategoriesOfClass(clsid, &pIEnumCatid);
  348. if (FAILED(hr)) {
  349. return hr;
  350. }
  351. for (;;) {
  352. hr = pIEnumCatid->Next(1, &catid, &got);
  353. if (FAILED(hr)) {
  354. hr = S_FALSE;
  355. break;
  356. }
  357. if (!got) {
  358. hr = S_FALSE;
  359. break;
  360. }
  361. // check if it implements any of the categories requested.
  362. for (i = 0; i < cImplemented; i++)
  363. if (IsEqualGUID(catid, ImplementedList[i]))
  364. break;
  365. if (i < cImplemented) {
  366. hr = S_OK;
  367. break;
  368. }
  369. }
  370. pIEnumCatid->Release();
  371. return hr;
  372. }
  373.