windows-nt/Source/XPSP1/NT/com/ole32/cs/backend/catreg.cxx

430 lines
13 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// Author: ushaji
// Date: December/Jan 1996
//
//
// Providing support for Component Categories in Class Store
//
// This source file contains implementations for ICatRegister interfaces.
//
// 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 = S_OK;
HANDLE hADs = NULL;
STRINGGUID szCatid;
ULONG i, j, cdesc = 0, posn, cAttr = 0, cgot = 0;
LPOLESTR *pszDescExisting = NULL, pszDesc = NULL;
WCHAR localedescription[128+16];
// sizeof description + seperator length + locale in hex
WCHAR *szFullName = NULL, szRDN[_MAX_PATH];
LPOLESTR AttrName = {LOCALEDESCRIPTION};
ADS_ATTR_INFO *pAttrGot = NULL, pAttr[6];
BOOL fExists = TRUE;
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++)
{
wsprintf(localedescription, L"%x %s %s", rgCategoryInfo[i].lcid, CAT_DESC_DELIMITER,
rgCategoryInfo[i].szDescription);
RDNFromGUID(rgCategoryInfo[i].catid, szRDN);
BuildADsPathFromParent(m_szCategoryName, szRDN, &szFullName);
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
&hADs);
if (SUCCEEDED(hr))
{
hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttrGot, &cgot);
fExists = TRUE;
}
else {
fExists = FALSE;
PackStrToAttr(pAttr, OBJECTCLASS, CLASS_CS_CATEGORY);
cAttr++;
PackGUIDToAttr(pAttr+cAttr, CATEGORYCATID, &(rgCategoryInfo[i].catid));
cAttr++;
hr = ADSICreateDSObject(m_ADsCategoryContainer, szRDN, pAttr, cAttr);
for (j = 0; j < cAttr; j++)
FreeAttr(pAttr[j]);
cAttr = 0;
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
&hADs);
}
ERROR_ON_FAILURE(hr);
if (fExists)
{
if (cgot)
UnpackStrArrFrom(pAttrGot[0], &pszDescExisting, &cdesc);
// Existing list of descriptions
if (posn = FindDescription(pszDescExisting, cdesc, &(rgCategoryInfo[i].lcid), NULL, 0))
{ // Delete the old value
PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, pszDescExisting+(posn-1), 1, FALSE); cAttr++;
}
CoTaskMemFree(pszDescExisting);
}
pszDesc = localedescription;
PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, &pszDesc, 1, TRUE);
cAttr++;
DWORD cModified = 0;
hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
CSDBGPrint((L"After Set, hr = 0x%x", hr));
if (hr == HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS))
hr = S_OK;
ERROR_ON_FAILURE(hr);
for (j = 0; j < cAttr; j++)
FreeAttr(pAttr[j]);
cAttr = 0;
if (pAttrGot)
FreeADsMem(pAttrGot);
pAttrGot = NULL;
if (szFullName)
FreeADsMem(szFullName);
szFullName = NULL;
if (hADs)
ADSICloseDSObject(hADs);
hADs = NULL;
}
Error_Cleanup:
if (pAttrGot)
FreeADsMem(pAttrGot);
if (szFullName)
FreeADsMem(szFullName);
if (hADs)
ADSICloseDSObject(hADs);
return RemapErrorCode(hr, m_szContainerName);
} /* 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 szRDN;
ULONG i;
HRESULT hr = S_OK;
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], szRDN);
hr = ADSIDeleteDSObject(m_ADsCategoryContainer, szRDN);
}
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 = S_OK;
STRINGGUIDRDN szRDN;
HANDLE hADs = NULL;
ULONG i, j;
STRINGGUID szGUID;
ADS_ATTR_INFO pAttr[4];
DWORD cAttr = 0;
WCHAR *szFullName = NULL;
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(szRDN, L"CN=%s", szGUID);
BuildADsPathFromParent(m_szClassName, szRDN, &szFullName);
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
&hADs);
// if it didn't exist create it.
if (FAILED(hr)) {
PackStrToAttr(pAttr+cAttr, OBJECTCLASS, CLASS_CS_CLASS);
cAttr++;
PackStrToAttr(pAttr+cAttr, CLASSCLSID, szGUID);
cAttr++;
hr = ADSICreateDSObject(m_ADsClassContainer, szRDN, pAttr, cAttr);
for (i = 0; i < cAttr; i++)
FreeAttr(pAttr[i]);
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
&hADs);
ERROR_ON_FAILURE(hr);
}
for (i = 0; i < cCategories; i++)
{
DWORD cModified=0;
PackGUIDArrToAttrEx(pAttr, impl_or_req, rgcatid+i, 1, TRUE);
hr = ADSISetObjectAttributes(hADs, pAttr, 1, &cModified);
FreeAttr(pAttr[0]);
if (hr == HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS)) // we are not supposed to return error
hr = S_OK; // if the category already exists.
ERROR_ON_FAILURE(hr);
}
Error_Cleanup:
if (szFullName)
FreeADsMem(szFullName);
if (hADs)
ADSICloseDSObject(hADs);
return RemapErrorCode(hr, m_szContainerName);
} /* 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 = S_OK;
STRINGGUIDRDN szRDN;
HANDLE hADs = NULL;
ULONG i, j, cModified = 0;
WCHAR *szFullName=NULL;
ADS_ATTR_INFO pAttr[1];
// 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, szRDN);
BuildADsPathFromParent(m_szClassName, szRDN, &szFullName);
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
&hADs);
CSDBGPrint((L"After Open in unRegXXX returned 0x%x", hr));
ERROR_ON_FAILURE(hr);
// reregister this.
for (i = 0; i < cCategories; i++) {
PackGUIDArrToAttrEx(pAttr, impl_or_req, rgcatid+i, 1, FALSE);
hr = ADSISetObjectAttributes(hADs, pAttr, 1, &cModified);
FreeAttr(pAttr[0]);
// we do not want to return error if the catids are not actually present.
if ((hr == E_ADS_PROPERTY_NOT_SET) || (hr == E_ADS_PROPERTY_NOT_FOUND) ||
(hr == HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE)))
hr = S_OK;
CSDBGPrint((L"After SetObjAtt in UnRegXXX returned 0x%x", hr));
ERROR_ON_FAILURE(hr);
}
Error_Cleanup:
if (szFullName)
FreeADsMem(szFullName);
if (hADs)
ADSICloseDSObject(hADs);
return RemapErrorCode(hr, m_szContainerName);
} /* 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 */
//--------------------------------------------------------------------