|
|
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1998.
//
// File: packages.cpp
//
// Contents: Methods on CScopePane related to package deployment
// and maintenence of the various index and cross-reference
// structures.
//
// Classes:
//
// Functions: CopyPackageDetail
// FreePackageDetail
// GetMsiProperty
//
// History: 2-03-1998 stevebl Created
// 3-25-1998 stevebl Added GetMsiProperty
// 5-20-1998 RahulTh - Added DetectUpgrades for automatic upgrade
// detection
// - Added GetCapitalizedExt
//
//---------------------------------------------------------------------------
// UNDONE - put in exception handling for low memory conditions
#include "precomp.hxx"
// uncomment this line to get the old behavior of putting up an upgrade
// dialog for auto-detected upgrades
//#define SHOWDETECTEDUPGRADEDIALOG
//IMalloc * g_pIMalloc = NULL;
BOOL IsNullGUID (GUID *pguid) {
return ( (pguid->Data1 == 0) && (pguid->Data2 == 0) && (pguid->Data3 == 0) && (pguid->Data4[0] == 0) && (pguid->Data4[1] == 0) && (pguid->Data4[2] == 0) && (pguid->Data4[3] == 0) && (pguid->Data4[4] == 0) && (pguid->Data4[5] == 0) && (pguid->Data4[6] == 0) && (pguid->Data4[7] == 0) ); }
void FreePlatformInfo(PLATFORMINFO * &ppiOut) { if (ppiOut) { OLESAFE_DELETE(ppiOut->prgPlatform); OLESAFE_DELETE(ppiOut->prgLocale); OLESAFE_DELETE(ppiOut); } }
HRESULT CopyPlatformInfo(PLATFORMINFO * &ppiOut, PLATFORMINFO * & ppiIn) { if (NULL == ppiIn) { ppiOut = NULL; return S_OK; } UINT n; ppiOut = (PLATFORMINFO *)OLEALLOC(sizeof(PLATFORMINFO)); if (!ppiOut) { goto out_of_memory; } memcpy(ppiOut, ppiIn, sizeof(PLATFORMINFO)); ppiOut->prgPlatform = NULL; ppiOut->prgLocale = NULL; n = ppiIn->cPlatforms; if (n) { ppiOut->prgPlatform = (CSPLATFORM*) OLEALLOC(sizeof(CSPLATFORM) * n); if (!ppiOut->prgPlatform) { goto out_of_memory; }
memcpy(ppiOut->prgPlatform, ppiIn->prgPlatform, sizeof(CSPLATFORM) * n); } n = ppiIn->cLocales; if (n) { ppiOut->prgLocale = (LCID *) OLEALLOC(sizeof(LCID) * n); if (!ppiOut->prgLocale) { goto out_of_memory; } memcpy(ppiOut->prgLocale, ppiIn->prgLocale, sizeof(LCID) * n); } return S_OK; out_of_memory: FreePlatformInfo(ppiOut); return E_OUTOFMEMORY; }
void FreeActInfo(ACTIVATIONINFO * &paiOut) { if (paiOut) { if (paiOut->pClasses) { UINT n = paiOut->cClasses; while (n--) { OLESAFE_DELETE(paiOut->pClasses[n].prgProgId); } OLESAFE_DELETE(paiOut->pClasses); } OLESAFE_DELETE(paiOut->prgInterfaceId); OLESAFE_DELETE(paiOut->prgPriority); if (paiOut->prgShellFileExt) { UINT n = paiOut->cShellFileExt; while (n--) { OLESAFE_DELETE(paiOut->prgShellFileExt[n]) } OLESAFE_DELETE(paiOut->prgShellFileExt); } OLESAFE_DELETE(paiOut->prgTlbId); OLESAFE_DELETE(paiOut); } }
HRESULT CopyActInfo(ACTIVATIONINFO * & paiOut, ACTIVATIONINFO * & paiIn) { if (NULL == paiIn) { paiOut = NULL; return S_OK; } UINT n; paiOut = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO)); if (!paiOut) { goto out_of_memory; } memcpy(paiOut, paiIn, sizeof(ACTIVATIONINFO)); paiOut->prgInterfaceId = NULL; paiOut->prgPriority = NULL; paiOut->prgShellFileExt = NULL; paiOut->prgTlbId = NULL; paiOut->pClasses = NULL; n = paiIn->cClasses;
paiOut->bHasClasses = paiIn->bHasClasses;
if (n) { paiOut->pClasses = (CLASSDETAIL *) OLEALLOC(sizeof(CLASSDETAIL) * n); if (!paiOut->pClasses) { goto out_of_memory; } memcpy(paiOut->pClasses, paiIn->pClasses, sizeof(CLASSDETAIL) * n); while (n--) { UINT n2 = paiIn->pClasses[n].cProgId; if (n2) { paiOut->pClasses[n].prgProgId = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n2); if (!paiOut->pClasses[n].prgProgId) { goto out_of_memory; } while (n2--) { OLESAFE_COPYSTRING(paiOut->pClasses[n].prgProgId[n2], paiIn->pClasses[n].prgProgId[n2]); } } } } n = paiIn->cShellFileExt; if (n) { paiOut->prgPriority = (UINT *) OLEALLOC(sizeof(UINT) * n); if (!paiOut->prgPriority) { goto out_of_memory; } memcpy(paiOut->prgPriority, paiIn->prgPriority, sizeof(UINT) * n); paiOut->prgShellFileExt = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n); if (!paiOut->prgShellFileExt) { goto out_of_memory; } while (n--) { OLESAFE_COPYSTRING(paiOut->prgShellFileExt[n], paiIn->prgShellFileExt[n]); } } n = paiIn->cInterfaces; if (n) { paiOut->prgInterfaceId = (IID *) OLEALLOC(sizeof(IID) * n); if (!paiOut->prgInterfaceId) { goto out_of_memory; } memcpy(paiOut->prgInterfaceId, paiIn->prgInterfaceId, sizeof(IID) * n); } n = paiIn->cTypeLib; if (n) { paiOut->prgTlbId = (GUID *) OLEALLOC(sizeof(GUID) * n); if (!paiOut->prgTlbId) { goto out_of_memory; } memcpy(paiOut->prgTlbId, paiIn->prgTlbId, sizeof(GUID) * n); } return S_OK; out_of_memory: FreeActInfo(paiOut); return E_OUTOFMEMORY; }
void FreeInstallInfo(INSTALLINFO * &piiOut) { if (piiOut) { if (piiOut->prgUpgradeInfoList) { UINT n = piiOut->cUpgrades; while (n--) { OLESAFE_DELETE(piiOut->prgUpgradeInfoList[n].szClassStore); } OLESAFE_DELETE(piiOut->prgUpgradeInfoList); } OLESAFE_DELETE(piiOut->pClsid); OLESAFE_DELETE(piiOut->pszScriptPath); OLESAFE_DELETE(piiOut->pszSetupCommand); OLESAFE_DELETE(piiOut->pszUrl); OLESAFE_DELETE(piiOut); } }
HRESULT CopyInstallInfo(INSTALLINFO * & piiOut, INSTALLINFO * & piiIn) { ULONG n; if (NULL == piiIn) { piiOut = NULL; return S_OK; } piiOut = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO)); if (!piiOut) { goto out_of_memory; } memcpy(piiOut, piiIn, sizeof(INSTALLINFO)); piiOut->pClsid = NULL; piiOut->prgUpgradeInfoList = NULL; piiOut->pszScriptPath = NULL; piiOut->pszSetupCommand = NULL; piiOut->pszUrl = NULL; OLESAFE_COPYSTRING(piiOut->pszScriptPath, piiIn->pszScriptPath); OLESAFE_COPYSTRING(piiOut->pszSetupCommand, piiIn->pszSetupCommand); OLESAFE_COPYSTRING(piiOut->pszUrl, piiIn->pszUrl); if (piiIn->pClsid) { piiOut->pClsid = (GUID *) OLEALLOC(sizeof(GUID)); if (!piiOut->pClsid) { goto out_of_memory; } memcpy(piiOut->pClsid, piiIn->pClsid, sizeof(GUID)); } n = piiIn->cUpgrades; if (n) { piiOut->prgUpgradeInfoList = (UPGRADEINFO *) OLEALLOC(sizeof(UPGRADEINFO) * n); if (!piiOut->prgUpgradeInfoList) { goto out_of_memory; } memcpy(piiOut->prgUpgradeInfoList, piiIn->prgUpgradeInfoList, sizeof(UPGRADEINFO) * n); while (n--) { OLESAFE_COPYSTRING(piiOut->prgUpgradeInfoList[n].szClassStore, piiIn->prgUpgradeInfoList[n].szClassStore); } } return S_OK; out_of_memory: FreeInstallInfo(piiOut); return E_OUTOFMEMORY; }
void InternalFreePackageDetail(PACKAGEDETAIL * &ppdOut) { if (ppdOut) { FreeActInfo(ppdOut->pActInfo); FreePlatformInfo(ppdOut->pPlatformInfo); FreeInstallInfo(ppdOut->pInstallInfo); OLESAFE_DELETE(ppdOut->pszPackageName); OLESAFE_DELETE(ppdOut->pszPublisher); if (ppdOut->pszSourceList) { UINT n = ppdOut->cSources; while (n--) { OLESAFE_DELETE(ppdOut->pszSourceList[n]); } OLESAFE_DELETE(ppdOut->pszSourceList); } OLESAFE_DELETE(ppdOut->rpCategory); } }
HRESULT CopyPackageDetail(PACKAGEDETAIL * & ppdOut, PACKAGEDETAIL * & ppdIn) { ULONG n; if (NULL == ppdIn) { ppdOut = NULL; return S_OK; } ppdOut = new PACKAGEDETAIL; if (!ppdOut) { goto out_of_memory; } memcpy(ppdOut, ppdIn, sizeof(PACKAGEDETAIL)); ppdOut->pActInfo = NULL; ppdOut->pInstallInfo = NULL; ppdOut->pPlatformInfo = NULL; ppdOut->pszPackageName = NULL; ppdOut->pszPublisher = NULL; ppdOut->pszSourceList = NULL; ppdOut->rpCategory = NULL; OLESAFE_COPYSTRING(ppdOut->pszPackageName, ppdIn->pszPackageName); n = ppdIn->cSources; if (n) { ppdOut->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n); if (!ppdOut->pszSourceList) { goto out_of_memory; } while (n--) { OLESAFE_COPYSTRING(ppdOut->pszSourceList[n], ppdIn->pszSourceList[n]); } } n = ppdIn->cCategories; if (n) { ppdOut->rpCategory = (GUID *)OLEALLOC(sizeof(GUID) * n); if (!ppdOut->rpCategory) { goto out_of_memory; } memcpy(ppdOut->rpCategory, ppdIn->rpCategory, sizeof(GUID) * n); } if FAILED(CopyActInfo(ppdOut->pActInfo, ppdIn->pActInfo)) goto out_of_memory; if FAILED(CopyPlatformInfo(ppdOut->pPlatformInfo, ppdIn->pPlatformInfo)) goto out_of_memory; if FAILED(CopyInstallInfo(ppdOut->pInstallInfo, ppdIn->pInstallInfo)) goto out_of_memory; return S_OK; out_of_memory: LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, E_OUTOFMEMORY); InternalFreePackageDetail(ppdOut); if (ppdOut) delete ppdOut; return E_OUTOFMEMORY; }
void FreePackageDetail(PACKAGEDETAIL * & ppd) { if (ppd) { ReleasePackageDetail(ppd); delete ppd; ppd = NULL; } }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::GetUniquePackageName
//
// Synopsis: Returns a unique package name.
//
// Arguments: [sz] - [in] the name of the package
// [out] the new name, guaranteed unique on this cs
//
// History: 1-23-1998 stevebl Created
//
// Notes: First the input name is checked for uniqueness. If it is
// already unique it is returned unchanged. If it is not
// unique then a new name is formed by adding " (2)" to the end
// of the string, then " (3)" and " (4)" and so on until a
// unique name is found.
//
// If you don't want a number appended to the name, nHint must
// be 1.
//
// The value passed back in nHint will be the seed for the
// next try.
//
//---------------------------------------------------------------------------
void CScopePane::GetUniquePackageName(CString szRoot, CString &szOut, int &nHint) { map<MMC_COOKIE, CAppData>::iterator i; set<CString> sNames; int cch = szRoot.GetLength(); for (i=m_AppData.begin(); i != m_AppData.end(); i++) { // As an optimization, I'm only going to add names that might match
// this one to the set.
LPOLESTR szName = i->second.m_pDetails->pszPackageName; if ((0 == wcsncmp(szRoot, szName, cch)) && (i->second.m_fVisible)) sNames.insert(szName); } szOut = szRoot; if (nHint++ == 1) // try the first name
{ if (sNames.end() == sNames.find(szOut)) return; } // now check for a match
do { szOut.Format(L"%s (%i)", (LPCTSTR)szRoot, nHint++); if (sNames.end() == sNames.find(szOut)) { // we are unique
return; } // try a different name
} while (TRUE); }
//+--------------------------------------------------------------------------
//
// Member: CScopePand::GetDeploymentType
//
// Synopsis:
//
// Arguments: [szPackagePath] -
// [lpFileTitle] -
//
// Returns:
//
// Modifies:
//
// Derivation:
//
// History: 6-29-1998 stevebl Created
//
// Notes:
//
//---------------------------------------------------------------------------
HRESULT CScopePane::GetDeploymentType(PACKAGEDETAIL * ppd, BOOL & fShowPropertySheet) { INSTALLINFO * pii = ppd->pInstallInfo; if (m_ToolDefaults.fUseWizard) { CDeployApp dlgDeployApp; // Turn on theme'ing for the dialog by activating the theme context
CThemeContextActivator themer; dlgDeployApp.m_fMachine = m_fMachine; dlgDeployApp.m_fCrappyZaw = pii->PathType == SetupNamePath; if (IDCANCEL == dlgDeployApp.DoModal()) { return E_FAIL; } switch (dlgDeployApp.m_iDeployment) { default: case 0: //published
pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall; break; case 1: // assigned
pii->dwActFlags = ACTFLG_Assigned | ACTFLG_UserInstall | ACTFLG_OnDemandInstall; break; case 3: // disabled
pii->dwActFlags = 0; break; case 2: // custom
if (m_fMachine) { pii->dwActFlags = ACTFLG_Assigned | ACTFLG_UserInstall | ACTFLG_OnDemandInstall; } else { pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall; } fShowPropertySheet = TRUE; } } else { switch (m_ToolDefaults.NPBehavior) { default: case NP_PUBLISHED: if (!m_fMachine) { pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall; break; } case NP_ASSIGNED: if (pii->PathType != SetupNamePath) { pii->dwActFlags = ACTFLG_Assigned | ACTFLG_UserInstall | ACTFLG_OnDemandInstall; } else { // Crappy ZAW app.. force it to be published.
pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall; } break; case NP_DISABLED: pii->dwActFlags = 0; break; } if (m_ToolDefaults.fCustomDeployment) { fShowPropertySheet = TRUE; } } return S_OK; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::DeployPackage
//
// Synopsis:
//
// Arguments: [hr] -
// [hr] -
//
// Returns:
//
// Modifies:
//
// Derivation:
//
// History: 6-29-1998 stevebl Created
//
// Notes:
//
//---------------------------------------------------------------------------
HRESULT CScopePane::DeployPackage(PACKAGEDETAIL * ppd, BOOL fShowPropertySheet) { CHourglass hourglass; INSTALLINFO * pii = ppd->pInstallInfo; HRESULT hrDeploy = S_OK; hrDeploy = PrepareExtensions(*ppd); if (SUCCEEDED(hrDeploy)) { DWORD dwRememberFlags; // put the entry in the class store
if (fShowPropertySheet) { dwRememberFlags = pii->dwActFlags; pii->dwActFlags = 0; // disabled state
} if (!m_pIClassAdmin) { hrDeploy = GetClassStore(TRUE); if (FAILED(hrDeploy)) { LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_NOCLASSSTORE_ERROR, hrDeploy); DebugMsg((DM_WARNING, TEXT("GetClassStore failed with 0x%x"), hrDeploy)); } } if (SUCCEEDED(hrDeploy)) { hrDeploy = m_pIClassAdmin->AddPackage(ppd, &ppd->pInstallInfo->PackageGuid); if (FAILED(hrDeploy)) { LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_ADDPACKAGE_ERROR, hrDeploy, ppd->pszPackageName); DebugMsg((DM_WARNING, TEXT("AddPackage failed with 0x%x"), hrDeploy)); } } if (FAILED(hrDeploy)) { return hrDeploy; } if (fShowPropertySheet) { pii->dwActFlags = dwRememberFlags; // restore state
} }
if (SUCCEEDED(hrDeploy)) { CString szCSPath; hrDeploy = GetClassStoreName(szCSPath, FALSE); if (FAILED(hrDeploy)) { DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hrDeploy)); return hrDeploy; }
CAppData data;
hrDeploy = CopyPackageDetail(data.m_pDetails, ppd); if (FAILED(hrDeploy)) { DebugMsg((DM_WARNING, TEXT("CopyPackageDetail failed with 0x%x"), hrDeploy)); return hrDeploy; }
data.InitializeExtraInfo();
m_lLastAllocated++;
// make sure that m_lLastAllocated hasn't already been used
while (m_AppData.end() != m_AppData.find(m_lLastAllocated)) { m_lLastAllocated++; }
data.m_fVisible = FALSE; m_AppData[m_lLastAllocated] = data;
BOOL fAddOk = TRUE;
// The admin has said he wants to do a "custom" deployment.
if (fShowPropertySheet) { HRESULT hr; // errors that happen while setting up
// the property sheets are NOT to be
// reported as deployment errors.
MMC_COOKIE cookie = m_lLastAllocated;
PROPSHEETHEADER psh; memset(&psh, 0, sizeof(psh)); psh.dwSize = sizeof(psh); psh.dwFlags = PSH_NOAPPLYNOW | PSH_PROPTITLE; psh.pszCaption = m_AppData[m_lLastAllocated].m_pDetails->pszPackageName; int nPage = 0; HPROPSHEETPAGE rgPages[6]; psh.phpage = rgPages;
//
// Create the Product property page
//
CProduct prpProduct; prpProduct.m_fPreDeploy = TRUE; prpProduct.m_pData = &m_AppData[m_lLastAllocated]; prpProduct.m_cookie = cookie; prpProduct.m_pScopePane = this; prpProduct.m_pAppData = &m_AppData; prpProduct.m_pIGPEInformation = m_pIGPEInformation; prpProduct.m_fMachine = m_fMachine; prpProduct.m_fRSOP = m_fRSOP; // no longer need to marshal this interface, just set it
prpProduct.m_pIClassAdmin = m_pIClassAdmin; m_pIClassAdmin->AddRef();
rgPages[nPage++] = CreateThemedPropertySheetPage(&prpProduct.m_psp);
//
// Create the Depeployment property page
//
CDeploy prpDeploy; prpDeploy.m_fPreDeploy = TRUE; prpDeploy.m_pData = &m_AppData[m_lLastAllocated]; prpDeploy.m_cookie = cookie; prpDeploy.m_fMachine = m_fMachine; prpDeploy.m_fRSOP = m_fRSOP; prpDeploy.m_pScopePane = this; #if 0
prpDeploy.m_pIGPEInformation = m_pIGPEInformation; #endif
// no longer need to marshal this interface, just set it
prpDeploy.m_pIClassAdmin = m_pIClassAdmin; m_pIClassAdmin->AddRef();
rgPages[nPage++] = CreateThemedPropertySheetPage(&prpDeploy.m_psp);
CUpgradeList prpUpgradeList; if (pii->PathType != SetupNamePath) { //
// Create the upgrades property page
//
prpUpgradeList.m_pData = &m_AppData[m_lLastAllocated]; prpUpgradeList.m_cookie = cookie; prpUpgradeList.m_pScopePane = this; prpUpgradeList.m_fPreDeploy = TRUE; prpUpgradeList.m_fMachine = m_fMachine; prpUpgradeList.m_fRSOP = m_fRSOP; #if 0
prpUpgradeList.m_pIGPEInformation = m_pIGPEInformation; #endif
// no longer need to marshal the interface, just set it
prpUpgradeList.m_pIClassAdmin = m_pIClassAdmin; m_pIClassAdmin->AddRef();
rgPages[nPage++] = CreateThemedPropertySheetPage(&prpUpgradeList.m_psp); }
//
// make sure we have an up-to-date categories list
//
ClearCategories(); hr = CsGetAppCategories(&m_CatList); if (FAILED(hr)) { // report it
LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GETCATEGORIES_ERROR, hr, NULL);
// Since failure only means the categories list will be
// empty, we'll proceed as if nothing happened.
hr = S_OK; }
//
// Create the Category property page
//
CCategory prpCategory; prpCategory.m_pData = &m_AppData[m_lLastAllocated]; prpCategory.m_cookie = cookie; prpCategory.m_pCatList = &m_CatList; prpCategory.m_fRSOP = m_fRSOP; prpCategory.m_fPreDeploy = TRUE;
// no longer need to marshal this interface, just set it
prpCategory.m_pIClassAdmin = m_pIClassAdmin; m_pIClassAdmin->AddRef();
rgPages[nPage++] = CreateThemedPropertySheetPage(&prpCategory.m_psp);
CXforms prpXforms; if (pii->PathType != SetupNamePath) { //
// Create the Xforms property page
//
prpXforms.m_fPreDeploy = TRUE; prpXforms.m_pData = &m_AppData[m_lLastAllocated]; prpXforms.m_cookie = cookie; prpXforms.m_pScopePane = this;
// no longer need to marshal the interface, just set it
prpXforms.m_pIClassAdmin = m_pIClassAdmin; m_pIClassAdmin->AddRef();
rgPages[nPage++] = CreateThemedPropertySheetPage(&prpXforms.m_psp); }
//
// Create the security property page
//
CString szPath; hr = GetPackageDSPath(szPath, m_AppData[m_lLastAllocated].m_pDetails->pszPackageName); if (SUCCEEDED(hr)) { LPSECURITYINFO pSI; hr = DSCreateISecurityInfoObject(szPath, NULL, 0, &pSI, NULL, NULL, 0); if (SUCCEEDED(hr)) { rgPages[nPage++] = CreateSecurityPage(pSI); pSI->Release(); } else { DebugMsg((DM_WARNING, TEXT("DSCreateISecurityInfoObject failed with 0x%x"), hr)); } } else { DebugMsg((DM_WARNING, TEXT("GetPackageDSPath failed with 0x%x"), hr)); } psh.nPages = nPage; psh.hwndParent = m_hwndMainWindow;
if (IDOK != PropertySheet(&psh)) { fAddOk = FALSE; RemovePackage(cookie, FALSE, TRUE); } else { // Make sure that the package is deployed with the proper
// deployment type
hr = m_pIClassAdmin->ChangePackageProperties(m_AppData[m_lLastAllocated].m_pDetails->pszPackageName, NULL, &m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->dwActFlags, NULL, NULL, NULL, NULL); if (SUCCEEDED(hr)) { if (FAILED(m_pIGPEInformation->PolicyChanged(m_fMachine, TRUE, &guidExtension, m_fMachine ? &guidMachSnapin : &guidUserSnapin ))) { ReportPolicyChangedError(m_hwndMainWindow); } }
} }
if (fAddOk) { set <CResultPane *>::iterator i; for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++) { RESULTDATAITEM resultItem; memset(&resultItem, 0, sizeof(resultItem));
if ((*i)->_fVisible) { resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM; resultItem.str = MMC_CALLBACK; resultItem.nImage = m_AppData[m_lLastAllocated].GetImageIndex(this); resultItem.lParam = m_lLastAllocated; hrDeploy = (*i)->m_pResult->InsertItem(&resultItem); }
// The following code must be excecuted wheather the InsertItem
// call succeeds or not.
// There are legitimate cases when InsertItem will fail. For
// instance, if the scope pane is being shown, but not the
// result pane.
m_AppData[m_lLastAllocated].m_fVisible = TRUE; m_AppData[m_lLastAllocated].m_itemID = resultItem.itemID; InsertExtensionEntry(m_lLastAllocated, m_AppData[m_lLastAllocated]); if (m_pFileExt) { m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0); } InsertUpgradeEntry(m_lLastAllocated, m_AppData[m_lLastAllocated]); m_UpgradeIndex[GetUpgradeIndex(m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->PackageGuid)] = m_lLastAllocated; // if this is an upgrade, set icons for upgraded apps to
// the proper icon and refresh any open property sheets
UINT n = m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->cUpgrades; while (n--) { map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(m_AppData[m_lLastAllocated].m_pDetails->pInstallInfo->prgUpgradeInfoList[n].PackageGuid)); if (i != m_UpgradeIndex.end()) { if (m_AppData[i->second].m_pUpgradeList) { m_AppData[i->second].m_pUpgradeList->SendMessage(WM_USER_REFRESH, 0, 0); } } }
if ((*i)->_fVisible) { if (SUCCEEDED(hrDeploy)) { (*i)->m_pResult->SetItem(&resultItem); (*i)->m_pResult->Sort((*i)->m_nSortColumn, (*i)->m_dwSortOptions, -1); } else { DebugMsg((DM_WARNING, TEXT("InsertItem failed with 0x%x"), hrDeploy)); hrDeploy = S_OK; } } } } } return hrDeploy; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::AddZAPPackage
//
// Synopsis:
//
// Arguments: [szPackagePath] -
// [lpFileTitle] -
//
// Returns:
//
// Modifies:
//
// Derivation:
//
// History: 6-29-1998 stevebl Created
//
// Notes:
//
//---------------------------------------------------------------------------
HRESULT CScopePane::AddZAPPackage(LPCOLESTR szPackagePath, LPCOLESTR lpFileTitle) { CHourglass hourglass; HRESULT hr = E_FAIL;
OLECHAR szBuffer[1024]; OLECHAR * sz = szBuffer; CString szFriendlyName; CString szUniqueFriendlyName; int nHint = 1; DWORD dw = GetPrivateProfileString( L"Application", L"FriendlyName", NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (0 == dw) { // either bogus FriendlyName or no setup command, both of which are fatal
goto bad_script; } szFriendlyName = sz; // save this for later
dw = GetPrivateProfileString( L"Application", L"SetupCommand", NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (0 == dw) { // either bogus file or no setup command, both of which are fatal
bad_script: { LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADZAP_ERROR, HRESULT_FROM_WIN32(dw), lpFileTitle); TCHAR szBadScriptBuffer[256]; ::LoadString(ghInstance, IDS_ADDFAILED_ZAP, szBadScriptBuffer, 256); m_pConsole->MessageBox(szBadScriptBuffer, lpFileTitle, MB_OK | MB_ICONEXCLAMATION, NULL); } return E_FAIL; } INSTALLINFO * pii = NULL; PLATFORMINFO * ppi = NULL; ACTIVATIONINFO * pai = NULL; PACKAGEDETAIL *ppd = new PACKAGEDETAIL; if (!ppd) { goto out_of_memory; } memset(ppd, 0, sizeof(PACKAGEDETAIL)); pii = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO)); ppd->pInstallInfo = pii; if (!pii) { goto out_of_memory; } memset(pii, 0, sizeof(INSTALLINFO)); ppi = (PLATFORMINFO *) OLEALLOC(sizeof(PLATFORMINFO)); ppd->pPlatformInfo = ppi; if (!ppi) { goto out_of_memory; } memset(ppi, 0, sizeof(PLATFORMINFO)); pai = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO)); ppd->pActInfo = pai; if (!pai) { goto out_of_memory; } else { memset(pai, 0, sizeof(ACTIVATIONINFO));
pai->bHasClasses = ! m_ToolDefaults.fExtensionsOnly;
// Munge the setup path.
// surround the path in quotes to be sure that spaces are dealt
// with properly
CString szPath = L'"'; szPath += szPackagePath; // strip off the package name
int ich = szPath.ReverseFind(L'\\'); // check for either slash symbol (just in case)
int ich2 = szPath.ReverseFind(L'/'); if (ich2 > ich) { ich = ich2; } if (ich >= 0) { szPath = szPath.Left(ich + 1); // keep the path separator
}
// merge it with the setup command string
BOOL fNeedQuote = TRUE; if (sz[0] == L'"') { // remember that we had a leading quote (no need to insert a quote)
// and strip it off
sz++; fNeedQuote = FALSE; } while (sz[0]) { if (sz[0] == L'.' && sz[1] == L'.' && (sz[2] == L'/' || sz[2] == L'\\')) { // strip off the last path element
// First strip off the path separator (the one we kept previously)
szPath = szPath.Left(ich); // now find the symbol
ich = szPath.ReverseFind(L'\\'); // check for either slash symbol (just in case)
ich2 = szPath.ReverseFind(L'/'); if (ich2 > ich) { ich = ich2; } if (ich >= 0) { szPath = szPath.Left(ich + 1); // keep the path separator
} // skip the "..\"
sz += 3; } else { if ((0 != sz[0] && L':' == sz[1]) || ((L'\\' == sz[0] || L'/' == sz[0]) && (L'\\' == sz[1] || L'/' == sz[1])) || (0 == wcsncmp(L"http:",sz,5))) { // hard path
// throw away szPath;
szPath = L""; if (!fNeedQuote) { // make sure we don't drop that quote
szPath += L'"'; } // and make sure we don't insert quotes where they're not wanted
fNeedQuote = FALSE; } // break the loop on anything other than "..\"
break; } }
if (fNeedQuote) { CString szTemp = sz; // copy everything up to the first space
ich = szTemp.Find(L' '); szPath += szTemp.Left(ich); // then add a quote
szPath += L'"'; szPath += szTemp.Mid(ich); } else { szPath += sz; }
OLESAFE_COPYSTRING(pii->pszScriptPath, szPath);
sz = szBuffer; dw = GetPrivateProfileString( L"Application", L"DisplayVersion", NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (dw) { // parse product version
CString szProdVersion = szBuffer; szProdVersion.TrimLeft(); CString szTemp = szProdVersion.SpanIncluding(L"0123456789"); (void) swscanf(szTemp, L"%u", &pii->dwVersionHi); szProdVersion = szProdVersion.Mid(szTemp.GetLength()); szTemp = szProdVersion.SpanExcluding(L"0123456789"); szProdVersion = szProdVersion.Mid(szTemp.GetLength()); (void) swscanf(szProdVersion, L"%u", &pii->dwVersionLo); }
dw = GetPrivateProfileString( L"Application", L"Publisher", NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (dw) { OLESAFE_COPYSTRING(ppd->pszPublisher, sz); }
dw = GetPrivateProfileString( L"Application", L"URL", NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (dw) { OLESAFE_COPYSTRING(pii->pszUrl, sz); }
set<DWORD> sPlatforms; dw = GetPrivateProfileString( L"Application", L"Architecture", NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath);
BOOL fValidPlatform;
fValidPlatform = FALSE;
if (dw) { CString szPlatforms = szBuffer; CString szTemp; while (szPlatforms.GetLength()) { szTemp = szPlatforms.SpanExcluding(L","); if (0 == szTemp.CompareNoCase(L"intel")) { sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL); fValidPlatform = TRUE; } else if (0 == szTemp.CompareNoCase(L"amd64")) { sPlatforms.insert(PROCESSOR_ARCHITECTURE_AMD64); fValidPlatform = TRUE; } else if (0 == szTemp.CompareNoCase(L"intel64")) { sPlatforms.insert(PROCESSOR_ARCHITECTURE_IA64); fValidPlatform = TRUE; } szPlatforms = szPlatforms.Mid(szTemp.GetLength()+1); } }
//
// Ensure that if we saw any platforms, at least one of them
// was a supported platform
//
if ( dw && ! fValidPlatform ) { ::LoadString(ghInstance, IDS_ILLEGAL_PLATFORM, szBuffer, 256); m_pConsole->MessageBox(szBuffer, lpFileTitle, MB_OK | MB_ICONEXCLAMATION, NULL);
delete ppd;
return E_FAIL; }
if (0 == sPlatforms.size()) { // If the ZAP file doesn't specify an architecture
// then we'll treat is as an x86 package
sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL); DebugMsg((DL_VERBOSE, TEXT("No platform detected, assuming x86."))); } ppi->cPlatforms = sPlatforms.size(); ppi->prgPlatform = (CSPLATFORM *) OLEALLOC(sizeof(CSPLATFORM) * (ppi->cPlatforms));; if (!ppi->prgPlatform) { ppi->cPlatforms = 0; goto out_of_memory; }
INT iIndex=0; set<DWORD>::iterator iPlatform;
for (iPlatform = sPlatforms.begin(); iPlatform != sPlatforms.end(); iPlatform++, iIndex++) { ppi->prgPlatform[iIndex].dwPlatformId = VER_PLATFORM_WIN32_NT; ppi->prgPlatform[iIndex].dwVersionHi = 5; ppi->prgPlatform[iIndex].dwVersionLo = 0; ppi->prgPlatform[iIndex].dwProcessorArch = *iPlatform; }
ppi->prgLocale = (LCID *) OLEALLOC(sizeof(LCID)); if (!ppi->prgLocale) { goto out_of_memory; } ppi->cLocales = 1; ppi->prgLocale[0] = 0; // if none is supplied we assume language neutral
dw = GetPrivateProfileString( L"Application", L"LCID", NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (dw) { (void) swscanf(szBuffer, L"%i", &ppi->prgLocale[0]); // we only deploy one LCID (the primary one)
}
// Get the list of extensions
dw = GetPrivateProfileString( L"ext", NULL, NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (dw) { vector<CString> v; TCHAR szName[256]; while (sz < &szBuffer[dw]) { while ('.' == sz[0]) sz++; CString szExt = "."; szExt += sz; v.push_back(szExt); sz += (wcslen(sz) + 1); } // build the new list
UINT n = v.size(); if (n > 0) { pai->prgShellFileExt = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n); if (!pai->prgShellFileExt) { goto out_of_memory; } pai->prgPriority = (UINT *) OLEALLOC(sizeof(UINT) * n); if (!pai->prgPriority) { goto out_of_memory; } pai->cShellFileExt = n; while (n--) { CString &szLower = v[n]; szLower.MakeLower(); OLESAFE_COPYSTRING(pai->prgShellFileExt[n], szLower); pai->prgPriority[n] = 0; } } }
// get the list of CLSIDs
vector<CLASSDETAIL> v; sz = szBuffer; dw = GetPrivateProfileString( L"CLSIDs", NULL, NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (dw) { while (sz < &szBuffer[dw]) { OLECHAR szType[256]; DWORD dwSubKey = GetPrivateProfileString( L"CLSIDs", sz, NULL, szType, sizeof(szType) / sizeof(szType[0]), szPackagePath); CLASSDETAIL cd; memset(&cd, 0, sizeof(CLASSDETAIL)); hr = CLSIDFromString(sz, &cd.Clsid); if (SUCCEEDED(hr)) { CString szTypes = szType; szTypes.MakeLower(); if (szTypes.Find(L"inprocserver32") >= 0) { cd.dwComClassContext |= CLSCTX_INPROC_SERVER; } if (szTypes.Find(L"localserver32") >= 0) { cd.dwComClassContext |= CLSCTX_LOCAL_SERVER; } if (szTypes.Find(L"inprochandler32") >= 0) { cd.dwComClassContext |= CLSCTX_INPROC_HANDLER; } v.push_back(cd); } sz += (wcslen(sz) + 1); } }
// get the list of ProgIDs
sz = szBuffer; dw = GetPrivateProfileString( L"ProgIDs", NULL, NULL, sz, sizeof(szBuffer) / sizeof(szBuffer[0]), szPackagePath); if (dw) { while (sz < &szBuffer[dw]) { OLECHAR szType[256]; DWORD dwSubKey = GetPrivateProfileString( L"ProgIDs", sz, NULL, szType, sizeof(szType) / sizeof(szType[0]), szPackagePath); CLSID cid; hr = CLSIDFromString(sz, &cid); if (SUCCEEDED(hr)) { // Match it to its CLASSDETAIL structure and insert it into the
// ProgID list.
// (fat and slow method)
vector<CLASSDETAIL>::iterator i; for (i = v.begin(); i != v.end(); i++) { if (0 == memcmp(&i->Clsid, &cid, sizeof(CLSID))) { // found a match
// hereiam
vector <CString> vIds; CString szAppIds = szType; CString szTemp; while (szAppIds.GetLength()) { szTemp = szAppIds.SpanExcluding(L","); szTemp.TrimLeft(); vIds.push_back(szTemp); szAppIds = szAppIds.Mid(szTemp.GetLength()+1); } while (i->cProgId--) { OLESAFE_DELETE(i->prgProgId[i->cProgId]); } OLESAFE_DELETE(i->prgProgId); DWORD cProgId = vIds.size(); LPOLESTR * prgProgId = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * (cProgId)); if (!prgProgId) { goto out_of_memory; } i->cProgId = cProgId; while (cProgId--) { OLESAFE_COPYSTRING(prgProgId[cProgId], vIds[cProgId]); } i->prgProgId = prgProgId; } } } sz += (wcslen(sz) + 1); } }
// create the list of CLASSDETAIL structures
{ UINT n = v.size(); if (n > 0) { pai->pClasses = (CLASSDETAIL *) OLEALLOC(sizeof(CLASSDETAIL) * n); if (!pai->pClasses) { goto out_of_memory; } pai->cClasses = n; while (n--) { pai->pClasses[n] = v[n]; } } }
ppd->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR)); if (!ppd->pszSourceList) { goto out_of_memory; } ppd->cSources = 1; OLESAFE_COPYSTRING(ppd->pszSourceList[0], szPackagePath);
GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint); OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName);
// Popup UI
pii->PathType = SetupNamePath;
BOOL fShowPropertyPage = FALSE;
hr = GetDeploymentType(ppd, fShowPropertyPage);
if (SUCCEEDED(hr)) { CHourglass hourglass; if (m_ToolDefaults.fZapOn64) { pii->dwActFlags |= ACTFLG_ExcludeX86OnWin64; // same as ACTFLG_ZAP_IncludeX86OfWin64
} do { hr = DeployPackage(ppd, fShowPropertyPage); if (hr == CS_E_OBJECT_ALREADY_EXISTS) { OLESAFE_DELETE(ppd->pszPackageName); GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint); OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName); } } while (hr == CS_E_OBJECT_ALREADY_EXISTS); }
if (FAILED(hr) && hr != E_FAIL) // don't report E_FAIL error
// because it's a benign error
// (probably a dialog cancellation)
{ // report the error in the event log
LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_DEPLOYMENT_ERROR, hr, lpFileTitle);
// now try to come up with a meaningful message for the user
if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr) { // access permission failure
::LoadString(ghInstance, IDS_ADDFAILED_ACCESS_DENIED, szBuffer, 256); } else { switch (hr) { // For these errors, we'll report the party line:
case CS_E_CLASS_NOTFOUND: case CS_E_INVALID_VERSION: case CS_E_NO_CLASSSTORE: case CS_E_OBJECT_NOTFOUND: case CS_E_OBJECT_ALREADY_EXISTS: case CS_E_INVALID_PATH: case CS_E_NETWORK_ERROR: case CS_E_ADMIN_LIMIT_EXCEEDED: case CS_E_SCHEMA_MISMATCH: case CS_E_PACKAGE_NOTFOUND: case CS_E_INTERNAL_ERROR: { dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), NULL); if (0 != dw) { // got a valid message string
break; } // otherwise fall through and give the generic message
} // Either these CS errors don't apply or an admin
// wouldn't know what they mean:
case CS_E_NOT_DELETABLE: default: // generic class store problem
::LoadString(ghInstance, IDS_ADDFAILED_CSFAILURE, szBuffer, 256); break; } } #if DBG
TCHAR szDebugBuffer[256]; dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szDebugBuffer, sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]), NULL); if (0 == dw) { (void) StringCchPrintf(szDebugBuffer, sizeof(szDebugBuffer)/sizeof(szDebugBuffer[0]), TEXT("(HRESULT: 0x%lX)"), hr); } (void) StringCchCat(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szDebugBuffer); #endif
m_pConsole->MessageBox(szBuffer, lpFileTitle, MB_OK | MB_ICONEXCLAMATION, NULL); } FreePackageDetail(ppd); }
return hr; out_of_memory: if (ppd) { LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, E_OUTOFMEMORY); InternalFreePackageDetail(ppd); delete ppd; } return E_OUTOFMEMORY; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::AddMSIPackage
//
// Synopsis: Add's one or more packages to the class store and adds the
// appropriate entries to the result pane.
//
// Arguments: [szPackagePath] - Full path to the Darwin package.
// [lpFileTitle] - file title from the open file dialog (used
// for UI)
//
// Returns: S_OK - succeeded
// E_FAIL - benign failure (probably a cancellation or something)
// other - significant failure
//
// History: 2-03-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CScopePane::AddMSIPackage(LPCOLESTR szPackagePath, LPCOLESTR lpFileTitle) { CHourglass hourglass; AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = E_FAIL; BOOL fPreparationDone = FALSE; // Used to identify if the routine has
// progressed passed the "prep" stage
// and is now in the deployment stage.
// Errors in the earlier part are most
// likely due to Darwin problems.
// Errors in teh latter part are most
// likely due to Class Store problems.
set<LCID> sLocales; CUpgrades dlgUpgrade; int nLocales; set<LCID>::iterator iLocale; PACKAGEDETAIL *ppd = NULL; CString szFriendlyName; CString szUniqueFriendlyName; int nHint = 1;
ASSERT(m_pConsole); { BOOL fShowPropertySheet = FALSE; GUID guid; INSTALLINFO *pii = NULL; PLATFORMINFO *ppi = NULL; ACTIVATIONINFO *pai = NULL; ppd = new PACKAGEDETAIL; if (!ppd) { goto out_of_memory; } memset(ppd, 0, sizeof(PACKAGEDETAIL)); pii = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO)); if (!pii) { goto out_of_memory; } memset(pii, 0, sizeof(INSTALLINFO)); ppi = (PLATFORMINFO *) OLEALLOC(sizeof(PLATFORMINFO)); ppd->pPlatformInfo = ppi; if (!ppi) { goto out_of_memory; } ppd->pInstallInfo = pii; memset(ppi, 0, sizeof(PLATFORMINFO)); pai = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO)); ppd->pActInfo = pai; if (!pai) { goto out_of_memory; } else { memset(pai, 0, sizeof(ACTIVATIONINFO));
pai->bHasClasses = ! m_ToolDefaults.fExtensionsOnly;
pii->PathType = DrwFilePath;
hr = GetDeploymentType(ppd, fShowPropertySheet); CHourglass hourglass; if (FAILED(hr)) { goto done; } if (!m_ToolDefaults.f32On64) { pii->dwActFlags |= ACTFLG_ExcludeX86OnWin64; // same as ACTFLG_ZAP_IncludeX86OfWin64
} if (m_ToolDefaults.fUninstallOnPolicyRemoval) { pii->dwActFlags |= ACTFLG_UninstallOnPolicyRemoval; } else { pii->dwActFlags |= ACTFLG_OrphanOnPolicyRemoval; } if (m_fMachine) { pii->dwActFlags |= ACTFLG_ForceUpgrade; } pii->InstallUiLevel = m_ToolDefaults.UILevel;
// disable MSI ui
MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
// Use MsiSummaryInfoGetProperty to get platform and locale info.
{ MSIHANDLE hSummaryInfo; UINT msiReturn = MsiGetSummaryInformation(0, szPackagePath, 0, &hSummaryInfo); if (ERROR_SUCCESS == msiReturn) { TCHAR szBuffer[256]; DWORD dwSize = 256; msiReturn = MsiSummaryInfoGetProperty(hSummaryInfo, 7, // PID_TEMPLATE
NULL, NULL, NULL, szBuffer, &dwSize); if (ERROR_SUCCESS == msiReturn) { // break out the locale and platform properties
CString szLocales = szBuffer; CString szPlatforms = szLocales.SpanExcluding(L";"); szLocales = szLocales.Mid(szPlatforms.GetLength()+1); CString szTemp; set<DWORD> sPlatforms; BOOL fValidPlatform; BOOL fPlatformsSpecified;
fValidPlatform = FALSE;
fPlatformsSpecified = 0 != szPlatforms.GetLength();
while (szPlatforms.GetLength()) { szTemp = szPlatforms.SpanExcluding(L","); if (0 == szTemp.CompareNoCase(L"intel")) { sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL); fValidPlatform = TRUE; } else if (0 == szTemp.CompareNoCase(L"amd64")) { sPlatforms.insert(PROCESSOR_ARCHITECTURE_AMD64); fValidPlatform = TRUE; } else if (0 == szTemp.CompareNoCase(L"intel64")) { sPlatforms.insert(PROCESSOR_ARCHITECTURE_IA64); fValidPlatform = TRUE; } szPlatforms = szPlatforms.Mid(szTemp.GetLength()+1); }
//
// If platforms have been specified, at least one of them
// must be valid
//
if ( fPlatformsSpecified && ! fValidPlatform ) { hr = HRESULT_FROM_WIN32( ERROR_INSTALL_PLATFORM_UNSUPPORTED ); ppi->cPlatforms = 0; goto done; }
while (szLocales.GetLength()) { szTemp = szLocales.SpanExcluding(L","); LCID lcid; if (swscanf(szTemp, L"%i", &lcid) != EOF) { sLocales.insert(lcid); szLocales = szLocales.Mid(szTemp.GetLength()+1); } } if (0 == sPlatforms.size()) { // If the MSI file doesn't specify an architecture
// then we'll mark it X86-allow on Win64.
sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL); pii->dwActFlags &= ~ACTFLG_ExcludeX86OnWin64; DebugMsg((DL_VERBOSE, TEXT("No platform detected, setting to X86 - allow on Win64."))); } if (0 == sLocales.size()) { // If the MSI file doesn't specify a locale then
// we'll just assume it's language neutral.
DebugMsg((DL_VERBOSE, TEXT("No locale detected, assuming neutral."))); sLocales.insert(0); } ppi->cPlatforms = sPlatforms.size(); ppi->prgPlatform = (CSPLATFORM *) OLEALLOC(sizeof(CSPLATFORM) * (ppi->cPlatforms));; if (!ppi->prgPlatform) { ppi->cPlatforms = 0; goto out_of_memory; } set<DWORD>::iterator iPlatform; INT n = 0; for (iPlatform = sPlatforms.begin(); iPlatform != sPlatforms.end(); iPlatform++, n++) { ppi->prgPlatform[n].dwPlatformId = VER_PLATFORM_WIN32_NT; ppi->prgPlatform[n].dwVersionHi = 5; ppi->prgPlatform[n].dwVersionLo = 0; ppi->prgPlatform[n].dwProcessorArch = *iPlatform; } } MsiCloseHandle(hSummaryInfo); } if (ERROR_SUCCESS != msiReturn) { hr = HRESULT_FROM_WIN32(msiReturn); LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle); goto done; } } { // Grovel through the database to get additional information
// that for some reason MSI won't give us any other way.
TCHAR szBuffer[256]; DWORD cch = 256; UINT msiReturn = GetMsiProperty(szPackagePath, L"ProductVersion", szBuffer, &cch); if (ERROR_SUCCESS != msiReturn) { hr = HRESULT_FROM_WIN32(msiReturn); LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle); goto done; } if (ERROR_SUCCESS == msiReturn) { // Parse Product Version
CString sz = szBuffer; sz.TrimLeft(); CString szTemp = sz.SpanIncluding(L"0123456789"); if (swscanf(szTemp, L"%u", &pii->dwVersionHi) == EOF) { hr = HRESULT_FROM_WIN32(GetLastError()); LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle); goto done; }
sz = sz.Mid(szTemp.GetLength()); szTemp = sz.SpanExcluding(L"0123456789"); sz = sz.Mid(szTemp.GetLength()); if (swscanf(sz, L"%u", &pii->dwVersionLo) == EOF) { hr = HRESULT_FROM_WIN32(GetLastError()); LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle); goto done; } } cch = 256; msiReturn = GetMsiProperty(szPackagePath, L"ProductCode", szBuffer, &cch); if (ERROR_SUCCESS != msiReturn) { hr = HRESULT_FROM_WIN32(msiReturn); LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, lpFileTitle); goto done; } if (ERROR_SUCCESS == msiReturn) { // Parse Product Code
CLSIDFromString(szBuffer, &pii->ProductCode); } cch = 256; msiReturn = GetMsiProperty(szPackagePath, L"ARPHELPLINK", szBuffer, &cch); if (ERROR_SUCCESS == msiReturn) { OLESAFE_COPYSTRING(pii->pszUrl, szBuffer); } cch = 256; msiReturn = GetMsiProperty(szPackagePath, L"LIMITUI", szBuffer, &cch); if (ERROR_SUCCESS == msiReturn) { pii->dwActFlags |= ACTFLG_MinimalInstallUI; pii->InstallUiLevel = INSTALLUILEVEL_BASIC; } } ppi->prgLocale = (LCID *) OLEALLOC(sizeof(LCID)); if (!ppi->prgLocale) { goto out_of_memory; } ppi->cLocales = 1; ppd->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR)); if (!ppd->pszSourceList) { goto out_of_memory; } ppd->cSources = 1; OLESAFE_COPYSTRING(ppd->pszSourceList[0], szPackagePath);
if (S_OK == DetectUpgrades(szPackagePath, ppd, dlgUpgrade)) { UINT n = dlgUpgrade.m_UpgradeList.size(); if (n) { pii->prgUpgradeInfoList = (UPGRADEINFO *) OLEALLOC(sizeof(UPGRADEINFO) * n); if (!pii->prgUpgradeInfoList) { goto out_of_memory; } pii->cUpgrades = n; map<CString, CUpgradeData>::iterator i = dlgUpgrade.m_UpgradeList.begin(); while (n--) { pii->prgUpgradeInfoList[n].Flag = i->second.m_flags; OLESAFE_COPYSTRING(pii->prgUpgradeInfoList[n].szClassStore, i->second.m_szClassStore); memcpy(&pii->prgUpgradeInfoList[n].PackageGuid, &i->second.m_PackageGuid, sizeof(GUID)); i++; } } }
//
// Only one locale may be specified for this package
//
nLocales = 1; iLocale = sLocales.begin();
{ ppi->prgLocale[0] = *iLocale;
// set the script path
hr = CoCreateGuid(&guid); if (FAILED(hr)) { goto done; } OLECHAR sz [256]; StringFromGUID2(guid, sz, 256); CString szScriptPath = m_szGPT_Path; szScriptPath += L"\\"; szScriptPath += sz; szScriptPath += L".aas"; OLESAFE_DELETE(pii->pszScriptPath); OLESAFE_COPYSTRING(pii->pszScriptPath, szScriptPath);
HWND hwnd; m_pConsole->GetMainWindow(&hwnd); hr = BuildScriptAndGetActInfo(*ppd, m_ToolDefaults.fExtensionsOnly);
// make sure the name is unique
szFriendlyName = ppd->pszPackageName; GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint); OLESAFE_DELETE(ppd->pszPackageName); OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName);
if (SUCCEEDED(hr)) { fPreparationDone = TRUE; do { hr = DeployPackage(ppd, fShowPropertySheet); if (hr == CS_E_OBJECT_ALREADY_EXISTS) { GetUniquePackageName(szFriendlyName, szUniqueFriendlyName, nHint); OLESAFE_DELETE(ppd->pszPackageName); OLESAFE_COPYSTRING(ppd->pszPackageName, szUniqueFriendlyName); } } while (hr == CS_E_OBJECT_ALREADY_EXISTS); } if (FAILED(hr)) { // clean up script file if deployment fails
DeleteFile(pii->pszScriptPath); } } done: if (FAILED(hr) && hr != E_FAIL) // don't report E_FAIL error
// because it's a benign error
// (probably a dialog cancellation)
{ // report the error in the event log
LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_DEPLOYMENT_ERROR, hr, lpFileTitle);
TCHAR szBuffer[256]; if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr) { // access permission failure
::LoadString(ghInstance, IDS_ADDFAILED_ACCESS_DENIED, szBuffer, 256); } else if ( HRESULT_FROM_WIN32( ERROR_INSTALL_PLATFORM_UNSUPPORTED ) == hr ) { ::LoadString(ghInstance, IDS_ILLEGAL_PLATFORM, szBuffer, 256); } else if ( HRESULT_FROM_WIN32( CS_E_ADMIN_LIMIT_EXCEEDED ) == hr ) { ::LoadString(ghInstance, IDS_ADDFAILED_METADATA_OVERFLOW, szBuffer, 256); } else { if (fPreparationDone) { switch (hr) { // For these errors, we'll report the party line:
case CS_E_CLASS_NOTFOUND: case CS_E_INVALID_VERSION: case CS_E_NO_CLASSSTORE: case CS_E_OBJECT_NOTFOUND: case CS_E_OBJECT_ALREADY_EXISTS: case CS_E_INVALID_PATH: case CS_E_NETWORK_ERROR: case CS_E_SCHEMA_MISMATCH: case CS_E_PACKAGE_NOTFOUND: case CS_E_INTERNAL_ERROR: { DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), NULL); if (0 != dw) { // got a valid message string
break; } // otherwise fall through and give the generic message
} // Either these CS errors don't apply or an admin
// wouldn't know what they mean:
case CS_E_NOT_DELETABLE: default: // generic class store problem
::LoadString(ghInstance, IDS_ADDFAILED_CSFAILURE, szBuffer, 256); break; } } else { // probably some error with the package itself
::LoadString(ghInstance, IDS_ADDFAILED, szBuffer, 256); } } #if DBG
TCHAR szDebugBuffer[256]; DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szDebugBuffer, sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]), NULL); if (0 == dw) { (void) StringCchPrintf(szDebugBuffer, sizeof(szDebugBuffer)/sizeof(szDebugBuffer[0]), TEXT("(HRESULT: 0x%lX)"), hr); } (void) StringCchCat(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szDebugBuffer); #endif
m_pConsole->MessageBox(szBuffer, lpFileTitle, MB_OK | MB_ICONEXCLAMATION, NULL); } InternalFreePackageDetail(ppd); delete ppd; } } return hr; out_of_memory: if (ppd) { LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, E_OUTOFMEMORY); InternalFreePackageDetail(ppd); delete ppd; } return E_OUTOFMEMORY; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::DetectUpgrades
//
// Synopsis: This functions checks if any of the existing packages in the
// class store can be upgraded by a given package. If any such
// packages exist, then this function populates the m_UpgradeList
// member of the dlgUpgrade parameter passed to it. This function
// also adds the upgrade code GUID to the PACKAGEDETAIL structure
// passed to it.
//
// Arguments:
// szPackagePath - the path of the given package
// ppd - pointer to the PACKAGEDETAIL structure of the
// given package
// dlgUpgrade - the dialog whose member m_UpgradeList needs to be
// populated
//
// Returns:
// S_OK the function succeeded in finding upgradeable packages
// S_FALSE the function did not encounter any errors, but no
// upgradeable packages were found
// other failure codes the function encountered errors
//
// History: 5/19/1998 RahulTh created
//
// Notes:
//
//---------------------------------------------------------------------------
HRESULT CScopePane::DetectUpgrades (LPCOLESTR szPackagePath, const PACKAGEDETAIL* ppd, CUpgrades& dlgUpgrade) { DWORD dwBufSize = 50; TCHAR szUpgradeCode[50]; //the upgrade GUID
GUID guidUpgradeCode; TCHAR szData[50]; DWORD dwOperator; HRESULT hr; HRESULT hres; MSIHANDLE hDatabase; UINT msiReturn; map<MMC_COOKIE, CAppData>::iterator i; INSTALLINFO* pii; BOOL fUpgradeable; LARGE_INTEGER verNew, verExisting; CString szCSPath; hr = GetClassStoreName(szCSPath, FALSE); if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr)); }
msiReturn = GetMsiProperty(szPackagePath, TEXT("UpgradeCode"), szUpgradeCode, &dwBufSize); if (ERROR_SUCCESS != msiReturn) return HRESULT_FROM_WIN32(msiReturn); //no upgrade code was found
hr = CLSIDFromString(szUpgradeCode, &guidUpgradeCode); if (FAILED(hr)) return hr;
//insert the upgrade code GUID into the packagedetail structure.
memcpy((LPVOID)&(ppd->pInstallInfo->Mvipc), (LPVOID)&guidUpgradeCode, sizeof(GUID));
verNew.LowPart = ppd->pInstallInfo->dwVersionLo; verNew.HighPart = ppd->pInstallInfo->dwVersionHi; hr = S_FALSE; //this will get set to S_OK only if we find any upgradeable packages
msiReturn = MsiOpenDatabase (szPackagePath, MSIDBOPEN_READONLY, &hDatabase); if (ERROR_SUCCESS == msiReturn) { CString szQuery; szQuery.Format (TEXT("SELECT `UpgradeCode`, `Attributes`, `VersionMin`, `VersionMax`, `Language` FROM `Upgrade`")); MSIHANDLE hView; msiReturn = MsiDatabaseOpenView(hDatabase, szQuery, &hView); if (ERROR_SUCCESS == msiReturn) { msiReturn = MsiViewExecute (hView, 0); if (ERROR_SUCCESS == msiReturn) { MSIHANDLE hRecord; //for each operator value returned by the query, if an operator is found that permits
//upgrades, iterate through the list of existing packages to see if any of those are
//upgradeable by the supplied package. If any such package is found, add it to the
//m_UpgradeList member of the upgrade dialog dlgUpgrade.
do { msiReturn = MsiViewFetch (hView, &hRecord); if (ERROR_SUCCESS == msiReturn) { //reset dwBufSize since it is modified by MsiRecordString during every iteration
//of the loop.
dwBufSize = 50; //get the upgrade code for this upgrade table entry
msiReturn = MsiRecordGetString (hRecord, 1, szData, &dwBufSize); hres = CLSIDFromString (szData, &guidUpgradeCode); if (FAILED(hres)) { MsiCloseHandle(hRecord); continue; //ignore this package and move on to the next
} dwBufSize = 50; //must reset to reflect the correct buffer size
//get the operator for this upgrade table entry
msiReturn = MsiRecordGetString (hRecord, 2, szData, &dwBufSize); int iRetVal; iRetVal = swscanf(szData, TEXT("%d"), &dwOperator); if ((iRetVal != EOF) && (0 == (dwOperator & 0x002))) { // we have a potential hit
LARGE_INTEGER verMin; LARGE_INTEGER verMax;
// get min version
dwBufSize = 50; //must reset to reflect the correct buffer size
BOOL fMin = FALSE; msiReturn = MsiRecordGetString (hRecord, 3, szData, &dwBufSize); if (ERROR_SUCCESS == msiReturn && 0 != szData[0]) { fMin = TRUE; // Parse Product Version
CString sz = szData; sz.TrimLeft(); CString szTemp = sz.SpanIncluding(L"0123456789");
if (swscanf(szTemp, L"%u", &verMin.HighPart) != EOF) { sz = sz.Mid(szTemp.GetLength()); szTemp = sz.SpanExcluding(L"0123456789"); sz = sz.Mid(szTemp.GetLength()); if (swscanf(sz, L"%u", &verMin.LowPart) == EOF) { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(GetLastError()), szPackagePath); } } else { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(GetLastError()), szPackagePath); } } else { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath); }
// get max version
dwBufSize = 50; //must reset to reflect the correct buffer size
BOOL fMax = FALSE; msiReturn = MsiRecordGetString (hRecord, 4, szData, &dwBufSize); if (ERROR_SUCCESS == msiReturn && 0 != szData[0]) { fMax = TRUE; // Parse Product Version
CString sz = szData; sz.TrimLeft(); CString szTemp = sz.SpanIncluding(L"0123456789"); if (swscanf(szTemp, L"%u", &verMax.HighPart) != EOF) { sz = sz.Mid(szTemp.GetLength()); szTemp = sz.SpanExcluding(L"0123456789"); sz = sz.Mid(szTemp.GetLength()); if (swscanf(sz, L"%u", &verMax.LowPart) == EOF) { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(GetLastError()), szPackagePath); } } else { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(GetLastError()), szPackagePath); } } else { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath); } // get lcid list
dwBufSize = 0; //must reset to reflect the correct buffer size
BOOL fLcids = FALSE; set<LCID> sLCID; msiReturn = MsiRecordGetString (hRecord, 5, szData, &dwBufSize); if (ERROR_MORE_DATA == msiReturn) { dwBufSize++; TCHAR * szLanguages = new TCHAR[dwBufSize]; if (szLanguages) { msiReturn = MsiRecordGetString (hRecord, 5, szLanguages, &dwBufSize); if (ERROR_SUCCESS == msiReturn) { // build set of LCIDs
CString sz = szLanguages; sz.TrimLeft(); while (!sz.IsEmpty()) { fLcids = TRUE; LCID lcid; CString szTemp = sz.SpanIncluding(L"0123456789"); if (swscanf(szTemp, L"%u", &lcid) != EOF) { sz = sz.Mid(szTemp.GetLength()); szTemp = sz.SpanExcluding(L"0123456789"); sz = sz.Mid(szTemp.GetLength()); sLCID.insert(lcid); } else { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(GetLastError()), szPackagePath);
} } } else { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath); } delete [] szLanguages; } } else { LogADEEvent(EVENTLOG_WARNING_TYPE, EVENT_ADE_UNEXPECTEDMSI_ERROR, HRESULT_FROM_WIN32(msiReturn), szPackagePath); }
//if an operator is found that that does not block installs and
//does not force uninstalling of existing apps, then search
//for any packages that can be upgraded
for (i = m_AppData.begin(); i != m_AppData.end(); i++) { //get the install info. for the app.
pii = (i->second.m_pDetails)->pInstallInfo; //process this only if it has the same upgrade code
if ( (guidUpgradeCode == pii->Mvipc) && ! IsNullGUID(&guidUpgradeCode) ) { //check if other conditions for the operator are satisfied.
verExisting.LowPart = pii->dwVersionLo; verExisting.HighPart = pii->dwVersionHi;
// don't even bother to upgrade unless the
// new version is greater or equal to the
// old version
fUpgradeable = (verNew.QuadPart >= verExisting.QuadPart);
if (fMin && fUpgradeable) { // check minimum
if (0 != (dwOperator & 0x100)) { // inclusive
fUpgradeable = verExisting.QuadPart >= verMin.QuadPart; } else { // exclusive
fUpgradeable = verExisting.QuadPart > verMin.QuadPart; } }
if (fMax && fUpgradeable) { // check maximum
if (0 != (dwOperator & 0x200)) { // inclusive
fUpgradeable = verExisting.QuadPart <= verMax.QuadPart; } else { // exclusive
fUpgradeable = verExisting.QuadPart < verMax.QuadPart; } }
if (fLcids && fUpgradeable) { // check the lcid
BOOL fMatch = FALSE;
// look for a match
PLATFORMINFO * ppi = (i->second.m_pDetails)->pPlatformInfo;
UINT n = ppi->cLocales; while ((n--) && !fMatch) { if (sLCID.end() != sLCID.find(ppi->prgLocale[n])) { fMatch = TRUE; } }
// set the upgradeable flag
if (0 != (dwOperator & 0x400)) { // exclusive
fUpgradeable = !fMatch; } else { // inclusive
fUpgradeable = fMatch; } }
if (fUpgradeable) //the package in question can be upgraded
{ CUpgradeData data; data.m_szClassStore = szCSPath; memcpy(&data.m_PackageGuid, &pii->PackageGuid, sizeof(GUID)); data.m_flags = UPGFLG_NoUninstall | UPGFLG_Enforced; dlgUpgrade.m_UpgradeList.insert(pair<const CString, CUpgradeData>(GetUpgradeIndex(data.m_PackageGuid), data)); hr = S_OK; } } } } MsiCloseHandle(hRecord); } } while (NULL != hRecord && ERROR_SUCCESS == msiReturn); MsiViewClose (hView); //close the view to be on the safe side, though it is not absolutely essential
} else hr = HRESULT_FROM_WIN32(msiReturn);
MsiCloseHandle(hView); } else hr = HRESULT_FROM_WIN32(msiReturn);
MsiCloseHandle (hDatabase); } else hr = HRESULT_FROM_WIN32(msiReturn);
if (FAILED(hr)) { if (msiReturn != ERROR_SUCCESS) { LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_BADMSI_ERROR, hr, szPackagePath); } else { LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_GENERAL_ERROR, hr); } }
return hr; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::DisplayPropSheet
//
// Synopsis: a generic routine for showing the property sheet for a package
//
// Arguments: [szPackeName] - name of the package to show properties for
// [iPage] - index of the preferred page to display
//
// Returns: nothing
//
// History: 3-11-1998 stevebl Created
//
// Notes: The property sheet will be started on the preferred page
// only if it isn't already being displayed, in which case
// whatever page was being displayed will retain the focus.
//
//---------------------------------------------------------------------------
void CScopePane::DisplayPropSheet(CString szPackageName, int iPage) { map <MMC_COOKIE, CAppData>::iterator i = m_AppData.begin(); while (i != m_AppData.end()) { if (0 == szPackageName.Compare(i->second.m_pDetails->pszPackageName)) { IDataObject * pDataObject; HRESULT hr = QueryDataObject(i->first, CCT_RESULT, &pDataObject); if (SUCCEEDED(hr)) { set <CResultPane *>::iterator i2; for (i2 = m_sResultPane.begin(); i2 != m_sResultPane.end(); i2++) { hr = m_pIPropertySheetProvider->FindPropertySheet(i->first, (*i2), pDataObject); if (S_FALSE == hr) { m_pIPropertySheetProvider->CreatePropertySheet(i->second.m_pDetails->pszPackageName, TRUE, i->first, pDataObject, 0); m_pIPropertySheetProvider->AddPrimaryPages((*i2)->GetUnknown(), FALSE, NULL, FALSE); m_pIPropertySheetProvider->AddExtensionPages(); m_pIPropertySheetProvider->Show(NULL, iPage); } } } return; } i++; } }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::RemovePackage
//
// Synopsis: Removes a package from the class store and the result pane.
//
// Arguments: [pDataObject] - data object for this result pane item
// [fForceUninstall] - TRUE - force app to be uninstalled on
// client machines
// FALSE - orphan any installations
//
// Returns: S_OK - success
//
// History: 2-03-1998 stevebl Created
// 3-30-1998 stevebl adde fForceUninstall
//
// Notes: bAssigned is used
//
//---------------------------------------------------------------------------
HRESULT CScopePane::RemovePackage(MMC_COOKIE cookie, BOOL fForceUninstall, BOOL fRemoveNow) { BOOL fAssigned; HRESULT hr = E_FAIL; // put up an hourglass (this could take a while)
CHourglass hourglass; CAppData & data = m_AppData[cookie]; CString szPackageName = data.m_pDetails->pszPackageName;
// We are now not removing script files here; instead the script
// file will be removed by the class store code when the package
// is actually removed from the DS.
#if 0
// only remove script files for packages that have script files
if (data.m_pDetails->pInstallInfo->PathType == DrwFilePath) { // We need to make sure it gets removed from
// the GPT before we delete it from the class store.
// check to see if it's an old style relative path
if (L'\\' != data.m_pDetails->pInstallInfo->pszScriptPath[0]) { // find the last element in the path
int iBreak = m_szGPT_Path.ReverseFind(L'{'); CString sz = m_szGPT_Path.Left(iBreak-1); sz += L"\\"; sz += data.m_pDetails->pInstallInfo->pszScriptPath; DeleteFile(sz); } else DeleteFile(data.m_pDetails->pInstallInfo->pszScriptPath); } #endif
if (0 != (data.m_pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned)) { fAssigned = TRUE; } else { fAssigned = FALSE; } hr = m_pIClassAdmin->RemovePackage((LPOLESTR)((LPCOLESTR)(data.m_pDetails->pszPackageName)), fRemoveNow ? 0 : ((fForceUninstall ? ACTFLG_Uninstall : ACTFLG_Orphan) | (data.m_pDetails->pInstallInfo->dwActFlags & (ACTFLG_ExcludeX86OnWin64 | ACTFLG_IgnoreLanguage))) );
if (SUCCEEDED(hr)) { // Notify clients of change
if (FAILED(m_pIGPEInformation->PolicyChanged(m_fMachine, TRUE, &guidExtension, m_fMachine ? &guidMachSnapin : &guidUserSnapin))) { ReportPolicyChangedError(m_hwndMainWindow); }
#if 0
if (data.m_fVisible) { set <CResultPane *>::iterator i; for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++) { (*i)->m_pResult->DeleteItem(data.m_itemID, 0); } } if (SUCCEEDED(hr)) { CString szCSPath; hr = GetClassStoreName(szCSPath, FALSE); if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr)); }
// remove its entries in the extension table
RemoveExtensionEntry(cookie, data); if (m_pFileExt) { m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0); } RemoveUpgradeEntry(cookie, data); m_UpgradeIndex.erase(GetUpgradeIndex(data.m_pDetails->pInstallInfo->PackageGuid)); // If this thing upgraded other apps or had apps that were
// upgrading, make sure that they get the proper icons and any
// property sheets get updated.
UINT n = data.m_pDetails->pInstallInfo->cUpgrades; while (n--) { map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(data.m_pDetails->pInstallInfo->prgUpgradeInfoList[n].PackageGuid)); if (i != m_UpgradeIndex.end()) { RESULTDATAITEM rd; memset(&rd, 0, sizeof(rd)); rd.mask = RDI_IMAGE; rd.itemID = m_AppData[i->second].m_itemID; rd.nImage = m_AppData[i->second].GetImageIndex(this); set <CResultPane *>::iterator i2; for (i2 = m_sResultPane.begin(); i2 != m_sResultPane.end(); i2++) { (*i2)->m_pResult->SetItem(&rd); } if (m_AppData[i->second].m_pUpgradeList) { m_AppData[i->second].m_pUpgradeList->SendMessage(WM_USER_REFRESH, 0, 0); } } } FreePackageDetail(data.m_pDetails); m_AppData.erase(cookie); set <CResultPane *>::iterator i; for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++) { (*i)->m_pResult->Sort((*i)->m_nSortColumn, (*i)->m_dwSortOptions, -1); } } #else
// just force a refresh
Refresh(); } #endif
else { DebugMsg((DM_WARNING, TEXT("RemovePackage failed with 0x%x"), hr)); }
if (FAILED(hr) && hr != E_FAIL) // don't report E_FAIL error
{ LogADEEvent(EVENTLOG_ERROR_TYPE, EVENT_ADE_REMOVE_ERROR, hr, data.m_pDetails->pszPackageName); TCHAR szBuffer[256]; if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr) { // access permission failure
::LoadString(ghInstance, IDS_DELFAILED_ACCESS_DENIED, szBuffer, 256); } else { switch (hr) { // For these errors, we'll report the party line:
case CS_E_CLASS_NOTFOUND: case CS_E_INVALID_VERSION: case CS_E_NO_CLASSSTORE: case CS_E_OBJECT_NOTFOUND: case CS_E_OBJECT_ALREADY_EXISTS: case CS_E_INVALID_PATH: case CS_E_NETWORK_ERROR: case CS_E_ADMIN_LIMIT_EXCEEDED: case CS_E_SCHEMA_MISMATCH: case CS_E_PACKAGE_NOTFOUND: case CS_E_INTERNAL_ERROR: case CS_E_NOT_DELETABLE: { DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), NULL); if (0 != dw) { // got a valid message string
break; } // otherwise fall through and give the generic message
} // Either these CS errors don't apply or an admin
// wouldn't know what they mean:
default: // generic class store problem
::LoadString(ghInstance, IDS_DELFAILED_CSFAILURE, szBuffer, 256); break; } } #if DBG
TCHAR szDebugBuffer[256]; DWORD dw = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szDebugBuffer, sizeof(szDebugBuffer) / sizeof(szDebugBuffer[0]), NULL); if (0 == dw) { (void) StringCchPrintf(szDebugBuffer, sizeof(szDebugBuffer)/sizeof(szDebugBuffer[0]), TEXT("(HRESULT: 0x%lX)"), hr); }
(void) StringCchCat(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szDebugBuffer); #endif
m_pConsole->MessageBox(szBuffer, szPackageName, MB_OK | MB_ICONEXCLAMATION, NULL); }
return hr; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::PopulateUpgradeLists
//
// Synopsis: Walks the list of apps, making sure that all the upgrade
// tables are complete.
//
// Arguments: none
//
// Returns:
//
// History: 2-02-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CScopePane::PopulateUpgradeLists() { HRESULT hr = S_OK; // For each app in the list, insert an entry in the upgrade tables of
// the apps it upgrades.
map <MMC_COOKIE, CAppData>::iterator iAppData; for (iAppData=m_AppData.begin(); iAppData != m_AppData.end(); iAppData++) { hr = InsertUpgradeEntry(iAppData->first, iAppData->second); if (FAILED(hr)) { return hr; } } return hr; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::InsertUpgradeEntry
//
// Synopsis: For every app that this app upgrades, place an entry in its
// upgrades set so that it points back to this one.
//
// Arguments: [cookie] -
// [data] -
//
// Returns:
//
// History: 2-02-1998 stevebl Created
//
// Notes: Needs to be able to deal with scripts that might not be in
// this OU.
//
//---------------------------------------------------------------------------
HRESULT CScopePane::InsertUpgradeEntry(MMC_COOKIE cookie, CAppData & data) { CString szCSPath; HRESULT hr = GetClassStoreName(szCSPath, FALSE); if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr)); } UINT uUpgrades = data.m_pDetails->pInstallInfo->cUpgrades; while (uUpgrades--) { map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(data.m_pDetails->pInstallInfo->prgUpgradeInfoList[uUpgrades].PackageGuid)); if (m_UpgradeIndex.end() != i) { // Make sure the entry isn't already added:
INSTALLINFO * pii = m_AppData[i->second].m_pDetails->pInstallInfo; BOOL fExists = FALSE; UINT uCount = pii->cUpgrades; while (uCount--) { if (0 == memcmp(&data.m_pDetails->pInstallInfo->PackageGuid, &pii->prgUpgradeInfoList[uCount].PackageGuid, sizeof(GUID))) { // it already exists
fExists = TRUE; break; } } if (!fExists) { // Add the entry to this app.
// We don't need to update the class store because it should
// maintain referential integrity for us. But we do need to
// update our own internal structures so we're consistent with
// what's in the class store.
UINT n = ++(pii->cUpgrades); UPGRADEINFO * prgUpgradeInfoList = (UPGRADEINFO *)OLEALLOC(sizeof(UPGRADEINFO) * n); if (!prgUpgradeInfoList) { // out of memory
// back out the change (this would be unfortunate but not fatal)
pii->cUpgrades--; } else { if (n > 1) { memcpy(prgUpgradeInfoList, pii->prgUpgradeInfoList, sizeof(UPGRADEINFO) * (n-1)); OLESAFE_DELETE(pii->prgUpgradeInfoList); } OLESAFE_COPYSTRING(prgUpgradeInfoList[n-1].szClassStore, (LPOLESTR)((LPCWSTR)szCSPath)); memcpy(&prgUpgradeInfoList[n-1].PackageGuid, &data.m_pDetails->pInstallInfo->PackageGuid, sizeof(GUID)); prgUpgradeInfoList[n-1].Flag = UPGFLG_UpgradedBy; pii->prgUpgradeInfoList = prgUpgradeInfoList; } } } } return S_OK; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::RemoveUpgradeEntry
//
// Synopsis: For every app that this app upgraded, remove the entry from
// its upgrades set.
//
// Arguments: [cookie] -
// [data] -
//
// Returns:
//
// History: 2-02-1998 stevebl Created
//
// Notes: Needs to be able to deal with scripts that might not be in
// this OU.
//
//---------------------------------------------------------------------------
HRESULT CScopePane::RemoveUpgradeEntry(MMC_COOKIE cookie, CAppData & data) { UINT uUpgradeIndex = data.m_pDetails->pInstallInfo->cUpgrades; while (uUpgradeIndex--) { map<CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(data.m_pDetails->pInstallInfo->prgUpgradeInfoList[uUpgradeIndex].PackageGuid)); if (m_UpgradeIndex.end() != i) { // Find which entry needs to be erased.
INSTALLINFO * pii = m_AppData[i->second].m_pDetails->pInstallInfo; UINT n = pii->cUpgrades; while (n--) { if (0 == memcmp(&data.m_pDetails->pInstallInfo->PackageGuid, &pii->prgUpgradeInfoList[n].PackageGuid, sizeof(GUID))) { // Now free this entry, copy the last entry over this
// one and decrement cUpgrades. Don't need to actually
// reallocate the array because it will be freed later.
OLESAFE_DELETE(pii->prgUpgradeInfoList[n].szClassStore); if (--(pii->cUpgrades)) { memcpy(&pii->prgUpgradeInfoList[n], &pii->prgUpgradeInfoList[pii->cUpgrades], sizeof(UPGRADEINFO)); } else { OLESAFE_DELETE(pii->prgUpgradeInfoList); } // If we ever were to need to update the class store,
// this is where we would do it.
break; } } } } return S_OK; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::PopulateExtensions
//
// Synopsis: Builds the file extension table from the list of applications.
//
// Arguments: (none)
//
// Returns:
//
// History: 1-29-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CScopePane::PopulateExtensions() { HRESULT hr = S_OK; // first erase the old extension list
m_Extensions.erase(m_Extensions.begin(), m_Extensions.end()); // now add each app's extensions to the table
map <MMC_COOKIE, CAppData>::iterator iAppData; for (iAppData=m_AppData.begin(); iAppData != m_AppData.end(); iAppData++) { hr = InsertExtensionEntry(iAppData->first, iAppData->second); if (FAILED(hr)) { return hr; } } if (m_pFileExt) { m_pFileExt->SendMessage(WM_USER_REFRESH, 0, 0); } return hr; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::InsertExtensionEntry
//
// Synopsis: Adds a single entry to the extension tables.
//
// Arguments: [cookie] -
// [data] -
//
// Returns:
//
// History: 1-29-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CScopePane::InsertExtensionEntry(MMC_COOKIE cookie, CAppData & data) { UINT n = data.m_pDetails->pActInfo->cShellFileExt; while (n--) { m_Extensions[data.m_pDetails->pActInfo->prgShellFileExt[n]].insert(cookie); } return S_OK; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::RemoveExtensionEntry
//
// Synopsis: Removes ane entry from the extension tables.
//
// Arguments: [cookie] -
// [data] -
//
// Returns:
//
// History: 1-29-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CScopePane::RemoveExtensionEntry(MMC_COOKIE cookie, CAppData & data) { UINT n = data.m_pDetails->pActInfo->cShellFileExt; while (n--) { m_Extensions[data.m_pDetails->pActInfo->prgShellFileExt[n]].erase(cookie); if (m_Extensions[data.m_pDetails->pActInfo->prgShellFileExt[n]].empty()) { m_Extensions.erase(data.m_pDetails->pActInfo->prgShellFileExt[n]); } } return S_OK; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::PrepareExtensions
//
// Synopsis: Sets extension priorities so that this data can be inserted
// into the extension list with the proper priority.
//
// Arguments: [pd] -
//
// Returns:
//
// Modifies:
//
// Derivation:
//
// History: 1-29-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CScopePane::PrepareExtensions(PACKAGEDETAIL &pd) { UINT n = pd.pActInfo->cShellFileExt; while (n--) { // For each extension that is going to be added, we need to assign
// it a priority that is one larger than the largest priority
// already added.
// NOTE: The odds of this number rolling over to 0 are so
// unlikely that it would be pointless to check for it. In any case
// the results of such a bug would be easy for the admin to remedy
// via the file extension priority dialog.
pd.pActInfo->prgPriority[n] = 0; EXTLIST::iterator i; CString sz = pd.pActInfo->prgShellFileExt[n]; for (i= m_Extensions[sz].begin(); i != m_Extensions[sz].end(); i++) { // look for the entry that matches this file extension
CAppData & data = m_AppData[*i]; UINT n2 = data.m_pDetails->pActInfo->cShellFileExt; while (n2--) { if (0 == sz.CompareNoCase(data.m_pDetails->pActInfo->prgShellFileExt[n2])) { break; } } if (data.m_pDetails->pActInfo->prgPriority[n2] >= pd.pActInfo->prgPriority[n]) { pd.pActInfo->prgPriority[n] = data.m_pDetails->pActInfo->prgPriority[n2] + 1; } } } return S_OK; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::ChangePackageState
//
// Synopsis: Changes the state of a package and puts up advisory message
// boxes informing the admin about the effects of the change.
//
// Arguments: [data] - entry to change
// [dwNewState] - new state
//
// History: 2-03-1998 stevebl Created
//
//---------------------------------------------------------------------------
STDMETHODIMP CScopePane::ChangePackageState(CAppData &data, DWORD dwNewState, BOOL fShowUI) { HRESULT hr = S_OK;
// first detect what's changed
DWORD dwOldState = data.m_pDetails->pInstallInfo->dwActFlags; DWORD dwChange = dwOldState ^ dwNewState;
if (dwChange) { // commit changes
hr = m_pIClassAdmin->ChangePackageProperties(data.m_pDetails->pszPackageName, NULL, &dwNewState, NULL, NULL, NULL, NULL); if (SUCCEEDED(hr)) { if (data.m_fVisible) { data.m_pDetails->pInstallInfo->dwActFlags = dwNewState; RESULTDATAITEM rd; memset(&rd, 0, sizeof(rd)); rd.mask = RDI_IMAGE; rd.itemID = data.m_itemID; rd.nImage = data.GetImageIndex(this); set <CResultPane *>::iterator i; for (i = m_sResultPane.begin(); i != m_sResultPane.end(); i++) { (*i)->m_pResult->SetItem(&rd); (*i)->m_pResult->Sort((*i)->m_nSortColumn, (*i)->m_dwSortOptions, -1); } } data.NotifyChange(); if (FAILED(m_pIGPEInformation->PolicyChanged(m_fMachine, TRUE, &guidExtension, m_fMachine ? &guidMachSnapin : &guidUserSnapin))) { ReportPolicyChangedError(m_hwndMainWindow); } } else { DebugMsg((DM_WARNING, TEXT("ChangePackageProperties failed with 0x%x"), hr)); } }
return hr; }
HRESULT CScopePane::ClearCategories() { while (m_CatList.cCategory) { m_CatList.cCategory--; OLESAFE_DELETE(m_CatList.pCategoryInfo[m_CatList.cCategory].pszDescription); } OLESAFE_DELETE(m_CatList.pCategoryInfo); return S_OK; }
//+--------------------------------------------------------------------------
//
// Function: GetUpgradeIndex
//
// Synopsis: utility function that returns an upgrade index entry for a package.
//
// Arguments: [PackageID] - the PackageID guid
//
// Returns: S_OK on success
//
// History: 8-12-1998 stevebl Created
//
// Notes: Pretty simple really, the index is just the string form of
// the GUID.
//
//---------------------------------------------------------------------------
CString GetUpgradeIndex(GUID & PackageID) { CString szIndex; WCHAR wsz[256]; StringFromGUID2(PackageID, wsz, 256); return wsz; }
//+--------------------------------------------------------------------------
//
// Member: CScopePane::GetPackageNameFromUpgradeInfo
//
// Synopsis: returns the name of a package given its PackageGuid and CSPath
//
// Arguments: [szPackageName] - [out] name of the package associated with
// this script
// [szScript] - [in] path to the script
//
// Returns: S_OK - found a package associated with this script
// (other) - failed to find a package (could be for any number
// of reasons)
//
// History: 4-07-1998 stevebl Created
//
// Notes: In cases where the package does not reside in this
// container, the package name will be returned as
// "Package Name (container name)"
// Note that this does not return the friendly name of the
// MSI package, it returns the name of the package entry in the
// class store. The two are not always the same.
//
//---------------------------------------------------------------------------
HRESULT CScopePane::GetPackageNameFromUpgradeInfo(CString & szPackageName, GUID &PackageGuid, LPOLESTR szCSPath) { HRESULT hr; IEnumPackage * pIPE = NULL;
CString szMyCSPath; hr = GetClassStoreName(szMyCSPath, FALSE); if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("GetClassStoreName failed with 0x%x"), hr)); }
// see if it's in our container
if (0 == _wcsicmp((LPOLESTR)((LPCWSTR)szMyCSPath), szCSPath)) { hr = E_FAIL; map <CString, MMC_COOKIE>::iterator i = m_UpgradeIndex.find(GetUpgradeIndex(PackageGuid)); if (m_UpgradeIndex.end() != i) { szPackageName = m_AppData[i->second].m_pDetails->pszPackageName; hr = S_OK; } } else { IClassAdmin * pIClassAdmin; hr = CsGetClassStore((LPOLESTR)((LPCOLESTR)szCSPath), (LPVOID*)&pIClassAdmin); if (SUCCEEDED(hr)) { PACKAGEDETAIL pd; hr = pIClassAdmin->GetPackageDetailsFromGuid(PackageGuid, &pd); if (SUCCEEDED(hr)) { if (0 == (pd.pInstallInfo->dwActFlags & (ACTFLG_Orphan | ACTFLG_Uninstall))) { GUID guid; LPOLESTR pszPolicyName;
hr = pIClassAdmin->GetGPOInfo(&guid, &pszPolicyName); if (SUCCEEDED(hr)) { szPackageName = pd.pszPackageName; szPackageName += L" ("; szPackageName += pszPolicyName; szPackageName += L")"; OLESAFE_DELETE(pszPolicyName); } } else { // this app is marked as deleted
hr = E_FAIL; } ReleasePackageDetail(&pd); } pIClassAdmin->Release(); } } return hr; }
//+--------------------------------------------------------------------------
//
// Function: GetMsiProperty
//
// Synopsis: Retrieves a property from the Property table of an MSI package.
//
// Arguments: [szPackagePath] - path to the MSI package
// [szProperty] - property to fetch
// [szValue] - buffer to contain the value
// [puiSize] - size of the buffer
//
// Returns: ERROR_SUCCESS if successful
//
// History: 3-25-1998 stevebl Created
//
//---------------------------------------------------------------------------
UINT GetMsiProperty(const TCHAR * szPackagePath, const TCHAR* szProperty, TCHAR* szValue, DWORD* puiSize) { MSIHANDLE hDatabase; UINT msiReturn = MsiOpenDatabase(szPackagePath, MSIDBOPEN_READONLY, &hDatabase); if (ERROR_SUCCESS == msiReturn) { CString szQuery; szQuery.Format(L"SELECT `Value` FROM `Property` WHERE `Property`='%s'", szProperty); MSIHANDLE hView; msiReturn = MsiDatabaseOpenView(hDatabase, szQuery, &hView); if (ERROR_SUCCESS == msiReturn) { msiReturn = MsiViewExecute(hView, 0); if (ERROR_SUCCESS == msiReturn) { MSIHANDLE hRecord; msiReturn = MsiViewFetch(hView, &hRecord); if (ERROR_SUCCESS == msiReturn) { msiReturn = MsiRecordGetString(hRecord, 1, szValue, puiSize); MsiCloseHandle(hRecord); } } MsiCloseHandle(hView); } MsiCloseHandle(hDatabase); } return msiReturn; }
//+--------------------------------------------------------------------------
//
// Function: GetCapitalizedExt
//
// Synopsis: Given a file name, this function finds the filename
// extension, and returns it capitalized.
//
// Arguments:
// [in] [szName] The file name
// [out][szExt] The capitalized extension
//
// Returns:
// TRUE - an extension was found
// FALSE - an extension could not be found
//
// History: 5/20/1998 RahulTh created
//
// Notes: If an extension cannot be found, then this function makes
// szExt an empty string
//
//---------------------------------------------------------------------------
BOOL GetCapitalizedExt (LPCOLESTR szName, CString& szExt) { int slashpos, dotpos; BOOL fRetVal = FALSE; CString szFileName = szName;
szExt.Empty(); //to be on the safe side
//get the positions of the last . and last backslash
dotpos = szFileName.ReverseFind('.'); slashpos = szFileName.ReverseFind('\\');
//if the last dot occurs after the last slash, this file has an extension
if (dotpos > slashpos) { szExt = szFileName.Mid(dotpos + 1); szExt.MakeUpper(); fRetVal = TRUE; }
return fRetVal; }
|