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.

440 lines
13 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 "csadm.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. hr = pADs->Put(impl_or_req, Var);
  223. RETURN_ON_FAILURE(hr);
  224. VariantClear(&Var);
  225. // save the data modified
  226. hr = StoreIt(pADs);
  227. pADs->Release();
  228. CoTaskMemFree(pCatids);
  229. if (pOldCatids)
  230. CoTaskMemFree(pOldCatids);
  231. return hr;
  232. } /* RegisterClassXXXCategories */
  233. //---------------------------------------------------------------------
  234. // UnRegisterClassXXXCategories
  235. // rclsid: classid from which the categories have to be removed.
  236. // cCategories: Number of Categories
  237. // rgcatid: Categories
  238. // impl_or_req: The property to which this has to be added.
  239. //
  240. // Presently gets all the categories from the class. parses through it
  241. // removes the ones that match in rgcatid and reregister the category.
  242. //---------------------------------------------------------------------
  243. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassXXXCategories(
  244. /* [in] */ REFCLSID rclsid,
  245. /* [in] */ ULONG cCategories,
  246. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],BSTR impl_or_req)
  247. {
  248. HRESULT hr;
  249. STRINGGUIDRDN szName;
  250. IADs *pADs = NULL;
  251. ULONG i, j;
  252. ULONG cNewCatids, cOldCatids;
  253. VARIANT Var;
  254. GUID *pOldCatids=NULL, *pNewCatids;
  255. // BUGBUG:: Have to decide some way of removing clsids once all categories
  256. // are unregistered.
  257. if (!m_fOpen)
  258. return E_FAIL;
  259. if (IsNullGuid(rclsid))
  260. return E_INVALIDARG;
  261. if (cCategories == 0)
  262. return S_OK;
  263. if (!IsValidPtrOut(this, sizeof(*this))) {
  264. return E_ACCESSDENIED;
  265. }
  266. if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
  267. return E_INVALIDARG; // gd
  268. }
  269. if (cCategories == 0)
  270. return S_OK;
  271. // Get all the catids corresp to this clsid.
  272. // Get the ADs interface corresponding to the clsid that is mentioned.
  273. RdnFromGUID(rclsid, szName);
  274. hr = m_ADsClassContainer->GetObject(NULL,
  275. szName,
  276. (IDispatch **)&pADs
  277. );
  278. RETURN_ON_FAILURE(hr);
  279. hr = GetPropertyListAllocGuid(pADs,
  280. impl_or_req,
  281. &cOldCatids,
  282. &pOldCatids);
  283. RETURN_ON_FAILURE(hr);
  284. // parse through this list and delete all the catids that is part of
  285. // the user supplied list.
  286. pNewCatids = (GUID *)CoTaskMemAlloc(sizeof(GUID)*cOldCatids);
  287. if (!pNewCatids)
  288. return E_OUTOFMEMORY;
  289. for (i = 0, cNewCatids = 0; i < cOldCatids; i++)
  290. {
  291. for (j = 0; j < cCategories; j++)
  292. if (memcmp(&pOldCatids[i], &rgcatid[j], sizeof(GUID)) == 0)
  293. break;
  294. if (j == cCategories)
  295. pNewCatids[cNewCatids++] = pOldCatids[i];
  296. }
  297. // reregister this.
  298. VariantInit(&Var);
  299. hr = PackGuidArray2Variant(pNewCatids, cNewCatids, &Var);
  300. RETURN_ON_FAILURE(hr);
  301. hr = pADs->Put(impl_or_req, Var);
  302. RETURN_ON_FAILURE(hr);
  303. VariantClear(&Var);
  304. // save the data modified
  305. hr = StoreIt(pADs);
  306. pADs->Release();
  307. CoTaskMemFree(pNewCatids);
  308. if (pOldCatids)
  309. CoTaskMemFree(pOldCatids);
  310. return hr;
  311. } /* UnRegisterClassXXXCategories */
  312. HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassImplCategories(
  313. /* [in] */ REFCLSID rclsid,
  314. /* [in] */ ULONG cCategories,
  315. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  316. {
  317. return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  318. IMPL_CATEGORIES);
  319. } /* RegisterClassImplCategories */
  320. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassImplCategories(
  321. /* [in] */ REFCLSID rclsid,
  322. /* [in] */ ULONG cCategories,
  323. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  324. {
  325. return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  326. IMPL_CATEGORIES);
  327. } /* UnRegisterClassImplCategories */
  328. HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassReqCategories(
  329. /* [in] */ REFCLSID rclsid,
  330. /* [in] */ ULONG cCategories,
  331. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  332. {
  333. return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  334. REQ_CATEGORIES);
  335. } /* RegisterClassReqCategories */
  336. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassReqCategories(
  337. /* [in] */ REFCLSID rclsid,
  338. /* [in] */ ULONG cCategories,
  339. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  340. {
  341. return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  342. REQ_CATEGORIES);
  343. } /* UnRegisterClassReqCategories */
  344. //--------------------------------------------------------------------