windows-nt/Source/XPSP1/NT/com/ole32/cs/admin/ui/packages.cpp
2020-09-26 16:20:57 +08:00

1239 lines
44 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1997.
//
// File: packages.cpp
//
// Contents: Methods on CComponentDataImpl related to package deployment
// and maintenence of the various index and cross-reference
// structures.
//
// Classes:
//
// Functions:
//
// History: 2-03-1998 stevebl Created
//
//---------------------------------------------------------------------------
// UNDONE - put in exception handling for low memory conditions
#include "precomp.hxx"
IMalloc * g_pIMalloc = NULL;
void CopyPlatformInfo(PLATFORMINFO * &ppiOut, PLATFORMINFO * & ppiIn)
{
if (NULL == ppiIn)
{
ppiOut = NULL;
return;
}
ppiOut = (PLATFORMINFO *)OLEALLOC(sizeof(PLATFORMINFO));
memcpy(ppiOut, ppiIn, sizeof(PLATFORMINFO));
UINT n = ppiIn->cPlatforms;
if (n)
{
ppiOut->prgPlatform = (CSPLATFORM*) OLEALLOC(sizeof(CSPLATFORM) * n);
memcpy(ppiOut->prgPlatform, ppiIn->prgPlatform, sizeof(CSPLATFORM) * n);
}
n = ppiIn->cLocales;
if (n)
{
ppiOut->prgLocale = (LCID *) OLEALLOC(sizeof(LCID) * n);
memcpy(ppiOut->prgLocale, ppiIn->prgLocale, sizeof(LCID) * n);
}
}
void CopyActInfo(ACTIVATIONINFO * & paiOut, ACTIVATIONINFO * & paiIn)
{
if (NULL == paiIn)
{
paiOut = NULL;
return;
}
paiOut = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO));
memcpy(paiOut, paiIn, sizeof(ACTIVATIONINFO));
UINT n = paiIn->cClasses;
if (n)
{
paiOut->pClasses = (CLASSDETAIL *) OLEALLOC(sizeof(CLASSDETAIL) * n);
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);
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);
memcpy(paiOut->prgPriority, paiIn->prgPriority, sizeof(UINT) * n);
paiOut->prgShellFileExt = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
while (n--)
{
OLESAFE_COPYSTRING(paiOut->prgShellFileExt[n], paiIn->prgShellFileExt[n]);
}
}
n = paiIn->cInterfaces;
if (n)
{
paiOut->prgInterfaceId = (IID *) OLEALLOC(sizeof(IID) * n);
memcpy(paiOut->prgInterfaceId, paiIn->prgInterfaceId, sizeof(IID) * n);
}
n = paiIn->cTypeLib;
if (n)
{
paiOut->prgTlbId = (GUID *) OLEALLOC(sizeof(GUID) * n);
memcpy(paiOut->prgTlbId, paiIn->prgTlbId, sizeof(GUID) * n);
}
}
void CopyInstallInfo(INSTALLINFO * & piiOut, INSTALLINFO * & piiIn)
{
if (NULL == piiIn)
{
piiOut = NULL;
return;
}
piiOut = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO));
memcpy(piiOut, piiIn, sizeof(INSTALLINFO));
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));
memcpy(piiOut->pClsid, piiIn->pClsid, sizeof(GUID));
}
UINT n = piiIn->cUpgrades;
if (n)
{
piiOut->prgUpgradeScript = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
piiOut->prgUpgradeFlag = (DWORD *) OLEALLOC(sizeof(DWORD) * n);
memcpy(piiOut->prgUpgradeFlag, piiIn->prgUpgradeFlag, sizeof(DWORD) * n);
while (n--)
{
OLESAFE_COPYSTRING(piiOut->prgUpgradeScript[n], piiIn->prgUpgradeScript[n]);
}
}
}
void CopyPackageDetail(PACKAGEDETAIL * & ppdOut, PACKAGEDETAIL * & ppdIn)
{
if (NULL == ppdIn)
{
ppdOut = NULL;
return;
}
ppdOut = new PACKAGEDETAIL;
memcpy(ppdOut, ppdIn, sizeof(PACKAGEDETAIL));
OLESAFE_COPYSTRING(ppdOut->pszPackageName, ppdIn->pszPackageName);
UINT n = ppdIn->cSources;
if (n)
{
ppdOut->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
while (n--)
{
OLESAFE_COPYSTRING(ppdOut->pszSourceList[n], ppdIn->pszSourceList[n]);
}
}
n = ppdIn->cCategories;
if (n)
{
ppdOut->rpCategory = (GUID *)OLEALLOC(sizeof(GUID) * n);
memcpy(ppdOut->rpCategory, ppdIn->rpCategory, sizeof(GUID) * n);
}
CopyActInfo(ppdOut->pActInfo, ppdIn->pActInfo);
CopyPlatformInfo(ppdOut->pPlatformInfo, ppdIn->pPlatformInfo);
CopyInstallInfo(ppdOut->pInstallInfo, ppdIn->pInstallInfo);
}
void FreeActInfo(ACTIVATIONINFO * & pai)
{
if (pai)
{
UINT n = pai->cClasses;
while (n--)
{
UINT n2 = pai->pClasses[n].cProgId;
while (n2--)
{
OLESAFE_DELETE(pai->pClasses[n].prgProgId[n2]);
}
OLESAFE_DELETE(pai->pClasses[n].prgProgId);
}
OLESAFE_DELETE(pai->pClasses);
n = pai->cShellFileExt;
while (n--)
{
OLESAFE_DELETE(pai->prgShellFileExt[n]);
}
OLESAFE_DELETE(pai->prgShellFileExt);
OLESAFE_DELETE(pai->prgPriority);
OLESAFE_DELETE(pai->prgInterfaceId);
OLESAFE_DELETE(pai->prgTlbId);
OLESAFE_DELETE(pai);
}
}
void FreePlatformInfo(PLATFORMINFO * &ppi)
{
if (ppi)
{
OLESAFE_DELETE(ppi->prgPlatform);
OLESAFE_DELETE(ppi->prgLocale);
OLESAFE_DELETE(ppi);
}
}
void FreeInstallInfo(INSTALLINFO * &pii)
{
if (pii)
{
OLESAFE_DELETE(pii->pszScriptPath);
OLESAFE_DELETE(pii->pszSetupCommand);
OLESAFE_DELETE(pii->pszUrl);
OLESAFE_DELETE(pii->pClsid);
UINT n = pii->cUpgrades;
while (n--)
{
OLESAFE_DELETE(pii->prgUpgradeScript[n]);
}
if (pii->cUpgrades > 0)
{
OLESAFE_DELETE(pii->prgUpgradeScript);
OLESAFE_DELETE(pii->prgUpgradeFlag);
}
OLESAFE_DELETE(pii);
}
}
void FreePackageDetail(PACKAGEDETAIL * & ppd)
{
if (ppd)
{
OLESAFE_DELETE(ppd->pszPackageName);
UINT n = ppd->cSources;
while (n--)
{
OLESAFE_DELETE(ppd->pszSourceList[n]);
}
OLESAFE_DELETE(ppd->rpCategory);
FreeActInfo(ppd->pActInfo);
FreePlatformInfo(ppd->pPlatformInfo);
FreeInstallInfo(ppd->pInstallInfo);
delete ppd;
ppd = NULL;
}
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::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.
//
//---------------------------------------------------------------------------
void CComponentDataImpl::GetUniquePackageName(CString &sz)
{
std::map<long, APP_DATA>::iterator i;
std::set<CString> sNames;
int cch = sz.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.pDetails->pszPackageName;
if (0 == wcsncmp(sz, szName, cch))
sNames.insert(szName);
}
CString szRoot = sz;
int index = 2; // start trying new names by adding (2) to the end
// now check for a match
do
{
if (sNames.end() == sNames.find(sz))
{
// we are unique
return;
}
// try a different name
sz.Format(L"%s (%i)", (LPCTSTR)szRoot, index++);
} while (TRUE);
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::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 CComponentDataImpl::AddMSIPackage(LPCOLESTR szPackagePath, LPCOLESTR lpFileTitle)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = E_FAIL;
if (m_pIClassAdmin)
{
ASSERT(m_pConsole);
{
BOOL fShowPropertySheet = FALSE;
BOOL fShowUpgradeDialog = FALSE;
GUID guid;
PACKAGEDETAIL *ppd = new PACKAGEDETAIL;
memset(ppd, 0, sizeof(PACKAGEDETAIL));
INSTALLINFO * pii = (INSTALLINFO *) OLEALLOC(sizeof(INSTALLINFO));
memset(pii, 0, sizeof(INSTALLINFO));
PLATFORMINFO * ppi = (PLATFORMINFO *) OLEALLOC(sizeof(PLATFORMINFO));
memset(ppi, 0, sizeof(PLATFORMINFO));
ACTIVATIONINFO * pai = (ACTIVATIONINFO *) OLEALLOC(sizeof(ACTIVATIONINFO));
memset(pai, 0, sizeof(ACTIVATIONINFO));
ppd->pActInfo = pai;
ppd->pPlatformInfo = ppi;
ppd->pInstallInfo = pii;
// If appropriate, use the deployment wizard to set the
// deployment type, otherwise use the default settings
switch (m_ToolDefaults.NPBehavior)
{
case NP_WIZARD:
{
CDeployApp dlgDeployApp;
if (IDCANCEL == dlgDeployApp.DoModal())
{
FreePackageDetail(ppd);
return E_FAIL;
}
switch (dlgDeployApp.m_iDeployment)
{
case 0: // upgrade
fShowUpgradeDialog = TRUE;
pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall;
break;
case 1: //published
pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall | ACTFLG_OnDemandInstall;
break;
case 2: // assigned
pii->dwActFlags = ACTFLG_Assigned | ACTFLG_OnDemandInstall;
break;
case 4: // custom
fShowPropertySheet = TRUE;
// fall through to disabled
case 3: // disabled
default:
pii->dwActFlags = ACTFLG_Published;
break;
}
}
break;
case NP_PUBLISHED:
pii->dwActFlags = ACTFLG_Published | ACTFLG_UserInstall;
if (m_ToolDefaults.fAutoInstall)
{
pii->dwActFlags |= ACTFLG_OnDemandInstall;
}
break;
case NP_ASSIGNED:
pii->dwActFlags = ACTFLG_Assigned | ACTFLG_OnDemandInstall;
break;
case NP_PROPPAGE:
fShowPropertySheet = TRUE;
// fall through to disabled
case NP_DISABLED:
default:
pii->dwActFlags = ACTFLG_Published;
break;
}
pii->PathType = DrwFilePath;
pii->InstallUiLevel = m_ToolDefaults.UILevel;
std::set<LCID> sLocales;
// 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;
std::set<DWORD> sPlatforms;
while (szPlatforms.GetLength())
{
szTemp = szPlatforms.SpanExcluding(L",");
if (0 == szTemp.CompareNoCase(L"alpha"))
{
sPlatforms.insert(PROCESSOR_ARCHITECTURE_ALPHA);
}
else if (0 == szTemp.CompareNoCase(L"intel"))
{
sPlatforms.insert(PROCESSOR_ARCHITECTURE_INTEL);
}
szPlatforms = szPlatforms.Mid(szTemp.GetLength()+1);
}
while (szLocales.GetLength())
{
szTemp = szLocales.SpanExcluding(L",");
LCID lcid;
swscanf(szTemp, L"%i", &lcid);
sLocales.insert(lcid);
szLocales = szLocales.Mid(szTemp.GetLength()+1);
}
if (0 == sLocales.size() || 0 == sPlatforms.size())
{
// either not enough locales or platforms
FreePackageDetail(ppd);
return E_FAIL; // need better error message?
}
ppi->cPlatforms = sPlatforms.size();
ppi->prgPlatform = (CSPLATFORM *) OLEALLOC(sizeof(CSPLATFORM) * (ppi->cPlatforms));;
std::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)
{
FreePackageDetail(ppd);
return HRESULT_FROM_WIN32(msiReturn);
}
}
ppi->cLocales = 1;
ppi->prgLocale = (LCID *) OLEALLOC(sizeof(LCID));
ppd->cSources = 1;
ppd->pszSourceList = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR));
OLESAFE_COPYSTRING(ppd->pszSourceList[0], szPackagePath);
// UNDONE - check to see if we can detect any upgrade relationships
if (fShowUpgradeDialog)
{
CUpgrades dlgUpgrade;
dlgUpgrade.m_pAppData = &m_AppData;
if (IDCANCEL == dlgUpgrade.DoModal())
{
FreePackageDetail(ppd);
return E_FAIL;
}
UINT n = dlgUpgrade.m_UpgradeList.size();
if (n)
{
pii->cUpgrades = n;
pii->prgUpgradeScript = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
pii->prgUpgradeFlag = (DWORD *) OLEALLOC(sizeof(DWORD) * n);
std::map<long, BOOL>::iterator i = dlgUpgrade.m_UpgradeList.begin();
while (n--)
{
if (i->second)
{
pii->prgUpgradeFlag[n] = UPGFLG_Uninstall;
}
else
{
pii->prgUpgradeFlag[n] = UPGFLG_NoUninstall;
}
LPOLESTR sz = m_AppData[i->first].pDetails->pInstallInfo->pszScriptPath;
OLESAFE_COPYSTRING(pii->prgUpgradeScript[n], sz);
i++;
}
}
}
// Put up the locale dialog and allow the user to remove locales
// from the list if he so desires.
if (1 < sLocales.size())
{
CLcidPick dlgLcidPick;
dlgLcidPick.m_psLocales = &sLocales;
int iReturn = dlgLcidPick.DoModal();
if (IDCANCEL == iReturn || 0 == sLocales.size())
{
FreePackageDetail(ppd);
return E_FAIL;
}
}
// For each locale left in the list, publish a package and add
// it to the class store.
int nLocales = sLocales.size();
std::set<LCID>::iterator iLocale;
for (iLocale = sLocales.begin(); iLocale != sLocales.end(); iLocale++)
{
ppi->prgLocale[0] = *iLocale;
// set the script path
hr = CoCreateGuid(&guid);
if (FAILED(hr))
{
FreePackageDetail(ppd);
return hr;
}
OLECHAR sz [256];
StringFromGUID2(guid, sz, 256);
CString szScriptPath = m_szScriptRoot;
szScriptPath += L"\\";
szScriptPath += sz;
szScriptPath += L".aas";
OLESAFE_DELETE(pii->pszScriptPath);
OLESAFE_COPYSTRING(pii->pszScriptPath, szScriptPath);
// set the package name
{
MSIHANDLE hProduct;
UINT msiReturn = MsiOpenPackage(szPackagePath, &hProduct);
if (ERROR_SUCCESS == msiReturn)
{
DWORD dw = 256;
OLECHAR szBuffer[256];
msiReturn = MsiGetProductProperty(hProduct, INSTALLPROPERTY_PRODUCTNAME, szBuffer, &dw);
if (ERROR_SUCCESS == msiReturn)
{
CString sz = szBuffer;
// If there is more than one locale in the
// locale list, then append the locale to the
// name to help distinguish it.
if (1 < nLocales)
{
sz += L" (";
GetLocaleInfo(ppi->prgLocale[0], LOCALE_SLANGUAGE, szBuffer, 256);
sz += szBuffer;
GetLocaleInfo(ppi->prgLocale[0], LOCALE_SCOUNTRY, szBuffer, 256);
sz += _T(" - ");
sz += szBuffer;
sz += L")";
}
// make sure the name is unique
GetUniquePackageName(sz);
OLESAFE_DELETE(ppd->pszPackageName);
OLESAFE_COPYSTRING(ppd->pszPackageName, sz);
}
MsiCloseHandle(hProduct);
}
if (ERROR_SUCCESS != msiReturn)
{
FreePackageDetail(ppd);
return HRESULT_FROM_WIN32(msiReturn);
}
}
HWND hwnd;
m_pConsole->GetMainWindow(&hwnd);
hr = BuildScriptAndGetActInfo(m_szGPTRoot, *ppd);
if (SUCCEEDED(hr))
{
hr = PrepareExtensions(*ppd);
if (SUCCEEDED(hr))
{
// put the script in the class store
hr = m_pIClassAdmin->AddPackage(ppd->pszPackageName, ppd);
}
}
if (S_OK != hr)
{
TCHAR szBuffer[256];
::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)
{
wsprintf(szDebugBuffer, TEXT("(HRESULT: 0x%lX)"), hr);
}
wcscat(szBuffer, szDebugBuffer);
#endif
m_pConsole->MessageBox(szBuffer,
lpFileTitle,
MB_OK, NULL);
FreePackageDetail(ppd);
return hr;
}
else
{
APP_DATA data;
CopyPackageDetail(data.pDetails, ppd);
data.InitializeExtraInfo();
m_lLastAllocated++;
m_AppData[m_lLastAllocated] = data;
RESULTDATAITEM resultItem;
resultItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
resultItem.str = MMC_CALLBACK;
resultItem.nImage = data.GetImageIndex(this);
// BUGBUG - need to make sure that m_lLastAllocated
// hasn't already been used!
resultItem.lParam = m_lLastAllocated;
hr = m_pSnapin->m_pResult->InsertItem(&resultItem);
if (SUCCEEDED(hr))
{
#if UGLY_SUBDIRECTORY_HACK
if (0 != (data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned))
{
CString sz = m_szGPTRoot;
sz += L"\\";
sz += data.pDetails->pInstallInfo->pszScriptPath;
// copy to subdirectories
CString szRoot;
CString szFile;
int i = sz.ReverseFind(L'\\');
szRoot = sz.Left(i);
szFile = sz.Mid(i+1);
CString szTemp;
for (i = data.pDetails->pPlatformInfo->cPlatforms; i--;)
{
if (PROCESSOR_ARCHITECTURE_INTEL == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
{
szTemp = szRoot;
szTemp += L"\\assigned\\x86\\";
szTemp += szFile;
CopyFile(sz, szTemp, FALSE);
}
if (PROCESSOR_ARCHITECTURE_ALPHA == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
{
szTemp = szRoot;
szTemp += L"\\assigned\\alpha\\";
szTemp += szFile;
CopyFile(sz, szTemp, FALSE);
}
}
}
#endif
m_AppData[m_lLastAllocated].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_ScriptIndex[data.pDetails->pInstallInfo->pszScriptPath] = m_lLastAllocated;
// if this is an upgrade, set icons for upgraded apps to
// the proper icon.
UINT n = data.pDetails->pInstallInfo->cUpgrades;
while (n--)
{
std::map<CString, long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
if (i != m_ScriptIndex.end())
{
RESULTDATAITEM rd;
memset(&rd, 0, sizeof(rd));
rd.mask = RDI_IMAGE;
rd.itemID = m_AppData[i->second].itemID;
rd.nImage = IMG_UPGRADE;
m_pSnapin->m_pResult->SetItem(&rd);
}
}
m_pSnapin->m_pResult->Sort(0, 0, -1);
}
}
}
FreePackageDetail(ppd);
}
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::RemovePackage
//
// Synopsis: Removes a package from the class store and the result pane.
//
// Arguments: [pDataObject] - data object for this result pane item
//
// Returns: S_OK - success
//
// History: 2-03-1998 stevebl Created
//
// Notes: bAssigned is used
//
//---------------------------------------------------------------------------
HRESULT CComponentDataImpl::RemovePackage(long cookie)
{
BOOL fAssigned;
HRESULT hr = E_FAIL;
// put up an hourglass (this could take a while)
CHourglass hourglass;
APP_DATA & data = m_AppData[cookie];
// We need to make sure it gets removed from
// the GPT before we delete it from the class store.
CString sz = m_szGPTRoot;
sz += L"\\";
sz += data.pDetails->pInstallInfo->pszScriptPath;
DeleteFile(sz);
#if UGLY_SUBDIRECTORY_HACK
{
// delete from subdirectories
CString szRoot;
CString szFile;
int i = sz.ReverseFind(L'\\');
szRoot = sz.Left(i);
szFile = sz.Mid(i+1);
CString szTemp;
szTemp = szRoot;
szTemp += L"\\assigned\\x86\\";
szTemp += szFile;
DeleteFile(szTemp);
szTemp = szRoot;
szTemp += L"\\assigned\\alpha\\";
szTemp += szFile;
DeleteFile(szTemp);
}
#endif
if (0 != (data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned))
{
fAssigned = TRUE;
}
else
{
fAssigned = FALSE;
}
hr = m_pIClassAdmin->RemovePackage((LPOLESTR)((LPCOLESTR)(data.pDetails->pszPackageName)));
if (SUCCEEDED(hr))
{
hr = m_pSnapin->m_pResult->DeleteItem(data.itemID, 0);
if (SUCCEEDED(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_ScriptIndex.erase(data.pDetails->pInstallInfo->pszScriptPath);
// If this thing upgraded other apps, make sure that
// they get the proper icons.
UINT n = data.pDetails->pInstallInfo->cUpgrades;
while (n--)
{
std::map<CString, long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
if (i != m_ScriptIndex.end())
{
RESULTDATAITEM rd;
memset(&rd, 0, sizeof(rd));
rd.mask = RDI_IMAGE;
rd.itemID = m_AppData[i->second].itemID;
rd.nImage = m_AppData[i->second].GetImageIndex(this);
m_pSnapin->m_pResult->SetItem(&rd);
}
}
// If other apps were upgrading this app, do the same.
std::set<long>::iterator i;
for (i = data.sUpgrades.begin(); i != data.sUpgrades.end(); i++)
{
RESULTDATAITEM rd;
memset(&rd, 0, sizeof(rd));
rd.mask = RDI_IMAGE;
rd.itemID = m_AppData[*i].itemID;
rd.nImage = m_AppData[*i].GetImageIndex(this);
m_pSnapin->m_pResult->SetItem(&rd);
}
FreePackageDetail(data.pDetails);
m_AppData.erase(cookie);
m_pSnapin->m_pResult->Sort(0, 0, -1);
// Notify clients of change
if (m_pIGPEInformation && fAssigned)
{
m_pIGPEInformation->PolicyChanged();
}
}
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::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 CComponentDataImpl::PopulateUpgradeLists()
{
HRESULT hr = S_OK;
// For each app in the list, insert an entry in the upgrade tables of
// the apps it upgrades.
std::map <long, APP_DATA>::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: CComponentDataImpl::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 CComponentDataImpl::InsertUpgradeEntry(long cookie, APP_DATA & data)
{
UINT n = data.pDetails->pInstallInfo->cUpgrades;
while (n--)
{
std::map<CString,long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
if (m_ScriptIndex.end() != i)
{
m_AppData[i->second].sUpgrades.insert(cookie);
}
}
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::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 CComponentDataImpl::RemoveUpgradeEntry(long cookie, APP_DATA & data)
{
UINT n = data.pDetails->pInstallInfo->cUpgrades;
while (n--)
{
std::map<CString,long>::iterator i = m_ScriptIndex.find(data.pDetails->pInstallInfo->prgUpgradeScript[n]);
if (m_ScriptIndex.end() != i)
{
m_AppData[i->second].sUpgrades.erase(cookie);
}
}
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::PopulateExtensions
//
// Synopsis: Builds the file extension table from the list of applications.
//
// Arguments: (none)
//
// Returns:
//
// History: 1-29-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CComponentDataImpl::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
std::map <long, APP_DATA>::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: CComponentDataImpl::InsertExtensionEntry
//
// Synopsis: Adds a single entry to the extension tables.
//
// Arguments: [cookie] -
// [data] -
//
// Returns:
//
// History: 1-29-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CComponentDataImpl::InsertExtensionEntry(long cookie, APP_DATA & data)
{
UINT n = data.pDetails->pActInfo->cShellFileExt;
while (n--)
{
m_Extensions[data.pDetails->pActInfo->prgShellFileExt[n]].insert(cookie);
}
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::RemoveExtensionEntry
//
// Synopsis: Removes ane entry from the extension tables.
//
// Arguments: [cookie] -
// [data] -
//
// Returns:
//
// History: 1-29-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CComponentDataImpl::RemoveExtensionEntry(long cookie, APP_DATA & data)
{
UINT n = data.pDetails->pActInfo->cShellFileExt;
while (n--)
{
m_Extensions[data.pDetails->pActInfo->prgShellFileExt[n]].erase(cookie);
if (m_Extensions[data.pDetails->pActInfo->prgShellFileExt[n]].empty())
{
m_Extensions.erase(data.pDetails->pActInfo->prgShellFileExt[n]);
}
}
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::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 CComponentDataImpl::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
APP_DATA & data = m_AppData[*i];
UINT n2 = data.pDetails->pActInfo->cShellFileExt;
while (n2--)
{
if (0 == sz.CompareNoCase(data.pDetails->pActInfo->prgShellFileExt[n2]))
{
break;
}
}
if (data.pDetails->pActInfo->prgPriority[n2] >= pd.pActInfo->prgPriority[n])
{
pd.pActInfo->prgPriority[n] = data.pDetails->pActInfo->prgPriority[n2] + 1;
}
}
}
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CComponentDataImpl::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 CComponentDataImpl::ChangePackageState(APP_DATA &data, DWORD dwNewState, BOOL fShowUI)
{
HRESULT hr = S_OK;
// first detect what's changed
DWORD dwOldState = data.pDetails->pInstallInfo->dwActFlags;
DWORD dwChange = dwOldState ^ dwNewState;
if (dwChange)
{
// something changed
if (fShowUI)
{
// Build a notification message
CString szNotify = L"";
WCHAR szBuffer [256];
BOOL fAskAboutAutoInstall = FALSE;
// changes we care about:
//
// Assigned flag changed:
// UserInstall flag changed:
// OnDemandInstall flag changed: (We only care about this if we
// aren't going to ask)
if (dwChange & (ACTFLG_Assigned | ACTFLG_Published))
{
if (dwNewState & ACTFLG_Assigned)
{
::LoadString(ghInstance, IDS_TO_ASSIGNED, szBuffer, 256);
}
else
{
::LoadString(ghInstance, IDS_TO_PUBLISHED, szBuffer, 256);
if (dwNewState & (ACTFLG_UserInstall | ACTFLG_OnDemandInstall))
fAskAboutAutoInstall = TRUE;
}
szNotify += szBuffer;
}
if (dwChange & ACTFLG_UserInstall)
{
if (dwNewState & ACTFLG_UserInstall)
{
::LoadString(ghInstance, IDS_USERINSTALL_ON, szBuffer, 256);
// This check takes care of making sure we ask about
// AutoInstall when moving from the Disabled to the
// Published state.
if ((!(dwNewState & ACTFLG_Assigned)) && !(dwOldState & ACTFLG_OnDemandInstall))
fAskAboutAutoInstall = TRUE;
}
else
{
::LoadString(ghInstance, IDS_USERINSTALL_OFF, szBuffer, 256);
}
szNotify += szBuffer;
}
if (fAskAboutAutoInstall)
{
::LoadString(ghInstance, IDS_ASK_AUTOINSTALL, szBuffer, 256);
szNotify += szBuffer;
int iReturn = ::MessageBox(NULL,
szNotify,
data.pDetails->pszPackageName,
MB_YESNOCANCEL);
if (IDCANCEL == iReturn)
{
return E_ABORT;
}
if (IDYES == iReturn)
dwNewState |= ACTFLG_OnDemandInstall;
else
dwNewState &= ~ACTFLG_OnDemandInstall;
}
else
{
if ((!(dwNewState & ACTFLG_Assigned)) && (dwChange & ACTFLG_OnDemandInstall))
{
if (dwNewState & ACTFLG_OnDemandInstall)
{
::LoadString(ghInstance, IDS_AUTOINSTALL_ON, szBuffer, 256);
}
else
{
::LoadString(ghInstance, IDS_AUTOINSTALL_OFF, szBuffer, 256);
}
szNotify += szBuffer;
}
int iReturn = ::MessageBox(NULL,
szNotify,
data.pDetails->pszPackageName,
MB_OKCANCEL);
if (IDCANCEL == iReturn)
{
return E_ABORT;
}
}
}
// commit changes
hr = m_pIClassAdmin->ChangePackageProperties(data.pDetails->pszPackageName, NULL, &dwNewState, NULL, NULL, NULL);
if (SUCCEEDED(hr))
{
data.pDetails->pInstallInfo->dwActFlags = dwNewState;
RESULTDATAITEM rd;
memset(&rd, 0, sizeof(rd));
rd.mask = RDI_IMAGE;
rd.itemID = data.itemID;
rd.nImage = data.GetImageIndex(this);
m_pSnapin->m_pResult->SetItem(&rd);
m_pSnapin->m_pResult->Sort(0, 0, -1);
data.NotifyChange();
#if UGLY_SUBDIRECTORY_HACK
{
CString sz = m_szGPTRoot;
sz += L"\\";
sz += data.pDetails->pInstallInfo->pszScriptPath;
// copy to subdirectories
CString szRoot;
CString szFile;
int i = sz.ReverseFind(L'\\');
szRoot = sz.Left(i);
szFile = sz.Mid(i+1);
CString szTemp;
if (0 != (data.pDetails->pInstallInfo->dwActFlags & ACTFLG_Assigned))
{
for (i = data.pDetails->pPlatformInfo->cPlatforms; i--;)
{
if (PROCESSOR_ARCHITECTURE_INTEL == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
{
szTemp = szRoot;
szTemp += L"\\assigned\\x86\\";
szTemp += szFile;
CopyFile(sz, szTemp, FALSE);
}
if (PROCESSOR_ARCHITECTURE_ALPHA == data.pDetails->pPlatformInfo->prgPlatform[i].dwProcessorArch)
{
szTemp = szRoot;
szTemp += L"\\assigned\\alpha\\";
szTemp += szFile;
CopyFile(sz, szTemp, FALSE);
}
}
}
else
{
szTemp = szRoot;
szTemp += L"\\assigned\\x86\\";
szTemp += szFile;
DeleteFile(szTemp);
szTemp = szRoot;
szTemp += L"\\assigned\\alpha\\";
szTemp += szFile;
DeleteFile(szTemp);
}
}
#endif
}
}
return hr;
}