// // Author: ushaji // Date: December 1996 // // // Providing support for Component Categories in Class Store // // This source file contains implementations for ICatInformation interfaces. ¦ // // Refer Doc "Design for Support of File Types and Component Categories // in Class Store" ? (or may be Class Store Schema) // #include "cstore.hxx" //--------------------------------------------------------------- // EnumCategories: // returns the enumerator to enumerate categories. // lcid: locale id. // ppenumcategoryinfo: Enumerator that is returned. // // ppEnumCategoryInfo value is undefined if an error occurs // I am assuming that except in rare conditions all the application in a // particular environment will have the same lcid. //--------------------------------------------------------------- HRESULT __stdcall CClassContainer::EnumCategories(LCID lcid, IEnumCATEGORYINFO **ppenumCategoryInfo) { VARIANT *pVarFilter = NULL; HRESULT hr; CSCEnumCategories *pEnum; if (!m_fOpen) return E_FAIL; if (!IsValidPtrOut(this, sizeof(*this))) return E_ACCESSDENIED; if (!IsValidPtrOut(ppenumCategoryInfo, sizeof(IEnumCATEGORYINFO *))) return E_INVALIDARG; *ppenumCategoryInfo=NULL; pEnum=new CSCEnumCategories; if(NULL == pEnum) return E_OUTOFMEMORY; hr = pEnum->Initialize(m_ADsCategoryContainer, lcid); if (FAILED(hr)) { delete pEnum; return hr; } hr = pEnum->QueryInterface(IID_IEnumCATEGORYINFO,(void**) ppenumCategoryInfo); if (FAILED(hr)) { delete pEnum; return hr; } return S_OK; } /* EnumCategories */ //--------------------------------------------------------------- // GetCategoryDesc: // returns the description of a given category. // rcatid: category id. // lcid: locale id. // ppszDesc pointer to the description string to be returned. // Allocated by the function. to be freed by client. //-------------------------------------------------------------------------- HRESULT __stdcall CClassContainer::GetCategoryDesc(REFCATID rcatid, LCID lcid, LPOLESTR *ppszDesc) { STRINGGUID guidstr; ULONG cdesc, i; LPOLESTR *localedesc; IADs *pADs; HRESULT hr; if (!IsValidPtrOut(ppszDesc, sizeof(LPOLESTR))) return E_INVALIDARG; if (IsNullGuid(rcatid)) return E_INVALIDARG; if (!IsValidPtrOut(this, sizeof(*this))) return E_ACCESSDENIED; RdnFromGUID(rcatid, guidstr); hr = m_ADsCategoryContainer->GetObject(NULL, guidstr, (IDispatch **)&pADs); if (FAILED(hr)) return CAT_E_CATIDNOEXIST; hr = GetPropertyListAlloc(pADs, LOCALEDESCRIPTION, &cdesc, &localedesc); if (hr == E_OUTOFMEMORY) return hr; if (FAILED(hr)) return CAT_E_NODESCRIPTION; *ppszDesc = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR)*128); if (!(*ppszDesc)) return E_OUTOFMEMORY; GetCategoryLocaleDesc(localedesc, cdesc, &lcid, *ppszDesc); for (i = 0; i < cdesc; i++) CoTaskMemFree(localedesc[i]); CoTaskMemFree(localedesc); pADs->Release(); return S_OK; } /* GetCategoryDesc */ //--------------------------------------------------------------- // EnumClassesOfCategories: // returns the enumerator for classes that implements given catids and // requires some given catids. // // cImplemented number of implemented categories. // (0 is error and -1 is ignore implemented. // rgcatidImpl list of implemented categories. // should be NULL in the two cases mentioned above. // // cRequired: number of required categories. // (0 is requiring nothing and -1 is ignore required. // rgcatidReq list of required categories. // should be NULL in the two cases mentioned above. // // ppenumClsid the enumerator of class ids. //-------------------------------------------------------------------------- HRESULT __stdcall CClassContainer::EnumClassesOfCategories(ULONG cImplemented, CATID rgcatidImpl[], ULONG cRequired, CATID rgcatidReq[], IEnumGUID **ppenumClsid) { ULONG i; CSCEnumClassesOfCategories *penumclasses; HRESULT hr; Data *pData; if (!IsValidPtrOut(ppenumClsid, sizeof(IEnumGUID *))) return E_INVALIDARG; if ((rgcatidImpl == NULL) && (cImplemented != 0) && (cImplemented != -1)) return E_INVALIDARG; if ((rgcatidReq == NULL) && (cRequired != 0) && (cRequired != -1)) return E_INVALIDARG; if ((cImplemented == -1) && (rgcatidImpl != NULL)) return E_POINTER; if ((cRequired == -1) && (rgcatidReq != NULL)) return E_POINTER; if (cImplemented == 0) return E_INVALIDARG; if ((rgcatidImpl) && (!IsValidReadPtrIn(rgcatidImpl, sizeof(CATID)*cImplemented))) { return E_INVALIDARG; } if ((rgcatidReq) && (!IsValidReadPtrIn(rgcatidReq, sizeof(CATID)*cRequired))) { return E_INVALIDARG; } if (!IsValidPtrOut(this, sizeof(*this))) return E_ACCESSDENIED; penumclasses = new CSCEnumClassesOfCategories; if (!penumclasses) { return E_OUTOFMEMORY; } hr = penumclasses->Initialize(cRequired, rgcatidReq, cImplemented, rgcatidImpl, m_ADsClassContainer, (ICatInformation *)this); if (FAILED(hr)) { delete penumclasses; return hr; } hr = penumclasses->QueryInterface(IID_IEnumCLSID, (void **)ppenumClsid); if (FAILED(hr)) { delete penumclasses; return hr; } return hr; } /* EnumClassesOfCategories */ //--------------------------------------------------------------- // EnumReqCategoriesOfClass: // see below EnumCategoriesofClass // //--------------------------------------------------------------- HRESULT CClassContainer::EnumReqCategoriesOfClass(REFCLSID rclsid, IEnumGUID **ppenumCatid) { if (!IsValidReadPtrIn(this, sizeof(*this))) return E_ACCESSDENIED; if (IsNullGuid(rclsid)) return E_INVALIDARG; if (!IsValidPtrOut(ppenumCatid, sizeof(IEnumGUID *))) return E_INVALIDARG; return EnumCategoriesOfClass(rclsid, REQ_CATEGORIES, ppenumCatid); } /* EnumReqClassesOfCategories */ //--------------------------------------------------------------- // EnumImplCategoriesOfClass: // see below EnumCategoriesofClass // //--------------------------------------------------------------- HRESULT CClassContainer::EnumImplCategoriesOfClass(REFCLSID rclsid, IEnumGUID **ppenumCatid) { if (!IsValidReadPtrIn(this, sizeof(*this))) return E_ACCESSDENIED; if (IsNullGuid(rclsid)) return E_INVALIDARG; if (!IsValidPtrOut(ppenumCatid, sizeof(IEnumGUID *))) return E_INVALIDARG; return EnumCategoriesOfClass(rclsid, IMPL_CATEGORIES, ppenumCatid); } /* EnumimplClassesOfCategories */ //--------------------------------------------------------------- // EnumCategoriesOfClass: // returns the enumerator for the implemented or required // rclsid: the class id. // impl_or_req the type of category to enumerated. // ppenumcatid the enumerator that is returned. // Prefetches all the catids and then enumerates them. //--------------------------------------------------------------- HRESULT CClassContainer::EnumCategoriesOfClass(REFCLSID rclsid, BSTR impl_or_req, IEnumGUID **ppenumCatid) { STRINGGUID szName; IADs *pADs = NULL; ULONG i; ULONG cCatid; CATID *Catid = NULL; CSCEnumCategoriesOfClass *pEnumCatid; HRESULT hr = S_OK; if (!m_fOpen) return E_FAIL; // 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, &cCatid, &Catid); pADs->Release(); RETURN_ON_FAILURE(hr); pEnumCatid = new CSCEnumCategoriesOfClass; if (!pEnumCatid) { if (Catid) CoTaskMemFree(Catid); return E_OUTOFMEMORY; } hr = pEnumCatid->Initialize(Catid, cCatid); if (Catid) CoTaskMemFree(Catid); if (FAILED(hr)) { delete pEnumCatid; return hr; } return pEnumCatid->QueryInterface(IID_IEnumCATID, (void **)ppenumCatid); } //--------------------------------------------------------------- // IsClassOfCategories: // similar to EnumClassesOfCategories but returns S_OK/S_FALSE for the // clsid rclsid. Finds the first class that implements these categories // and is of this clsid and checks its required. //--------------------------------------------------------------- HRESULT __stdcall CClassContainer::IsClassOfCategories(REFCLSID rclsid, ULONG cImplemented, CATID __RPC_FAR rgcatidImpl[ ], ULONG cRequired, CATID __RPC_FAR rgcatidReq[ ]) { ULONG cRead, i; Data *pData; HRESULT hr, hr1; if (IsNullGuid(rclsid)) return E_INVALIDARG; if (!IsValidPtrOut(this, sizeof(*this))) return E_ACCESSDENIED; if (cImplemented == 0) return E_INVALIDARG; if ((rgcatidImpl == NULL) && (cImplemented != 0) && (cImplemented != -1)) return E_INVALIDARG; if ((rgcatidReq == NULL) && (cRequired != 0) && (cRequired != -1)) return E_INVALIDARG; if ((cImplemented == -1) && (rgcatidImpl != NULL)) return E_POINTER; if ((cRequired == -1) && (rgcatidReq != NULL)) return E_POINTER; if ((rgcatidImpl) && (!IsValidReadPtrIn(rgcatidImpl, sizeof(CATID)*cImplemented))) { return E_INVALIDARG; } if ((rgcatidReq) && (!IsValidReadPtrIn(rgcatidReq, sizeof(CATID)*cRequired))) { return E_INVALIDARG; } hr = ImplSatisfied(rclsid, cImplemented, rgcatidImpl, this); RETURN_ON_FAILURE(hr); if (hr == S_OK) { hr = ReqSatisfied(rclsid, cRequired, rgcatidReq, this); RETURN_ON_FAILURE(hr); } if (hr != S_OK) return S_FALSE; return S_OK; } /* IsClassOfCategories */ //-------------------------------------------------------------------------------- // ReqSatisfied: // Returns S_OK/S_FALSE depending on whether the clsid satisfies the required // condition for the clsid. // clsid: Class ID of the class. // cAvailReq: Number of Available required classes. // AvailReq: Avail required classes. // calls the enumerator and sees whether there is any required class not present in // the available list. returns S_OK if cAvailReq = -1. //-------------------------------------------------------------------------------- HRESULT ReqSatisfied(CLSID clsid, ULONG cAvailReq, CATID *AvailReq, ICatInformation *pICatInfo) { IEnumGUID *pIEnumCatid; ULONG got, i; CATID catid; HRESULT hr; if (cAvailReq == -1) return S_OK; hr = pICatInfo->EnumReqCategoriesOfClass(clsid, &pIEnumCatid); if (FAILED(hr)) { return hr; } for (;;) { hr = pIEnumCatid->Next(1, &catid, &got); if (FAILED(hr)) { hr = S_FALSE; break; } if (!got) { hr = S_OK; break; } /// check if the required categories are available for (i = 0; i < cAvailReq; i++) if (IsEqualGUID(catid, AvailReq[i])) break; if (i == cAvailReq) { hr = S_FALSE; break; } } pIEnumCatid->Release(); return hr; } //-------------------------------------------------------------------------------- // Implements: // Returns S_OK/S_FALSE depending on whether the clsid satisfies the required // condition for the clsid. // clsid: Class ID of the class. // cImplemented: Number of Implemented categories. // ImplementedList: Implemented Categories. // calls the enumerator and sees whether there is any required class not present in // the available list. returns S_OK if cImplemented = -1. //-------------------------------------------------------------------------------- // BUGBUG:: This should return error when the enumerator return errors. HRESULT ImplSatisfied(CLSID clsid, ULONG cImplemented, CATID *ImplementedList, ICatInformation *pICatInfo) { IEnumGUID *pIEnumCatid; ULONG got, i; CATID catid; HRESULT hr; if (cImplemented == -1) return S_OK; hr = pICatInfo->EnumImplCategoriesOfClass(clsid, &pIEnumCatid); if (FAILED(hr)) { return hr; } for (;;) { hr = pIEnumCatid->Next(1, &catid, &got); if (FAILED(hr)) { hr = S_FALSE; break; } if (!got) { hr = S_FALSE; break; } // check if it implements any of the categories requested. for (i = 0; i < cImplemented; i++) if (IsEqualGUID(catid, ImplementedList[i])) break; if (i < cImplemented) { hr = S_OK; break; } } pIEnumCatid->Release(); return hr; }