windows-nt/Source/XPSP1/NT/com/ole32/cs/cstore/csdsadm.cxx

1489 lines
41 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//
// Author: DebiM
// Date: January 97
//
//
// Class Store Administration Implementation
//
// This source file contains implementations for
// IClassAdmin interface.
//
// It uses ADs interfaces (over LDAP) to talk to an LDAP
// provider such as NTDS.
//
//---------------------------------------------------------------------
#include "cstore.hxx"
void GetCurrentUsn(LPOLESTR pStoreUsn);
//----------------------------------------------------------
// Implementation for CClassContainer
//----------------------------------------------------------
//
CClassContainer::CClassContainer()
{
m_fOpen = FALSE;
m_ADsContainer = NULL;
m_pADsClassStore = NULL;
m_ADsClassContainer = NULL;
m_ADsPackageContainer = NULL;
m_ADsCategoryContainer = NULL;
m_uRefs = 1;
StartQuery(&m_pIDBCreateCommand);
}
//
// CClassContainer implementation
//
CClassContainer::CClassContainer(LPOLESTR szStoreName,
HRESULT *phr)
{
IADs *pADs = NULL;
LPOLESTR pszName = NULL;
DWORD dwStoreVersion = 0;
*phr = S_OK;
m_fOpen = FALSE;
m_ADsContainer = NULL;
m_pADsClassStore = NULL;
m_ADsClassContainer = NULL;
m_ADsPackageContainer = NULL;
m_ADsCategoryContainer = NULL;
//
// For every interface pointer, we create a separate Query session
//
StartQuery(&m_pIDBCreateCommand);
// Bind to a Class Store Container Object
// Cache the interface pointer
//
wcscpy (m_szContainerName, szStoreName);
*phr = ADsGetObject(
szStoreName,
IID_IADsContainer,
(void **)&m_ADsContainer
);
if (!SUCCEEDED(*phr))
return;
//
// Check the Schema Version of this container
//
*phr = m_ADsContainer->QueryInterface (IID_IADs, (void **)&m_pADsClassStore);
if (!SUCCEEDED(*phr))
return;
*phr = GetPropertyDW (m_pADsClassStore, STOREVERSION, &dwStoreVersion);
if ((!SUCCEEDED(*phr)) ||
(dwStoreVersion != SCHEMA_VERSION_NUMBER))
{
*phr = CS_E_INVALID_VERSION;
return;
}
//
// Bind to the class container Object
// Cache the interface pointer
//
m_ADsClassContainer = NULL;
*phr = m_ADsContainer->GetObject(
NULL,
CLASSCONTAINERNAME,
(IDispatch **)&pADs
);
if (!SUCCEEDED(*phr))
return;
pADs->QueryInterface(IID_IADsContainer,
(void **)&m_ADsClassContainer
);
*phr = pADs->get_ADsPath(&pszName);
wcscpy (m_szClassName, pszName);
SysFreeString(pszName);
pADs->Release();
pADs = NULL;
if (!SUCCEEDED(*phr))
return;
//
// Bind to the Package container Object
// Cache the interface pointer
//
m_ADsPackageContainer = NULL;
*phr = m_ADsContainer->GetObject(
NULL,
PACKAGECONTAINERNAME,
(IDispatch **)&pADs);
if (!SUCCEEDED(*phr))
return;
pADs->QueryInterface(IID_IADsContainer,
(void **)&m_ADsPackageContainer
);
*phr = pADs->get_ADsPath(&pszName);
wcscpy (m_szPackageName, pszName);
SysFreeString(pszName);
pADs->Release();
pADs = NULL;
if (!SUCCEEDED(*phr))
return;
//
// Bind to the category container Object
// Cache the interface pointer
//
m_ADsCategoryContainer = NULL;
*phr = m_ADsContainer->GetObject(
NULL,
CATEGORYCONTAINERNAME,
(IDispatch **)&pADs);
if (!SUCCEEDED(*phr))
return;
pADs->QueryInterface(IID_IADsContainer,
(void **)&m_ADsCategoryContainer
);
pADs->Release();
pADs = NULL;
m_fOpen = TRUE;
m_uRefs = 1;
return;
}
CClassContainer::~CClassContainer(void)
{
UINT i;
EndQuery(m_pIDBCreateCommand);
m_pIDBCreateCommand = NULL;
if (m_fOpen)
{
m_fOpen = FALSE;
}
if (m_ADsClassContainer)
{
m_ADsClassContainer->Release();
m_ADsClassContainer = NULL;
}
if (m_ADsPackageContainer)
{
m_ADsPackageContainer->Release();
m_ADsPackageContainer = NULL;
}
if (m_ADsCategoryContainer)
{
m_ADsCategoryContainer->Release();
m_ADsCategoryContainer = NULL;
}
if (m_ADsContainer)
{
m_ADsContainer->Release();
m_ADsContainer = NULL;
}
if (m_pADsClassStore)
{
m_pADsClassStore->Release();
m_pADsClassStore = NULL;
}
}
//
// Removing a class from the database
//
HRESULT CClassContainer::DeleteClass (LPOLESTR szClsid)
{
WCHAR szName[_MAX_PATH];
HRESULT hr = S_OK;
IADs *pADs = NULL;
DWORD refcount = 0;
if (!m_fOpen)
return E_FAIL;
wsprintf(szName, L"CN=%s", szClsid);
hr = m_ADsClassContainer->GetObject(NULL, szName, (IDispatch **)&pADs);
if (SUCCEEDED(hr))
hr = GetPropertyDW(pADs, CLASSREFCOUNTER, &refcount);
if (refcount <= 1)
hr = m_ADsClassContainer->Delete(CLASS_CS_CLASS, szName);
else {
refcount--;
hr = SetPropertyDW(pADs, CLASSREFCOUNTER, refcount);
if (SUCCEEDED(hr))
hr = StoreIt(pADs);
}
if (pADs)
pADs->Release();
return hr;
}
extern LPOLESTR szPackageInfoColumns;
HRESULT CClassContainer::EnumPackages(
LPOLESTR pszFileExt,
GUID *pCategory,
DWORD dwAppFlags,
DWORD *pdwLocale,
CSPLATFORM *pPlatform,
IEnumPackage **ppIEnumPackage
)
{
HRESULT hr = S_OK;
CEnumPackage *pEnum = NULL;
WCHAR szCommand[1000], szQry[1000];
if (pszFileExt && IsBadStringPtr(pszFileExt, _MAX_PATH))
return E_INVALIDARG;
if (pCategory && !IsValidReadPtrIn(pCategory, sizeof(GUID)))
return E_INVALIDARG;
if (!IsValidPtrOut(ppIEnumPackage, sizeof(IEnumPackage *)))
return E_INVALIDARG;
*ppIEnumPackage = NULL;
pEnum = new CEnumPackage;
if(NULL == pEnum)
return E_OUTOFMEMORY;
//
// Create a CommandText
//
wsprintf(szCommand, L"<%s>;(& (objectClass=packageRegistration) ", m_szPackageName);
if (pszFileExt)
{
wsprintf(szQry, L"(%s=%s*) ", PKGFILEEXTNLIST, pszFileExt);
wcscat(szCommand, szQry);
}
if (pCategory)
{
STRINGGUID szCat;
StringFromGUID (*pCategory, szCat);
wsprintf(szQry, L"(%s=%s) ", PKGCATEGORYLIST, szCat);
wcscat(szCommand, szQry);
}
wcscat(szCommand, L");");
wsprintf(szQry, L" %s", szPackageInfoColumns);
wcscat(szCommand, szQry);
hr = pEnum->Initialize(szCommand, dwAppFlags, pdwLocale, pPlatform);
if (FAILED(hr)) {
delete pEnum;
return hr;
}
hr = pEnum->QueryInterface(IID_IEnumPackage, (void**)ppIEnumPackage);
return hr;
}
// GetPackageDetails
// pszPackageName : name of the package to be got.
// pInstallInfo : InstallInfo to be filled in. ignored if NULL.
// pPlatformInfo : PlatformInfo to be filled in. ignored if NULL.
// both can be sent in as NULL to check whether package exists or not.
HRESULT CClassContainer::GetPackageDetails (
LPOLESTR pszPackageName,
PACKAGEDETAIL *pPackageDetail)
{
HRESULT hr = S_OK;
IADs *pPackageADs = NULL;
WCHAR szRdn [_MAX_PATH];
if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
return E_INVALIDARG;
wcscpy (szRdn, L"CN=");
wcscat (szRdn, pszPackageName);
hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
if (!SUCCEEDED(hr))
return CS_E_PACKAGE_NOTFOUND;
hr = GetPackageDetail (pPackageADs, pPackageDetail);
return hr;
}
HRESULT CClassContainer::ChangePackageProperties(
LPOLESTR pszPackageName,
LPOLESTR pszNewName,
DWORD *pdwFlags,
LPOLESTR pszUrl,
LPOLESTR pszScriptPath,
UINT *pInstallUiLevel
)
{
HRESULT hr = S_OK;
IADs *pPackageADs = NULL;
WCHAR szRdn [_MAX_PATH];
WCHAR szNewRdn [_MAX_PATH];
LPOLESTR pszPackageDN;
WCHAR Usn[20];
if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
return E_INVALIDARG;
wcscpy (szRdn, L"CN=");
wcscat (szRdn, pszPackageName);
if (pszNewName)
{
//
// rename package
//
if (IsBadStringPtr(pszNewName, _MAX_PATH))
return E_INVALIDARG;
//
// Check to see if any other change is requested.
//
if (pszScriptPath ||
pszUrl ||
pdwFlags ||
pInstallUiLevel)
return E_INVALIDARG;
BuildADsPathFromParent (m_szPackageName, szRdn, &pszPackageDN);
wcscpy (szNewRdn, L"CN=");
wcscat (szNewRdn, pszNewName);
hr = m_ADsPackageContainer->MoveHere(pszPackageDN, szNewRdn, (IDispatch **)&pPackageADs);
FreeADsMem(pszPackageDN);
if (SUCCEEDED(hr))
{
hr = SetProperty(pPackageADs, PACKAGENAME, pszNewName);
if (SUCCEEDED(hr))
hr = StoreIt(pPackageADs);
pPackageADs->Release();
}
return hr;
}
if (!(pszScriptPath ||
pszUrl ||
pdwFlags ||
pInstallUiLevel))
return E_INVALIDARG;
//
// No rename.
// Just change some properties.
//
hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
if (!SUCCEEDED(hr))
return CS_E_PACKAGE_NOTFOUND;
//
// Update the TimeStamp
//
GetCurrentUsn(&Usn[0]);
hr = UsnUpd(pPackageADs, PKGUSN, &Usn[0]);
ERROR_ON_FAILURE(hr);
//
// Change Package Flags
//
if (pdwFlags)
{
hr = SetPropertyDW (pPackageADs, PACKAGEFLAGS, *pdwFlags);
ERROR_ON_FAILURE(hr);
}
//
// Change Package Script
//
if (pszScriptPath)
{
hr = SetProperty(pPackageADs, SCRIPTPATH, pszScriptPath);
ERROR_ON_FAILURE(hr);
}
//
// Change Package Help URL
//
if (pszUrl)
{
hr = SetProperty(pPackageADs, HELPURL, pszUrl);
ERROR_ON_FAILURE(hr);
}
//
// Change UI Level
//
if (pInstallUiLevel)
{
hr = SetPropertyDW (pPackageADs, UILEVEL, *pInstallUiLevel);
ERROR_ON_FAILURE(hr);
}
hr = StoreIt(pPackageADs);
Error_Cleanup:
pPackageADs->Release();
return hr;
}
HRESULT CClassContainer::ChangePackageCategories(
LPOLESTR pszPackageName,
UINT cCategories,
GUID *rpCategory
)
{
//
// Does not change USN
//
HRESULT hr = S_OK;
IADs *pPackageADs = NULL;
WCHAR szRdn [_MAX_PATH];
LPOLESTR *pszGuid = NULL;
UINT count;
wcscpy (szRdn, L"CN=");
wcscat (szRdn, pszPackageName);
if ((!cCategories) ||
(!rpCategory) ||
(!IsValidReadPtrIn(rpCategory, sizeof(GUID) * cCategories)))
return E_INVALIDARG;
hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
if (!SUCCEEDED(hr))
return CS_E_PACKAGE_NOTFOUND;
// fill in the categories
pszGuid = (LPOLESTR *)CoTaskMemAlloc(cCategories * sizeof(LPOLESTR));
if (!pszGuid)
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (count = 0; (count < cCategories); count++)
{
pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
StringFromGUID(rpCategory[count], pszGuid[count]);
}
hr = SetPropertyList(pPackageADs, PKGCATEGORYLIST, cCategories,
pszGuid);
ERROR_ON_FAILURE(hr);
for (count = 0; (count < cCategories); count++)
CoTaskMemFree(pszGuid[count]);
CoTaskMemFree(pszGuid);
hr = StoreIt(pPackageADs);
Error_Cleanup:
pPackageADs->Release();
return hr;
}
HRESULT CClassContainer::SetPriorityByFileExt(
LPOLESTR pszPackageName,
LPOLESTR pszFileExt,
UINT Priority
)
{
//
// Does not change USN
//
HRESULT hr = S_OK;
IADs *pPackageADs = NULL;
WCHAR szRdn [_MAX_PATH];
LPOLESTR *prgFileExt = NULL;
ULONG cShellFileExt;
UINT i;
wcscpy (szRdn, L"CN=");
wcscat (szRdn, pszPackageName);
hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
if (!SUCCEEDED(hr))
return CS_E_PACKAGE_NOTFOUND;
hr = GetPropertyListAlloc (pPackageADs, PKGFILEEXTNLIST,
&cShellFileExt,
&prgFileExt);
for (i=0; i < cShellFileExt; ++i)
{
if (wcsncmp(prgFileExt[i], pszFileExt, wcslen(pszFileExt)) == 0)
{
wsprintf(prgFileExt[i], L"%s:%2d",
pszFileExt,
Priority);
break;
}
}
if (i == cShellFileExt)
{
hr = CS_E_PACKAGE_NOTFOUND;
ERROR_ON_FAILURE(hr);
}
hr = SetPropertyList(pPackageADs, PKGFILEEXTNLIST, cShellFileExt, prgFileExt);
hr = StoreIt(pPackageADs);
Error_Cleanup:
pPackageADs->Release();
return hr;
}
extern LPOLESTR szAppCategoryColumns;
HRESULT CClassContainer::GetAppCategories (
LCID Locale,
APPCATEGORYINFOLIST *pAppCategoryList
)
{
HRESULT hr = S_OK;
WCHAR szCommand[1000], szQry[1000];
WCHAR szRootPath[_MAX_PATH],
szAppCategoryContainer[_MAX_PATH];
IRowset * pIRow = NULL;
HACCESSOR HAcc;
IAccessor * pIAccessor = NULL;
IDBCreateCommand * pIDBCreateCommand = NULL;
LPOLESTR ** ppszDesc = NULL;
DWORD cgot = 0;
if (!IsValidPtrOut(pAppCategoryList, sizeof(APPCATEGORYINFOLIST)))
return E_INVALIDARG;
hr = GetRootPath(szRootPath);
wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX,
APPCATEGORYCONTAINERNAME, szRootPath+wcslen(LDAPPREFIX));
wsprintf(szCommand, L"<%s>; (objectClass=categoryRegistration); %s", szAppCategoryContainer,
szAppCategoryColumns);
hr = StartQuery(&(pIDBCreateCommand));
RETURN_ON_FAILURE(hr);
hr = ExecuteQuery (pIDBCreateCommand,
szCommand,
APPCATEGORY_COLUMN_COUNT,
NULL,
&HAcc,
&pIAccessor,
&pIRow
);
RETURN_ON_FAILURE(hr);
pAppCategoryList->cCategory = 500;
// upper limit presently.
hr = FetchCategory(pIRow,
HAcc,
(pAppCategoryList->cCategory),
&cgot,
&(pAppCategoryList->pCategoryInfo),
Locale);
pAppCategoryList->cCategory = cgot;
CloseQuery(pIAccessor,
HAcc,
pIRow);
EndQuery(pIDBCreateCommand);
return hr;
}
HRESULT CClassContainer::RegisterAppCategory (
APPCATEGORYINFO *pAppCategory
)
{
WCHAR szRootPath[_MAX_PATH], *localedescription = NULL,
szAppCategoryContainer[_MAX_PATH], szRDN[_MAX_PATH];
HRESULT hr = S_OK;
IADsContainer *pADsContainer = NULL;
IADs *pADs = NULL;
IDispatch *pUnknown = NULL;
ULONG i, j, cdesc, posn;
LPOLESTR *pszDescExisting = NULL, *pszDesc = NULL;
if (!pAppCategory || !IsValidReadPtrIn(pAppCategory, sizeof(APPCATEGORYINFO)))
return E_INVALIDARG;
if ((pAppCategory->pszDescription == NULL) ||
IsBadStringPtr(pAppCategory->pszDescription, _MAX_PATH))
return E_INVALIDARG;
if (IsNullGuid(pAppCategory->AppCategoryId))
return E_INVALIDARG;
hr = GetRootPath(szRootPath);
// Bind to a AppCategory container
wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX,
APPCATEGORYCONTAINERNAME, szRootPath+wcslen(LDAPPREFIX));
hr = ADsGetObject(
szAppCategoryContainer,
IID_IADsContainer,
(void **)&pADsContainer
);
RETURN_ON_FAILURE(hr);
RdnFromGUID(pAppCategory->AppCategoryId, szRDN);
localedescription = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(128+16));
wsprintf(localedescription, L"%x %s %s", pAppCategory->Locale, CATSEPERATOR,
pAppCategory->pszDescription);
hr = pADsContainer->GetObject(NULL, szRDN, (IDispatch **)&pADs);
if (SUCCEEDED(hr))
{
hr = GetPropertyListAlloc (pADs, LOCALEDESCRIPTION, &cdesc, &pszDescExisting);
ERROR_ON_FAILURE(hr);
// Existing list of descriptions
pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(cdesc+1));
if ((cdesc) && (!pszDesc)) {
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (j = 0; j < cdesc; j++)
pszDesc[j] = pszDescExisting[j];
if (!(posn = FindDescription(pszDescExisting, cdesc, &(pAppCategory->Locale), 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 = pADsContainer->Create(
CLASS_CS_CATEGORY,
szRDN,
&pUnknown
);
ERROR_ON_FAILURE(hr);
pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR));
if (!pszDesc) {
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
cdesc = 1;
pszDesc[0] = localedescription;
hr = pUnknown->QueryInterface(IID_IADs, (void **)&pADs);
RETURN_ON_FAILURE(hr);
pUnknown->Release();
}
hr = SetPropertyGuid(pADs, CATEGORYCATID, pAppCategory->AppCategoryId);
ERROR_ON_FAILURE(hr);
hr = SetPropertyList(pADs, LOCALEDESCRIPTION, cdesc, pszDesc);
for (j = 0; j < cdesc; j++)
CoTaskMemFree(pszDesc[j]);
CoTaskMemFree(pszDesc);
ERROR_ON_FAILURE(hr);
hr = StoreIt(pADs);
ERROR_ON_FAILURE(hr);
Error_Cleanup:
if (pADs)
pADs->Release();
if (pADsContainer)
pADsContainer->Release();
// Add this category.
return hr;
}
HRESULT CClassContainer::UnregisterAppCategory (
GUID *pAppCategoryId
)
{
WCHAR szRootPath[_MAX_PATH], szRDN[_MAX_PATH],
szAppCategoryContainer[_MAX_PATH];
HRESULT hr = S_OK;
IADsContainer *pADsContainer = NULL;
if (!IsValidReadPtrIn(pAppCategoryId, sizeof(GUID)))
return E_INVALIDARG;
hr = GetRootPath(szRootPath);
// Bind to a AppCategory container
wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX,
APPCATEGORYCONTAINERNAME, szRootPath+wcslen(LDAPPREFIX));
hr = ADsGetObject(
szAppCategoryContainer,
IID_IADsContainer,
(void **)&pADsContainer
);
RETURN_ON_FAILURE(hr);
RdnFromGUID(*pAppCategoryId, szRDN);
hr = pADsContainer->Delete(CLASS_CS_CATEGORY, szRDN);
pADsContainer->Release();
// Delete this category
return hr;
}
//+
HRESULT CClassContainer::RemovePackage (LPOLESTR pszPackageName)
//
// Remove a Package and the associated Classes from class store
//
{
HRESULT hr = S_OK;
IADs *pADs = NULL;
DWORD cClasses = 0, count = 0;
WCHAR szRdn [_MAX_PATH];
LPOLESTR *szClasses;
if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
return E_INVALIDARG;
if ((pszPackageName == NULL) ||
(*(pszPackageName) == NULL))
return E_INVALIDARG;
wcscpy (szRdn, L"CN=");
wcscat (szRdn, pszPackageName);
if (!m_fOpen)
return E_FAIL;
hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pADs);
RETURN_ON_FAILURE(hr);
hr = GetPropertyListAlloc(pADs, PKGCLSIDLIST, &cClasses, &szClasses);
for (count = 0; count < cClasses; count++)
hr = DeleteClass(szClasses[count]);
// ignore errors
for (count = 0; count < cClasses; count++)
CoTaskMemFree(szClasses[count]);
CoTaskMemFree(szClasses);
pADs->Release();
hr = m_ADsPackageContainer->Delete(CLASS_CS_PACKAGE, szRdn);
return hr;
}
//+
HRESULT CClassContainer::NewClass (CLASSDETAIL *pClassDetail)
//
// Add a new class to the database
//
{
HRESULT hr = S_OK;
IADs * pADs = NULL;
IDispatch * pUnknown = NULL;
STRINGGUID szGUID;
WCHAR szRDN [_MAX_PATH];
if (!m_fOpen)
return E_FAIL;
//
// Cant be a NULL guid
//
if (IsNullGuid(pClassDetail->Clsid))
return E_INVALIDARG;
StringFromGUID(pClassDetail->Clsid, szGUID);
//
// Create the RDN for the Class Object
//
// BUGBUG:: attaching package name creates problems.
wsprintf(szRDN, L"CN=%s", szGUID);
hr = m_ADsClassContainer->Create(
CLASS_CS_CLASS,
szRDN,
&pUnknown
);
RETURN_ON_FAILURE(hr);
hr = pUnknown->QueryInterface(
IID_IADs,
(void **)&pADs
);
pUnknown->Release();
hr = SetProperty (pADs, CLASSCLSID, szGUID);
ERROR_ON_FAILURE(hr);
if (pClassDetail->cProgId)
{
hr = SetPropertyList(pADs, PROGIDLIST, pClassDetail->cProgId,
pClassDetail->prgProgId);
ERROR_ON_FAILURE(hr);
}
if (!IsNullGuid(pClassDetail->TreatAs))
{
StringFromGUID(pClassDetail->TreatAs, szGUID);
hr = SetProperty (pADs, TREATASCLSID, szGUID);
ERROR_ON_FAILURE(hr);
}
hr = SetPropertyDW(pADs, CLASSREFCOUNTER, 1);
ERROR_ON_FAILURE(hr);
hr = StoreIt (pADs);
// this does not return an error for an alreay existing entry.
if (hr == E_ADS_LDAP_ALREADY_EXISTS)
{
DWORD refcount = 0;
pADs->Release(); // release the interface pointer already got.
hr = m_ADsClassContainer->GetObject(NULL, // CLASS_CS_CLASS
szRDN,
(IDispatch **)&pADs);
RETURN_ON_FAILURE(hr);
if (pClassDetail->cProgId)
{
hr = SetPropertyListMerge(pADs, PROGIDLIST, pClassDetail->cProgId,
pClassDetail->prgProgId);
ERROR_ON_FAILURE(hr);
}
// increment reference counter.
hr = GetPropertyDW(pADs, CLASSREFCOUNTER, &refcount);
ERROR_ON_FAILURE(hr);
refcount++;
hr = SetPropertyDW(pADs, CLASSREFCOUNTER, refcount);
ERROR_ON_FAILURE(hr);
// No merging of the treatas.
hr = StoreIt(pADs);
}
Error_Cleanup:
pADs->Release();
return hr;
}
#define SCRIPT_IN_DIRECTORY 256
HRESULT CClassContainer::AddPackage(LPOLESTR pszPackageName,
PACKAGEDETAIL *pPackageDetail)
{
HRESULT hr;
IADs *pPackageADs = NULL;
IDispatch *pUnknown = NULL;
WCHAR szRDN [_MAX_PATH];
LPOLESTR *pszGuid, *pszProgId;
DWORD *pdwArch=NULL, count = 0, cPackProgId = 0;
WCHAR Usn[20];
if (!pszPackageName)
return E_INVALIDARG;
if (!pPackageDetail)
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail, sizeof(PACKAGEDETAIL)))
return E_INVALIDARG;
LPWSTR pName = pszPackageName;
while (*pName)
{
if ((*pName == L':') ||
(*pName == L',') ||
(*pName == L';') ||
(*pName == L'/') ||
(*pName == L'<') ||
(*pName == L'>') ||
(*pName == L'\\'))
return E_INVALIDARG;
++pName;
}
// Validating ActivationInfo
if (pPackageDetail->pActInfo)
{
if (!IsValidReadPtrIn(pPackageDetail->pActInfo, sizeof(ACTIVATIONINFO)))
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pActInfo->pClasses,
sizeof(CLASSDETAIL) * (pPackageDetail->pActInfo->cClasses)))
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgShellFileExt,
sizeof(LPOLESTR) * (pPackageDetail->pActInfo->cShellFileExt)))
return E_INVALIDARG;
for (count = 0; count < (pPackageDetail->pActInfo->cShellFileExt); count++)
{
if (!pPackageDetail->pActInfo->prgShellFileExt[count])
return E_INVALIDARG;
}
if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgPriority,
sizeof(UINT) * (pPackageDetail->pActInfo->cShellFileExt)))
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgInterfaceId,
sizeof(IID) * (pPackageDetail->pActInfo->cInterfaces)))
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgTlbId,
sizeof(GUID) * (pPackageDetail->pActInfo->cTypeLib)))
return E_INVALIDARG;
}
// Validating InstallInfo
if ((pPackageDetail->pInstallInfo == NULL) ||
(!IsValidReadPtrIn(pPackageDetail->pInstallInfo, sizeof(INSTALLINFO)))
)
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pInstallInfo->prgUpgradeFlag,
sizeof(DWORD)*(pPackageDetail->pInstallInfo->cUpgrades)))
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pInstallInfo->prgUpgradeScript,
sizeof(LPOLESTR)*(pPackageDetail->pInstallInfo->cUpgrades)))
return E_INVALIDARG;
for (count = 0; count < (pPackageDetail->pInstallInfo->cUpgrades); count++)
{
if ((!(pPackageDetail->pInstallInfo->prgUpgradeScript[count])) ||
IsBadStringPtr((pPackageDetail->pInstallInfo->prgUpgradeScript[count]), _MAX_PATH))
return E_INVALIDARG;
if ((pPackageDetail->pInstallInfo->prgUpgradeFlag[count] != UPGFLG_Uninstall) &&
(pPackageDetail->pInstallInfo->prgUpgradeFlag[count] != UPGFLG_NoUninstall))
return E_INVALIDARG;
}
// Validating PlatformInfo
if ((pPackageDetail->pPlatformInfo == NULL) ||
(!IsValidReadPtrIn(pPackageDetail->pPlatformInfo, sizeof(PLATFORMINFO)))
)
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo->prgPlatform,
sizeof(CSPLATFORM) * (pPackageDetail->pPlatformInfo->cPlatforms)))
return E_INVALIDARG;
if ((pPackageDetail->pPlatformInfo->cLocales == 0) ||
(pPackageDetail->pPlatformInfo->cPlatforms == 0))
return E_INVALIDARG;
if (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo->prgLocale,
sizeof(LCID) * (pPackageDetail->pPlatformInfo->cLocales)))
return E_INVALIDARG;
// Validating other fields in PackageDetail structure
if ((pPackageDetail->pszSourceList == NULL) ||
(!IsValidReadPtrIn(pPackageDetail->pszSourceList,
sizeof(LPOLESTR) * (pPackageDetail->cSources)))
)
return E_INVALIDARG;
for (count = 0; count < (pPackageDetail->cSources); count++)
if (!pPackageDetail->pszSourceList[count])
return E_INVALIDARG;
if (pPackageDetail->rpCategory)
{
if (!IsValidReadPtrIn(pPackageDetail->rpCategory,
sizeof(GUID) * (pPackageDetail->cCategories)))
return E_INVALIDARG;
}
//
// Now we create the package
//
wcscpy (szRDN, L"CN=");
wcscat (szRDN, pszPackageName);
pUnknown = NULL;
hr = m_ADsPackageContainer->Create(
CLASS_CS_PACKAGE,
szRDN,
&pUnknown
);
RETURN_ON_FAILURE(hr);
hr = pUnknown->QueryInterface(
IID_IADs,
(void **)&pPackageADs
);
pUnknown->Release();
// fill in the activation info
if (pPackageDetail->pActInfo)
{
if ((pPackageDetail->pActInfo)->cClasses)
{
pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cClasses)*sizeof(LPOLESTR));
if (!pszGuid)
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++)
{
pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*STRINGGUIDLEN);
StringFromGUID(pPackageDetail->pActInfo->pClasses[count].Clsid, pszGuid[count]);
cPackProgId += pPackageDetail->pActInfo->pClasses[count].cProgId;
}
hr = SetPropertyList(pPackageADs, PKGCLSIDLIST, (pPackageDetail->pActInfo)->cClasses, pszGuid);
ERROR_ON_FAILURE(hr);
for (count = 0; (count < pPackageDetail->pActInfo->cClasses); count++)
CoTaskMemFree(pszGuid[count]);
CoTaskMemFree(pszGuid);
}
// collecting all the progids from the various clsids.
if (cPackProgId)
{
pszProgId = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*cPackProgId);
if (!pszProgId)
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (count = 0, cPackProgId = 0; count < pPackageDetail->pActInfo->cClasses; count++)
{
DWORD cClassProgId = 0;
for (cClassProgId = 0; cClassProgId < pPackageDetail->pActInfo->pClasses[count].cProgId;
cClassProgId++)
{
pszProgId[cPackProgId++] =
pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId];
}
}
hr = SetPropertyList(pPackageADs, PROGIDLIST, cPackProgId, pszProgId);
CoTaskMemFree(pszProgId);
}
ERROR_ON_FAILURE(hr);
if (pPackageDetail->pActInfo->cShellFileExt)
{
//
// Store a tuple in the format <file ext>:<priority>
//
pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cShellFileExt) * sizeof(LPOLESTR));
if (!pszGuid)
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (count = 0; count < pPackageDetail->pActInfo->cShellFileExt; count++)
{
pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *
(wcslen(pPackageDetail->pActInfo->prgShellFileExt[count])+1+2+1));
// format is fileext+:+nn+NULL where nn = 2 digit priority
wsprintf(pszGuid[count], L"%s:%2d",
pPackageDetail->pActInfo->prgShellFileExt[count],
pPackageDetail->pActInfo->prgPriority[count]);
}
hr = SetPropertyList(pPackageADs, PKGFILEEXTNLIST, pPackageDetail->pActInfo->cShellFileExt, pszGuid);
for (count = 0; (count < pPackageDetail->pActInfo->cShellFileExt); count++)
CoTaskMemFree(pszGuid[count]);
CoTaskMemFree(pszGuid);
//
// Now IDS Workaround
// BUGBUG. Remove this when the DS bug is fixed. 130491 in NTDEV
//
hr = SetPropertyList(pPackageADs,
QRYFILEEXT,
pPackageDetail->pActInfo->cShellFileExt,
pPackageDetail->pActInfo->prgShellFileExt);
}
ERROR_ON_FAILURE(hr);
if (pPackageDetail->pActInfo->cInterfaces)
{
pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cInterfaces)*sizeof(LPOLESTR));
if (!pszGuid)
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++)
{
pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
if (!pszGuid[count])
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
StringFromGUID((pPackageDetail->pActInfo->prgInterfaceId)[count], pszGuid[count]);
}
hr = SetPropertyList(pPackageADs, PKGIIDLIST, pPackageDetail->pActInfo->cInterfaces,
pszGuid);
ERROR_ON_FAILURE(hr);
for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++)
CoTaskMemFree(pszGuid[count]);
CoTaskMemFree(pszGuid);
}
if (pPackageDetail->pActInfo->cTypeLib)
{
pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cTypeLib)*sizeof(LPOLESTR));
if (!pszGuid)
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (count = 0; (count < (pPackageDetail->pActInfo)->cTypeLib); count++)
{
pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
if (!pszGuid[count])
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
StringFromGUID((pPackageDetail->pActInfo->prgTlbId)[count], pszGuid[count]);
}
hr = SetPropertyList(pPackageADs, PKGTLBIDLIST, pPackageDetail->pActInfo->cTypeLib,
pszGuid);
ERROR_ON_FAILURE(hr);
for (count = 0; (count < (pPackageDetail->pActInfo->cTypeLib)); count++)
CoTaskMemFree(pszGuid[count]);
CoTaskMemFree(pszGuid);
}
}
// fill in the platforminfo
// BUGBUG::***os version
if ((pPackageDetail->pPlatformInfo)->cPlatforms)
{
pdwArch = (DWORD *)CoTaskMemAlloc(sizeof(DWORD)*
((pPackageDetail->pPlatformInfo)->cPlatforms));
for (count = 0; (count < (pPackageDetail->pPlatformInfo)->cPlatforms); count++)
UnpackPlatform (pdwArch+count, ((pPackageDetail->pPlatformInfo)->prgPlatform)+count);
hr = SetPropertyListDW (pPackageADs, ARCHLIST, (pPackageDetail->pPlatformInfo)->cPlatforms, pdwArch);
ERROR_ON_FAILURE(hr);
CoTaskMemFree(pdwArch);
}
if ((pPackageDetail->pPlatformInfo)->cLocales)
{
hr = SetPropertyListDW (pPackageADs,
LOCALEID, (pPackageDetail->pPlatformInfo)->cLocales,
(pPackageDetail->pPlatformInfo)->prgLocale);
ERROR_ON_FAILURE(hr);
}
// fill in the installinfo
hr = SetProperty(pPackageADs, PACKAGENAME, pszPackageName);
ERROR_ON_FAILURE(hr);
hr = SetPropertyDW (pPackageADs, PACKAGETYPE, (DWORD)pPackageDetail->pInstallInfo->PathType);
ERROR_ON_FAILURE(hr);
if (pPackageDetail->pInstallInfo->pszScriptPath)
{
hr = SetProperty(pPackageADs, SCRIPTPATH, pPackageDetail->pInstallInfo->pszScriptPath);
ERROR_ON_FAILURE(hr);
}
if (pPackageDetail->pInstallInfo->pszSetupCommand)
{
hr = SetProperty(pPackageADs, SETUPCOMMAND, pPackageDetail->pInstallInfo->pszSetupCommand);
ERROR_ON_FAILURE(hr);
}
if (pPackageDetail->pInstallInfo->pszUrl)
{
hr = SetProperty(pPackageADs, HELPURL, pPackageDetail->pInstallInfo->pszUrl);
ERROR_ON_FAILURE(hr);
}
GetCurrentUsn(&Usn[0]);
hr = UsnUpd(pPackageADs, PKGUSN, &Usn[0]);
ERROR_ON_FAILURE(hr);
hr = SetPropertyDW (pPackageADs, PACKAGEFLAGS, pPackageDetail->pInstallInfo->dwActFlags);
ERROR_ON_FAILURE(hr);
hr = SetPropertyDW (pPackageADs, CLASSCTX, pPackageDetail->pInstallInfo->dwComClassContext);
ERROR_ON_FAILURE(hr);
hr = SetPropertyDW (pPackageADs, VERSIONHI, pPackageDetail->pInstallInfo->dwVersionHi);
ERROR_ON_FAILURE(hr);
hr = SetPropertyDW (pPackageADs, VERSIONLO, pPackageDetail->pInstallInfo->dwVersionLo);
ERROR_ON_FAILURE(hr);
hr = SetPropertyDW (pPackageADs, SCRIPTSIZE, pPackageDetail->pInstallInfo->cScriptLen);
ERROR_ON_FAILURE(hr);
hr = SetPropertyDW (pPackageADs, UILEVEL, (DWORD)pPackageDetail->pInstallInfo->InstallUiLevel);
ERROR_ON_FAILURE(hr);
if (pPackageDetail->pInstallInfo->cUpgrades)
{
LPOLESTR *rpszUpgrades;
rpszUpgrades = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*pPackageDetail->pInstallInfo->cUpgrades);
for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
{
UINT l = wcslen(pPackageDetail->pInstallInfo->prgUpgradeScript[count]);
rpszUpgrades[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(4+l));
wsprintf(rpszUpgrades[count], L"%s:%1d",
pPackageDetail->pInstallInfo->prgUpgradeScript[count],
pPackageDetail->pInstallInfo->prgUpgradeFlag[count]);
}
hr = SetPropertyList(pPackageADs, UPGRADESCRIPTNAMES, pPackageDetail->pInstallInfo->cUpgrades,
rpszUpgrades);
ERROR_ON_FAILURE(hr);
for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
CoTaskMemFree(rpszUpgrades[count]);
CoTaskMemFree(rpszUpgrades);
}
// fill in the sources
if (pPackageDetail->cSources)
{
hr = SetPropertyList(pPackageADs, MSIFILELIST, pPackageDetail->cSources,
pPackageDetail->pszSourceList);
ERROR_ON_FAILURE(hr);
}
// fill in the categories
if (pPackageDetail->cCategories)
{
pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->cCategories) * sizeof(LPOLESTR));
if (!pszGuid)
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
for (count = 0; (count < pPackageDetail->cCategories); count++)
{
pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
if (!pszGuid[count])
{
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
StringFromGUID((pPackageDetail->rpCategory)[count], pszGuid[count]);
}
hr = SetPropertyList(pPackageADs, PKGCATEGORYLIST, pPackageDetail->cCategories,
pszGuid);
ERROR_ON_FAILURE(hr);
for (count = 0; (count < pPackageDetail->cCategories); count++)
CoTaskMemFree(pszGuid[count]);
CoTaskMemFree(pszGuid);
}
//
// Store the script in the directory
//
/*
if ((pPackageDetail->pInstallInfo->dwActFlags & SCRIPT_IN_DIRECTORY) &&
(pPackageDetail->pInstallInfo->cScriptLen))
{
if ((pPackageDetail->pInstallInfo->cScriptLen) &&
(!IsValidReadPtrIn(pPackageDetail->pInstallInfo->pScript, pPackageDetail->pInstallInfo->cScriptLen)))
return E_INVALIDARG;
SAFEARRAYBOUND size; // Get rid of 16
SAFEARRAY FAR *psa;
CHAR HUGEP *pArray=NULL;
LONG dwSLBound = 0;
LONG dwSUBound = 0;
VARIANT vData;
VariantInit(&vData);
size.cElements = pPackageDetail->pInstallInfo->cScriptLen;
size.lLbound = 0;
psa = SafeArrayCreate(VT_UI1, 1, &size);
if (!psa) {
return(E_OUTOFMEMORY);
}
hr = SafeArrayAccessData( psa, (void HUGEP * FAR *) &pArray );
RETURN_ON_FAILURE(hr);
memcpy( pArray, pPackageDetail->pInstallInfo->pScript, size.cElements );
SafeArrayUnaccessData( psa );
V_VT(&vData) = VT_ARRAY | VT_UI1;
V_ARRAY(&vData) = psa;
hr = pPackageADs->Put(PKGSCRIPT, vData);
VariantClear(&vData);
ERROR_ON_FAILURE(hr);
}
*/
hr = StoreIt(pPackageADs);
ERROR_ON_FAILURE(hr);
if (pPackageDetail->pActInfo)
{
for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++)
{
hr = NewClass((pPackageDetail->pActInfo->pClasses)+count);
ERROR_ON_FAILURE(hr);
}
}
Error_Cleanup:
pPackageADs->Release();
return hr;
}