//+-------------------------------------------------------------------------- // // 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::iterator i; std::set 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 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 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::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::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::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::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::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::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 ::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::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::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 ::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; }