// // 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(); }