// // 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 HRESULT GetCategoryProperty (HANDLE hADs, ADS_SEARCH_HANDLE hSearchHandle, CATEGORYINFO *pcategoryinfo, LCID lcid) { HRESULT hr = S_OK; WCHAR *szName = NULL; LPOLESTR *pdesc = NULL; ULONG i, cdesc = 0; ADS_SEARCH_COLUMN column; hr = ADSIGetColumn(hADs, hSearchHandle, CATEGORYCATID, &column); RETURN_ON_FAILURE(hr); hr = UnpackGUIDFrom(column, &(pcategoryinfo->catid)); RETURN_ON_FAILURE(hr); ADSIFreeColumn(hADs, &column); hr = ADSIGetColumn(hADs, hSearchHandle, LOCALEDESCRIPTION, &column); RETURN_ON_FAILURE(hr); UnpackStrArrAllocFrom(column, &pdesc, &cdesc); pcategoryinfo->lcid = lcid; hr = GetCategoryLocaleDesc(pdesc, cdesc, &(pcategoryinfo->lcid), (pcategoryinfo->szDescription)); ADSIFreeColumn(hADs, &column); 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; ULONG dwCount = 0, cElems = 0; if ((celt > 1) && (!pceltFetched)) return E_INVALIDARG; if (pceltFetched) (*pceltFetched) = 0; if (celt < 0) return E_INVALIDARG; if (!IsValidPtrOut(rgelt, sizeof(CATEGORYINFO)*celt)) return E_INVALIDARG; for ((dwCount) = 0; (dwCount) < celt;) { if ((!m_dwPosition) && (!cElems)) hr = ADSIGetFirstRow(m_hADs, m_hADsSearchHandle); else hr = ADSIGetNextRow(m_hADs, m_hADsSearchHandle); cElems++; if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS)) break; hr = GetCategoryProperty(m_hADs, m_hADsSearchHandle, &(rgelt[dwCount]), m_lcid); if (FAILED(hr)) continue; (dwCount)++; } m_dwPosition += dwCount; if (pceltFetched) (*pceltFetched) = dwCount; if (dwCount == celt) return S_OK; return S_FALSE; } //--------------------------------------------------- // skip: // skips elements. // celt Number of elements to skip. //--------------------------------------------------- HRESULT CSCEnumCategories::Skip(ULONG celt) { CATEGORYINFO *dummy = NULL; ULONG got = 0; HRESULT hr = S_OK; dummy = new CATEGORYINFO[celt]; if (!dummy) return E_OUTOFMEMORY; hr = Next(celt, dummy, &got); delete dummy; return hr; } //--------------------------------------------------- // Reset: // Resets the pointer. //--------------------------------------------------- HRESULT CSCEnumCategories::Reset(void) { HRESULT hr = S_OK; WCHAR szfilter[_MAX_PATH]; m_dwPosition = 0; if (m_hADsSearchHandle) { ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle); m_hADsSearchHandle = NULL; } wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CATEGORY); hr = ADSIExecuteSearch(m_hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &m_hADsSearchHandle); return RemapErrorCode(hr, m_szCategoryName); } //-------------------------------------------------------------- // 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_szCategoryName, 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_hADs = NULL; m_hADsSearchHandle = NULL; wcscpy(m_szCategoryName, L""); m_lcid = 0; m_dwPosition = 0; } // clone will go over the wire again. // reference counting will be good. HRESULT CSCEnumCategories::Initialize(WCHAR *szCategoryName, LCID lcid) { HRESULT hr = S_OK; WCHAR szfilter[_MAX_PATH]; ADS_SEARCHPREF_INFO SearchPrefs[2]; // set the search preference. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL; SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[1].vValue.Integer = 20; wcscpy(m_szCategoryName, szCategoryName); hr = ADSIOpenDSObject(m_szCategoryName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &m_hADs); RETURN_ON_FAILURE(hr); hr = ADSISetSearchPreference(m_hADs, SearchPrefs, 2); RETURN_ON_FAILURE(hr); wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CATEGORY); hr = ADSIExecuteSearch(m_hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &m_hADsSearchHandle); RETURN_ON_FAILURE(hr); m_lcid = lcid; return S_OK; } /* EnumCategories */ CSCEnumCategories::~CSCEnumCategories() { if (m_hADs) ADSICloseDSObject(m_hADs); if (m_hADsSearchHandle) ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle); } // 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 ((cCatid) && (!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 i, dwCount=0; HRESULT hr = S_OK; CLSID clsid; WCHAR * szClsid = NULL; DWORD cElems = 0; ADS_SEARCH_COLUMN column; 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;) { if ((!m_dwPosition) && (!cElems)) hr = ADSIGetFirstRow(m_hADs, m_hADsSearchHandle); else hr = ADSIGetNextRow(m_hADs, m_hADsSearchHandle); cElems++; if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS)) { if (pceltFetched) *pceltFetched = dwCount; return S_FALSE; } hr = ADSIGetColumn(m_hADs, m_hADsSearchHandle, CLASSCLSID, &column); if (FAILED(hr)) { if (pceltFetched) *pceltFetched = dwCount; return S_FALSE; } UnpackStrFrom(column, &szClsid); GUIDFromString(szClsid, &clsid); if ((ImplSatisfied(m_cImplemented, m_rgcatidImpl, m_hADs, m_hADsSearchHandle) == S_OK) && (ReqSatisfied(m_cRequired, m_rgcatidReq, m_hADs, m_hADsSearchHandle) == S_OK)) { rgelt[dwCount] = clsid; (dwCount)++; } } m_dwPosition += dwCount; if (pceltFetched) *pceltFetched = dwCount; return S_OK; } HRESULT CSCEnumClassesOfCategories::Skip(ULONG celt) { CLSID *dummyclasses=NULL; ULONG celtFetched=0; HRESULT hr=S_OK; dummyclasses = new CLSID[celt]; hr = Next(celt, dummyclasses, &celtFetched); delete dummyclasses; return hr; } HRESULT CSCEnumClassesOfCategories::Reset() { LPOLESTR AttrNames[] = {CLASSCLSID, IMPL_CATEGORIES, REQ_CATEGORIES}; DWORD cAttrs = 3; WCHAR szfilter[_MAX_PATH]; HRESULT hr = S_OK; m_dwPosition = 0; if (m_hADsSearchHandle) { ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle); m_hADsSearchHandle = NULL; } wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CLASS); hr = ADSIExecuteSearch(m_hADs, szfilter, AttrNames, cAttrs, &m_hADsSearchHandle); return RemapErrorCode(hr, m_szClassName); } HRESULT CSCEnumClassesOfCategories::Clone(IEnumGUID **ppenum) { HRESULT hr=S_OK; CSCEnumClassesOfCategories *pEnumClone=NULL; 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_szClassName); 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; wcscpy(m_szClassName,L""); m_dwPosition = 0; m_hADs = NULL; m_hADsSearchHandle = NULL; } HRESULT CSCEnumClassesOfCategories::Initialize(ULONG cRequired, CATID rgcatidReq[], ULONG cImplemented, CATID rgcatidImpl[], WCHAR *szClassName) { ULONG i; HRESULT hr = S_OK; ADS_SEARCHPREF_INFO SearchPrefs[2]; LPOLESTR AttrNames[] = {CLASSCLSID, IMPL_CATEGORIES, REQ_CATEGORIES}; DWORD cAttrs = 3; WCHAR szfilter[_MAX_PATH]; SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL; SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[1].vValue.Integer = 20; wcscpy(m_szClassName, szClassName); hr = ADSIOpenDSObject(m_szClassName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &m_hADs); ERROR_ON_FAILURE(hr); hr = ADSISetSearchPreference(m_hADs, SearchPrefs, 2); ERROR_ON_FAILURE(hr); wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CLASS); hr = ADSIExecuteSearch(m_hADs, szfilter, AttrNames, cAttrs, &m_hADsSearchHandle); ERROR_ON_FAILURE(hr); m_cRequired = cRequired; if (cRequired != -1) { m_rgcatidReq = new CATID[cRequired]; if (!m_rgcatidReq) { hr = E_OUTOFMEMORY; ERROR_ON_FAILURE(hr); } 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) { hr = E_OUTOFMEMORY; ERROR_ON_FAILURE(hr); } for (i = 0; i < m_cImplemented; i++) m_rgcatidImpl[i] = rgcatidImpl[i]; } Error_Cleanup: return RemapErrorCode(hr, m_szClassName); } CSCEnumClassesOfCategories::~CSCEnumClassesOfCategories() { if (m_rgcatidReq) delete m_rgcatidReq; if (m_rgcatidImpl) delete m_rgcatidImpl; if (m_hADsSearchHandle) ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle); if (m_hADs) ADSICloseDSObject(m_hADs); }