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.
 
 
 
 
 
 

680 lines
16 KiB

//
// Author: ushaji
// Date: December 1996
//
//
// Providing support for Component Categories in Class Store
//
// This source file contains implementations for Enumerator Interfaces.
//
// Refer Doc "Design for Support of File Types and Component Categories
// in Class Store" ? (or may be Class Store Schema). Most of these uses
// OLE DB interfaces within the interfaces.
//
//----------------------------------------------------------------------------
#include "cstore.hxx"
//
// Private defines
//
#define MAX_ADS_FILTERS 10
#define MAX_ADS_ENUM 100
// BUGBUG:: Should this go to common
HRESULT
EnumCsObject(
IADsContainer * pADsContainer,
LPWSTR * lppPathNames,
DWORD dwPathNames,
IEnumVARIANT ** ppEnumVariant
)
{
ULONG cElementFetched = 0L;
VARIANT VarFilter;
HRESULT hr;
DWORD dwObjects = 0, dwEnumCount = 0, i = 0;
BOOL fContinue = TRUE;
if (dwPathNames)
{
VariantInit(&VarFilter);
hr = BuildVarArrayStr(
lppPathNames,
dwPathNames,
&VarFilter
);
RETURN_ON_FAILURE(hr);
hr = pADsContainer->put_Filter(VarFilter);
RETURN_ON_FAILURE(hr);
VariantClear(&VarFilter);
}
hr = ADsBuildEnumerator(
pADsContainer,
ppEnumVariant
);
return hr;
}
HRESULT
GetNextEnum(
IEnumVARIANT * pEnum,
IADs **ppADs
)
{
HRESULT hr;
VARIANT VariantArray[MAX_ADS_ENUM];
IDispatch *pDispatch = NULL;
hr = ADsEnumerateNext(
pEnum,
1,
VariantArray,
NULL
);
if (hr == S_FALSE)
return hr;
RETURN_ON_FAILURE(hr);
pDispatch = VariantArray[0].pdispVal;
memset(VariantArray, 0, sizeof(VARIANT)*MAX_ADS_ENUM);
hr = pDispatch->QueryInterface(IID_IADs, (void **) ppADs) ;
pDispatch->Release();
return(S_OK);
}
HRESULT GetCategoryProperty (IADs *pADs,
CATEGORYINFO *pcategoryinfo, LCID lcid)
{
HRESULT hr = S_OK;
WCHAR szName[_MAX_PATH];
LPOLESTR *pdesc = NULL;
ULONG i, cdesc;
hr = GetPropertyGuid(pADs, CATEGORYCATID, &(pcategoryinfo->catid));
RETURN_ON_FAILURE(hr);
hr = GetPropertyListAlloc(pADs, LOCALEDESCRIPTION, &cdesc, &pdesc);
RETURN_ON_FAILURE(hr);
pcategoryinfo->lcid = lcid;
hr = GetCategoryLocaleDesc(pdesc, cdesc, &(pcategoryinfo->lcid),
(pcategoryinfo->szDescription));
for (i = 0; i < cdesc; i++)
CoTaskMemFree(pdesc[i]);
CoTaskMemFree(pdesc);
if (FAILED(hr))
*(pcategoryinfo->szDescription) = L'\0';
return S_OK;
}
//----------------------------------------------
// IEnumCATEGORYINFO:
// IUnknown methods
HRESULT CSCEnumCategories::QueryInterface(REFIID riid, void** ppObject)
{
*ppObject = NULL; //gd
if ((riid==IID_IUnknown) || (riid==IID_IEnumCATEGORYINFO))
{
*ppObject=(IUnknown *)(IEnumCATEGORYINFO*) this;
}
else
{
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG CSCEnumCategories::AddRef()
{
InterlockedIncrement((long*) &m_dwRefCount);
return m_dwRefCount;
}
ULONG CSCEnumCategories::Release()
{
ULONG dwRefCount;
if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
{
delete this;
return 0;
}
return dwRefCount;
}
// IEnumCATEGORYINFO methods
//--------------------------------------------------------------------
// Next:
// celt: Number of elements to be fetched.
// rgelt: Buffer to return the elements.
// pceltFetched: ptr to Number of elements actually fetched.
// Takes care of that being NULL.
// Uses OLE DS interfaces to get the next enumerators.
//--------------------------------------------------------------------
HRESULT CSCEnumCategories::Next(ULONG celt, CATEGORYINFO *rgelt, ULONG *pceltFetched)
{
HRESULT hr = S_OK;
IADs *pCatADs = NULL;
ULONG dwCount;
if ((celt > 1) && (!pceltFetched))
return E_INVALIDARG;
if (pceltFetched)
(*pceltFetched) = 0;
if (m_pEnumVariant == NULL)
return E_UNEXPECTED;
if (celt < 0)
return E_INVALIDARG;
if (!IsValidPtrOut(rgelt, sizeof(CATEGORYINFO)*celt)) {
return E_INVALIDARG;
}
for ((dwCount) = 0; (dwCount) < celt;) {
hr = GetNextEnum(m_pEnumVariant, &pCatADs);
if ((FAILED(hr)) || (hr == S_FALSE))
break;
hr = GetCategoryProperty(pCatADs, &(rgelt[dwCount]), m_lcid);
pCatADs->Release();
if (FAILED(hr))
continue;
(dwCount)++;
}
m_dwPosition += dwCount;
if (pceltFetched)
(*pceltFetched) = dwCount;
return hr;
}
//---------------------------------------------------
// skip:
// skips elements.
// celt Number of elements to skip.
//---------------------------------------------------
HRESULT CSCEnumCategories::Skip(ULONG celt)
{
CATEGORYINFO *dummy;
ULONG got;
HRESULT hr;
dummy = new CATEGORYINFO[celt];
if (!dummy)
return E_OUTOFMEMORY;
if (m_pEnumVariant == NULL)
{
delete dummy;
return E_UNEXPECTED;
}
hr = Next(celt, dummy, &got);
delete dummy;
return hr;
}
//---------------------------------------------------
// Reset:
// Resets the pointer.
//---------------------------------------------------
HRESULT CSCEnumCategories::Reset(void)
{
LPOLESTR pszPathNames [2];
HRESULT hr;
pszPathNames [0] = CLASS_CS_CATEGORY;
if (m_pEnumVariant == NULL)
return E_UNEXPECTED;
m_pEnumVariant->Release();
hr = EnumCsObject(m_ADsCategoryContainer, &pszPathNames[0],
0, &m_pEnumVariant);
m_dwPosition = 0;
return hr;
}
//--------------------------------------------------------------
// Clone:
// returns another interface which points to the same data.
// ppenum: enumerator
//------------------------------------------------------------
////////////////////////////////////////////////////////////////////
HRESULT CSCEnumCategories::Clone(IEnumCATEGORYINFO **ppenum)
{
CSCEnumCategories* pClone=NULL;
if (!IsValidPtrOut(ppenum, sizeof(IEnumCATEGORYINFO *))) {
return E_INVALIDARG;
}
pClone=new CSCEnumCategories();
if (!pClone)
{
return E_OUTOFMEMORY;
}
if (FAILED(pClone->Initialize(m_ADsCategoryContainer, m_lcid)))
{
delete pClone;
return E_UNEXPECTED;
}
pClone->Skip(m_dwPosition);
if (SUCCEEDED(pClone->QueryInterface(IID_IEnumCATEGORYINFO, (void**) ppenum)))
{
return S_OK;
}
delete pClone;
return E_UNEXPECTED;
}
CSCEnumCategories::CSCEnumCategories()
{
m_dwRefCount=0;
m_pEnumVariant = NULL;
m_ADsCategoryContainer = NULL;
m_lcid=0;
m_dwPosition = 0;
}
HRESULT CSCEnumCategories::Initialize(IADsContainer *ADsCategoryContainer, LCID lcid)
{
LPOLESTR pszPathNames [2];
HRESULT hr;
pszPathNames [0] = CLASS_CS_CATEGORY;
m_ADsCategoryContainer = ADsCategoryContainer;
m_ADsCategoryContainer->AddRef();
hr = EnumCsObject(m_ADsCategoryContainer, &pszPathNames[0], 0, &m_pEnumVariant);
RETURN_ON_FAILURE(hr);
m_lcid = lcid;
return S_OK;
} /* EnumCategories */
CSCEnumCategories::~CSCEnumCategories()
{
if (m_ADsCategoryContainer)
m_ADsCategoryContainer->Release();
if (m_pEnumVariant)
m_pEnumVariant->Release();
}
// CSCEnumCategoriesOfClass:
// IUnknown methods
HRESULT CSCEnumCategoriesOfClass::QueryInterface(REFIID riid, void** ppObject)
{
if ((riid==IID_IUnknown) || (riid==IID_IEnumCATID))
{
*ppObject=(IEnumCATID*) this;
}
else
{
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG CSCEnumCategoriesOfClass::AddRef()
{
InterlockedIncrement((long*) &m_dwRefCount);
return m_dwRefCount;
}
ULONG CSCEnumCategoriesOfClass::Release()
{
ULONG dwRefCount;
if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
{
delete this;
return 0;
}
return dwRefCount;
}
// IEnumCATID methods
HRESULT CSCEnumCategoriesOfClass::Next(ULONG celt, GUID *rgelt, ULONG *pceltFetched)
{
ULONG dwCount;
if ((celt > 1) && (!pceltFetched))
return E_INVALIDARG;
if (pceltFetched)
(*pceltFetched) = 0;
if (celt < 0)
return E_INVALIDARG;
if (!IsValidPtrOut(rgelt, sizeof(GUID)*celt))
return E_INVALIDARG;
for ( (dwCount) = 0; (((dwCount) < celt) && (m_dwPosition < m_cCatid));
(dwCount)++, m_dwPosition++)
rgelt[(dwCount)] = m_catid[m_dwPosition];
if (pceltFetched)
(*pceltFetched) = dwCount;
if (dwCount == celt)
return S_OK;
return S_FALSE;
}
HRESULT CSCEnumCategoriesOfClass::Skip(ULONG celt)
{
if (m_cCatid >= (celt + m_dwPosition)) {
m_dwPosition += celt;
return S_OK;
}
m_dwPosition = m_cCatid;
return S_FALSE;
}
HRESULT CSCEnumCategoriesOfClass::Reset(void)
{
m_dwPosition = 0;
return S_OK;
}
HRESULT CSCEnumCategoriesOfClass::Clone(IEnumGUID **ppenum)
{
HRESULT hr = S_OK;
CSCEnumCategoriesOfClass *pEnumClone = NULL;
if (!IsValidPtrOut(ppenum, sizeof(IEnumGUID *)))
return E_POINTER;
pEnumClone = new CSCEnumCategoriesOfClass;
if (pEnumClone == NULL)
return E_OUTOFMEMORY;
pEnumClone->Initialize(m_catid, m_cCatid);
pEnumClone->m_dwPosition = m_dwPosition;
if (SUCCEEDED(hr = pEnumClone->QueryInterface(IID_IEnumCATID, (void**) ppenum)))
return S_OK;
delete pEnumClone;
return hr;
}
CSCEnumCategoriesOfClass::CSCEnumCategoriesOfClass()
{
m_dwRefCount=0;
m_dwPosition = 0;
m_catid = NULL;
}
HRESULT CSCEnumCategoriesOfClass::Initialize(CATID catid[], ULONG cCatid)
{
ULONG i;
m_catid = new CATID[cCatid];
if (!m_catid)
return E_OUTOFMEMORY;
m_cCatid = cCatid;
for (i = 0; i < cCatid; i++)
m_catid[i] = catid[i];
m_dwPosition = 0;
return S_OK;
}
CSCEnumCategoriesOfClass::~CSCEnumCategoriesOfClass()
{
if (m_catid)
delete m_catid;
}
// CEnumClassesOfCategories:
// IUnknown methods
HRESULT CSCEnumClassesOfCategories::QueryInterface(REFIID riid, void** ppObject)
{
if (riid==IID_IUnknown || riid==IID_IEnumCLSID)
{
*ppObject=(IEnumCLSID*) this;
}
else
{
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG CSCEnumClassesOfCategories::AddRef()
{
InterlockedIncrement((long*) &m_dwRefCount);
return m_dwRefCount;
}
ULONG CSCEnumClassesOfCategories::Release()
{
ULONG dwRefCount;
if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0)
{
delete this;
return 0;
}
return dwRefCount;
}
// IEnumGUID methods
HRESULT CSCEnumClassesOfCategories::Next(ULONG celt, GUID *rgelt, ULONG *pceltFetched)
{
ULONG cRead;
ULONG i, dwCount, cgot;
HRESULT hr;
CLSID clsid;
IADs *pclsid;
WCHAR szClsid[_MAX_PATH];
if ((celt > 1) && (!pceltFetched))
return E_INVALIDARG;
if (pceltFetched)
(*pceltFetched) = 0;
if ((celt < 0) || (!IsValidPtrOut(rgelt, sizeof(GUID)*celt)))
return E_INVALIDARG;
for ((dwCount) = 0; (dwCount) < celt;) {
hr = GetNextEnum(m_pEnumVariant, &pclsid);
if ((FAILED(hr)) || (hr == S_FALSE))
{
if (pceltFetched)
*pceltFetched = dwCount;
return S_FALSE;
}
hr = GetProperty (pclsid, CLASSCLSID, szClsid);
pclsid->Release();
if (FAILED(hr)) {
if (pceltFetched)
*pceltFetched = dwCount;
return S_FALSE;
}
GUIDFromString(szClsid, &clsid);
if ((ImplSatisfied(clsid, m_cImplemented, m_rgcatidImpl, m_pICatInfo) == S_OK) &&
(ReqSatisfied(clsid, m_cRequired, m_rgcatidReq, m_pICatInfo) == S_OK))
{
rgelt[dwCount] = clsid;
(dwCount)++;
}
}
m_dwPosition += dwCount;
if (pceltFetched)
*pceltFetched = dwCount;
return S_OK;
}
HRESULT CSCEnumClassesOfCategories::Skip(ULONG celt)
{
CLSID *dummyclasses;
ULONG celtFetched;
HRESULT hr;
dummyclasses = new CLSID[celt];
hr = Next(celt, dummyclasses, &celtFetched);
delete dummyclasses;
return hr;
}
HRESULT CSCEnumClassesOfCategories::Reset()
{
LPOLESTR pszPathNames [2];
HRESULT hr;
pszPathNames [0] = CLASS_CS_CLASS;
if (m_pEnumVariant == NULL)
return E_UNEXPECTED;
m_pEnumVariant->Release();
hr = EnumCsObject(m_ADsClassContainer, &pszPathNames[0],
0, &m_pEnumVariant);
m_dwPosition = 0;
return hr;
}
HRESULT CSCEnumClassesOfCategories::Clone(IEnumGUID **ppenum)
{
HRESULT hr;
CSCEnumClassesOfCategories *pEnumClone;
if (!ppenum)
return E_INVALIDARG;
pEnumClone = new CSCEnumClassesOfCategories;
if (!pEnumClone)
return E_OUTOFMEMORY;
hr = pEnumClone->Initialize(m_cRequired, m_rgcatidReq,
m_cImplemented, m_rgcatidImpl,
m_ADsClassContainer,
m_pICatInfo);
if (FAILED(hr))
{
delete pEnumClone;
return hr;
}
pEnumClone->Skip(m_dwPosition);
hr = pEnumClone->QueryInterface(IID_IEnumCLSID, (void **)ppenum);
if (FAILED(hr))
{
delete pEnumClone;
}
return hr;
}
CSCEnumClassesOfCategories::CSCEnumClassesOfCategories()
{
m_dwRefCount = 0;
m_rgcatidReq = NULL;
m_rgcatidImpl = NULL;
m_pICatInfo = NULL;
m_ADsClassContainer = NULL;
m_pEnumVariant = NULL;
m_dwPosition = 0;
}
HRESULT CSCEnumClassesOfCategories::Initialize(ULONG cRequired, CATID rgcatidReq[],
ULONG cImplemented, CATID rgcatidImpl[],
IADsContainer *ADsClassContainer,
ICatInformation *pICatInfo)
{
ULONG i;
HRESULT hr;
LPOLESTR pszPathNames [2];
pszPathNames [0] = CLASS_CS_CLASS;
m_ADsClassContainer = ADsClassContainer;
m_ADsClassContainer->AddRef();
hr = EnumCsObject(m_ADsClassContainer, &pszPathNames[0], 0, &m_pEnumVariant);
RETURN_ON_FAILURE(hr);
m_pICatInfo = pICatInfo;
RETURN_ON_FAILURE(m_pICatInfo->AddRef());
m_cRequired = cRequired;
if (cRequired != -1)
{
m_rgcatidReq = new CATID[cRequired];
if (!m_rgcatidReq)
return E_OUTOFMEMORY;
for (i = 0; i < m_cRequired; i++)
m_rgcatidReq[i] = rgcatidReq[i];
}
m_cImplemented = cImplemented;
if (cImplemented != -1)
{
m_rgcatidImpl = new CATID[cImplemented];
if (!m_rgcatidImpl)
return E_OUTOFMEMORY;
for (i = 0; i < m_cImplemented; i++)
m_rgcatidImpl[i] = rgcatidImpl[i];
}
return S_OK;
}
CSCEnumClassesOfCategories::~CSCEnumClassesOfCategories()
{
if (m_rgcatidReq)
delete m_rgcatidReq;
if (m_rgcatidImpl)
delete m_rgcatidImpl;
if (m_pICatInfo)
m_pICatInfo->Release();
if (m_ADsClassContainer)
m_ADsClassContainer->Release();
if (m_pEnumVariant)
m_pEnumVariant->Release();
}