// // 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 : // 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; }