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.

448 lines
14 KiB

  1. //
  2. // Author: ushaji
  3. // Date: December/Jan 1996
  4. //
  5. //
  6. // Providing support for Component Categories in Class Store
  7. //
  8. // This source file contains implementations for ICatRegister 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. //----------------------------------------------------------------------------
  14. #include "cstore.hxx"
  15. //-------------------------------------------------------------
  16. // RegisterCategories:
  17. // registering categories in the class store.
  18. // cCategories: Number of Categories
  19. // rgCategoryInfo: Size cCategories
  20. //
  21. // Returns as soon as one of them fails.
  22. //-------------------------------------------------------------
  23. HRESULT STDMETHODCALLTYPE CClassContainer::RegisterCategories(
  24. /* [in] */ ULONG cCategories,
  25. /* [size_is][in] */ CATEGORYINFO __RPC_FAR rgCategoryInfo[ ])
  26. {
  27. /* Registering a list of Category ID in the Class Store */
  28. HRESULT hr;
  29. IADs *pADs = NULL;
  30. IDispatch *pUnknown = NULL;
  31. STRINGGUIDRDN szCatid;
  32. ULONG i, j, cdesc, posn;
  33. LPOLESTR *pszDescExisting, *pszDesc;
  34. WCHAR *localedescription = NULL;
  35. // sizeof description + seperator length + locale in hex
  36. /* BUGBUG::Should check whether write permissions exist? */
  37. if (!IsValidReadPtrIn(this, sizeof(*this))) {
  38. return E_ACCESSDENIED;
  39. }
  40. if (!IsValidReadPtrIn(rgCategoryInfo, sizeof(rgCategoryInfo[0])*cCategories))
  41. {
  42. return E_INVALIDARG; // gd
  43. }
  44. if (!m_fOpen)
  45. return E_FAIL;
  46. for (i = 0; i < cCategories; i++)
  47. {
  48. localedescription = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR)*(128+16));
  49. if (!localedescription)
  50. return E_OUTOFMEMORY;
  51. RdnFromGUID(rgCategoryInfo[i].catid, szCatid);
  52. wsprintf(localedescription, L"%x %s %s", rgCategoryInfo[i].lcid, CATSEPERATOR,
  53. rgCategoryInfo[i].szDescription);
  54. hr = m_ADsCategoryContainer->GetObject(NULL, szCatid, (IDispatch **)&pADs);
  55. if (SUCCEEDED(hr))
  56. {
  57. hr = GetPropertyListAlloc (pADs, LOCALEDESCRIPTION, &cdesc, &pszDescExisting);
  58. RETURN_ON_FAILURE(hr);
  59. // Existing list of descriptions
  60. pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(cdesc+1));
  61. if (!pszDesc)
  62. return E_OUTOFMEMORY;
  63. for (j = 0; j < cdesc; j++)
  64. pszDesc[j] = pszDescExisting[j];
  65. if (!(posn = FindDescription(pszDescExisting, cdesc, &(rgCategoryInfo[i].lcid), NULL, 0)))
  66. {
  67. // if no description exists for the lcid.
  68. pszDesc[cdesc] = localedescription;
  69. cdesc++;
  70. }
  71. else
  72. { // overwrite the old value
  73. CoTaskMemFree(pszDesc[posn-1]);
  74. pszDesc[posn-1] = localedescription;
  75. }
  76. }
  77. else
  78. {
  79. hr = m_ADsCategoryContainer->Create(
  80. CLASS_CS_CATEGORY,
  81. szCatid,
  82. &pUnknown
  83. );
  84. RETURN_ON_FAILURE(hr);
  85. pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR));
  86. if (!pszDesc)
  87. return E_OUTOFMEMORY;
  88. cdesc = 1;
  89. pszDesc[0] = localedescription;
  90. hr = pUnknown->QueryInterface(IID_IADs, (void **)&pADs);
  91. RETURN_ON_FAILURE(hr);
  92. pUnknown->Release();
  93. }
  94. // StringFromGUID(rgCategoryInfo[i].catid, szCatid);
  95. // SetProperty(pADs, CATEGORYCATID, szCatid);
  96. hr = SetPropertyGuid(pADs, CATEGORYCATID, rgCategoryInfo[i].catid);
  97. RETURN_ON_FAILURE(hr);
  98. SetPropertyList(pADs, LOCALEDESCRIPTION, cdesc, pszDesc);
  99. for (j = 0; j < cdesc; j++)
  100. CoTaskMemFree(pszDesc[j]);
  101. CoTaskMemFree(pszDesc);
  102. RETURN_ON_FAILURE(hr);
  103. hr = StoreIt (pADs);
  104. RETURN_ON_FAILURE(hr);
  105. pADs->Release();
  106. }
  107. return hr;
  108. } /* RegisterCategories */
  109. //--------------------------------------------------------
  110. // Unregistering categories from the class store
  111. // cCategories: Number of Categories
  112. // rgcatid: catids of the categories.
  113. //
  114. // Stops after any one of them returns a error.
  115. // Doesn't remove the category ids from each of the class ids.
  116. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterCategories(
  117. /* [in] */ ULONG cCategories,
  118. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  119. {
  120. STRINGGUIDRDN szCatid;
  121. ULONG i;
  122. HRESULT hr;
  123. if (!IsValidPtrOut(this, sizeof(*this))){
  124. return E_ACCESSDENIED;
  125. }
  126. if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
  127. return E_INVALIDARG;
  128. }
  129. // Checking whether the caller has permissions
  130. if (!m_fOpen)
  131. return E_FAIL;
  132. for (i = 0; i < cCategories; i++)
  133. {
  134. RdnFromGUID(rgcatid[i], szCatid);
  135. hr = m_ADsCategoryContainer->Delete(CLASS_CS_CATEGORY,
  136. szCatid);
  137. }
  138. return S_OK;
  139. } /* UnRegisterCategories */
  140. //------------------------------------------------------------------
  141. // RegisterClassXXXCategories:
  142. // rclsid: This category will be registered with this clsid.
  143. // cCategories: The number of categories to be added.
  144. // rgcatid The categories to be added (cCategories)
  145. // impl_or_req The property to which this category will be added.
  146. // "Implemented Categories" or "Required Categories"
  147. //
  148. //
  149. // add all the categories given to the class store for this class.
  150. // The previous entries will be lost and on error it would not be
  151. // restored or made empty. A PRIVATE METHOD called by the 2 public methods.
  152. //------------------------------------------------------------------
  153. HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassXXXCategories(
  154. /* [in] */ REFCLSID rclsid,
  155. /* [in] */ ULONG cCategories,
  156. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],BSTR impl_or_req)
  157. {
  158. HRESULT hr;
  159. STRINGGUIDRDN szName;
  160. IADs *pADs = NULL;
  161. ULONG i, j, tobeadded;
  162. VARIANT Var;
  163. GUID *pCatids, *pOldCatids=NULL;
  164. IDispatch *pUnknown = NULL;
  165. STRINGGUID szGUID;
  166. if (!m_fOpen)
  167. return E_FAIL;
  168. if (!IsValidPtrOut(this, sizeof(*this))) {
  169. return E_ACCESSDENIED;
  170. }
  171. if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
  172. return E_INVALIDARG; // gd
  173. }
  174. if (IsNullGuid(rclsid))
  175. return E_INVALIDARG;
  176. // Get the ADs interface corresponding to the clsid that is mentioned.
  177. StringFromGUID(rclsid, szGUID);
  178. wsprintf(szName, L"CN=%s", szGUID);
  179. hr = m_ADsClassContainer->GetObject(NULL,
  180. szName,
  181. (IDispatch **)&pADs
  182. );
  183. // if it didn't exist create it.
  184. if (FAILED(hr)) {
  185. hr = m_ADsClassContainer->Create(
  186. CLASS_CS_CLASS,
  187. szName,
  188. &pUnknown
  189. );
  190. RETURN_ON_FAILURE(hr);
  191. hr = pUnknown->QueryInterface(
  192. IID_IADs,
  193. (void **)&pADs
  194. );
  195. pUnknown->Release();
  196. }
  197. hr = SetProperty (pADs, CLASSCLSID, szGUID);
  198. RETURN_ON_FAILURE(hr);
  199. hr = GetPropertyListAllocGuid(pADs, impl_or_req, &tobeadded, &pOldCatids);
  200. RETURN_ON_FAILURE(hr);
  201. pCatids = (GUID *)CoTaskMemAlloc(sizeof(GUID)*(tobeadded+cCategories));
  202. if (!pCatids)
  203. return E_OUTOFMEMORY;
  204. for (i = 0; i < tobeadded; i++)
  205. pCatids[i] = pOldCatids[i];
  206. for (i=0; i < cCategories; ++i) {
  207. for (j = 0; j < tobeadded; j++)
  208. {
  209. if (memcmp(&rgcatid[i], &pCatids[j], sizeof(GUID)) == 0)
  210. break;
  211. }
  212. if (j < tobeadded)
  213. continue;
  214. // The ith element is already there in the array.
  215. // Make sure of this when the property name changes.
  216. pCatids[tobeadded] = rgcatid[i];
  217. tobeadded++;
  218. }
  219. VariantInit(&Var);
  220. hr = PackGuidArray2Variant(pCatids, tobeadded, &Var);
  221. RETURN_ON_FAILURE(hr);
  222. if (tobeadded)
  223. hr = pADs->Put(impl_or_req, Var);
  224. else
  225. hr = pADs->PutEx(ADS_PROPERTY_CLEAR, impl_or_req, Var);
  226. RETURN_ON_FAILURE(hr);
  227. VariantClear(&Var);
  228. // save the data modified
  229. hr = StoreIt(pADs);
  230. pADs->Release();
  231. CoTaskMemFree(pCatids);
  232. if (pOldCatids)
  233. CoTaskMemFree(pOldCatids);
  234. return hr;
  235. } /* RegisterClassXXXCategories */
  236. //---------------------------------------------------------------------
  237. // UnRegisterClassXXXCategories
  238. // rclsid: classid from which the categories have to be removed.
  239. // cCategories: Number of Categories
  240. // rgcatid: Categories
  241. // impl_or_req: The property to which this has to be added.
  242. //
  243. // Presently gets all the categories from the class. parses through it
  244. // removes the ones that match in rgcatid and reregister the category.
  245. //---------------------------------------------------------------------
  246. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassXXXCategories(
  247. /* [in] */ REFCLSID rclsid,
  248. /* [in] */ ULONG cCategories,
  249. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],BSTR impl_or_req)
  250. {
  251. HRESULT hr;
  252. STRINGGUIDRDN szName;
  253. IADs *pADs = NULL;
  254. ULONG i, j;
  255. ULONG cNewCatids, cOldCatids;
  256. VARIANT Var;
  257. GUID *pOldCatids=NULL, *pNewCatids;
  258. // BUGBUG:: Have to decide some way of removing clsids once all categories
  259. // are unregistered.
  260. if (!m_fOpen)
  261. return E_FAIL;
  262. if (IsNullGuid(rclsid))
  263. return E_INVALIDARG;
  264. if (cCategories == 0)
  265. return S_OK;
  266. if (!IsValidPtrOut(this, sizeof(*this))) {
  267. return E_ACCESSDENIED;
  268. }
  269. if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
  270. return E_INVALIDARG; // gd
  271. }
  272. if (cCategories == 0)
  273. return S_OK;
  274. // Get all the catids corresp to this clsid.
  275. // Get the ADs interface corresponding to the clsid that is mentioned.
  276. RdnFromGUID(rclsid, szName);
  277. hr = m_ADsClassContainer->GetObject(NULL,
  278. szName,
  279. (IDispatch **)&pADs
  280. );
  281. RETURN_ON_FAILURE(hr);
  282. hr = GetPropertyListAllocGuid(pADs,
  283. impl_or_req,
  284. &cOldCatids,
  285. &pOldCatids);
  286. RETURN_ON_FAILURE(hr);
  287. // parse through this list and delete all the catids that is part of
  288. // the user supplied list.
  289. pNewCatids = (GUID *)CoTaskMemAlloc(sizeof(GUID)*cOldCatids);
  290. if (!pNewCatids)
  291. return E_OUTOFMEMORY;
  292. for (i = 0, cNewCatids = 0; i < cOldCatids; i++)
  293. {
  294. for (j = 0; j < cCategories; j++)
  295. if (memcmp(&pOldCatids[i], &rgcatid[j], sizeof(GUID)) == 0)
  296. break;
  297. if (j == cCategories)
  298. pNewCatids[cNewCatids++] = pOldCatids[i];
  299. }
  300. // reregister this.
  301. VariantInit(&Var);
  302. hr = PackGuidArray2Variant(pNewCatids, cNewCatids, &Var);
  303. RETURN_ON_FAILURE(hr);
  304. if (cNewCatids)
  305. hr = pADs->Put(impl_or_req, Var);
  306. else
  307. hr = pADs->PutEx(ADS_PROPERTY_CLEAR, impl_or_req, Var);
  308. RETURN_ON_FAILURE(hr);
  309. VariantClear(&Var);
  310. // save the data modified
  311. hr = StoreIt(pADs);
  312. pADs->Release();
  313. CoTaskMemFree(pNewCatids);
  314. if (pOldCatids)
  315. CoTaskMemFree(pOldCatids);
  316. return hr;
  317. } /* UnRegisterClassXXXCategories */
  318. HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassImplCategories(
  319. /* [in] */ REFCLSID rclsid,
  320. /* [in] */ ULONG cCategories,
  321. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  322. {
  323. return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  324. IMPL_CATEGORIES);
  325. } /* RegisterClassImplCategories */
  326. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassImplCategories(
  327. /* [in] */ REFCLSID rclsid,
  328. /* [in] */ ULONG cCategories,
  329. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  330. {
  331. return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  332. IMPL_CATEGORIES);
  333. } /* UnRegisterClassImplCategories */
  334. HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassReqCategories(
  335. /* [in] */ REFCLSID rclsid,
  336. /* [in] */ ULONG cCategories,
  337. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  338. {
  339. return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  340. REQ_CATEGORIES);
  341. } /* RegisterClassReqCategories */
  342. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassReqCategories(
  343. /* [in] */ REFCLSID rclsid,
  344. /* [in] */ ULONG cCategories,
  345. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  346. {
  347. return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  348. REQ_CATEGORIES);
  349. } /* UnRegisterClassReqCategories */
  350. //--------------------------------------------------------------------