|
|
//
// 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 */
//--------------------------------------------------------------------
|