|
|
//
// 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"
// utility functions
HRESULT UpdateStoreUsn(HANDLE hADs, LPOLESTR szUsn) { ADS_ATTR_INFO pAttr[1]; DWORD cModified = 0; HRESULT hr = S_OK; PackStrToAttr(pAttr, STOREUSN, szUsn); hr = ADSISetObjectAttributes(hADs, pAttr, 1, &cModified); FreeAttr(pAttr[0]); return hr; }
//----------------------------------------------------------
// Implementation for CClassContainer
//----------------------------------------------------------
//
CClassContainer::CClassContainer()
{ m_fOpen = FALSE; m_ADsContainer = NULL; m_ADsClassContainer = NULL; m_ADsPackageContainer = NULL; m_ADsCategoryContainer = NULL; m_szCategoryName = NULL; m_szPackageName = NULL; m_szClassName = NULL;
m_szPolicyName = NULL; memset (&m_PolicyId, 0, sizeof(GUID)); m_uRefs = 1; }
//---------------------------------------------------------------
//
// Function: Constructor
//
// Synopsis: Binds to the ClassStore given a class store path.
//
// Arguments:
// [in]
// szStoreName
// Class Store Path without the leading ADCS:
//
// [out]
// phr
// Sucess code.
//
// Does an ADSI bind at the class store container and matches the
// version numbers. if the version numbers match then it binds to the
// class, package and category containers and keeps the bind handles.
//----------------------------------------------------------------
CClassContainer::CClassContainer(LPOLESTR szStoreName, HRESULT *phr) { DWORD dwStoreVersion = 0; LPOLESTR AttrNames[] = {STOREVERSION, POLICYDN, POLICYNAME}; ADS_ATTR_INFO * pAttrsGot = NULL; DWORD cgot = 0, posn = 0; ADS_SEARCHPREF_INFO SearchPrefs[2]; // set the search preference to one level search
// and make the results come back in batches of size
// 20 as default.
SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL; SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[1].vValue.Integer = 20; // BUGBUG: This should be defined as a constant.
// initialising.
*phr = S_OK;
m_fOpen = FALSE; m_ADsContainer = NULL; m_ADsClassContainer = NULL; m_ADsPackageContainer = NULL; m_ADsCategoryContainer = NULL; m_szCategoryName = NULL; m_szPackageName = NULL; m_szClassName = NULL; m_szPolicyName = NULL; memset (&m_PolicyId, 0, sizeof(GUID));
// Bind to a Class Store Container Object
// Cache the interface pointer
//
wcscpy (m_szContainerName, szStoreName); *phr = ADSIOpenDSObject(m_szContainerName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &m_ADsContainer); ERROR_ON_FAILURE(*phr); //
// Check the Schema Version of this container
//
*phr = ADSIGetObjectAttributes(m_ADsContainer, AttrNames, 3, &pAttrsGot, &cgot); if ((SUCCEEDED(*phr)) && (cgot)) { posn = GetPropertyFromAttr(pAttrsGot, cgot, STOREVERSION); dwStoreVersion = 0; if (posn < cgot) { UnpackDWFrom(pAttrsGot[posn], &dwStoreVersion); } if ((!SUCCEEDED(*phr)) || (dwStoreVersion != SCHEMA_VERSION_NUMBER)) { *phr = CS_E_INVALID_VERSION; }
if (SUCCEEDED(*phr)) { LPOLESTR szPolicyPath = NULL, szPolicyName = NULL;
posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYDN); if (posn < cgot) { LPOLESTR szParentPath = NULL, szPolicyGuid = NULL; UnpackStrFrom(pAttrsGot[posn], &szPolicyPath); //
BuildADsParentPath(szPolicyPath, &szParentPath, &szPolicyGuid); if (szParentPath) FreeADsMem(szParentPath);
if (szPolicyGuid) { if (wcslen(szPolicyGuid) == 41) { // valid GUID
GUIDFromString(&szPolicyGuid[4], &m_PolicyId); } FreeADsMem(szPolicyGuid); } }
posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYNAME); if (posn < cgot) { UnpackStrAllocFrom(pAttrsGot[posn], &m_szPolicyName); } } } else { *phr = CS_E_INVALID_VERSION; } if (pAttrsGot) FreeADsMem(pAttrsGot);
ERROR_ON_FAILURE(*phr); //
// Bind to the class container Object
// Cache the interface pointer
//
// get the class container name.
BuildADsPathFromParent(m_szContainerName, CLASSCONTAINERNAME, &m_szClassName); m_ADsClassContainer = NULL; // bind to the class container.
*phr = ADSIOpenDSObject(m_szClassName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &m_ADsClassContainer); ERROR_ON_FAILURE(*phr); // set the search preference on the handle.
*phr = ADSISetSearchPreference(m_ADsClassContainer, SearchPrefs, 2); ERROR_ON_FAILURE(*phr); //
// Bind to the Package container Object
// Cache the interface pointer
//
// get the package container name.
BuildADsPathFromParent(m_szContainerName, PACKAGECONTAINERNAME, &m_szPackageName); m_ADsPackageContainer = NULL; // bind to the package container.
*phr = ADSIOpenDSObject(m_szPackageName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &m_ADsPackageContainer); ERROR_ON_FAILURE(*phr); // set the search preference.
*phr = ADSISetSearchPreference(m_ADsPackageContainer, SearchPrefs, 2); ERROR_ON_FAILURE(*phr); //
// Bind to the category container Object
// Cache the interface pointer
//
// get the category container name
BuildADsPathFromParent(m_szContainerName, CATEGORYCONTAINERNAME, &m_szCategoryName); m_ADsCategoryContainer = NULL; // bind to the category container.
*phr = ADSIOpenDSObject(m_szCategoryName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &m_ADsCategoryContainer); ERROR_ON_FAILURE(*phr); // set the search preferences.
*phr = ADSISetSearchPreference(m_ADsCategoryContainer, SearchPrefs, 2); ERROR_ON_FAILURE(*phr); m_fOpen = TRUE; m_uRefs = 1; Error_Cleanup: *phr = RemapErrorCode(*phr, m_szContainerName); return; }
CClassContainer::~CClassContainer(void) { if (m_fOpen) { m_fOpen = FALSE; } if (m_ADsClassContainer) { ADSICloseDSObject(m_ADsClassContainer); m_ADsClassContainer = NULL; } // the bind might have failed while we succeeded in getting a path.
if (m_szClassName) FreeADsMem(m_szClassName);
if (m_ADsPackageContainer) { ADSICloseDSObject(m_ADsPackageContainer); m_ADsPackageContainer = NULL; }
if (m_szPackageName) FreeADsMem(m_szPackageName); if (m_ADsCategoryContainer) { ADSICloseDSObject(m_ADsCategoryContainer); m_ADsCategoryContainer = NULL; } if (m_szCategoryName) FreeADsMem(m_szCategoryName);
if (m_ADsContainer) { ADSICloseDSObject(m_ADsContainer); m_ADsContainer = NULL; } }
// currently unused.
BOOL InvalidDSName(LPWSTR pName) {
if (wcslen(pName) >= 56) return TRUE;
while (*pName) { if ((*pName == L':') || (*pName == L',') || (*pName == L';') || (*pName == L'/') || (*pName == L'<') || (*pName == L'>') || (*pName == L'\\')|| (*pName == L'+')) return TRUE; ++pName; }
return FALSE; }
HRESULT CClassContainer::GetGPOInfo(GUID *pGPOId, LPOLESTR *pszPolicyName) { if ((!pGPOId) || (!IsValidPtrOut(pGPOId, sizeof(GUID)))) return E_INVALIDARG;
if ((!pszPolicyName) || (!IsValidPtrOut(pszPolicyName, sizeof(LPOLESTR)))) return E_OUTOFMEMORY;
memcpy(pGPOId, &m_PolicyId, sizeof(GUID));
if (m_szPolicyName) { *pszPolicyName = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(1+wcslen(m_szPolicyName))); if (!(*pszPolicyName)) return E_INVALIDARG; wcscpy(*pszPolicyName, m_szPolicyName); } else { *pszPolicyName = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*2); if (!(*pszPolicyName)) return E_OUTOFMEMORY;
(*pszPolicyName)[0] = L'\0'; } return S_OK; }
//
// Removing a class from the database
//
//---------------------------------------------------------------
//
// Function: DeleteClass
//
// Synopsis: Internal function. Deletes the clsid from the ClassContainer.
//
// UsedBy RemovePackage
//
//
// Arguments:
// [in]
// szClsid
// Stringised Clsid
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
//
// Binds to the clsid object under the class container.
// and decrements the reference count. If the reference
// count goes to zero, then it deletes the clsid.
// BUGBUG: If 2 objects try to delete it at the same
// time this might not work properly.
//----------------------------------------------------------------
HRESULT CClassContainer::DeleteClass (LPOLESTR szClsid) { WCHAR szName[_MAX_PATH], *szFullName = NULL; HRESULT hr = S_OK; DWORD refcount = 0, cgot = 0, cAttr = 1, cModified = 0; HANDLE hADs = NULL; LPOLESTR AttrName = CLASSREFCOUNTER; ADS_ATTR_INFO * pAttr = NULL; ADS_ATTR_INFO Attr; if (!m_fOpen) return E_FAIL; // constructs the fullname from the clsid and class container Name.
wsprintf(szName, L"CN=%s", szClsid); BuildADsPathFromParent(m_szClassName, szName, &szFullName); // binds to the class object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs); if (szFullName) FreeADsMem(szFullName);
ERROR_ON_FAILURE(hr);
// gets the reference count attribute.
hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttr, &cgot); if ((SUCCEEDED(hr)) && (cgot)) UnpackDWFrom(pAttr[0], (DWORD *)&refcount); if (pAttr) FreeADsMem(pAttr); if (refcount <= 1) { // Delete the object if the reference count is less than zero.
hr = ADSIDeleteDSObject(m_ADsClassContainer, szName); if (hADs) ADSICloseDSObject(hADs); } else { // Decrement the reference count and store it back.
refcount--; PackDWToAttr(&Attr, CLASSREFCOUNTER, refcount); hr = ADSISetObjectAttributes(hADs, &Attr, cAttr, &cModified); ADSICloseDSObject(hADs); FreeAttr(Attr); } Error_Cleanup: return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
//
// Function: EnumPackages
//
// Synopsis: Returns an Enumerator for all the packages that satisfies
// the query.
//
// UsedBy Add/Remove Programs
//
// Arguments:
// [in]
// pszFileExt
// FileExt that has to be queried on. ignored if NULL.
// pCategory
// Category that has to be queried on. ignored if NULL.
// dwAppFlags
// One of the APPINFO_XXX. ignored if it is APPINFO_ALL.
// pdwLocale
// Locale that has to be queried on. Ignored if NULL.
// pPlatform
// Platform that has to be queried on. Ignored if NULL.
//
// [out]
// ppIEnumPackage
// Enumerator is returned.
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
//
// Validates the inputs, Creates a EnumPackage object, makes up the
// search string made up of file extension, category.
//----------------------------------------------------------------
HRESULT CClassContainer::EnumPackages( LPOLESTR pszFileExt, GUID *pCategory, DWORD dwAppFlags, DWORD *pdwLocale, CSPLATFORM *pPlatform, IEnumPackage **ppIEnumPackage ) { HRESULT hr = S_OK; CEnumPackage *pEnum = NULL; WCHAR szfilter[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(m_PolicyId, m_szPolicyName); if(NULL == pEnum) return E_OUTOFMEMORY; //
// Create a CommandText
//
wsprintf(szfilter, L"(& (objectClass=%s) ", CLASS_CS_PACKAGE); if (pszFileExt) { wsprintf(szQry, L"(%s=%s*) ", PKGFILEEXTNLIST, pszFileExt); wcscat(szfilter, szQry); } if (pCategory) { STRINGGUID szCat; StringFromGUID (*pCategory, szCat); wsprintf(szQry, L"(%s=%s) ", PKGCATEGORYLIST, szCat); wcscat(szfilter, szQry); } wcscat(szfilter, L")"); hr = pEnum->Initialize(m_szPackageName, szfilter, dwAppFlags, pPlatform); ERROR_ON_FAILURE(hr); hr = pEnum->QueryInterface(IID_IEnumPackage, (void**)ppIEnumPackage); ERROR_ON_FAILURE(hr); return S_OK; Error_Cleanup: if (pEnum) delete pEnum; *ppIEnumPackage = NULL; return RemapErrorCode(hr, m_szContainerName); }
HRESULT CClassContainer::GetDNFromPackageName(LPOLESTR pszPackageName, LPOLESTR *szDN) { HRESULT hr = S_OK; WCHAR szfilter[_MAX_PATH]; LPOLESTR AttrNames[] = {OBJECTCLASS, PACKAGEFLAGS, OBJECTDN}; DWORD cAttr = 3; ADS_SEARCH_HANDLE hADsSearchHandle = NULL; ADS_SEARCH_COLUMN column; DWORD dwFlags = 0;
wsprintf(szfilter, L"%s=%s", PACKAGENAME, pszPackageName);
hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, AttrNames, cAttr, &hADsSearchHandle); RETURN_ON_FAILURE(hr);
for (hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle); ((SUCCEEDED(hr)) && (hr != S_ADS_NOMORE_ROWS)); hr = ADSIGetNextRow(m_ADsPackageContainer, hADsSearchHandle)) { hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, PACKAGEFLAGS, &column); if (SUCCEEDED(hr)) { UnpackDWFrom(column, &dwFlags); ADSIFreeColumn(m_ADsPackageContainer, &column); } else continue;
if ((dwFlags & ACTFLG_Orphan) || (dwFlags & ACTFLG_Uninstall)) continue;
hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, OBJECTDN, &column); if (SUCCEEDED(hr)) { UnpackStrAllocFrom(column, szDN); ADSIFreeColumn(m_ADsPackageContainer, &column); } else continue;
break;
} if (hADsSearchHandle) ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle); return hr; }
// Gets the RDN of a package given the package Guid.
HRESULT CClassContainer::BuildDNFromPackageGuid(GUID PackageGuid, LPOLESTR *szDN) { HRESULT hr = S_OK; LPOLESTR AttrName = {OBJECTDN}; WCHAR szfilter[_MAX_PATH]; ADS_SEARCH_HANDLE hADsSearchHandle = NULL; ADS_SEARCH_COLUMN column; LPWSTR EncodedGuid = NULL;
hr = ADsEncodeBinaryData((PBYTE)&PackageGuid, sizeof(GUID), &EncodedGuid);
wsprintf(szfilter, L"(%s=%s)", OBJECTGUID, EncodedGuid);
FreeADsMem(EncodedGuid);
hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, &AttrName, 1, &hADsSearchHandle);
RETURN_ON_FAILURE(hr);
hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle); if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS)) { ERROR_ON_FAILURE(hr = CS_E_PACKAGE_NOTFOUND); }
hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, AttrName, &column); ERROR_ON_FAILURE(hr);
if (SUCCEEDED(hr)) { UnpackStrAllocFrom(column, szDN); }
ADSIFreeColumn(m_ADsPackageContainer, &column);
Error_Cleanup: if (hADsSearchHandle) ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
return hr; }
HRESULT CClassContainer::GetPackageGuid(WCHAR *szRDN, GUID *pPackageGuid) { HRESULT hr = S_OK; LPOLESTR AttrName = {OBJECTGUID}; WCHAR szfilter[_MAX_PATH]; ADS_SEARCH_HANDLE hADsSearchHandle = NULL; ADS_SEARCH_COLUMN column;
hr = ADSIExecuteSearch(m_ADsPackageContainer, szRDN, &AttrName, 1, &hADsSearchHandle);
RETURN_ON_FAILURE(hr);
hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle); if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS)) { ERROR_ON_FAILURE(hr = CS_E_PACKAGE_NOTFOUND); }
hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, AttrName, &column); ERROR_ON_FAILURE(hr);
if (SUCCEEDED(hr)) UnpackGUIDFrom(column, pPackageGuid);
ADSIFreeColumn(m_ADsPackageContainer, &column);
Error_Cleanup: if (hADsSearchHandle) ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
return hr; } //---------------------------------------------------------------
//
// Function: GetPackageDetails
//
// Synopsis: Returns the PackageDetail corresponding to the PackageName.
//
// Arguments:
// [in]
// pszPackageId
// Id of the Package.
// [out]
// pPackageDetail
// PackageDetail info that is returned.
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
//
// Binds to the Package object and calls GetPackageDetail with it.
//----------------------------------------------------------------
HRESULT CClassContainer::GetPackageDetails ( LPOLESTR pszPackageName, PACKAGEDETAIL * pPackageDetail ) { HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR * szFullName = NULL; ADS_ATTR_INFO * pAttr = NULL; DWORD cgot = 0; // this can be made into a search based API. Not required for the time being.
// Should change it if perf is a big issue.
if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH)) return E_INVALIDARG;
hr = GetDNFromPackageName(pszPackageName, &szFullName); ERROR_ON_FAILURE(hr);
if (hr != S_OK) return CS_E_OBJECT_NOTFOUND; // binding to the package object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs); ERROR_ON_FAILURE(hr); // calling GetPackageDetail.
hr = GetPackageDetail (hADs, m_szClassName, pPackageDetail); ADSICloseDSObject(hADs); if (pAttr) FreeADsMem(pAttr); if (szFullName) CoTaskMemFree(szFullName); Error_Cleanup: return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
//
// Function: GetPackageDetails
//
// Synopsis: Returns the PackageDetail corresponding to the PackageName.
//
// Arguments:
// [in]
// pszPackageId
// Id of the Package.
// [out]
// pPackageDetail
// PackageDetail info that is returned.
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
//
// Binds to the Package object and calls GetPackageDetail with it.
//----------------------------------------------------------------
HRESULT CClassContainer::GetPackageDetailsFromGuid ( GUID PkgGuid, PACKAGEDETAIL *pPackageDetail ) { HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR * szFullName = NULL, szRDN[_MAX_PATH]; ADS_ATTR_INFO * pAttr = NULL; DWORD cgot = 0; // this can be made into a search based API. Not required for the time being.
// Should change it if perf is a big issue.
if (IsNullGuid(PkgGuid)) return E_INVALIDARG;
BuildDNFromPackageGuid(PkgGuid, &szFullName); ERROR_ON_FAILURE(hr);
if (hr != S_OK) return CS_E_OBJECT_NOTFOUND; // binding to the package object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs); ERROR_ON_FAILURE(hr); // calling GetPackageDetail.
hr = GetPackageDetail (hADs, m_szClassName, pPackageDetail); ADSICloseDSObject(hADs); if (pAttr) FreeADsMem(pAttr); if (szFullName) CoTaskMemFree(szFullName);
Error_Cleanup: return RemapErrorCode(hr, m_szContainerName); }
#define FREEARR(ARR, SZ) { \
DWORD curIndex; \ for (curIndex = 0; curIndex < (SZ); curIndex++) \ CoTaskMemFree((ARR)[curIndex]); \ CoTaskMemFree(ARR); \ ARR = NULL; \ } \
//---------------------------------------------------------------
//
// Function: ChangePackageUpgradeInfoIncremental
//
// Synopsis: Mark the package as upgraded by another package
//
// Arguments:
// [in]
// PackageGuid
// Package Guid to identify the package.
// szUpgradedByClassStore
// Class Store where the package that upgrades exists
// UpgradedByPackageGuid
// The Guid of the package that upgrades
// Add Add or remove the upgradedByrelation
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
// Otherwise it packs all the required attributes in the ATTR_INFO
// structure and sends it to the Directory.
//----------------------------------------------------------------
HRESULT CClassContainer::ChangePackageUpgradeInfoIncremental( GUID PackageGuid, UPGRADEINFO UpgradeInfo, DWORD OpFlags ) { HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR *szFullName=NULL, szGuid[_MAX_PATH], szUsn[20]; LPOLESTR pProp = NULL; ADS_ATTR_INFO pAttr[2]; DWORD cAttr = 0, cModified = 0, i=0; UINT len=0;
hr = BuildDNFromPackageGuid(PackageGuid, &szFullName); ERROR_ON_FAILURE(hr); // Bind to the Package Object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr);
StringFromGUID(UpgradeInfo.PackageGuid, szGuid);
len = wcslen(UpgradeInfo.szClassStore); pProp = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2+1)); // Guid size+::+length++:+flagDigit+2
wsprintf(pProp, L"%s%s%s%s%02x", UpgradeInfo.szClassStore, PKG_UPG_DELIMITER1, szGuid, PKG_UPG_DELIMITER2, UpgradeInfo.Flag%16);
PackStrArrToAttrEx(pAttr+cAttr, UPGRADESPACKAGES, &pProp, 1, OpFlags?TRUE:FALSE); cAttr++;
//
// Update the TimeStamp
//
GetCurrentUsn(szUsn); PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn); cAttr++;
hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
if (hADs) ADSICloseDSObject(hADs); // ignore it if the property already exists.
if (hr == HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS)) hr = S_OK;
for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); Error_Cleanup: if (szFullName) CoTaskMemFree(szFullName);
return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
//
// Function: ChangePackageProperties
//
// Synopsis: Change Various (most commonly changed) properties
// for a given package.
//
// Arguments:
// [in]
// PackageId
// Package Id to identify the package.
// pszNewname
// new Name for the Package. If it is being renamed
// all other changes should be NULL.
// pdwFlags
// The Deployment Flags. Should be ACTFLG_XXX
// Ignored if NULL.
// pszUrl
// Help Url for the Package. Ignored if NULL.
// pszScriptPath
// Script Path for the Package. Ignored if NULL.
// pInstallUiLevel
// The InstallationUiLevel. Ignored if NULL.
// pdwRevision
// REVISION. Ignored if NULL.
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
// Otherwise it packs all the required attributes in the ATTR_INFO
// structure and sends it to the Directory.
//----------------------------------------------------------------
HRESULT CClassContainer::ChangePackageProperties( LPOLESTR pszPackageName, LPOLESTR pszNewName, DWORD *pdwFlags, LPOLESTR pszUrl, LPOLESTR pszScriptPath, UINT *pInstallUiLevel, DWORD *pdwRevision ) { HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR *szRDN=NULL, *szFullName=NULL; WCHAR szUsn[20]; ADS_ATTR_INFO pAttr[7]; DWORD cAttr = 0, cModified = 0, i=0; if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH)) return E_INVALIDARG;
hr = GetDNFromPackageName(pszPackageName, &szFullName); ERROR_ON_FAILURE(hr);
if (hr != S_OK) return CS_E_OBJECT_NOTFOUND;
// if no properties have to be changed.
if (!(pszScriptPath || pszUrl || pdwFlags || pInstallUiLevel || pdwRevision || pszNewName)) return E_INVALIDARG;
if (pszNewName) { // rename package
WCHAR szNewRDN[_MAX_PATH]; BOOL GenerateGuid = FALSE; GUID PackageGuidId; WCHAR pszPackageNewId[_MAX_PATH], *szJunk = NULL;
if (IsBadStringPtr(pszNewName, _MAX_PATH)) return E_INVALIDARG; if (pszScriptPath || pszUrl || pdwFlags || pInstallUiLevel || pdwRevision) return E_INVALIDARG;
// see whether the new name is valid.
// GenerateGuid = InvalidDSName(pszNewName);
// see whether the newName already exists. Notice that if the same package name is
// entered it will return error.
hr = GetDNFromPackageName(pszNewName, &szJunk);
if (szJunk) CoTaskMemFree(szJunk); szJunk = NULL;
ERROR_ON_FAILURE(hr);
if (hr == S_OK) return CS_E_OBJECT_ALREADY_EXISTS; /*
packages are going to have a guid as a name and nothing else. // generate guid if required.
if (GenerateGuid) { CoCreateGuid(&PackageGuidId); StringFromGUID(PackageGuidId, pszPackageNewId); } else wcscpy(pszPackageNewId, pszNewName); // generate the new RDN
wsprintf(szNewRDN, L"CN=%s", pszPackageNewId);
BuildADsParentPath(szFullName, &szJunk, &szRDN); if (szJunk) FreeADsMem(szJunk);
hr = ADSIModifyRdn(m_ADsPackageContainer, szRDN, szNewRDN);
if (szRDN) FreeADsMem(szRDN);
ERROR_ON_FAILURE(hr);
if (szFullName) CoTaskMemFree(szFullName); szFullName = NULL;
// construct the Full Path for the Package.
BuildADsPathFromParent(m_szPackageName, szNewRDN, &szFullName); */ // Bind to the Package Object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); if (szFullName) FreeADsMem(szFullName); szFullName = NULL;
ERROR_ON_FAILURE(hr); } else { // Bind to the Package Object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr);
if (szFullName) CoTaskMemFree(szFullName); szFullName = NULL; } // Just change some properties.
//
// Update the TimeStamp
//
GetCurrentUsn(szUsn); PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn); cAttr++; //
// Change Package Flags
//
if (pdwFlags) { PackDWToAttr (pAttr+cAttr, PACKAGEFLAGS, *pdwFlags); cAttr++; } //
// Change Package Script
//
if (pszScriptPath) { PackStrToAttr(pAttr+cAttr, SCRIPTPATH, pszScriptPath); cAttr++; } //
// Change Package Help URL
//
if (pszUrl) { PackStrToAttr(pAttr+cAttr, HELPURL, pszUrl); cAttr++; } //
// Change Package UI Level.
//
if (pInstallUiLevel) { PackDWToAttr (pAttr+cAttr, UILEVEL, *pInstallUiLevel); cAttr++; } //
// Change Revision.
//
if (pdwRevision) { PackDWToAttr (pAttr+cAttr, REVISION, *pdwRevision); cAttr++; } if (pszNewName) { PackStrToAttr(pAttr+cAttr, PACKAGENAME, pszNewName); cAttr++; }
hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
if (hADs) ADSICloseDSObject(hADs); for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); if (SUCCEEDED(hr)) { //
// Update Class Store Usn
//
UpdateStoreUsn(m_ADsContainer, szUsn); } Error_Cleanup: if (szFullName) CoTaskMemFree(szFullName); return RemapErrorCode(hr, m_szContainerName); } //---------------------------------------------------------------
// Function: ChangePackageCategories
//
// Synopsis: Change (Not Add) the Categories that a package
// belongs to.
//
// Arguments:
// [in]
// pszPackageName
// Package Name to identify the package.
// cCategories
// Number of Categories.
// rpCategory
// Array of categories.
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
// Binds to the Package Object, Converts all the categories to strings
// Packs it and sends it to the DS.
//----------------------------------------------------------------
HRESULT CClassContainer::ChangePackageCategories( LPOLESTR pszPackageName, UINT cCategories, GUID *rpCategory ) { //
// Does not change USN
//
HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR *szFullName = NULL; LPOLESTR *pszGuid = NULL; UINT count; ADS_ATTR_INFO pAttr[1]; DWORD cAttr = 0, cModified = 0, i=0; if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH)) return E_INVALIDARG;
if ((cCategories) && ((!rpCategory) || (!IsValidReadPtrIn(rpCategory, sizeof(GUID) * cCategories)))) return E_INVALIDARG;
// Construct the Name of the Package Object.
GetDNFromPackageName(pszPackageName, &szFullName); ERROR_ON_FAILURE(hr);
if (hr != S_OK) return CS_E_OBJECT_NOTFOUND; hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr); // fill in the categories
pszGuid = (LPOLESTR *)CoTaskMemAlloc(cCategories * sizeof(LPOLESTR)); if (!pszGuid) { hr = E_OUTOFMEMORY; ERROR_ON_FAILURE(hr); } // convert the GUIDs to Strings.
for (count = 0; (count < cCategories); count++) { pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR)); if (!(pszGuid[count])) { FREEARR(pszGuid, count); ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); } StringFromGUID(rpCategory[count], pszGuid[count]); } // Pack it into Attribute Structure.
PackStrArrToAttr(pAttr+cAttr, PKGCATEGORYLIST, pszGuid, cCategories); cAttr++; // Set the Attribute
hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified); Error_Cleanup: if (hADs) ADSICloseDSObject(hADs); if (pszGuid) for (count = 0; (count < cCategories); count++) CoTaskMemFree(pszGuid[count]); CoTaskMemFree(pszGuid);
if (szFullName) CoTaskMemFree(szFullName);
for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
// Function: SetPriorityByFileExt
//
// Synopsis: Changes the priority of a Package corresp. to
// a file Extension.
//
// Arguments:
// [in]
// pszPackageName
// Package Name to identify the package.
// pszFileExt
// File Extension for which the priority has to be changed.
// Priority
// Priority for the Package.
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
// Binds to the Package Object, Gets the file Extensions and changes
// the priority corresponding to the File Extension.
//----------------------------------------------------------------
HRESULT CClassContainer::SetPriorityByFileExt( LPOLESTR pszPackageName, LPOLESTR pszFileExt, UINT Priority ) { HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR *szFullName=NULL; LPOLESTR *prgFileExt = NULL; WCHAR szUsn[20]; ADS_ATTR_INFO pAttr[4], *pAttrGot = NULL; DWORD cAttr = 0, cAttrGot = 0, cModified = 0, cShellFileExt = 0, i=0; LPOLESTR pAttrNames[] = {PKGFILEEXTNLIST}; // Construct the Package Name
GetDNFromPackageName(pszPackageName, &szFullName); ERROR_ON_FAILURE(hr);
if (hr != S_OK) return CS_E_OBJECT_NOTFOUND; // Bind to the Package Object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr); //
// Update the TimeStamp
//
GetCurrentUsn(szUsn); PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn); cAttr++; // get the file extensions.
hr = ADSIGetObjectAttributes(hADs, pAttrNames, 1, &pAttrGot, &cAttrGot); if ((SUCCEEDED(hr)) && (cAttrGot)) UnpackStrArrFrom(pAttrGot[0], &prgFileExt, &cShellFileExt); // Look for the given file extension.
for (i=0; i < cShellFileExt; ++i) { if (wcsncmp(prgFileExt[i], pszFileExt, wcslen(pszFileExt)) == 0) { // if the file extension is found, change the corresponding priority.
if (wcslen(prgFileExt[i]) != (wcslen(pszFileExt)+3)) continue;
wsprintf(prgFileExt[i], L"%s:%2d", pszFileExt, Priority%100); break; } } if (i == cShellFileExt) { ERROR_ON_FAILURE(hr = CS_E_OBJECT_NOTFOUND); } if (cShellFileExt) { PackStrArrToAttr(pAttr+cAttr, PKGFILEEXTNLIST, prgFileExt, cShellFileExt); cAttr++; } hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified); if (SUCCEEDED(hr)) { //
// Update Store Usn
//
UpdateStoreUsn(m_ADsContainer, szUsn); } Error_Cleanup: CoTaskMemFree(prgFileExt); if (szFullName) CoTaskMemFree(szFullName);
for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); if (pAttrGot) FreeADsMem(pAttrGot); ADSICloseDSObject(hADs); return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
// Function: ChangePackageSourceList
//
// Synopsis: Changes the priority of a Package corresp. to
// a file Extension.
//
// Arguments:
// [in]
// pszPackageName
// Package Name to identify the package.
// cSources
// Number of sources
// pszSourceList
// List of sources
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
// Binds to the Package Object, Makes the new sourcelist with the order
// maintained.
//----------------------------------------------------------------
HRESULT CClassContainer::ChangePackageSourceList( LPOLESTR pszPackageName, UINT cSources, LPOLESTR *pszSourceList ) { HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR *szFullName = NULL; UINT count; WCHAR szUsn[20]; LPOLESTR *pszPrioritySourceList = NULL; ADS_ATTR_INFO pAttr[2]; DWORD cAttr = 0, cModified = 0, i=0; if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH)) return E_INVALIDARG;
if ((!pszSourceList) || (!IsValidReadPtrIn(pszSourceList, sizeof(LPOLESTR) * cSources))) return E_INVALIDARG; for (count = 0; (count < cSources); count++) if ((!pszSourceList[count]) || (IsBadStringPtr(pszSourceList[count], _MAX_PATH))) return E_INVALIDARG;
// Construct the Name of the Package Object.
GetDNFromPackageName(pszPackageName, &szFullName); ERROR_ON_FAILURE(hr);
if (hr != S_OK) return CS_E_OBJECT_NOTFOUND; hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr);
// Local variable for adding the order to the list.
pszPrioritySourceList = (LPOLESTR *)CoTaskMemAlloc(cSources * sizeof(LPOLESTR)); if (!pszPrioritySourceList) { hr = E_OUTOFMEMORY; ERROR_ON_FAILURE(hr); }
// add the order to the list
for (count = 0; (count < cSources); count++) { pszPrioritySourceList[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(wcslen(pszSourceList[count])+ 1+1+1+NumDigits10(cSources))); if (!(pszPrioritySourceList[count])) { FREEARR(pszPrioritySourceList, count); ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); } wsprintf(pszPrioritySourceList[count], L"%d:%s", count, pszSourceList[count]); }
//
// Update the TimeStamp
//
GetCurrentUsn(szUsn); PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn); cAttr++;
// Pack it into Attribute Structure.
PackStrArrToAttr(pAttr+cAttr, MSIFILELIST, pszPrioritySourceList, cSources); cAttr++; // Set the Attribute
hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified); if (SUCCEEDED(hr)) { //
// Update Store Usn
//
UpdateStoreUsn(m_ADsContainer, szUsn); } Error_Cleanup: if (hADs) ADSICloseDSObject(hADs); for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); if (szFullName) CoTaskMemFree(szFullName);
return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
// Function: ChangePackageUpgradeList
//
// Synopsis: Changes the priority of a Package corresp. to
// a file Extension.
//
// Arguments:
// [in]
// pszPackageName
// Package Name to identify the package.
// cSources
// Number of sources
// pszSourceList
// List of sources
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
// Binds to the Package Object, Makes the new sourcelist with the order
// maintained.
//----------------------------------------------------------------
HRESULT CClassContainer::ChangePackageUpgradeList( LPOLESTR pszPackageName, UINT cUpgrades, UPGRADEINFO *prgUpgradeInfoList ) { HRESULT hr = S_OK; HANDLE hADs = NULL; WCHAR *szFullName = NULL; UINT count = 0, count1 = 0, count2 = 0; LPOLESTR *pProp = NULL, pAttrNames[2] = {UPGRADESPACKAGES, OBJECTGUID}, *rpszUpgrades = NULL; ADS_ATTR_INFO pAttr[2], *pAttrGot = NULL; DWORD cAttr = 0, cModified = 0, i=0, posn = 0, cUpgradeInfoStored = 0, cAddList = 0, cRemoveList = 0, cgot = 0; GUID PkgGuid; WCHAR szUsn[20]; UPGRADEINFO *pUpgradeInfoStored = NULL, *pAddList = NULL, *pRemoveList = NULL; if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH)) return E_INVALIDARG;
if ((cUpgrades) && ((!prgUpgradeInfoList) || (!IsValidReadPtrIn(prgUpgradeInfoList, sizeof(UPGRADEINFO) * cUpgrades)))) return E_INVALIDARG;
for (count = 0; (count < cUpgrades); count++) { if ((!(prgUpgradeInfoList[count].szClassStore)) || IsBadStringPtr((prgUpgradeInfoList[count].szClassStore), _MAX_PATH)) return E_INVALIDARG;
if (IsNullGuid(prgUpgradeInfoList[count].PackageGuid)) return E_INVALIDARG;
if (((prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) == 0) && ((prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall) == 0) && ((prgUpgradeInfoList[count].Flag & UPGFLG_UpgradedBy) == 0)) return E_INVALIDARG; }
// Construct the Name of the Package Object.
hr = GetDNFromPackageName(pszPackageName, &szFullName); ERROR_ON_FAILURE(hr); if (hr != S_OK) return CS_E_OBJECT_NOTFOUND; hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr); // get the guid and upgrade info
hr = ADSIGetObjectAttributes(hADs, pAttrNames, 2, &pAttrGot, &cgot); // Package guid
posn = GetPropertyFromAttr(pAttrGot, cgot, OBJECTGUID); if (posn < cgot) UnpackGUIDFrom(pAttrGot[posn], &PkgGuid);
// Upgrade package
posn = GetPropertyFromAttr(pAttrGot, cgot, UPGRADESPACKAGES); if (posn < cgot) UnpackStrArrFrom(pAttrGot[posn], &pProp, &cUpgradeInfoStored);
// allocating the lists
pUpgradeInfoStored = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*(cUpgradeInfoStored)); pAddList = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*(cUpgrades+cUpgradeInfoStored)); pRemoveList = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*(cUpgrades+cUpgradeInfoStored));
if ((!pUpgradeInfoStored) || (!pAddList) || (!pRemoveList)) ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
// convert the strings to upgradinfo structures.
for (count = 0; count < (cUpgradeInfoStored); count++) { WCHAR *pStr = NULL; LPOLESTR ptr = pProp[count]; UINT len = wcslen (ptr); pUpgradeInfoStored[count].szClassStore = pProp[count];
if (len <= 41) continue;
*(ptr + len - 3) = NULL; pUpgradeInfoStored[count].Flag = wcstoul(ptr+(len-2), &pStr, 16);
*(ptr + len - 3 - 36 - 2) = L'\0'; /* -GUID-'::'*/ GUIDFromString(ptr+len-3-36, &(pUpgradeInfoStored[count].PackageGuid)); }
cUpgradeInfoStored = count; // we might have skipped some.
// AddList formed.
for (count = 0; count < cUpgrades; count++) { for (count1 = 0; count1 < cUpgradeInfoStored; count1++) { // ignore flag changes
if ((wcscmp(pUpgradeInfoStored[count1].szClassStore, prgUpgradeInfoList[count].szClassStore) == 0) && (memcmp(&pUpgradeInfoStored[count1].PackageGuid, &prgUpgradeInfoList[count].PackageGuid, sizeof(GUID)) == 0)) break; }
if (count1 == cUpgradeInfoStored) pAddList[cAddList++] = prgUpgradeInfoList[count]; }
// remove list formed.
for (count1 = 0; count1 < cUpgradeInfoStored; count1++) { for (count = 0; count < cUpgrades; count++) { // ignore flag changes
if ((wcscmp(pUpgradeInfoStored[count1].szClassStore, prgUpgradeInfoList[count].szClassStore) == 0) && (memcmp(&pUpgradeInfoStored[count1].PackageGuid, &prgUpgradeInfoList[count].PackageGuid, sizeof(GUID)) == 0)) break; }
if (count == cUpgrades) pRemoveList[cRemoveList++] = pUpgradeInfoStored[count]; }
for (count = 0; count < cAddList; count++) { // in case of UpgradedBy do no try to fix up the links.
if (!(pAddList[count].Flag & UPGFLG_UpgradedBy)) { DWORD Flags = 0; if (pAddList[count].Flag & UPGFLG_Enforced) Flags = UPGFLG_Enforced; } }
for (count = 0; count < cRemoveList; count++) { // in case of UpgradedBy do no try to fix up the links.
if (!(pRemoveList[count].Flag & UPGFLG_UpgradedBy)) { DWORD Flags = 0; if (pRemoveList[count].Flag & UPGFLG_Enforced) Flags = UPGFLG_Enforced; } }
rpszUpgrades = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*cUpgrades); if (!rpszUpgrades) ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; (count < cUpgrades); count++) { WCHAR szPackageGuid[_MAX_PATH]; UINT len = wcslen(prgUpgradeInfoList[count].szClassStore);
rpszUpgrades[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2)); // Guid size+::+length++:+flagDigit+2
if (!rpszUpgrades[count]) { FREEARR(rpszUpgrades, count); ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); }
StringFromGUID(prgUpgradeInfoList[count].PackageGuid, szPackageGuid); wsprintf(rpszUpgrades[count], L"%s%s%s%s%02x", prgUpgradeInfoList[count].szClassStore, PKG_UPG_DELIMITER1, szPackageGuid, PKG_UPG_DELIMITER2, prgUpgradeInfoList[count].Flag%16); }
PackStrArrToAttr(pAttr+cAttr, UPGRADESPACKAGES, rpszUpgrades, cUpgrades); cAttr++;
//
// Update the TimeStamp
//
GetCurrentUsn(szUsn); PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn); cAttr++; // Set the Attribute
hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified); if (SUCCEEDED(hr)) { //
// Update Store Usn
//
UpdateStoreUsn(m_ADsContainer, szUsn); } Error_Cleanup: if (hADs) ADSICloseDSObject(hADs);
if (szFullName) CoTaskMemFree(szFullName); for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]);
if (pAttrGot) FreeADsMem(pAttrGot);
if (pProp) CoTaskMemFree(pProp);
if (pUpgradeInfoStored) CoTaskMemFree(pUpgradeInfoStored); if (pAddList) CoTaskMemFree(pAddList); if (pRemoveList) CoTaskMemFree(pRemoveList);
return RemapErrorCode(hr, m_szContainerName); }
extern LPOLESTR szAppCategoryColumns;
//---------------------------------------------------------------
// Function: GetAppCategories
//
// Synopsis: gets the list of Package Categories in the Domain.
//
// Arguments:
// [in]
// Locale
// Locale for the categories. Used to get the description.
// [out]
// pAppCategoryList
// the list of Application Categories in the domain
//
// Returns:
// S_OK, E_OUTOFMEMORY, CS_E_XXX
//
// Gets the FullName of the Domain, binds to the AppCategory container
// below that. and gets all the categories with approp. types.
//----------------------------------------------------------------
HRESULT CClassContainer::GetAppCategories ( LCID Locale, APPCATEGORYINFOLIST *pAppCategoryList ) { HRESULT hr = S_OK; WCHAR szfilter[_MAX_PATH]; WCHAR szRootPath[_MAX_PATH], szAppCategoryContainer[_MAX_PATH]; HANDLE hADs = NULL; ADS_SEARCH_HANDLE hADsSearchHandle = NULL; ADS_SEARCHPREF_INFO SearchPrefs[2]; // set the search preference.
SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL; // we do not expect too many categories
SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[1].vValue.Integer = 20; if (!IsValidPtrOut(pAppCategoryList, sizeof(APPCATEGORYINFOLIST))) return E_INVALIDARG; // get the name of the domain.
hr = GetRootPath(szRootPath); ERROR_ON_FAILURE(hr); // Names returned by GetRootPath are in only 1 format and we don't need to
// use BuildADsPath.
wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME, szRootPath+LDAPPREFIXLENGTH); wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CATEGORY); //binds to the category container
hr = ADSIOpenDSObject(szAppCategoryContainer, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr); hr = ADSISetSearchPreference(hADs, SearchPrefs, 2); ERROR_ON_FAILURE(hr); // gets a search handle
hr = ADSIExecuteSearch(hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &hADsSearchHandle); ERROR_ON_FAILURE(hr); // tries to find out the number of categories.
pAppCategoryList->cCategory = 0; for (hr = ADSIGetFirstRow(hADs, hADsSearchHandle); ((SUCCEEDED(hr)) && (hr != S_ADS_NOMORE_ROWS)); hr = ADSIGetNextRow(hADs, hADsSearchHandle)) pAppCategoryList->cCategory++; // get the number of elements.
pAppCategoryList->pCategoryInfo = (APPCATEGORYINFO *)CoTaskMemAlloc( sizeof(APPCATEGORYINFO)* pAppCategoryList->cCategory); if (!(pAppCategoryList->pCategoryInfo)) { pAppCategoryList->cCategory = 0; ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); } // if it has come till here, it has to have a search handle
ADSICloseSearchHandle(hADs, hADsSearchHandle); hADsSearchHandle = NULL;
memset(pAppCategoryList->pCategoryInfo, 0, sizeof(APPCATEGORYINFO)*pAppCategoryList->cCategory);
// gets a search handle
hr = ADSIExecuteSearch(hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &hADsSearchHandle); ERROR_ON_FAILURE(hr);
// passes the search handle and gets the categorylist.
hr = FetchCategory(hADs, hADsSearchHandle, pAppCategoryList, Locale); ERROR_ON_FAILURE(hr); Error_Cleanup: if (hADsSearchHandle) ADSICloseSearchHandle(hADs, hADsSearchHandle);
if (hADs) ADSICloseDSObject(hADs); return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
// Function: RegisterAppCategory
//
// Synopsis: Adda category and assoc desc. for the whole Domain(This is per domain
// and not per class store.)
//
// Arguments:
// [in]
// pAppCategory
// Pointer to a APPCATEGORYINFO structure to be added.
//
// Returns:
// S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
//
// Finds the root path of the domain. binds to the category container
// underneath it. deletes this particular AppCategory.
//----------------------------------------------------------------
HRESULT CClassContainer::RegisterAppCategory ( APPCATEGORYINFO *pAppCategory ) { WCHAR szRootPath[_MAX_PATH], localedescription[128+16], szAppCategoryContainer[_MAX_PATH], szRDN[_MAX_PATH], * szFullName = NULL, szAppCatid[_MAX_PATH];
HRESULT hr = S_OK; HANDLE hADsContainer = NULL, hADs = NULL; ULONG i, j, cdesc = 0, posn = 0; LPOLESTR * pszDescExisting = NULL, pszDesc = NULL; LPOLESTR AttrName = LOCALEDESCRIPTION; ADS_ATTR_INFO * pAttrGot = NULL, pAttr[6]; DWORD cgot = 0, cAttr = 0; BOOL fExists = TRUE; 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; // get the name of the root of the domain
hr = GetRootPath(szRootPath); ERROR_ON_FAILURE(hr); // Bind to a AppCategory container
// Names returned by GetRootPath are in only 1 format and we don't need to
// use BuildADsPath.
wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME, szRootPath+LDAPPREFIXLENGTH); // container is supposed to exist.
hr = ADSIOpenDSObject(szAppCategoryContainer, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADsContainer); ERROR_ON_FAILURE(hr);
RDNFromGUID(pAppCategory->AppCategoryId, szRDN); wsprintf(localedescription, L"%x %s %s", pAppCategory->Locale, CAT_DESC_DELIMITER, pAppCategory->pszDescription); BuildADsPathFromParent(szAppCategoryContainer, szRDN, &szFullName); // BUGBUG:: ADS_FAST_BIND and the create seems to be going twice. why?
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); if (SUCCEEDED(hr)) hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttrGot, &cgot);
if (SUCCEEDED(hr)) { fExists = TRUE; } else { fExists = FALSE; PackStrToAttr(pAttr, OBJECTCLASS, CLASS_CS_CATEGORY); cAttr++; PackGUIDToAttr(pAttr+cAttr, CATEGORYCATID, &(pAppCategory->AppCategoryId)); cAttr++; hr = ADSICreateDSObject(hADsContainer, szRDN, pAttr, cAttr); for (j = 0; j < cAttr; j++) FreeAttr(pAttr[j]); cAttr = 0; if (hADs) { ADSICloseDSObject(hADs); hADs = NULL; } hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); } if (szFullName) FreeADsMem(szFullName); ERROR_ON_FAILURE(hr); if (fExists) { if (cgot) { UnpackStrArrFrom(pAttrGot[0], &pszDescExisting, &cdesc); } // Existing list of descriptions
if (posn = FindDescription(pszDescExisting, cdesc, &(pAppCategory->Locale), 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; hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified); Error_Cleanup: if (pAttrGot) FreeADsMem(pAttrGot); for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); if (hADs) ADSICloseDSObject(hADs); if (hADsContainer) ADSICloseDSObject(hADsContainer); return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
// Function: UnregisterAppCategory
//
// Synopsis: Removes a category from the whole Domain(This is per domain)
// and not per class store.
//
// Arguments:
// [in]
// pAppCategoryId
// Pointer to a GUID that has to be removed.
//
// Returns:
// S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
//
// Finds the root path of the domain. binds to the category container
// underneath it. deletes this particular AppCategory.
//----------------------------------------------------------------
HRESULT CClassContainer::UnregisterAppCategory ( GUID *pAppCategoryId ) { WCHAR szRootPath[_MAX_PATH], szRDN[_MAX_PATH], szAppCategoryContainer[_MAX_PATH]; HRESULT hr = S_OK; HANDLE hADs = NULL; if (!IsValidReadPtrIn(pAppCategoryId, sizeof(GUID))) return E_INVALIDARG; hr = GetRootPath(szRootPath); // Bind to a AppCategory container
// Names returned by GetRootPath are in only 1 format and we don't need to
// use BuildADsPath.
wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME, szRootPath+LDAPPREFIXLENGTH); hr = ADSIOpenDSObject(szAppCategoryContainer, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr); RDNFromGUID(*pAppCategoryId, szRDN); hr = ADSIDeleteDSObject(hADs, szRDN); ADSICloseDSObject(hADs); // Delete this category
Error_Cleanup: return RemapErrorCode(hr, m_szContainerName); }
//---------------------------------------------------------------
// Function: DeletePackage
//
// Synopsis: Permanently remove a package and the associated Classes
// from class store
//
// Arguments:
// [in]
// PackageGuid
// Guid of the package that has to be removed.
//
// Returns:
// S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
//
// Deletes the package and all the clsids associated with the
// package (using DeleteClass) Ignores the error from DeleteClass
// Tries to delete all the upgrade relationships from this package.
// Errors are ignored.
//----------------------------------------------------------------
HRESULT CClassContainer::DeletePackage (LPOLESTR szFullName ) { HRESULT hr = S_OK; DWORD cStr = 0, count = 0, cgot = 0, posn = 0; LPOLESTR szRDN = NULL, szJunk = NULL; LPOLESTR * szStr = NULL; LPOLESTR pAttrName[] = {PKGCLSIDLIST, UPGRADESPACKAGES, OBJECTGUID}; ADS_ATTR_INFO * pAttr = NULL; HANDLE hADs = NULL; WCHAR szUsn[20]; GUID PackageGuid;
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); if (!SUCCEEDED(hr)) return hr; GetCurrentUsn(szUsn); hr = ADSIGetObjectAttributes(hADs, pAttrName, 3, &pAttr, &cgot);
memset(&PackageGuid, 0, sizeof(GUID)); posn = GetPropertyFromAttr(pAttr, cgot, OBJECTGUID); if (posn < cgot) UnpackGUIDFrom(pAttr[posn], &PackageGuid);
posn = GetPropertyFromAttr(pAttr, cgot, PKGCLSIDLIST); if (posn < cgot) UnpackStrArrFrom(pAttr[posn], &szStr, &cStr);
for (count = 0; count < cStr; count++) { if (wcslen(szStr[count]) > (STRINGGUIDLEN-1)) szStr[count][STRINGGUIDLEN-1] = L'\0'; hr = DeleteClass(szStr[count]); }
if (szStr) CoTaskMemFree(szStr); szStr = NULL; cStr = 0;
posn = GetPropertyFromAttr(pAttr, cgot, UPGRADESPACKAGES); if (posn < cgot) UnpackStrArrFrom(pAttr[posn], &szStr, &cStr);
for (count = 0; count < cStr; count++) { GUID UpgradeeGuid; WCHAR *pStr = NULL; LPOLESTR ptr = szStr[count]; UINT len = wcslen (ptr); DWORD UpgradeFlag, Flags = 0;
if (len <= 41) continue;
*(ptr + (len - 3)) = NULL; UpgradeFlag = wcstoul(ptr+(len-2), &pStr, 16);
*(ptr + (len - 3 - 36 - 2)) = L'\0'; /* -GUID-'::'*/ GUIDFromString(ptr+len-3-36, &UpgradeeGuid); if (UpgradeFlag & UPGFLG_Enforced) Flags = UPGFLG_Enforced;
} if (szStr) CoTaskMemFree(szStr); szStr = NULL; cStr = 0;
// ignore errors
if (pAttr) FreeADsMem(pAttr); ADSICloseDSObject(hADs); BuildADsParentPath(szFullName, &szJunk, &szRDN); if (szJunk) FreeADsMem(szJunk);
hr = ADSIDeleteDSObject(m_ADsPackageContainer, szRDN); if (szRDN) FreeADsMem(szRDN);
if (SUCCEEDED(hr)) { //
// Update Store Usn
//
UpdateStoreUsn(m_ADsContainer, szUsn); } return hr; }
//---------------------------------------------------------------
// Function: RemovePackage
//
// Synopsis: Mark a package as disabled or orphaned
// Or permanently remove a package and the associated Classes
// from class store
//
// Arguments:
// [in]
// PackageGuid
// Guid of the package that has to be removed.
// [in]
// dwFlags
// The new flags for the package. To delete the package explicitly
// use flag zero or orphan.
//
// Returns:
// S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
//
// Calls Delete package if the flags is zero or Orphan.
// Otherwise it sets the new flags and stamps the new time stamp.
//----------------------------------------------------------------
HRESULT CClassContainer::RemovePackage ( LPOLESTR pszPackageName, DWORD dwFlags ) { HRESULT hr = S_OK; WCHAR *szRDN = NULL, *szFullName = NULL; HANDLE hADs = NULL; WCHAR szUsn[20]; ADS_ATTR_INFO pAttr[7]; DWORD cAttr = 0, cModified = 0, i=0;
if ((dwFlags != 0) && (dwFlags != ACTFLG_Orphan) && (dwFlags != ACTFLG_Uninstall)) return E_INVALIDARG; hr = GetDNFromPackageName(pszPackageName, &szFullName); ERROR_ON_FAILURE(hr);
if (hr != S_OK) return CS_E_OBJECT_NOTFOUND;
if (dwFlags == 0) // delete the package from the class store
{ hr = DeletePackage(szFullName); } else { GUID NewPackageId; WCHAR szNewRDN[_MAX_PATH], *szRDN = NULL, *szJunk = NULL; //
// PackageName is unchanged.
//
GetCurrentUsn(szUsn);
/*
CoCreateGuid(&NewPackageId); RDNFromGUID(NewPackageId, szNewRDN);
BuildADsParentPath(szFullName, &szJunk, &szRDN); if (szJunk) FreeADsMem(szJunk);
hr = ADSIModifyRdn(m_ADsPackageContainer, szRDN, szNewRDN); if (szRDN) FreeADsMem(szRDN);
ERROR_ON_FAILURE(hr); // construct the Full Path for the Package.
BuildADsPathFromParent(m_szPackageName, szNewRDN, &szFullName); */ // Bind to the Package Object.
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs); ERROR_ON_FAILURE(hr);
// setting the flag as orphan/uninstall
PackDWToAttr (pAttr+cAttr, PACKAGEFLAGS, dwFlags); cAttr++;
// stamping the modification time for cleanup later.
PackStrToAttr (pAttr+cAttr, PKGUSN, szUsn); cAttr++;
hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
if (hADs) ADSICloseDSObject(hADs);
for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); if (SUCCEEDED(hr)) { //
// Update Class Store Usn
//
UpdateStoreUsn(m_ADsContainer, szUsn); } } Error_Cleanup: if (szFullName) CoTaskMemFree(szFullName);
return RemapErrorCode(hr, m_szContainerName); }
// Merges list1 and List2 into ResList removing duplicates.
HRESULT MergePropList(LPOLESTR *List1, DWORD cList1, LPOLESTR *List2, DWORD cList2, LPOLESTR **ResList,DWORD *cResList) { DWORD i, j; *cResList = 0; *ResList = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(cList1+cList2)); if (!*ResList) return E_OUTOFMEMORY;
for (i = 0; i < cList1; i++) (*ResList)[i] = List1[i]; for (i = 0; i < cList2; i++) { for (j = 0; j < cList1; j++) if (wcscmp((*ResList)[j], List2[i]) == 0) break; if (j == cList1) (*ResList)[(*cResList)++] = List2[i]; }
return S_OK; }
//---------------------------------------------------------------
// Function: NewClass
//
// Synopsis: Adds classes corresp. to a package under the DS.
// Called by AddPackage.
//
// Arguments:
// [in]
// pClassDetail
// Class Detail of the clsid that needs to be added.
// Validation is specified in class store doc.
//
// Returns:
// S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
//
// Validates the classdetail structure. If the clsid already exists in
// the DS, it adds these values under the same clsid and increases the refcount.
//----------------------------------------------------------------
HRESULT CClassContainer::NewClass (CLASSDETAIL *pClassDetail) { HRESULT hr = S_OK; STRINGGUID szGUID1, szGUID2; WCHAR szRDN [_MAX_PATH], * szFullName = NULL; ADS_ATTR_INFO pAttr[6], *pAttrsGot = NULL; BOOL fExists = FALSE; HANDLE hADs = NULL; LPOLESTR AttrNames[] = {PKGFILEEXTNLIST, PROGIDLIST, CLASSREFCOUNTER}; DWORD posn = 0, cProp = 0, cPropMerged = 0, refcount = 0, cAttr = 0, cModified = 0, cgot = 0, i; LPOLESTR * pszProp = NULL, *pszPropMerged = NULL; if (!m_fOpen) return E_FAIL; //
// Cant be a NULL guid
//
if (IsNullGuid(pClassDetail->Clsid)) return E_INVALIDARG;
// Not using RDNFrom GUID b'cos szGUID1 is used below
StringFromGUID(pClassDetail->Clsid, szGUID1); wsprintf(szRDN, L"CN=%s", szGUID1); BuildADsPathFromParent(m_szClassName, szRDN, &szFullName); hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs); if (SUCCEEDED(hr)) { fExists = TRUE; hr = ADSIGetObjectAttributes(hADs, AttrNames, 3, &pAttrsGot, &cgot); } // BUGBUG :: bug in adsldpc doesn't return error in open.
if (!SUCCEEDED(hr)) fExists = FALSE; //
// Create the RDN for the Class Object
//
if (!fExists) { PackStrToAttr(pAttr+cAttr, OBJECTCLASS, CLASS_CS_CLASS); cAttr++; PackStrToAttr(pAttr+cAttr, CLASSCLSID, szGUID1); cAttr++; } if (pClassDetail->cProgId) { if (fExists) posn = GetPropertyFromAttr(pAttrsGot, cgot, PROGIDLIST); if (posn < cgot) UnpackStrArrFrom(pAttrsGot[posn], &pszProp, &cProp); // we can not just append b'cos duplicate values are valid conditions.
MergePropList(pszProp, cProp, pClassDetail->prgProgId, pClassDetail->cProgId, &pszPropMerged, &cPropMerged); PackStrArrToAttr(pAttr+cAttr, PROGIDLIST, pszPropMerged, cPropMerged); cAttr++; CoTaskMemFree(pszPropMerged); pszPropMerged = NULL; cPropMerged = 0; CoTaskMemFree(pszProp); pszProp = NULL; cProp = 0; } if (!IsNullGuid(pClassDetail->TreatAs)) { StringFromGUID(pClassDetail->TreatAs, szGUID2); PackStrToAttr(pAttr+cAttr, TREATASCLSID, szGUID2); cAttr++; } // this is going to be modified if find that an entry already exists.
if (fExists) { posn = GetPropertyFromAttr(pAttrsGot, cgot, CLASSREFCOUNTER); if (posn < cgot) { UnpackDWFrom(pAttrsGot[posn], &refcount); } } refcount++; PackDWToAttr(pAttr+cAttr, CLASSREFCOUNTER, refcount); cAttr++; if (fExists) hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified); else hr = ADSICreateDSObject(m_ADsClassContainer, szRDN, pAttr, cAttr); if (pAttrsGot) FreeADsMem(pAttrsGot); if (szFullName) FreeADsMem(szFullName); for (i = 0; i < cAttr; i++) FreeAttr(pAttr[i]); return RemapErrorCode(hr, m_szContainerName); }
#define SCRIPT_IN_DIRECTORY 256
//---------------------------------------------------------------
// Function: AddPackage
//
// Synopsis: Adds a package object in the DS.
//
// Arguments:
// [out]
// pszPackageId
// An Id that is returned corresponding to the package.
// [in]
// pPackageDetail
// Pointer to a PACKAGEDETAIL info for this package
// The various validations that is done is documented
// in associated class store doc.
//
// Returns:
// S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
//
// Validates the packagedetail structure. Packs ADS_ATTR_INFO structure with
// the values and tries to create the object in the DS.
// Calls NewClass to add all the clsids after that.
// If this returns error
// the whole package is removed.
//----------------------------------------------------------------
HRESULT CClassContainer::AddPackage ( PACKAGEDETAIL *pPackageDetail, GUID *pPkgGuid ) { HRESULT hr = S_OK; WCHAR szRDN [_MAX_PATH]; LPOLESTR * pszGuid1 = NULL, *pszGuid2 = NULL, * pszGuid3 = NULL, *pszGuid4 = NULL, * pszProgId = NULL, *pszFileExt = NULL, * rpszUpgrades = NULL, *rpszSources = NULL, szPackageId = NULL, szJunk = NULL;
DWORD * pdwArch=NULL, count = 0, cPackProgId = 0; ADS_ATTR_INFO pAttr[29]; DWORD cAttr = 0; WCHAR szUsn[20]; BOOL fPackageCreated = FALSE, GenerateGuid = FALSE; GUID PackageGuidId; if ((!pPkgGuid) || !IsValidReadPtrIn(pPkgGuid, sizeof(GUID))) return E_INVALIDARG;
if ((!(pPackageDetail->pszPackageName)) || IsBadStringPtr((pPackageDetail->pszPackageName), _MAX_PATH)) return E_INVALIDARG;
if (!pPackageDetail) return E_INVALIDARG; if (!IsValidReadPtrIn(pPackageDetail, sizeof(PACKAGEDETAIL))) return E_INVALIDARG; // 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;
// validating classdetail
for (count = 0; (count < (pPackageDetail->pActInfo->cClasses)); count++) { CLASSDETAIL *pClassDetail = (pPackageDetail->pActInfo->pClasses)+count; if (IsNullGuid(pClassDetail->Clsid)) return E_INVALIDARG;
for (DWORD count1 = 0; (count1 < (pClassDetail->cProgId)); count1++) { // if profid is NULL or an empty string.
if ((!((pClassDetail->prgProgId)[count1])) || (!((pClassDetail->prgProgId)[count1][0]))) 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
// BUGBUG:: Validate ProductCode, Mvipc
if ((pPackageDetail->pInstallInfo == NULL) || (!IsValidReadPtrIn(pPackageDetail->pInstallInfo, sizeof(INSTALLINFO))) ) return E_INVALIDARG; if (!IsValidReadPtrIn(pPackageDetail->pInstallInfo->prgUpgradeInfoList, sizeof(UPGRADEINFO)*(pPackageDetail->pInstallInfo->cUpgrades))) return E_INVALIDARG; for (count = 0; count < (pPackageDetail->pInstallInfo->cUpgrades); count++) { if ((!(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore)) || IsBadStringPtr((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore), _MAX_PATH)) return E_INVALIDARG;
if (IsNullGuid(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].PackageGuid)) return E_INVALIDARG;
if (((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) == 0) && ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall) == 0) && ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_UpgradedBy) == 0)) 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 InstallInfo
// 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]) || (IsBadStringPtr(pPackageDetail->pszSourceList[count], _MAX_PATH))) return E_INVALIDARG; } if (pPackageDetail->rpCategory) { if (!IsValidReadPtrIn(pPackageDetail->rpCategory, sizeof(GUID) * (pPackageDetail->cCategories))) return E_INVALIDARG; }
// If the restrictions are too constrictive then we should go to
// the DS, to see whether it is a valid name or not. till then..
// GenerateGuid = InvalidDSName(pPackageDetail->pszPackageName);
hr = GetDNFromPackageName(pPackageDetail->pszPackageName, &szJunk); if (szJunk) CoTaskMemFree(szJunk);
if (FAILED(hr)) return RemapErrorCode(hr, m_szContainerName);
if (hr == S_OK) { return CS_E_OBJECT_ALREADY_EXISTS; }
/* szPackageId = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(GenerateGuid?41:
(wcslen(pPackageDetail->pszPackageName)+1))); */
szPackageId = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*41);
if (!(szPackageId)) return E_OUTOFMEMORY;
memset(&PackageGuidId, 0, sizeof(GUID)); /*
if (GenerateGuid) { CoCreateGuid(&PackageGuidId); StringFromGUID(PackageGuidId, szPackageId); } else wcscpy(szPackageId, pPackageDetail->pszPackageName); */ // always generate guid
CoCreateGuid(&PackageGuidId); StringFromGUID(PackageGuidId, szPackageId);
//
// Create the RDN for the Package Object
//
wsprintf(szRDN, L"CN=%s", szPackageId);
PackStrToAttr(pAttr+cAttr, OBJECTCLASS, CLASS_CS_PACKAGE); cAttr++; // fill in the activation info
// add the class to the packagecontainer list
if (pPackageDetail->pActInfo) { if (pPackageDetail->pActInfo->cClasses) { pszGuid1 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cClasses)*sizeof(LPOLESTR)); if (!pszGuid1) { ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); } for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++) { WCHAR szCtx[9];
pszGuid1[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(STRINGGUIDLEN+9)); if (!pszGuid1[count]) { FREEARR(pszGuid1, count); ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); }
StringFromGUID(pPackageDetail->pActInfo->pClasses[count].Clsid, pszGuid1[count]); wsprintf(szCtx, L":%8x", pPackageDetail->pActInfo->pClasses[count].dwComClassContext); wcscat(pszGuid1[count], szCtx); cPackProgId += pPackageDetail->pActInfo->pClasses[count].cProgId; } PackStrArrToAttr(pAttr+cAttr, PKGCLSIDLIST, pszGuid1, pPackageDetail->pActInfo->cClasses); cAttr++; } // collecting all the progids from the various clsids.
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++) { // for each clsid
DWORD cClassProgId, j = 0; for (cClassProgId = 0; cClassProgId < pPackageDetail->pActInfo->pClasses[count].cProgId; cClassProgId++) { // for each progid within ClassDetail
for (j = 0; j < cPackProgId; j++) { if (_wcsicmp(pszProgId[j], pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId]) == 0) break; } // needs to be added if there are no dups.
if (j == cPackProgId) { pszProgId[cPackProgId] = pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId]; _wcslwr(pszProgId[cPackProgId]); CSDBGPrint((L"AddPackage: Progid = %s\n", pszProgId[cPackProgId])); cPackProgId++; } } } if (cPackProgId) { PackStrArrToAttr(pAttr+cAttr, PROGIDLIST, pszProgId, cPackProgId); cAttr++; } CoTaskMemFree(pszProgId); if (pPackageDetail->pActInfo->cShellFileExt) { //
// Store a tuple in the format <file ext>:<priority>
//
pszFileExt = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cShellFileExt) * sizeof(LPOLESTR)); if (!pszFileExt) { hr = E_OUTOFMEMORY; ERROR_ON_FAILURE(hr); } for (count = 0; count < pPackageDetail->pActInfo->cShellFileExt; count++) { pszFileExt[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) * (wcslen(pPackageDetail->pActInfo->prgShellFileExt[count])+1+2+1)); if (!pszFileExt[count]) { FREEARR(pszFileExt, count); ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); } // format is fileext+:+nn+NULL where nn = 2 digit priority
wsprintf(pszFileExt[count], L"%s:%2d", pPackageDetail->pActInfo->prgShellFileExt[count], pPackageDetail->pActInfo->prgPriority[count]%100);
_wcslwr(pszFileExt[count]); } PackStrArrToAttr(pAttr+cAttr, PKGFILEEXTNLIST, pszFileExt, pPackageDetail->pActInfo->cShellFileExt); cAttr++; } if (pPackageDetail->pActInfo->cInterfaces) { pszGuid2 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cInterfaces)*sizeof(LPOLESTR)); if (!pszGuid2) { ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); } for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++) { pszGuid2[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR)); if (!pszGuid2[count]) { FREEARR(pszGuid2, count); ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); } StringFromGUID((pPackageDetail->pActInfo->prgInterfaceId)[count], pszGuid2[count]); } PackStrArrToAttr(pAttr+cAttr, PKGIIDLIST, pszGuid2, pPackageDetail->pActInfo->cInterfaces); cAttr++; } /*
if (pPackageDetail->pActInfo->cTypeLib) { pszGuid3 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cTypeLib)*sizeof(LPOLESTR)); if (!pszGuid3) { ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); } for (count = 0; (count < (pPackageDetail->pActInfo->cTypeLib)); count++) { pszGuid3[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR)); if (!pszGuid3[count]) { FREEARR(pszGuid3, count); ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); } StringFromGUID((pPackageDetail->pActInfo->prgTlbId)[count], pszGuid3[count]); } PackStrArrToAttr(pAttr+cAttr, PKGTLBIDLIST, pszGuid3, pPackageDetail->pActInfo->cTypeLib); cAttr++; } */ } // fill in the platforminfo
// BUGBUG::***os version
if (pPackageDetail->pPlatformInfo->cPlatforms) { pdwArch = (DWORD *)CoTaskMemAlloc(sizeof(DWORD)*(pPackageDetail->pPlatformInfo->cPlatforms)); if (!pdwArch) ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; (count < (pPackageDetail->pPlatformInfo->cPlatforms)); count++) UnpackPlatform (pdwArch+count, (pPackageDetail->pPlatformInfo->prgPlatform)+count); PackDWArrToAttr(pAttr+cAttr, ARCHLIST, pdwArch, pPackageDetail->pPlatformInfo->cPlatforms); cAttr++; } if (pPackageDetail->pPlatformInfo->cLocales) { PackDWArrToAttr(pAttr+cAttr, LOCALEID, pPackageDetail->pPlatformInfo->prgLocale, pPackageDetail->pPlatformInfo->cLocales); cAttr++; } // fill in the installinfo
PackStrToAttr(pAttr+cAttr, PACKAGENAME, pPackageDetail->pszPackageName); cAttr++;
PackDWToAttr(pAttr+cAttr, PACKAGETYPE, (DWORD)(pPackageDetail->pInstallInfo->PathType)); cAttr++; if (pPackageDetail->pInstallInfo->pszScriptPath) { PackStrToAttr(pAttr+cAttr, SCRIPTPATH, pPackageDetail->pInstallInfo->pszScriptPath); cAttr++; } if (pPackageDetail->pInstallInfo->pszSetupCommand) { PackStrToAttr(pAttr+cAttr, SETUPCOMMAND, pPackageDetail->pInstallInfo->pszSetupCommand); cAttr++; } if (pPackageDetail->pInstallInfo->pszUrl) { PackStrToAttr(pAttr+cAttr, HELPURL, pPackageDetail->pInstallInfo->pszUrl); cAttr++; } //
// Store the current USN
//
GetCurrentUsn(szUsn); PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn); cAttr++; // package flags
PackDWToAttr(pAttr+cAttr, PACKAGEFLAGS, pPackageDetail->pInstallInfo->dwActFlags); cAttr++; // product code, different from pkg guid
PackGUIDToAttr(pAttr+cAttr, PRODUCTCODE, &(pPackageDetail->pInstallInfo->ProductCode)); cAttr++; // Mvipc
PackGUIDToAttr(pAttr+cAttr, MVIPC, &(pPackageDetail->pInstallInfo->Mvipc)); cAttr++;
// Hi Version of the package
PackDWToAttr(pAttr+cAttr, VERSIONHI, pPackageDetail->pInstallInfo->dwVersionHi); cAttr++;
// Low Version of the package
PackDWToAttr(pAttr+cAttr, VERSIONLO, pPackageDetail->pInstallInfo->dwVersionLo); cAttr++; // Revision
PackDWToAttr(pAttr+cAttr, REVISION, pPackageDetail->pInstallInfo->dwRevision); cAttr++;
// scriptsize
PackDWToAttr(pAttr+cAttr, SCRIPTSIZE, pPackageDetail->pInstallInfo->cScriptLen); cAttr++; // uilevel
PackDWToAttr (pAttr+cAttr, UILEVEL, (DWORD)pPackageDetail->pInstallInfo->InstallUiLevel); cAttr++; // adding cUpgrade number of Classstore/PackageGuid combinations
if (pPackageDetail->pInstallInfo->cUpgrades) { WCHAR szPackageGuid[_MAX_PATH];
rpszUpgrades = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*pPackageDetail->pInstallInfo->cUpgrades); if (!rpszUpgrades) ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++) { UINT len = wcslen(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore); rpszUpgrades[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2)); // Guid size+::+length++:+flagDigit+2
if (!rpszUpgrades[count]) { FREEARR(rpszUpgrades, count); ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); }
StringFromGUID(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].PackageGuid, szPackageGuid); wsprintf(rpszUpgrades[count], L"%s%s%s%s%02x", pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore, PKG_UPG_DELIMITER1, szPackageGuid, PKG_UPG_DELIMITER2, pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag%16); } PackStrArrToAttr(pAttr+cAttr, UPGRADESPACKAGES, rpszUpgrades, pPackageDetail->pInstallInfo->cUpgrades); cAttr++; } // Fill in the source list
// Maintain the serial number associated with the sources. Order matters!!
if (pPackageDetail->cSources) { rpszSources = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(pPackageDetail->cSources)); if (!rpszSources) ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; count < (pPackageDetail->cSources); count++) { rpszSources[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(wcslen(pPackageDetail->pszSourceList[count])+ 1+1+NumDigits10(pPackageDetail->cSources))); if (!rpszSources[count]) { FREEARR(rpszSources, count); ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); } wsprintf(rpszSources[count], L"%d:%s", count, pPackageDetail->pszSourceList[count]); } PackStrArrToAttr(pAttr+cAttr, MSIFILELIST, rpszSources, pPackageDetail->cSources); cAttr++; } // fill in the categories
// Add the package Categories
if (pPackageDetail->cCategories) { pszGuid4 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->cCategories) * sizeof(LPOLESTR)); if (!pszGuid4) { ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); } for (count = 0; (count < pPackageDetail->cCategories); count++) { pszGuid4[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR)); if (!pszGuid4[count]) { FREEARR(pszGuid4, count); ERROR_ON_FAILURE(hr = E_OUTOFMEMORY); } StringFromGUID((pPackageDetail->rpCategory)[count], pszGuid4[count]); } PackStrArrToAttr(pAttr+cAttr, PKGCATEGORYLIST, pszGuid4, pPackageDetail->cCategories); cAttr++; } // fill in the vendor
// Publisher
if (pPackageDetail->pszPublisher) { PackStrToAttr(pAttr+cAttr, PUBLISHER, pPackageDetail->pszPublisher); cAttr++; } /*
//
// 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; if (pPackageDetail->pInstallInfo->cScriptLen) { PackBinToAttr(pAttr+cAttr, PKGSCRIPT, pPackageDetail->pInstallInfo->pScript, pPackageDetail->pInstallInfo->cScriptLen); cAttr++; } } */ hr = ADSICreateDSObject(m_ADsPackageContainer, szRDN, pAttr, cAttr); ERROR_ON_FAILURE(hr);
memset(pPkgGuid, 0, sizeof(GUID));
// memcpy(pPkgGuid, &PackageGuidId, sizeof(GUID));
hr = GetPackageGuid(szRDN, pPkgGuid); ERROR_ON_FAILURE(hr);
fPackageCreated = TRUE;
if (pPackageDetail->pActInfo) { for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++) { hr = NewClass((pPackageDetail->pActInfo->pClasses)+count); ERROR_ON_FAILURE(hr); } } if (!(pPackageDetail->pInstallInfo->dwActFlags & ACTFLG_Uninstall) && !(pPackageDetail->pInstallInfo->dwActFlags & ACTFLG_Orphan)) { if (pPackageDetail->pInstallInfo->cUpgrades) { //
// Need to fixup the other packages that this package upgrades
//
for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++) { if ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) || (pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall)) { DWORD Flags = 0;
if (pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_Enforced) Flags = UPGFLG_Enforced;
} } for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++) CoTaskMemFree(rpszUpgrades[count]); CoTaskMemFree(rpszUpgrades); } } if (SUCCEEDED(hr)) { //
// Update Store Usn
//
UpdateStoreUsn(m_ADsContainer, szUsn); } Error_Cleanup: for (count = 0; count < cAttr; count++) FreeAttr(pAttr[count]); if (pszGuid1) { for (count = 0; (count < pPackageDetail->pActInfo->cClasses); count++) CoTaskMemFree(pszGuid1[count]); CoTaskMemFree(pszGuid1); } if (pszGuid2) { for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++) CoTaskMemFree(pszGuid2[count]); CoTaskMemFree(pszGuid2); } if (pszGuid3) { for (count = 0; (count < (pPackageDetail->pActInfo->cTypeLib)); count++) CoTaskMemFree(pszGuid3[count]); CoTaskMemFree(pszGuid3); } if (pszGuid4) { for (count = 0; (count < pPackageDetail->cCategories); count++) CoTaskMemFree(pszGuid4[count]); CoTaskMemFree(pszGuid4); } if (pszFileExt) { for (count = 0; (count < pPackageDetail->pActInfo->cShellFileExt); count++) CoTaskMemFree(pszFileExt[count]); CoTaskMemFree(pszFileExt); } if (pdwArch) { CoTaskMemFree(pdwArch); } if (rpszSources) { for (count = 0; (count < pPackageDetail->cSources); count++) CoTaskMemFree(rpszSources[count]); CoTaskMemFree(rpszSources); }
//
// On failure, the package should be removed from the ds if we
// created it there.
//
if (FAILED(hr) && (fPackageCreated)) { HRESULT hrDeleted; LPWSTR wszPackageFullPath;
//
// Need to get a full path to the package in order to delete it.
//
hrDeleted = BuildADsPathFromParent(m_szPackageName, szRDN, &wszPackageFullPath);
ASSERT(SUCCEEDED(hrDeleted));
CSDBGPrint((L"AddPackage failed, attempting to remove deleted package with path %s\n", wszPackageFullPath));
hrDeleted = DeletePackage(wszPackageFullPath);
CSDBGPrint((L"DeletePackage returned %x\n", hrDeleted)); //
// Free the full path
//
CoTaskMemFree(wszPackageFullPath); }
return RemapErrorCode(hr, m_szContainerName); }
//+
//
// Cleanup old packages from Class Store based on lastChangeTime
//
HRESULT CClassContainer::Cleanup ( FILETIME *pTimeBefore ) { //
// Delete all packages marked as "Uninstall"
// OR "Orphan" and are older than the time given
//
ULONG cRowsFetched = 0; ADS_SEARCH_HANDLE hADsSearchHandle = NULL; WCHAR szFilter[_MAX_PATH], szRDN[_MAX_PATH]; HRESULT hr = S_OK; ADS_ATTR_INFO pAttr; SYSTEMTIME SystemTime; ADS_SEARCH_COLUMN column; DWORD dwPackageFlags; LPOLESTR pszPackageId = NULL; if ((!pTimeBefore) || !IsValidReadPtrIn(pTimeBefore, sizeof(FILETIME))) return E_INVALIDARG; FileTimeToSystemTime( (CONST FILETIME *) pTimeBefore, &SystemTime); wsprintf (szFilter, L"(%s<=%04d%02d%02d%02d%02d%02d)", PKGUSN, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond); // execute the search and keep the handle returned.
hr = ADSIExecuteSearch(m_ADsPackageContainer, szFilter, pszDeleteAttrNames, cDeleteAttr, &hADsSearchHandle); hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle); while (TRUE) { if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS)) break; dwPackageFlags = 0; // Get the Package State
hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, PACKAGEFLAGS, &column); if (SUCCEEDED(hr)) { UnpackDWFrom(column, &dwPackageFlags); ADSIFreeColumn(m_ADsPackageContainer, &column); } //
// Check flag values to see if this package is Orphaned or Uninstalled
//
if ((dwPackageFlags & ACTFLG_Orphan) || (dwPackageFlags & ACTFLG_Uninstall)) { hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, OBJECTDN, &column); if (SUCCEEDED(hr)) { WCHAR * szDN = NULL;
UnpackStrFrom(column, &szDN); hr = DeletePackage(szDN);
ADSIFreeColumn(m_ADsPackageContainer, &column); ERROR_ON_FAILURE(hr); } } hr = ADSIGetNextRow(m_ADsPackageContainer, hADsSearchHandle); } Error_Cleanup: if (hADsSearchHandle) ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle); return RemapErrorCode(hr, m_szContainerName); }
|