449 lines
14 KiB
C++
449 lines
14 KiB
C++
|
//
|
|||
|
// Author: ushaji
|
|||
|
// Date: December/Jan 1996
|
|||
|
//
|
|||
|
//
|
|||
|
// Providing support for Component Categories in Class Store
|
|||
|
//
|
|||
|
// This source file contains implementations for ICatRegister interfaces. <20>
|
|||
|
//
|
|||
|
// Refer Doc "Design for Support of File Types and Component Categories
|
|||
|
// in Class Store" ? (or may be Class Store Schema)
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
#include "cstore.hxx"
|
|||
|
|
|||
|
//-------------------------------------------------------------
|
|||
|
// RegisterCategories:
|
|||
|
// registering categories in the class store.
|
|||
|
// cCategories: Number of Categories
|
|||
|
// rgCategoryInfo: Size cCategories
|
|||
|
//
|
|||
|
// Returns as soon as one of them fails.
|
|||
|
//-------------------------------------------------------------
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::RegisterCategories(
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATEGORYINFO __RPC_FAR rgCategoryInfo[ ])
|
|||
|
{
|
|||
|
/* Registering a list of Category ID in the Class Store */
|
|||
|
|
|||
|
HRESULT hr;
|
|||
|
IADs *pADs = NULL;
|
|||
|
IDispatch *pUnknown = NULL;
|
|||
|
STRINGGUIDRDN szCatid;
|
|||
|
ULONG i, j, cdesc, posn;
|
|||
|
LPOLESTR *pszDescExisting, *pszDesc;
|
|||
|
WCHAR *localedescription = NULL;
|
|||
|
// sizeof description + seperator length + locale in hex
|
|||
|
|
|||
|
/* BUGBUG::Should check whether write permissions exist? */
|
|||
|
if (!IsValidReadPtrIn(this, sizeof(*this))) {
|
|||
|
return E_ACCESSDENIED;
|
|||
|
}
|
|||
|
|
|||
|
if (!IsValidReadPtrIn(rgCategoryInfo, sizeof(rgCategoryInfo[0])*cCategories))
|
|||
|
{
|
|||
|
return E_INVALIDARG; // gd
|
|||
|
}
|
|||
|
|
|||
|
if (!m_fOpen)
|
|||
|
return E_FAIL;
|
|||
|
|
|||
|
for (i = 0; i < cCategories; i++)
|
|||
|
{
|
|||
|
localedescription = (WCHAR *)CoTaskMemAlloc(sizeof(WCHAR)*(128+16));
|
|||
|
if (!localedescription)
|
|||
|
return E_OUTOFMEMORY;
|
|||
|
|
|||
|
RdnFromGUID(rgCategoryInfo[i].catid, szCatid);
|
|||
|
|
|||
|
wsprintf(localedescription, L"%x %s %s", rgCategoryInfo[i].lcid, CATSEPERATOR,
|
|||
|
rgCategoryInfo[i].szDescription);
|
|||
|
|
|||
|
hr = m_ADsCategoryContainer->GetObject(NULL, szCatid, (IDispatch **)&pADs);
|
|||
|
|
|||
|
if (SUCCEEDED(hr))
|
|||
|
{
|
|||
|
hr = GetPropertyListAlloc (pADs, LOCALEDESCRIPTION, &cdesc, &pszDescExisting);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
// Existing list of descriptions
|
|||
|
|
|||
|
pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(cdesc+1));
|
|||
|
if (!pszDesc)
|
|||
|
return E_OUTOFMEMORY;
|
|||
|
for (j = 0; j < cdesc; j++)
|
|||
|
pszDesc[j] = pszDescExisting[j];
|
|||
|
|
|||
|
if (!(posn = FindDescription(pszDescExisting, cdesc, &(rgCategoryInfo[i].lcid), NULL, 0)))
|
|||
|
{
|
|||
|
// if no description exists for the lcid.
|
|||
|
pszDesc[cdesc] = localedescription;
|
|||
|
cdesc++;
|
|||
|
}
|
|||
|
else
|
|||
|
{ // overwrite the old value
|
|||
|
CoTaskMemFree(pszDesc[posn-1]);
|
|||
|
pszDesc[posn-1] = localedescription;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
hr = m_ADsCategoryContainer->Create(
|
|||
|
CLASS_CS_CATEGORY,
|
|||
|
szCatid,
|
|||
|
&pUnknown
|
|||
|
);
|
|||
|
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR));
|
|||
|
if (!pszDesc)
|
|||
|
return E_OUTOFMEMORY;
|
|||
|
cdesc = 1;
|
|||
|
pszDesc[0] = localedescription;
|
|||
|
|
|||
|
hr = pUnknown->QueryInterface(IID_IADs, (void **)&pADs);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
pUnknown->Release();
|
|||
|
}
|
|||
|
|
|||
|
// StringFromGUID(rgCategoryInfo[i].catid, szCatid);
|
|||
|
// SetProperty(pADs, CATEGORYCATID, szCatid);
|
|||
|
hr = SetPropertyGuid(pADs, CATEGORYCATID, rgCategoryInfo[i].catid);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
SetPropertyList(pADs, LOCALEDESCRIPTION, cdesc, pszDesc);
|
|||
|
for (j = 0; j < cdesc; j++)
|
|||
|
CoTaskMemFree(pszDesc[j]);
|
|||
|
CoTaskMemFree(pszDesc);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = StoreIt (pADs);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
pADs->Release();
|
|||
|
}
|
|||
|
return hr;
|
|||
|
} /* RegisterCategories */
|
|||
|
|
|||
|
|
|||
|
//--------------------------------------------------------
|
|||
|
// Unregistering categories from the class store
|
|||
|
// cCategories: Number of Categories
|
|||
|
// rgcatid: catids of the categories.
|
|||
|
//
|
|||
|
// Stops after any one of them returns a error.
|
|||
|
// Doesn't remove the category ids from each of the class ids.
|
|||
|
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterCategories(
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
|
|||
|
{
|
|||
|
STRINGGUIDRDN szCatid;
|
|||
|
ULONG i;
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
|
|||
|
if (!IsValidPtrOut(this, sizeof(*this))){
|
|||
|
return E_ACCESSDENIED;
|
|||
|
}
|
|||
|
if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
|
|||
|
return E_INVALIDARG;
|
|||
|
}
|
|||
|
// Checking whether the caller has permissions
|
|||
|
|
|||
|
if (!m_fOpen)
|
|||
|
return E_FAIL;
|
|||
|
|
|||
|
for (i = 0; i < cCategories; i++)
|
|||
|
{
|
|||
|
RdnFromGUID(rgcatid[i], szCatid);
|
|||
|
|
|||
|
hr = m_ADsCategoryContainer->Delete(CLASS_CS_CATEGORY,
|
|||
|
szCatid);
|
|||
|
}
|
|||
|
return S_OK;
|
|||
|
} /* UnRegisterCategories */
|
|||
|
|
|||
|
//------------------------------------------------------------------
|
|||
|
// RegisterClassXXXCategories:
|
|||
|
// rclsid: This category will be registered with this clsid.
|
|||
|
// cCategories: The number of categories to be added.
|
|||
|
// rgcatid The categories to be added (cCategories)
|
|||
|
// impl_or_req The property to which this category will be added.
|
|||
|
// "Implemented Categories" or "Required Categories"
|
|||
|
//
|
|||
|
//
|
|||
|
// add all the categories given to the class store for this class.
|
|||
|
// The previous entries will be lost and on error it would not be
|
|||
|
// restored or made empty. A PRIVATE METHOD called by the 2 public methods.
|
|||
|
//------------------------------------------------------------------
|
|||
|
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassXXXCategories(
|
|||
|
/* [in] */ REFCLSID rclsid,
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],BSTR impl_or_req)
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
STRINGGUIDRDN szName;
|
|||
|
IADs *pADs = NULL;
|
|||
|
ULONG i, j, tobeadded;
|
|||
|
VARIANT Var;
|
|||
|
GUID *pCatids, *pOldCatids=NULL;
|
|||
|
IDispatch *pUnknown = NULL;
|
|||
|
STRINGGUID szGUID;
|
|||
|
|
|||
|
if (!m_fOpen)
|
|||
|
return E_FAIL;
|
|||
|
|
|||
|
if (!IsValidPtrOut(this, sizeof(*this))) {
|
|||
|
return E_ACCESSDENIED;
|
|||
|
}
|
|||
|
|
|||
|
if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
|
|||
|
return E_INVALIDARG; // gd
|
|||
|
}
|
|||
|
|
|||
|
if (IsNullGuid(rclsid))
|
|||
|
return E_INVALIDARG;
|
|||
|
|
|||
|
// Get the ADs interface corresponding to the clsid that is mentioned.
|
|||
|
StringFromGUID(rclsid, szGUID);
|
|||
|
wsprintf(szName, L"CN=%s", szGUID);
|
|||
|
|
|||
|
hr = m_ADsClassContainer->GetObject(NULL,
|
|||
|
szName,
|
|||
|
(IDispatch **)&pADs
|
|||
|
);
|
|||
|
|
|||
|
// if it didn't exist create it.
|
|||
|
if (FAILED(hr)) {
|
|||
|
hr = m_ADsClassContainer->Create(
|
|||
|
CLASS_CS_CLASS,
|
|||
|
szName,
|
|||
|
&pUnknown
|
|||
|
);
|
|||
|
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = pUnknown->QueryInterface(
|
|||
|
IID_IADs,
|
|||
|
(void **)&pADs
|
|||
|
);
|
|||
|
|
|||
|
pUnknown->Release();
|
|||
|
}
|
|||
|
|
|||
|
hr = SetProperty (pADs, CLASSCLSID, szGUID);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyListAllocGuid(pADs, impl_or_req, &tobeadded, &pOldCatids);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
pCatids = (GUID *)CoTaskMemAlloc(sizeof(GUID)*(tobeadded+cCategories));
|
|||
|
if (!pCatids)
|
|||
|
return E_OUTOFMEMORY;
|
|||
|
|
|||
|
for (i = 0; i < tobeadded; i++)
|
|||
|
pCatids[i] = pOldCatids[i];
|
|||
|
|
|||
|
for (i=0; i < cCategories; ++i) {
|
|||
|
for (j = 0; j < tobeadded; j++)
|
|||
|
{
|
|||
|
if (memcmp(&rgcatid[i], &pCatids[j], sizeof(GUID)) == 0)
|
|||
|
break;
|
|||
|
}
|
|||
|
if (j < tobeadded)
|
|||
|
continue;
|
|||
|
// The ith element is already there in the array.
|
|||
|
// Make sure of this when the property name changes.
|
|||
|
|
|||
|
pCatids[tobeadded] = rgcatid[i];
|
|||
|
tobeadded++;
|
|||
|
}
|
|||
|
|
|||
|
VariantInit(&Var);
|
|||
|
hr = PackGuidArray2Variant(pCatids, tobeadded, &Var);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
if (tobeadded)
|
|||
|
hr = pADs->Put(impl_or_req, Var);
|
|||
|
else
|
|||
|
hr = pADs->PutEx(ADS_PROPERTY_CLEAR, impl_or_req, Var);
|
|||
|
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
VariantClear(&Var);
|
|||
|
|
|||
|
// save the data modified
|
|||
|
hr = StoreIt(pADs);
|
|||
|
pADs->Release();
|
|||
|
|
|||
|
CoTaskMemFree(pCatids);
|
|||
|
if (pOldCatids)
|
|||
|
CoTaskMemFree(pOldCatids);
|
|||
|
return hr;
|
|||
|
} /* RegisterClassXXXCategories */
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------------
|
|||
|
// UnRegisterClassXXXCategories
|
|||
|
// rclsid: classid from which the categories have to be removed.
|
|||
|
// cCategories: Number of Categories
|
|||
|
// rgcatid: Categories
|
|||
|
// impl_or_req: The property to which this has to be added.
|
|||
|
//
|
|||
|
// Presently gets all the categories from the class. parses through it
|
|||
|
// removes the ones that match in rgcatid and reregister the category.
|
|||
|
//---------------------------------------------------------------------
|
|||
|
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassXXXCategories(
|
|||
|
/* [in] */ REFCLSID rclsid,
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATID __RPC_FAR rgcatid[ ],BSTR impl_or_req)
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
STRINGGUIDRDN szName;
|
|||
|
IADs *pADs = NULL;
|
|||
|
ULONG i, j;
|
|||
|
ULONG cNewCatids, cOldCatids;
|
|||
|
VARIANT Var;
|
|||
|
GUID *pOldCatids=NULL, *pNewCatids;
|
|||
|
|
|||
|
// BUGBUG:: Have to decide some way of removing clsids once all categories
|
|||
|
// are unregistered.
|
|||
|
|
|||
|
if (!m_fOpen)
|
|||
|
return E_FAIL;
|
|||
|
|
|||
|
if (IsNullGuid(rclsid))
|
|||
|
return E_INVALIDARG;
|
|||
|
|
|||
|
if (cCategories == 0)
|
|||
|
return S_OK;
|
|||
|
|
|||
|
if (!IsValidPtrOut(this, sizeof(*this))) {
|
|||
|
return E_ACCESSDENIED;
|
|||
|
}
|
|||
|
|
|||
|
if (!IsValidReadPtrIn(rgcatid, sizeof(rgcatid[0])*cCategories)){
|
|||
|
return E_INVALIDARG; // gd
|
|||
|
}
|
|||
|
|
|||
|
if (cCategories == 0)
|
|||
|
return S_OK;
|
|||
|
|
|||
|
// Get all the catids corresp to this clsid.
|
|||
|
// Get the ADs interface corresponding to the clsid that is mentioned.
|
|||
|
RdnFromGUID(rclsid, szName);
|
|||
|
hr = m_ADsClassContainer->GetObject(NULL,
|
|||
|
szName,
|
|||
|
(IDispatch **)&pADs
|
|||
|
);
|
|||
|
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyListAllocGuid(pADs,
|
|||
|
impl_or_req,
|
|||
|
&cOldCatids,
|
|||
|
&pOldCatids);
|
|||
|
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
// parse through this list and delete all the catids that is part of
|
|||
|
// the user supplied list.
|
|||
|
|
|||
|
pNewCatids = (GUID *)CoTaskMemAlloc(sizeof(GUID)*cOldCatids);
|
|||
|
if (!pNewCatids)
|
|||
|
return E_OUTOFMEMORY;
|
|||
|
|
|||
|
for (i = 0, cNewCatids = 0; i < cOldCatids; i++)
|
|||
|
{
|
|||
|
for (j = 0; j < cCategories; j++)
|
|||
|
if (memcmp(&pOldCatids[i], &rgcatid[j], sizeof(GUID)) == 0)
|
|||
|
break;
|
|||
|
if (j == cCategories)
|
|||
|
pNewCatids[cNewCatids++] = pOldCatids[i];
|
|||
|
}
|
|||
|
|
|||
|
// reregister this.
|
|||
|
|
|||
|
VariantInit(&Var);
|
|||
|
hr = PackGuidArray2Variant(pNewCatids, cNewCatids, &Var);
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
if (cNewCatids)
|
|||
|
hr = pADs->Put(impl_or_req, Var);
|
|||
|
else
|
|||
|
hr = pADs->PutEx(ADS_PROPERTY_CLEAR, impl_or_req, Var);
|
|||
|
|
|||
|
RETURN_ON_FAILURE(hr);
|
|||
|
|
|||
|
VariantClear(&Var);
|
|||
|
|
|||
|
// save the data modified
|
|||
|
hr = StoreIt(pADs);
|
|||
|
pADs->Release();
|
|||
|
|
|||
|
CoTaskMemFree(pNewCatids);
|
|||
|
if (pOldCatids)
|
|||
|
CoTaskMemFree(pOldCatids);
|
|||
|
|
|||
|
return hr;
|
|||
|
} /* UnRegisterClassXXXCategories */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassImplCategories(
|
|||
|
/* [in] */ REFCLSID rclsid,
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
|
|||
|
{
|
|||
|
return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
|
|||
|
IMPL_CATEGORIES);
|
|||
|
} /* RegisterClassImplCategories */
|
|||
|
|
|||
|
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassImplCategories(
|
|||
|
/* [in] */ REFCLSID rclsid,
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
|
|||
|
{
|
|||
|
|
|||
|
return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
|
|||
|
IMPL_CATEGORIES);
|
|||
|
|
|||
|
} /* UnRegisterClassImplCategories */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::RegisterClassReqCategories(
|
|||
|
/* [in] */ REFCLSID rclsid,
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
|
|||
|
{
|
|||
|
return RegisterClassXXXCategories(rclsid, cCategories, rgcatid,
|
|||
|
REQ_CATEGORIES);
|
|||
|
|
|||
|
} /* RegisterClassReqCategories */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
HRESULT STDMETHODCALLTYPE CClassContainer::UnRegisterClassReqCategories(
|
|||
|
/* [in] */ REFCLSID rclsid,
|
|||
|
/* [in] */ ULONG cCategories,
|
|||
|
/* [size_is][in] */ CATID __RPC_FAR rgcatid[ ])
|
|||
|
{
|
|||
|
return UnRegisterClassXXXCategories(rclsid, cCategories, rgcatid,
|
|||
|
REQ_CATEGORIES);
|
|||
|
|
|||
|
} /* UnRegisterClassReqCategories */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//--------------------------------------------------------------------
|
|||
|
|