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.

511 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 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. //---------------------------------------------------------------
  22. HRESULT __stdcall CClassContainer::EnumCategories(LCID lcid, IEnumCATEGORYINFO **ppenumCategoryInfo)
  23. {
  24. HRESULT hr = S_OK;
  25. CSCEnumCategories *pEnum = NULL;
  26. if (!m_fOpen)
  27. return E_FAIL;
  28. if (!IsValidPtrOut(this, sizeof(*this)))
  29. return E_ACCESSDENIED;
  30. if (!IsValidPtrOut(ppenumCategoryInfo, sizeof(IEnumCATEGORYINFO *)))
  31. return E_INVALIDARG;
  32. *ppenumCategoryInfo=NULL;
  33. // get the enumerator object.
  34. pEnum=new CSCEnumCategories;
  35. if(NULL == pEnum)
  36. return E_OUTOFMEMORY;
  37. // initialize the enumerator object with the name.
  38. hr = pEnum->Initialize(m_szCategoryName, lcid);
  39. ERROR_ON_FAILURE(hr);
  40. hr = pEnum->QueryInterface(IID_IEnumCATEGORYINFO, (void**)ppenumCategoryInfo);
  41. ERROR_ON_FAILURE(hr);
  42. return S_OK;
  43. Error_Cleanup:
  44. if (pEnum)
  45. delete pEnum;
  46. return RemapErrorCode(hr, m_szContainerName);
  47. } /* EnumCategories */
  48. //---------------------------------------------------------------
  49. // GetCategoryDesc:
  50. // returns the description of a given category.
  51. // rcatid: category id.
  52. // lcid: locale id.
  53. // ppszDesc pointer to the description string to be returned.
  54. // Allocated by the function. to be freed by client.
  55. //--------------------------------------------------------------------------
  56. HRESULT __stdcall CClassContainer::GetCategoryDesc(REFCATID rcatid, LCID lcid, LPOLESTR *ppszDesc)
  57. {
  58. STRINGGUIDRDN szRDN;
  59. ULONG cdesc = 0, i, cgot = 0;
  60. LPOLESTR * localedesc = NULL;
  61. HANDLE hADs = NULL;
  62. HRESULT hr = S_OK;
  63. WCHAR * szFullName = NULL;
  64. LPOLESTR AttrName = LOCALEDESCRIPTION;
  65. ADS_ATTR_INFO * pAttr = NULL;
  66. if (!IsValidPtrOut(ppszDesc, sizeof(LPOLESTR)))
  67. return E_INVALIDARG;
  68. if (IsNullGuid(rcatid))
  69. return E_INVALIDARG;
  70. if (!IsValidPtrOut(this, sizeof(*this)))
  71. return E_ACCESSDENIED;
  72. RDNFromGUID(rcatid, szRDN);
  73. BuildADsPathFromParent(m_szCategoryName, szRDN, &szFullName);
  74. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  75. &hADs);
  76. if (FAILED(hr))
  77. return CAT_E_CATIDNOEXIST;
  78. // get the array of localized descriptions
  79. hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttr, &cgot);
  80. if (FAILED(hr) || (!cgot))
  81. return CAT_E_NODESCRIPTION;
  82. hr = UnpackStrArrFrom(pAttr[0], &localedesc, &cdesc);
  83. if (hr == E_OUTOFMEMORY)
  84. return hr;
  85. *ppszDesc = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR)*128);
  86. if (!(*ppszDesc))
  87. return E_OUTOFMEMORY;
  88. // get a description closest to the locale we need.
  89. GetCategoryLocaleDesc(localedesc, cdesc, &lcid, *ppszDesc);
  90. CoTaskMemFree(localedesc);
  91. ADSICloseDSObject(hADs);
  92. FreeADsMem(pAttr);
  93. FreeADsMem(szFullName);
  94. return S_OK;
  95. } /* GetCategoryDesc */
  96. //---------------------------------------------------------------
  97. // EnumClassesOfCategories:
  98. // returns the enumerator for classes that implements given catids and
  99. // requires some given catids.
  100. //
  101. // cImplemented number of implemented categories.
  102. // (0 is error and -1 is ignore implemented.
  103. // rgcatidImpl list of implemented categories.
  104. // should be NULL in the two cases mentioned above.
  105. //
  106. // cRequired: number of required categories.
  107. // (0 is requiring nothing and -1 is ignore required.
  108. // rgcatidReq list of required categories.
  109. // should be NULL in the two cases mentioned above.
  110. //
  111. // ppenumClsid the enumerator of class ids.
  112. //--------------------------------------------------------------------------
  113. HRESULT __stdcall CClassContainer::EnumClassesOfCategories(ULONG cImplemented, CATID rgcatidImpl[],
  114. ULONG cRequired, CATID rgcatidReq[],
  115. IEnumGUID **ppenumClsid)
  116. {
  117. ULONG i;
  118. CSCEnumClassesOfCategories *penumclasses = NULL;
  119. HRESULT hr = S_OK;
  120. if (!IsValidPtrOut(ppenumClsid, sizeof(IEnumGUID *)))
  121. return E_INVALIDARG;
  122. if ((rgcatidImpl == NULL) && (cImplemented != 0) && (cImplemented != -1))
  123. return E_INVALIDARG;
  124. if ((rgcatidReq == NULL) && (cRequired != 0) && (cRequired != -1))
  125. return E_INVALIDARG;
  126. if ((cImplemented == -1) && (rgcatidImpl != NULL))
  127. return E_POINTER;
  128. if ((cRequired == -1) && (rgcatidReq != NULL))
  129. return E_POINTER;
  130. if (cImplemented == 0)
  131. return E_INVALIDARG;
  132. if ((rgcatidImpl) && (!IsValidReadPtrIn(rgcatidImpl, sizeof(CATID)*cImplemented)))
  133. {
  134. return E_INVALIDARG;
  135. }
  136. if ((rgcatidReq) && (!IsValidReadPtrIn(rgcatidReq, sizeof(CATID)*cRequired)))
  137. {
  138. return E_INVALIDARG;
  139. }
  140. if (!IsValidPtrOut(this, sizeof(*this)))
  141. return E_ACCESSDENIED;
  142. penumclasses = new CSCEnumClassesOfCategories;
  143. if (!penumclasses)
  144. {
  145. return E_OUTOFMEMORY;
  146. }
  147. // initialize the enumerator
  148. hr = penumclasses->Initialize(cRequired, rgcatidReq, cImplemented, rgcatidImpl,
  149. m_szClassName);
  150. ERROR_ON_FAILURE(hr);
  151. hr = penumclasses->QueryInterface(IID_IEnumCLSID, (void **)ppenumClsid);
  152. ERROR_ON_FAILURE(hr);
  153. return S_OK;
  154. Error_Cleanup:
  155. if (penumclasses)
  156. delete penumclasses;
  157. return RemapErrorCode(hr, m_szContainerName);
  158. } /* EnumClassesOfCategories */
  159. //---------------------------------------------------------------
  160. // EnumReqCategoriesOfClass:
  161. // see below EnumCategoriesofClass
  162. //
  163. //---------------------------------------------------------------
  164. HRESULT CClassContainer::EnumReqCategoriesOfClass(REFCLSID rclsid, IEnumGUID **ppenumCatid)
  165. {
  166. if (!IsValidReadPtrIn(this, sizeof(*this)))
  167. return E_ACCESSDENIED;
  168. if (IsNullGuid(rclsid))
  169. return E_INVALIDARG;
  170. if (!IsValidPtrOut(ppenumCatid, sizeof(IEnumGUID *)))
  171. return E_INVALIDARG;
  172. return EnumCategoriesOfClass(rclsid, REQ_CATEGORIES, ppenumCatid);
  173. } /* EnumReqClassesOfCategories */
  174. //---------------------------------------------------------------
  175. // EnumImplCategoriesOfClass:
  176. // see below EnumCategoriesofClass
  177. //
  178. //---------------------------------------------------------------
  179. HRESULT CClassContainer::EnumImplCategoriesOfClass(REFCLSID rclsid, IEnumGUID **ppenumCatid)
  180. {
  181. if (!IsValidReadPtrIn(this, sizeof(*this)))
  182. return E_ACCESSDENIED;
  183. if (IsNullGuid(rclsid))
  184. return E_INVALIDARG;
  185. if (!IsValidPtrOut(ppenumCatid, sizeof(IEnumGUID *)))
  186. return E_INVALIDARG;
  187. return EnumCategoriesOfClass(rclsid, IMPL_CATEGORIES, ppenumCatid);
  188. } /* EnumimplClassesOfCategories */
  189. //---------------------------------------------------------------
  190. // EnumCategoriesOfClass:
  191. // returns the enumerator for the implemented or required
  192. // rclsid: the class id.
  193. // impl_or_req the type of category to enumerated.
  194. // ppenumcatid the enumerator that is returned.
  195. // Prefetches all the catids and then enumerates them.
  196. //---------------------------------------------------------------
  197. HRESULT CClassContainer::EnumCategoriesOfClass(REFCLSID rclsid, BSTR impl_or_req,
  198. IEnumGUID **ppenumCatid)
  199. {
  200. STRINGGUIDRDN szRDN;
  201. HANDLE hADs = NULL;
  202. ULONG i;
  203. ULONG cCatid = 0, cgot = 0;
  204. CATID * Catid = NULL;
  205. CSCEnumCategoriesOfClass * pEnumCatid = NULL;
  206. HRESULT hr = S_OK;
  207. WCHAR * szFullName = NULL;
  208. ADS_ATTR_INFO * pAttr = NULL;
  209. if (!m_fOpen)
  210. return E_FAIL;
  211. // Get the ADs interface corresponding to the clsid that is mentioned.
  212. RDNFromGUID(rclsid, szRDN);
  213. BuildADsPathFromParent(m_szClassName, szRDN, &szFullName);
  214. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  215. &hADs);
  216. RETURN_ON_FAILURE(hr);
  217. // get the implemented or required cateogory list.
  218. hr = ADSIGetObjectAttributes(hADs, &impl_or_req, 1, &pAttr, &cgot);
  219. ERROR_ON_FAILURE(hr);
  220. if (cgot)
  221. hr = UnpackGUIDArrFrom(pAttr[0], &Catid, &cCatid);
  222. pEnumCatid = new CSCEnumCategoriesOfClass;
  223. if (!pEnumCatid)
  224. {
  225. hr = E_OUTOFMEMORY;
  226. ERROR_ON_FAILURE(hr);
  227. }
  228. // initialize the enumerator
  229. hr = pEnumCatid->Initialize(Catid, cCatid);
  230. ERROR_ON_FAILURE(hr);
  231. hr = pEnumCatid->QueryInterface(IID_IEnumCATID, (void **)ppenumCatid);
  232. Error_Cleanup:
  233. if (Catid)
  234. CoTaskMemFree(Catid);
  235. if (FAILED(hr)) {
  236. delete pEnumCatid;
  237. return hr;
  238. }
  239. if (szFullName)
  240. FreeADsMem(szFullName);
  241. if (pAttr)
  242. FreeADsMem(pAttr);
  243. if (hADs)
  244. ADSICloseDSObject(hADs);
  245. return RemapErrorCode(hr, m_szContainerName);
  246. }
  247. //---------------------------------------------------------------
  248. // IsClassOfCategories:
  249. // similar to EnumClassesOfCategories but returns S_OK/S_FALSE for the
  250. // clsid rclsid. Finds the first class that implements these categories
  251. // and is of this clsid and checks its required.
  252. //---------------------------------------------------------------
  253. HRESULT __stdcall CClassContainer::IsClassOfCategories(REFCLSID rclsid, ULONG cImplemented,
  254. CATID __RPC_FAR rgcatidImpl[ ],
  255. ULONG cRequired, CATID __RPC_FAR rgcatidReq[ ])
  256. {
  257. HRESULT hr = S_OK;
  258. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  259. WCHAR szfilter[_MAX_PATH];
  260. LPOLESTR AttrNames[] = {IMPL_CATEGORIES, REQ_CATEGORIES, L"cn"};
  261. DWORD cAttr = 3;
  262. STRINGGUID szClsid;
  263. if (IsNullGuid(rclsid))
  264. return E_INVALIDARG;
  265. if (!IsValidPtrOut(this, sizeof(*this)))
  266. return E_ACCESSDENIED;
  267. if (cImplemented == 0)
  268. return E_INVALIDARG;
  269. if ((rgcatidImpl == NULL) && (cImplemented != 0) && (cImplemented != -1))
  270. return E_INVALIDARG;
  271. if ((rgcatidReq == NULL) && (cRequired != 0) && (cRequired != -1))
  272. return E_INVALIDARG;
  273. if ((cImplemented == -1) && (rgcatidImpl != NULL))
  274. return E_POINTER;
  275. if ((cRequired == -1) && (rgcatidReq != NULL))
  276. return E_POINTER;
  277. if ((rgcatidImpl) && (!IsValidReadPtrIn(rgcatidImpl, sizeof(CATID)*cImplemented)))
  278. {
  279. return E_INVALIDARG;
  280. }
  281. if ((rgcatidReq) && (!IsValidReadPtrIn(rgcatidReq, sizeof(CATID)*cRequired)))
  282. {
  283. return E_INVALIDARG;
  284. }
  285. StringFromGUID(rclsid, szClsid);
  286. wsprintf(szfilter, L"(cn=%s)", szClsid);
  287. // doing a search so that we can pass the same parameters to the
  288. // xxxSatisfied functions below.
  289. hr = ADSIExecuteSearch(m_ADsClassContainer, szfilter, AttrNames, cAttr, &hADsSearchHandle);
  290. RETURN_ON_FAILURE(hr);
  291. hr = ADSIGetFirstRow(m_ADsClassContainer, hADsSearchHandle);
  292. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  293. {
  294. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  295. ERROR_ON_FAILURE(hr);
  296. }
  297. hr = ImplSatisfied(cImplemented, rgcatidImpl, m_ADsClassContainer, hADsSearchHandle);
  298. ERROR_ON_FAILURE(hr);
  299. if (hr == S_OK)
  300. {
  301. hr = ReqSatisfied(cRequired, rgcatidReq, m_ADsClassContainer, hADsSearchHandle);
  302. ERROR_ON_FAILURE(hr);
  303. }
  304. if (hr != S_OK)
  305. hr = S_FALSE;
  306. Error_Cleanup:
  307. ADSICloseSearchHandle(m_ADsClassContainer, hADsSearchHandle);
  308. return hr;
  309. } /* IsClassOfCategories */
  310. //--------------------------------------------------------------------------------
  311. // ReqSatisfied:
  312. // Returns S_OK/S_FALSE depending on whether the clsid satisfies the required
  313. // condition for the clsid.
  314. // clsid: Class ID of the class.
  315. // cAvailReq: Number of Available required classes.
  316. // AvailReq: Avail required classes.
  317. // calls the enumerator and sees whether there is any required class not present in
  318. // the available list. returns S_OK if cAvailReq = -1.
  319. //--------------------------------------------------------------------------------
  320. HRESULT ReqSatisfied(ULONG cAvailReq, CATID *AvailReq,
  321. HANDLE hADs,
  322. ADS_SEARCH_HANDLE hADsSearchHandle)
  323. {
  324. HRESULT hr = S_OK;
  325. ADS_SEARCH_COLUMN column;
  326. GUID * ReqGuid = NULL;
  327. DWORD i, j, cReq = 0;
  328. if (cAvailReq == -1)
  329. return S_OK;
  330. hr = ADSIGetColumn(hADs, hADsSearchHandle, REQ_CATEGORIES, &column);
  331. if (FAILED(hr))
  332. return S_OK;
  333. hr = S_OK;
  334. UnpackGUIDArrFrom(column, &ReqGuid, &cReq);
  335. for (j = 0; j < cReq; j++) {
  336. /// check if the required categories are available
  337. for (i = 0; i < cAvailReq; i++)
  338. if (IsEqualGUID(ReqGuid[j], AvailReq[i]))
  339. break;
  340. if (i == cAvailReq) {
  341. hr = S_FALSE;
  342. break;
  343. }
  344. }
  345. CoTaskMemFree(ReqGuid);
  346. ADSIFreeColumn(hADs, &column);
  347. return hr;
  348. }
  349. //--------------------------------------------------------------------------------
  350. // Implements:
  351. // Returns S_OK/S_FALSE depending on whether the clsid satisfies the required
  352. // condition for the clsid.
  353. // clsid: Class ID of the class.
  354. // cImplemented: Number of Implemented categories.
  355. // ImplementedList: Implemented Categories.
  356. // calls the enumerator and sees whether there is any required class not present in
  357. // the available list. returns S_OK if cImplemented = -1.
  358. //--------------------------------------------------------------------------------
  359. HRESULT ImplSatisfied(ULONG cImplemented, CATID *ImplementedList,
  360. HANDLE hADs,
  361. ADS_SEARCH_HANDLE hADsSearchHandle)
  362. {
  363. ADS_SEARCH_COLUMN column;
  364. GUID * ImplGuid = NULL;
  365. ULONG i, j, cImpl = 0;
  366. HRESULT hr = S_FALSE;
  367. if (cImplemented == -1)
  368. return S_OK;
  369. hr = ADSIGetColumn(hADs, hADsSearchHandle, IMPL_CATEGORIES, &column);
  370. if (FAILED(hr))
  371. return S_FALSE;
  372. hr = S_FALSE;
  373. UnpackGUIDArrFrom(column, &ImplGuid, &cImpl);
  374. for (j = 0;j < cImpl; j++) {
  375. // check if it implements any of the categories requested.
  376. for (i = 0; i < cImplemented; i++)
  377. if (IsEqualGUID(ImplGuid[j], ImplementedList[i]))
  378. break;
  379. if (i < cImplemented) {
  380. hr = S_OK;
  381. break;
  382. }
  383. }
  384. CoTaskMemFree(ImplGuid);
  385. ADSIFreeColumn(hADs, &column);
  386. return hr;
  387. }
  388.