464 lines
14 KiB
C++
464 lines
14 KiB
C++
//
|
||
// 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;
|
||
}
|
||
|
||
|
||
|