mirror of https://github.com/tongzx/nt5src
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
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();
|
|
}
|
|
|
|
|