// // Author: ushaji // Date: December/Jan 1996 // // // Providing support for Component Categories in Class Store // // This source file contains implementations for ICatRegister interfaces. ¦ // // Refer Doc "Design for Support of File Types and Component Categories // in Class Store" ? (or may be Class Store Schema) // //---------------------------------------------------------------------------- #include "cstore.hxx" //------------------------------------------------------------- // RegisterCategories: // registering categories in the class store. // cCategories: Number of Categories // rgCategoryInfo: Size cCategories // // Returns as soon as one of them fails. //------------------------------------------------------------- HRESULT STDMETHODCALLTYPE CClassContainer::RegisterCategories( /* [in] */ ULONG cCategories, /* [size_is][in] */ CATEGORYINFO __RPC_FAR rgCategoryInfo[ ]) { /* Registering a list of Category ID in the Class Store */ HRESULT hr; IADs *pADs = NULL; IDispatch *pUnknown = NULL; STRINGGUIDRDN szCatid; ULONG i, j, cdesc, posn; LPOLESTR *pszDescExisting, *pszDesc; WCHAR *localedescription = NULL; // sizeof description + seperator length + locale in hex /* BUGBUG::Should check whether write permissions exist? */ if (!IsValidReadPtrIn(this, sizeof(*this))) { return E_ACCESSDENIED; } if (!IsValidReadPtrIn(rgCategoryInfo, sizeof(rgCategoryInfo[0])*cCategories)) { return E_INVALIDARG; // gd } if (!m_fOpen) return E_FAIL; for (i = 0; i < cCategories; i++) { localedescription = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR)*(128+16)); if (!localedescription) return E_OUTOFMEMORY; RdnFromGUID(rgCategoryInfo[i].catid, szCatid); wsprintf(localedescription, L"%x %s %s", rgCategoryInfo[i].lcid, CATSEPERATOR, rgCategoryInfo[i].szDescription); hr = m_ADsCategoryContainer->GetObject(NULL, szCatid, (IDispatch **)&pADs); if (SUCCEEDED(hr)) { hr = GetPropertyListAlloc (pADs, LOCALEDESCRIPTION, &cdesc, &pszDescExisting); RETURN_ON_FAILURE(hr); // Existing list of descriptions pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(cdesc+1)); if (!pszDesc) return E_OUTOFMEMORY; for (j = 0; j < cdesc; j++) pszDesc[j] = pszDescExisting[j]; if (!(posn = FindDescription(pszDescExisting, cdesc, &(rgCategoryInfo[i].lcid), NULL, 0))) { // if no description exists for the lcid. pszDesc[cdesc] = localedescription; cdesc++; } else { // overwrite the old value CoTaskMemFree(pszDesc[posn-1]); pszDesc[posn-1] = localedescription; } } else { hr = m_ADsCategoryContainer->Create( CLASS_CS_CATEGORY, szCatid, &pUnknown ); RETURN_ON_FAILURE(hr); pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)); if (!pszDesc) return E_OUTOFMEMORY; cdesc = 1; pszDesc[0] = localedescription; hr = pUnknown->QueryInterface(IID_IADs, (void **)&pADs); RETURN_ON_FAILURE(hr); pUnknown->Release(); } // StringFromGUID(rgCategoryInfo[i].catid, szCatid); // SetProperty(pADs, CATEGORYCATID, szCatid); hr = SetPropertyGuid(pADs, CATEGORYCATID, rgCategoryInfo[i].catid); RETURN_ON_FAILURE(hr); SetPropertyList(pADs, LOCALEDESCRIPTION, cdesc, pszDesc); for (j = 0; j < cdesc; j++) CoTaskMemFree(pszDesc[j]); CoTaskMemFree(pszDesc); RETURN_ON_FAILURE(hr); hr = StoreIt (pADs); RETURN_ON_FAILURE(hr); pADs->Release(); } return hr; } /* RegisterCategories */ //-------------------------------------------------------- // Unregistering categories from the class store // cCategories: Number of Categories // rgcatid: catids of the categories. // // Stops after any one of them returns a error. // Doesn't remove the category ids from each of the class ids. HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterCategories( /* [in] */ ULONG cCategories, /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ]) { STRINGGUIDRDN szCatid; ULONG i; HRESULT hr; if (!IsValidPtrOut(this, sizeof(*this))){ return E_ACCESSDENIED; } if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){ return E_INVALIDARG; } // Checking whether the caller has permissions if (!m_fOpen) return E_FAIL; for (i = 0; i < cCategories; i++) { RdnFromGUID(rgcatid[i], szCatid); hr = m_ADsCategoryContainer->Delete(CLASS_CS_CATEGORY, szCatid); } return S_OK; } /* UnRegisterCategories */ //------------------------------------------------------------------ // RegisterClassXXXCategories: // rclsid: This category will be registered with this clsid. // cCategories: The number of categories to be added. // rgcatid The categories to be added (cCategories) // impl_or_req The property to which this category will be added. // "Implemented Categories" or "Required Categories" // // // add all the categories given to the class store for this class. // The previous entries will be lost and on error it would not be // restored or made empty. A PRIVATE METHOD called by the 2 public methods. //------------------------------------------------------------------ HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassXXXCategories( /* [in] */ REFCLSID rclsid, /* [in] */ ULONG cCategories, /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],BSTR impl_or_req) { HRESULT hr; STRINGGUIDRDN szName; IADs *pADs = NULL; ULONG i, j, tobeadded; VARIANT Var; GUID *pCatids, *pOldCatids=NULL; IDispatch *pUnknown = NULL; STRINGGUID szGUID; if (!m_fOpen) return E_FAIL; if (!IsValidPtrOut(this, sizeof(*this))) { return E_ACCESSDENIED; } if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){ return E_INVALIDARG; // gd } if (IsNullGuid(rclsid)) return E_INVALIDARG; // Get the ADs interface corresponding to the clsid that is mentioned. StringFromGUID(rclsid, szGUID); wsprintf(szName, L"CN=%s", szGUID); hr = m_ADsClassContainer->GetObject(NULL, szName, (IDispatch **)&pADs ); // if it didn't exist create it. if (FAILED(hr)) { hr = m_ADsClassContainer->Create( CLASS_CS_CLASS, szName, &pUnknown ); RETURN_ON_FAILURE(hr); hr = pUnknown->QueryInterface( IID_IADs, (void **)&pADs ); pUnknown->Release(); } hr = SetProperty (pADs, CLASSCLSID, szGUID); RETURN_ON_FAILURE(hr); hr = GetPropertyListAllocGuid(pADs, impl_or_req, &tobeadded, &pOldCatids); RETURN_ON_FAILURE(hr); pCatids = (GUID *)CoTaskMemAlloc(sizeof(GUID)*(tobeadded+cCategories)); if (!pCatids) return E_OUTOFMEMORY; for (i = 0; i < tobeadded; i++) pCatids[i] = pOldCatids[i]; for (i=0; i < cCategories; ++i) { for (j = 0; j < tobeadded; j++) { if (memcmp(&rgcatid[i], &pCatids[j], sizeof(GUID)) == 0) break; } if (j < tobeadded) continue; // The ith element is already there in the array. // Make sure of this when the property name changes. pCatids[tobeadded] = rgcatid[i]; tobeadded++; } VariantInit(&Var); hr = PackGuidArray2Variant(pCatids, tobeadded, &Var); RETURN_ON_FAILURE(hr); if (tobeadded) hr = pADs->Put(impl_or_req, Var); else hr = pADs->PutEx(ADS_PROPERTY_CLEAR, impl_or_req, Var); RETURN_ON_FAILURE(hr); VariantClear(&Var); // save the data modified hr = StoreIt(pADs); pADs->Release(); CoTaskMemFree(pCatids); if (pOldCatids) CoTaskMemFree(pOldCatids); return hr; } /* RegisterClassXXXCategories */ //--------------------------------------------------------------------- // UnRegisterClassXXXCategories // rclsid: classid from which the categories have to be removed. // cCategories: Number of Categories // rgcatid: Categories // impl_or_req: The property to which this has to be added. // // Presently gets all the categories from the class. parses through it // removes the ones that match in rgcatid and reregister the category. //--------------------------------------------------------------------- HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassXXXCategories( /* [in] */ REFCLSID rclsid, /* [in] */ ULONG cCategories, /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],BSTR impl_or_req) { HRESULT hr; STRINGGUIDRDN szName; IADs *pADs = NULL; ULONG i, j; ULONG cNewCatids, cOldCatids; VARIANT Var; GUID *pOldCatids=NULL, *pNewCatids; // BUGBUG:: Have to decide some way of removing clsids once all categories // are unregistered. if (!m_fOpen) return E_FAIL; if (IsNullGuid(rclsid)) return E_INVALIDARG; if (cCategories == 0) return S_OK; if (!IsValidPtrOut(this, sizeof(*this))) { return E_ACCESSDENIED; } if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){ return E_INVALIDARG; // gd } if (cCategories == 0) return S_OK; // Get all the catids corresp to this clsid. // Get the ADs interface corresponding to the clsid that is mentioned. RdnFromGUID(rclsid, szName); hr = m_ADsClassContainer->GetObject(NULL, szName, (IDispatch **)&pADs ); RETURN_ON_FAILURE(hr); hr = GetPropertyListAllocGuid(pADs, impl_or_req, &cOldCatids, &pOldCatids); RETURN_ON_FAILURE(hr); // parse through this list and delete all the catids that is part of // the user supplied list. pNewCatids = (GUID *)CoTaskMemAlloc(sizeof(GUID)*cOldCatids); if (!pNewCatids) return E_OUTOFMEMORY; for (i = 0, cNewCatids = 0; i < cOldCatids; i++) { for (j = 0; j < cCategories; j++) if (memcmp(&pOldCatids[i], &rgcatid[j], sizeof(GUID)) == 0) break; if (j == cCategories) pNewCatids[cNewCatids++] = pOldCatids[i]; } // reregister this. VariantInit(&Var); hr = PackGuidArray2Variant(pNewCatids, cNewCatids, &Var); RETURN_ON_FAILURE(hr); if (cNewCatids) hr = pADs->Put(impl_or_req, Var); else hr = pADs->PutEx(ADS_PROPERTY_CLEAR, impl_or_req, Var); RETURN_ON_FAILURE(hr); VariantClear(&Var); // save the data modified hr = StoreIt(pADs); pADs->Release(); CoTaskMemFree(pNewCatids); if (pOldCatids) CoTaskMemFree(pOldCatids); return hr; } /* UnRegisterClassXXXCategories */ HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassImplCategories( /* [in] */ REFCLSID rclsid, /* [in] */ ULONG cCategories, /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ]) { return RegisterClassXXXCategories(rclsid, cCategories, rgcatid, IMPL_CATEGORIES); } /* RegisterClassImplCategories */ HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassImplCategories( /* [in] */ REFCLSID rclsid, /* [in] */ ULONG cCategories, /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ]) { return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid, IMPL_CATEGORIES); } /* UnRegisterClassImplCategories */ HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassReqCategories( /* [in] */ REFCLSID rclsid, /* [in] */ ULONG cCategories, /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ]) { return RegisterClassXXXCategories(rclsid, cCategories, rgcatid, REQ_CATEGORIES); } /* RegisterClassReqCategories */ HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassReqCategories( /* [in] */ REFCLSID rclsid, /* [in] */ ULONG cCategories, /* [size_is][in] */ CATID __RPC_FAR rgcatid[ ]) { return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid, REQ_CATEGORIES); } /* UnRegisterClassReqCategories */ //--------------------------------------------------------------------