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.

429 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 "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
  24. CClassContainer::RegisterCategories(/* [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 = S_OK;
  29. HANDLE hADs = NULL;
  30. STRINGGUID szCatid;
  31. ULONG i, j, cdesc = 0, posn, cAttr = 0, cgot = 0;
  32. LPOLESTR *pszDescExisting = NULL, pszDesc = NULL;
  33. WCHAR localedescription[128+16];
  34. // sizeof description + seperator length + locale in hex
  35. WCHAR *szFullName = NULL, szRDN[_MAX_PATH];
  36. LPOLESTR AttrName = {LOCALEDESCRIPTION};
  37. ADS_ATTR_INFO *pAttrGot = NULL, pAttr[6];
  38. BOOL fExists = TRUE;
  39. if (!IsValidReadPtrIn(this, sizeof(*this))) {
  40. return E_ACCESSDENIED;
  41. }
  42. if (!IsValidReadPtrIn(rgCategoryInfo, sizeof(rgCategoryInfo[0])*cCategories))
  43. {
  44. return E_INVALIDARG; // gd
  45. }
  46. if (!m_fOpen)
  47. return E_FAIL;
  48. for (i = 0; i < cCategories; i++)
  49. {
  50. wsprintf(localedescription, L"%x %s %s", rgCategoryInfo[i].lcid, CAT_DESC_DELIMITER,
  51. rgCategoryInfo[i].szDescription);
  52. RDNFromGUID(rgCategoryInfo[i].catid, szRDN);
  53. BuildADsPathFromParent(m_szCategoryName, szRDN, &szFullName);
  54. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  55. &hADs);
  56. if (SUCCEEDED(hr))
  57. {
  58. hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttrGot, &cgot);
  59. fExists = TRUE;
  60. }
  61. else {
  62. fExists = FALSE;
  63. PackStrToAttr(pAttr, OBJECTCLASS, CLASS_CS_CATEGORY);
  64. cAttr++;
  65. PackGUIDToAttr(pAttr+cAttr, CATEGORYCATID, &(rgCategoryInfo[i].catid));
  66. cAttr++;
  67. hr = ADSICreateDSObject(m_ADsCategoryContainer, szRDN, pAttr, cAttr);
  68. for (j = 0; j < cAttr; j++)
  69. FreeAttr(pAttr[j]);
  70. cAttr = 0;
  71. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  72. &hADs);
  73. }
  74. ERROR_ON_FAILURE(hr);
  75. if (fExists)
  76. {
  77. if (cgot)
  78. UnpackStrArrFrom(pAttrGot[0], &pszDescExisting, &cdesc);
  79. // Existing list of descriptions
  80. if (posn = FindDescription(pszDescExisting, cdesc, &(rgCategoryInfo[i].lcid), NULL, 0))
  81. { // Delete the old value
  82. PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, pszDescExisting+(posn-1), 1, FALSE); cAttr++;
  83. }
  84. CoTaskMemFree(pszDescExisting);
  85. }
  86. pszDesc = localedescription;
  87. PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, &pszDesc, 1, TRUE);
  88. cAttr++;
  89. DWORD cModified = 0;
  90. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  91. CSDBGPrint((L"After Set, hr = 0x%x", hr));
  92. if (hr == HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS))
  93. hr = S_OK;
  94. ERROR_ON_FAILURE(hr);
  95. for (j = 0; j < cAttr; j++)
  96. FreeAttr(pAttr[j]);
  97. cAttr = 0;
  98. if (pAttrGot)
  99. FreeADsMem(pAttrGot);
  100. pAttrGot = NULL;
  101. if (szFullName)
  102. FreeADsMem(szFullName);
  103. szFullName = NULL;
  104. if (hADs)
  105. ADSICloseDSObject(hADs);
  106. hADs = NULL;
  107. }
  108. Error_Cleanup:
  109. if (pAttrGot)
  110. FreeADsMem(pAttrGot);
  111. if (szFullName)
  112. FreeADsMem(szFullName);
  113. if (hADs)
  114. ADSICloseDSObject(hADs);
  115. return RemapErrorCode(hr, m_szContainerName);
  116. } /* RegisterCategories */
  117. //--------------------------------------------------------
  118. // Unregistering categories from the class store
  119. // cCategories: Number of Categories
  120. // rgcatid: catids of the categories.
  121. //
  122. // Stops after any one of them returns a error.
  123. // Doesn't remove the category ids from each of the class ids.
  124. HRESULT STDMETHODCALLTYPE
  125. CClassContainer::UnRegisterCategories(/* [in] */ ULONG cCategories,
  126. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  127. {
  128. STRINGGUIDRDN szRDN;
  129. ULONG i;
  130. HRESULT hr = S_OK;
  131. if (!IsValidPtrOut(this, sizeof(*this))) {
  132. return E_ACCESSDENIED;
  133. }
  134. if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)) {
  135. return E_INVALIDARG;
  136. }
  137. // Checking whether the caller has permissions
  138. if (!m_fOpen)
  139. return E_FAIL;
  140. for (i = 0; i < cCategories; i++)
  141. {
  142. RDNFromGUID(rgcatid[i], szRDN);
  143. hr = ADSIDeleteDSObject(m_ADsCategoryContainer, szRDN);
  144. }
  145. return S_OK;
  146. } /* UnRegisterCategories */
  147. //------------------------------------------------------------------
  148. // RegisterClassXXXCategories:
  149. // rclsid: This category will be registered with this clsid.
  150. // cCategories: The number of categories to be added.
  151. // rgcatid The categories to be added (cCategories)
  152. // impl_or_req The property to which this category will be added.
  153. // "Implemented Categories" or "Required Categories"
  154. //
  155. //
  156. // add all the categories given to the class store for this class.
  157. // The previous entries will be lost and on error it would not be
  158. // restored or made empty. A PRIVATE METHOD called by the 2 public methods.
  159. //------------------------------------------------------------------
  160. HRESULT STDMETHODCALLTYPE
  161. CClassContainer::RegisterClassXXXCategories(/* [in] */ REFCLSID rclsid,
  162. /* [in] */ ULONG cCategories,
  163. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],
  164. BSTR impl_or_req)
  165. {
  166. HRESULT hr = S_OK;
  167. STRINGGUIDRDN szRDN;
  168. HANDLE hADs = NULL;
  169. ULONG i, j;
  170. STRINGGUID szGUID;
  171. ADS_ATTR_INFO pAttr[4];
  172. DWORD cAttr = 0;
  173. WCHAR *szFullName = NULL;
  174. if (!m_fOpen)
  175. return E_FAIL;
  176. if (!IsValidPtrOut(this, sizeof(*this))) {
  177. return E_ACCESSDENIED;
  178. }
  179. if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)) {
  180. return E_INVALIDARG; // gd
  181. }
  182. if (IsNullGuid(rclsid))
  183. return E_INVALIDARG;
  184. // Get the ADs interface corresponding to the clsid that is mentioned.
  185. StringFromGUID(rclsid, szGUID);
  186. wsprintf(szRDN, L"CN=%s", szGUID);
  187. BuildADsPathFromParent(m_szClassName, szRDN, &szFullName);
  188. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  189. &hADs);
  190. // if it didn't exist create it.
  191. if (FAILED(hr)) {
  192. PackStrToAttr(pAttr+cAttr, OBJECTCLASS, CLASS_CS_CLASS);
  193. cAttr++;
  194. PackStrToAttr(pAttr+cAttr, CLASSCLSID, szGUID);
  195. cAttr++;
  196. hr = ADSICreateDSObject(m_ADsClassContainer, szRDN, pAttr, cAttr);
  197. for (i = 0; i < cAttr; i++)
  198. FreeAttr(pAttr[i]);
  199. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  200. &hADs);
  201. ERROR_ON_FAILURE(hr);
  202. }
  203. for (i = 0; i < cCategories; i++)
  204. {
  205. DWORD cModified=0;
  206. PackGUIDArrToAttrEx(pAttr, impl_or_req, rgcatid+i, 1, TRUE);
  207. hr = ADSISetObjectAttributes(hADs, pAttr, 1, &cModified);
  208. FreeAttr(pAttr[0]);
  209. if (hr == HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS)) // we are not supposed to return error
  210. hr = S_OK; // if the category already exists.
  211. ERROR_ON_FAILURE(hr);
  212. }
  213. Error_Cleanup:
  214. if (szFullName)
  215. FreeADsMem(szFullName);
  216. if (hADs)
  217. ADSICloseDSObject(hADs);
  218. return RemapErrorCode(hr, m_szContainerName);
  219. } /* RegisterClassXXXCategories */
  220. //---------------------------------------------------------------------
  221. // UnRegisterClassXXXCategories
  222. // rclsid: classid from which the categories have to be removed.
  223. // cCategories: Number of Categories
  224. // rgcatid: Categories
  225. // impl_or_req: The property to which this has to be added.
  226. //
  227. // Presently gets all the categories from the class. parses through it
  228. // removes the ones that match in rgcatid and reregister the category.
  229. //---------------------------------------------------------------------
  230. HRESULT STDMETHODCALLTYPE
  231. CClassContainer::UnRegisterClassXXXCategories(/* [in] */ REFCLSID rclsid,
  232. /* [in] */ ULONG cCategories,
  233. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],
  234. BSTR impl_or_req)
  235. {
  236. HRESULT hr = S_OK;
  237. STRINGGUIDRDN szRDN;
  238. HANDLE hADs = NULL;
  239. ULONG i, j, cModified = 0;
  240. WCHAR *szFullName=NULL;
  241. ADS_ATTR_INFO pAttr[1];
  242. // BUGBUG:: Have to decide some way of removing clsids once all categories
  243. // are unregistered.
  244. if (!m_fOpen)
  245. return E_FAIL;
  246. if (IsNullGuid(rclsid))
  247. return E_INVALIDARG;
  248. if (cCategories == 0)
  249. return S_OK;
  250. if (!IsValidPtrOut(this, sizeof(*this))) {
  251. return E_ACCESSDENIED;
  252. }
  253. if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
  254. return E_INVALIDARG; // gd
  255. }
  256. if (cCategories == 0)
  257. return S_OK;
  258. // Get all the catids corresp to this clsid.
  259. // Get the ADs interface corresponding to the clsid that is mentioned.
  260. RDNFromGUID(rclsid, szRDN);
  261. BuildADsPathFromParent(m_szClassName, szRDN, &szFullName);
  262. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  263. &hADs);
  264. CSDBGPrint((L"After Open in unRegXXX returned 0x%x", hr));
  265. ERROR_ON_FAILURE(hr);
  266. // reregister this.
  267. for (i = 0; i < cCategories; i++) {
  268. PackGUIDArrToAttrEx(pAttr, impl_or_req, rgcatid+i, 1, FALSE);
  269. hr = ADSISetObjectAttributes(hADs, pAttr, 1, &cModified);
  270. FreeAttr(pAttr[0]);
  271. // we do not want to return error if the catids are not actually present.
  272. if ((hr == E_ADS_PROPERTY_NOT_SET) || (hr == E_ADS_PROPERTY_NOT_FOUND) ||
  273. (hr == HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE)))
  274. hr = S_OK;
  275. CSDBGPrint((L"After SetObjAtt in UnRegXXX returned 0x%x", hr));
  276. ERROR_ON_FAILURE(hr);
  277. }
  278. Error_Cleanup:
  279. if (szFullName)
  280. FreeADsMem(szFullName);
  281. if (hADs)
  282. ADSICloseDSObject(hADs);
  283. return RemapErrorCode(hr, m_szContainerName);
  284. } /* UnRegisterClassXXXCategories */
  285. HRESULT STDMETHODCALLTYPE
  286. CClassContainer::RegisterClassImplCategories(/* [in] */ REFCLSID rclsid,
  287. /* [in] */ ULONG cCategories,
  288. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  289. {
  290. return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  291. IMPL_CATEGORIES);
  292. } /* RegisterClassImplCategories */
  293. HRESULT STDMETHODCALLTYPE
  294. CClassContainer::UnRegisterClassImplCategories(/* [in] */ REFCLSID rclsid,
  295. /* [in] */ ULONG cCategories,
  296. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  297. {
  298. return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  299. IMPL_CATEGORIES);
  300. } /* UnRegisterClassImplCategories */
  301. HRESULT STDMETHODCALLTYPE
  302. CClassContainer::RegisterClassReqCategories(/* [in] */ REFCLSID rclsid,
  303. /* [in] */ ULONG cCategories,
  304. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  305. {
  306. return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  307. REQ_CATEGORIES);
  308. } /* RegisterClassReqCategories */
  309. HRESULT STDMETHODCALLTYPE
  310. CClassContainer::UnRegisterClassReqCategories(/* [in] */ REFCLSID rclsid,
  311. /* [in] */ ULONG cCategories,
  312. /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
  313. {
  314. return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
  315. REQ_CATEGORIES);
  316. } /* UnRegisterClassReqCategories */
  317. //--------------------------------------------------------------------