|
|
//
// 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
//---------------------------------------------------------------
HRESULT __stdcall CClassContainer::EnumCategories(LCID lcid, IEnumCATEGORYINFO **ppenumCategoryInfo) { HRESULT hr = S_OK; CSCEnumCategories *pEnum = NULL; if (!m_fOpen) return E_FAIL; if (!IsValidPtrOut(this, sizeof(*this))) return E_ACCESSDENIED; if (!IsValidPtrOut(ppenumCategoryInfo, sizeof(IEnumCATEGORYINFO *))) return E_INVALIDARG; *ppenumCategoryInfo=NULL; // get the enumerator object.
pEnum=new CSCEnumCategories; if(NULL == pEnum) return E_OUTOFMEMORY; // initialize the enumerator object with the name.
hr = pEnum->Initialize(m_szCategoryName, lcid); ERROR_ON_FAILURE(hr); hr = pEnum->QueryInterface(IID_IEnumCATEGORYINFO, (void**)ppenumCategoryInfo); ERROR_ON_FAILURE(hr);
return S_OK; Error_Cleanup: if (pEnum) delete pEnum; return RemapErrorCode(hr, m_szContainerName); } /* 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) { STRINGGUIDRDN szRDN; ULONG cdesc = 0, i, cgot = 0; LPOLESTR * localedesc = NULL; HANDLE hADs = NULL; HRESULT hr = S_OK; WCHAR * szFullName = NULL; LPOLESTR AttrName = LOCALEDESCRIPTION; ADS_ATTR_INFO * pAttr = NULL; if (!IsValidPtrOut(ppszDesc, sizeof(LPOLESTR))) return E_INVALIDARG; if (IsNullGuid(rcatid)) return E_INVALIDARG; if (!IsValidPtrOut(this, sizeof(*this))) return E_ACCESSDENIED; RDNFromGUID(rcatid, szRDN); BuildADsPathFromParent(m_szCategoryName, szRDN, &szFullName); hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs); if (FAILED(hr)) return CAT_E_CATIDNOEXIST; // get the array of localized descriptions
hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttr, &cgot); if (FAILED(hr) || (!cgot)) return CAT_E_NODESCRIPTION; hr = UnpackStrArrFrom(pAttr[0], &localedesc, &cdesc); if (hr == E_OUTOFMEMORY) return hr; *ppszDesc = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR)*128); if (!(*ppszDesc)) return E_OUTOFMEMORY; // get a description closest to the locale we need.
GetCategoryLocaleDesc(localedesc, cdesc, &lcid, *ppszDesc); CoTaskMemFree(localedesc); ADSICloseDSObject(hADs); FreeADsMem(pAttr); FreeADsMem(szFullName); 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 = NULL; HRESULT hr = S_OK; 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; } // initialize the enumerator
hr = penumclasses->Initialize(cRequired, rgcatidReq, cImplemented, rgcatidImpl, m_szClassName); ERROR_ON_FAILURE(hr); hr = penumclasses->QueryInterface(IID_IEnumCLSID, (void **)ppenumClsid); ERROR_ON_FAILURE(hr);
return S_OK;
Error_Cleanup: if (penumclasses) delete penumclasses; return RemapErrorCode(hr, m_szContainerName); } /* 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) { STRINGGUIDRDN szRDN; HANDLE hADs = NULL; ULONG i; ULONG cCatid = 0, cgot = 0; CATID * Catid = NULL; CSCEnumCategoriesOfClass * pEnumCatid = NULL; HRESULT hr = S_OK; WCHAR * szFullName = NULL; ADS_ATTR_INFO * pAttr = NULL; if (!m_fOpen) return E_FAIL; // Get the ADs interface corresponding to the clsid that is mentioned.
RDNFromGUID(rclsid, szRDN); BuildADsPathFromParent(m_szClassName, szRDN, &szFullName); hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs); RETURN_ON_FAILURE(hr); // get the implemented or required cateogory list.
hr = ADSIGetObjectAttributes(hADs, &impl_or_req, 1, &pAttr, &cgot); ERROR_ON_FAILURE(hr); if (cgot) hr = UnpackGUIDArrFrom(pAttr[0], &Catid, &cCatid); pEnumCatid = new CSCEnumCategoriesOfClass; if (!pEnumCatid) { hr = E_OUTOFMEMORY; ERROR_ON_FAILURE(hr); } // initialize the enumerator
hr = pEnumCatid->Initialize(Catid, cCatid); ERROR_ON_FAILURE(hr); hr = pEnumCatid->QueryInterface(IID_IEnumCATID, (void **)ppenumCatid); Error_Cleanup: if (Catid) CoTaskMemFree(Catid); if (FAILED(hr)) { delete pEnumCatid; return hr; } if (szFullName) FreeADsMem(szFullName); if (pAttr) FreeADsMem(pAttr); if (hADs) ADSICloseDSObject(hADs); return RemapErrorCode(hr, m_szContainerName);
} //---------------------------------------------------------------
// 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[ ]) { HRESULT hr = S_OK; ADS_SEARCH_HANDLE hADsSearchHandle = NULL; WCHAR szfilter[_MAX_PATH]; LPOLESTR AttrNames[] = {IMPL_CATEGORIES, REQ_CATEGORIES, L"cn"}; DWORD cAttr = 3; STRINGGUID szClsid; 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; } StringFromGUID(rclsid, szClsid); wsprintf(szfilter, L"(cn=%s)", szClsid); // doing a search so that we can pass the same parameters to the
// xxxSatisfied functions below.
hr = ADSIExecuteSearch(m_ADsClassContainer, szfilter, AttrNames, cAttr, &hADsSearchHandle); RETURN_ON_FAILURE(hr); hr = ADSIGetFirstRow(m_ADsClassContainer, hADsSearchHandle); if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS)) { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); ERROR_ON_FAILURE(hr); } hr = ImplSatisfied(cImplemented, rgcatidImpl, m_ADsClassContainer, hADsSearchHandle); ERROR_ON_FAILURE(hr); if (hr == S_OK) { hr = ReqSatisfied(cRequired, rgcatidReq, m_ADsClassContainer, hADsSearchHandle); ERROR_ON_FAILURE(hr); } if (hr != S_OK) hr = S_FALSE; Error_Cleanup: ADSICloseSearchHandle(m_ADsClassContainer, hADsSearchHandle); return hr; } /* 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(ULONG cAvailReq, CATID *AvailReq, HANDLE hADs, ADS_SEARCH_HANDLE hADsSearchHandle) { HRESULT hr = S_OK; ADS_SEARCH_COLUMN column; GUID * ReqGuid = NULL; DWORD i, j, cReq = 0; if (cAvailReq == -1) return S_OK; hr = ADSIGetColumn(hADs, hADsSearchHandle, REQ_CATEGORIES, &column); if (FAILED(hr)) return S_OK; hr = S_OK; UnpackGUIDArrFrom(column, &ReqGuid, &cReq); for (j = 0; j < cReq; j++) { /// check if the required categories are available
for (i = 0; i < cAvailReq; i++) if (IsEqualGUID(ReqGuid[j], AvailReq[i])) break; if (i == cAvailReq) { hr = S_FALSE; break; } } CoTaskMemFree(ReqGuid); ADSIFreeColumn(hADs, &column); 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.
//--------------------------------------------------------------------------------
HRESULT ImplSatisfied(ULONG cImplemented, CATID *ImplementedList, HANDLE hADs, ADS_SEARCH_HANDLE hADsSearchHandle) { ADS_SEARCH_COLUMN column; GUID * ImplGuid = NULL; ULONG i, j, cImpl = 0; HRESULT hr = S_FALSE; if (cImplemented == -1) return S_OK; hr = ADSIGetColumn(hADs, hADsSearchHandle, IMPL_CATEGORIES, &column); if (FAILED(hr)) return S_FALSE; hr = S_FALSE; UnpackGUIDArrFrom(column, &ImplGuid, &cImpl); for (j = 0;j < cImpl; j++) { // check if it implements any of the categories requested.
for (i = 0; i < cImplemented; i++) if (IsEqualGUID(ImplGuid[j], ImplementedList[i])) break; if (i < cImplemented) { hr = S_OK; break; } } CoTaskMemFree(ImplGuid); ADSIFreeColumn(hADs, &column); return hr; }
|