mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
fixing bug 198081 - Old GRE's left on disk when upgrading Mozilla. r=dveditz, sr=jag, a=dbaron
This commit is contained in:
parent
d971762a99
commit
815c99f4f5
@ -95,6 +95,13 @@ Default Setup Type=Setup Type 0
|
||||
; TRUE
|
||||
Refresh Icons=FALSE
|
||||
|
||||
; GRE Cleanup Orphans= will cleanup old copies of GRE that will are no
|
||||
; longer being used by anyone except for the app that will install/use
|
||||
; it (dictated by -app_path).
|
||||
; Possible values: TRUE, FALSE
|
||||
; Default: FALSE
|
||||
GRE Cleanup Orphans=TRUE
|
||||
|
||||
;*** LOCALIZE ME BABY ***
|
||||
GRE Cleanup Orphans Message=Cleaning up orphaned GREs (Gecko Runtime Environments), please wait...
|
||||
|
||||
|
@ -3067,6 +3067,17 @@ void CommitInstall(void)
|
||||
|
||||
if(RetrieveResults == WIZ_OK)
|
||||
{
|
||||
// Clean up old versions of GRE previously installed.
|
||||
// These GREs should only be fully uninstalled if they were only
|
||||
// being used by the mozilla that we're installing over/ontop of
|
||||
// (upgrade scenario).
|
||||
// We should only do this type of cleanup if we're about to install'
|
||||
// GRE in shared mode.
|
||||
//
|
||||
// This should only be called when the installer is installing GRE!
|
||||
if(IsInstallerProductGRE())
|
||||
CleanupOrphanedGREs();
|
||||
|
||||
if(sgProduct.bInstallFiles)
|
||||
{
|
||||
/* Check to see if Turbo is required. If so, set the
|
||||
|
@ -71,6 +71,11 @@ char *ExcludeRemoveList[] = {"plugins",
|
||||
"install_status.log",
|
||||
""};
|
||||
|
||||
// Path and filename to the GRE's uninstaller. This is used to cleanup
|
||||
// old versions of GRE that have been orphaned when upgrading mozilla.
|
||||
#define GRE_UNINSTALLER_FILE "[WINDIR]\\GREUninstall.exe"
|
||||
|
||||
#define GRE_REG_KEY "Software\\mozilla.org\\GRE"
|
||||
#define SETUP_STATE_REG_KEY "Software\\%s\\%s\\%s\\Setup"
|
||||
#define APP_PATHS_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s"
|
||||
|
||||
@ -2240,7 +2245,7 @@ HRESULT GetInfoFromInstalledGreConfigIni(greInfo *aGre)
|
||||
}
|
||||
|
||||
/* Function: GetInfoFromGreInstaller()
|
||||
* in: char *aGreInstallerFile: full path to the gre installer.
|
||||
* in: char *aGreInstallerFile: full path to the GRE installer.
|
||||
* greInfo *aGre: gre class to fill the homePath for.
|
||||
* out: returns homePath in aGre.
|
||||
* purpose: To retrieve the GRE home path from the GRE installer.
|
||||
@ -2264,7 +2269,7 @@ void GetInfoFromGreInstaller(char *aGreInstallerFile, greInfo *aGre)
|
||||
|
||||
*aGre->homePath = '\0';
|
||||
|
||||
/* uncompress gre installer's config.ini file in order to parse for:
|
||||
/* uncompress GRE installer's config.ini file in order to parse for:
|
||||
* [General]
|
||||
* Path=
|
||||
* User Agent=
|
||||
@ -2280,6 +2285,193 @@ void GetInfoFromGreInstaller(char *aGreInstallerFile, greInfo *aGre)
|
||||
DeleteFile(extractedConfigFile);
|
||||
}
|
||||
|
||||
/* Function: CleanupOrphanedGREs()
|
||||
* in: none.
|
||||
* out: none.
|
||||
* purpose: To clean up GREs that were left on the system by previous
|
||||
* installations of this product only (not by any other product).
|
||||
*/
|
||||
HRESULT CleanupOrphanedGREs()
|
||||
{
|
||||
HKEY greIDKeyHandle;
|
||||
HKEY greAppListKeyHandle;
|
||||
DWORD totalGreIDSubKeys;
|
||||
DWORD totalGREAppListSubKeys;
|
||||
char **greIDListToClean = NULL;
|
||||
char **greAppListToClean = NULL;
|
||||
char greKeyID[MAX_BUF_MEDIUM];
|
||||
char greRegKey[MAX_BUF];
|
||||
char greKeyAppList[MAX_BUF_MEDIUM];
|
||||
char greAppListKeyPath[MAX_BUF];
|
||||
char greUninstaller[MAX_BUF];
|
||||
DWORD idKeySize;
|
||||
DWORD appListKeySize;
|
||||
DWORD indexOfGREID;
|
||||
DWORD indexOfGREAppList;
|
||||
int rv = WIZ_OK;
|
||||
|
||||
DecryptString(greUninstaller, GRE_UNINSTALLER_FILE);
|
||||
// If greCleanupOrphans is false (set either in config.ini or passed in
|
||||
// thru the cmdline) or GRE's uninstaller file does not exist, then
|
||||
// simply do nothing and return.
|
||||
if(!sgProduct.greCleanupOrphans || !FileExists(greUninstaller))
|
||||
return(WIZ_OK);
|
||||
|
||||
// If GRE is installed locally, then use the private GRE key, else
|
||||
// use the default global GRE key in the windows registry.
|
||||
if(sgProduct.greType == GRE_LOCAL)
|
||||
DecryptString(greRegKey, sgProduct.grePrivateKey);
|
||||
else
|
||||
MozCopyStr(GRE_REG_KEY, greRegKey, sizeof(greRegKey));
|
||||
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, greRegKey, 0, KEY_READ, &greIDKeyHandle) != ERROR_SUCCESS)
|
||||
return(WIZ_ERROR_UNDEFINED);
|
||||
|
||||
// Build the list of GRE's given greRegKey. For example, if greRegKey is:
|
||||
//
|
||||
// HKLM\Software\mozilla.org\GRE
|
||||
//
|
||||
// then build a list of the GRE IDs inside this key.
|
||||
totalGreIDSubKeys = 0;
|
||||
if(RegQueryInfoKey(greIDKeyHandle, NULL, NULL, NULL, &totalGreIDSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
rv = WIZ_ERROR_UNDEFINED;
|
||||
|
||||
if((rv == WIZ_OK) && (greIDListToClean = NS_GlobalAlloc(sizeof(char *) * totalGreIDSubKeys)) == NULL)
|
||||
{
|
||||
RegCloseKey(greIDKeyHandle);
|
||||
return(WIZ_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// Show message that orphaned GREs are being cleaned up
|
||||
if(*sgProduct.greCleanupOrphansMessage != '\0');
|
||||
ShowMessage(sgProduct.greCleanupOrphansMessage, TRUE);
|
||||
|
||||
if(rv == WIZ_OK)
|
||||
{
|
||||
// Initialize the array of pointers (of GRE ID keys) to NULL
|
||||
for(indexOfGREID = 0; indexOfGREID < totalGreIDSubKeys; indexOfGREID++)
|
||||
greIDListToClean[indexOfGREID] = NULL;
|
||||
|
||||
// Enumerate the GRE ID list and save the GRE ID to each of its array element
|
||||
for(indexOfGREID = 0; indexOfGREID < totalGreIDSubKeys; indexOfGREID++)
|
||||
{
|
||||
idKeySize = sizeof(greKeyID);
|
||||
if(RegEnumKeyEx(greIDKeyHandle, indexOfGREID, greKeyID, &idKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
if((greIDListToClean[indexOfGREID] = NS_GlobalAlloc(sizeof(char) * (idKeySize + 1))) == NULL)
|
||||
{
|
||||
RegCloseKey(greIDKeyHandle);
|
||||
rv = WIZ_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
MozCopyStr(greKeyID, greIDListToClean[indexOfGREID], idKeySize + 1);
|
||||
}
|
||||
}
|
||||
RegCloseKey(greIDKeyHandle);
|
||||
|
||||
if(rv == WIZ_OK)
|
||||
{
|
||||
// Enumerate the GRE ID list built from above to get to each of it's AppList key.
|
||||
// The list that we need to build now is from the following key:
|
||||
//
|
||||
// HKLM\Software\mozilla.org\GRE\[GRE ID]\AppList
|
||||
for(indexOfGREID = 0; indexOfGREID < totalGreIDSubKeys; indexOfGREID++)
|
||||
{
|
||||
// If we find the same GRE version as what we're trying to install,
|
||||
// then we don't want to process it because if we do, it will
|
||||
// uninstall it. Which means that it'll reinstall it again. We don't
|
||||
// want to have reinstall when we don't need to.
|
||||
//
|
||||
// szUserAgent is the GRE unique id if this instance of the installer is
|
||||
// installing GRE.
|
||||
if(strcmpi(sgProduct.szUserAgent, greIDListToClean[indexOfGREID]) == 0)
|
||||
continue;
|
||||
|
||||
_snprintf(greAppListKeyPath, sizeof(greAppListKeyPath), "%s\\%s\\AppList",
|
||||
GRE_REG_KEY, greIDListToClean[indexOfGREID]);
|
||||
greAppListKeyPath[sizeof(greAppListKeyPath) - 1] = '\0';
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, greAppListKeyPath, 0, KEY_READ, &greAppListKeyHandle) != ERROR_SUCCESS)
|
||||
{
|
||||
rv = WIZ_ERROR_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
|
||||
totalGREAppListSubKeys = 0;
|
||||
if(RegQueryInfoKey(greAppListKeyHandle, NULL, NULL, NULL, &totalGREAppListSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
rv = WIZ_ERROR_UNDEFINED;
|
||||
|
||||
if((rv == WIZ_OK) && (greAppListToClean = NS_GlobalAlloc(sizeof(char *) * totalGREAppListSubKeys)) == NULL)
|
||||
{
|
||||
RegCloseKey(greAppListKeyHandle);
|
||||
rv = WIZ_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize the GREAppList elements to NULL.
|
||||
for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
|
||||
greAppListToClean[indexOfGREAppList] = NULL;
|
||||
|
||||
// enumerate the GRE AppList key and build a list.
|
||||
for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
|
||||
{
|
||||
appListKeySize = sizeof(greKeyAppList);
|
||||
if(RegEnumKeyEx(greAppListKeyHandle, indexOfGREAppList, greKeyAppList, &appListKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
{
|
||||
if((greAppListToClean[indexOfGREAppList] = NS_GlobalAlloc(sizeof(char) * (appListKeySize + 1))) == NULL)
|
||||
{
|
||||
RegCloseKey(greAppListKeyHandle);
|
||||
rv = WIZ_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
MozCopyStr(greKeyAppList, greAppListToClean[indexOfGREAppList], appListKeySize + 1);
|
||||
}
|
||||
}
|
||||
RegCloseKey(greAppListKeyHandle);
|
||||
|
||||
if(rv != WIZ_OK)
|
||||
break;
|
||||
|
||||
// Enumerate the saved GREAppList and start calling GREUninstall.exe
|
||||
// to remove them if appropriate.
|
||||
// GREUninstall.exe will take care of determining if the particular
|
||||
// GRE should be fully removed or not.
|
||||
// We need to enumerate the list again instead of doing this in the
|
||||
// save loop as above because deleting keys while at the same time
|
||||
// enumerating thru its parent key is a Bad Thing(TM).
|
||||
for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
|
||||
{
|
||||
char programNamePath[MAX_BUF];
|
||||
char greUninstallParam[MAX_BUF];
|
||||
|
||||
DecryptString(programNamePath, sgProduct.szAppPath);
|
||||
_snprintf(greUninstallParam, sizeof(greUninstallParam), "-mmi -ms -ua \"%s\" -app \"%s\" -app_path \"%s\"",
|
||||
greIDListToClean[indexOfGREID], greAppListToClean[indexOfGREAppList], programNamePath);
|
||||
greUninstallParam[sizeof(greUninstallParam) - 1] = '\0';
|
||||
WinSpawn(greUninstaller, greUninstallParam, szTempDir, SW_SHOWNORMAL, WS_WAIT);
|
||||
}
|
||||
|
||||
// Cleanup allocated memory
|
||||
for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
|
||||
FreeMemory(&greAppListToClean[indexOfGREAppList]);
|
||||
if(greAppListToClean)
|
||||
GlobalFree(greAppListToClean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup allocated memory
|
||||
for(indexOfGREID = 0; indexOfGREID < totalGreIDSubKeys; indexOfGREID++)
|
||||
FreeMemory(&greIDListToClean[indexOfGREID]);
|
||||
if(greIDListToClean)
|
||||
GlobalFree(greIDListToClean);
|
||||
|
||||
// Hide message that orphaned GREs are being cleaned up
|
||||
if(*sgProduct.greCleanupOrphansMessage != '\0');
|
||||
ShowMessage(sgProduct.greCleanupOrphansMessage, FALSE);
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
void LaunchOneComponent(siC *siCObject, greInfo *aGre)
|
||||
{
|
||||
BOOL bArchiveFound;
|
||||
@ -2556,7 +2748,7 @@ void CleanupOnUpgrade()
|
||||
|
||||
/* Function: ProcessGre()
|
||||
* in: none.
|
||||
* out: path to where gre is installed at.
|
||||
* out: path to where GRE is installed at.
|
||||
* purpose: To install GRE on the system, so this installer can use it's
|
||||
* xpinstall engine. It uses gre->homePath to see if GRE is already
|
||||
* installed on the system. If GRE is already present on the system,
|
||||
@ -2667,7 +2859,7 @@ HRESULT ProcessXpinstallEngine()
|
||||
* GRE's installer that's already on the system. This will setup
|
||||
* GRE so it can be used as the xpinstall engine (if it's needed).
|
||||
*/
|
||||
if(lstrcmpi(sgProduct.szProductNameInternal, "GRE") != 0)
|
||||
if(!IsInstallerProductGRE())
|
||||
rv = ProcessGre(&gGre);
|
||||
|
||||
if(*siCFXpcomFile.szMessage != '\0')
|
||||
@ -3236,6 +3428,8 @@ HRESULT InitSetupGeneral()
|
||||
if((sgProduct.szRegPath = NS_GlobalAlloc(MAX_BUF)) == NULL)
|
||||
return(1);
|
||||
|
||||
sgProduct.greCleanupOrphans = FALSE;
|
||||
*sgProduct.greCleanupOrphansMessage = '\0';
|
||||
*sgProduct.greID = '\0';
|
||||
*sgProduct.grePrivateKey = '\0';
|
||||
return(0);
|
||||
@ -4670,7 +4864,7 @@ HRESULT InitComponentDiskSpaceInfo(dsN **dsnComponentDSRequirement)
|
||||
if(*(siCObject->szDestinationPath) == '\0')
|
||||
lstrcpy(szBuf, sgProduct.szPath);
|
||||
else if((lstrcmpi(siCObject->szReferenceName, "Component GRE") == 0) &&
|
||||
(lstrcmpi(sgProduct.szProductName, "GRE") != 0))
|
||||
!IsInstallerProductGRE())
|
||||
/* We found 'Component GRE' and this product is not 'GRE'. The GRE
|
||||
* product happens to also have a 'Component GRE', but we don't
|
||||
* care about that one. */
|
||||
@ -5759,6 +5953,7 @@ void PrintUsage(void)
|
||||
|
||||
ReplacePrivateProfileStrCR(szBuf);
|
||||
_snprintf(szUsageMsg, sizeof(szUsageMsg), szBuf, szProcessFilename);
|
||||
szUsageMsg[sizeof(szUsageMsg) - 1] = '\0';
|
||||
GetPrivateProfileString("Messages", "DLG_USAGE_TITLE", "", strUsage, sizeof(strUsage), szFileIniInstall);
|
||||
MessageBox(hWndMain, szUsageMsg, strUsage, MB_ICONEXCLAMATION);
|
||||
}
|
||||
@ -5920,6 +6115,10 @@ DWORD ParseCommandLine(LPSTR aMessageToClose, LPSTR lpszCmdLine)
|
||||
sgProduct.checkCleanupOnUpgrade = TRUE;
|
||||
else if(!lstrcmpi(szArgVBuf, "-noCleanupOnUpgrade") || !lstrcmpi(szArgVBuf, "/noCleanupOnUpgrade"))
|
||||
sgProduct.checkCleanupOnUpgrade = FALSE;
|
||||
else if(!lstrcmpi(szArgVBuf, "-greCleanupOrphans") || !lstrcmpi(szArgVBuf, "/greCleanupOrphans"))
|
||||
sgProduct.greCleanupOrphans = TRUE;
|
||||
else if(!lstrcmpi(szArgVBuf, "-greNoCleanupOrphans") || !lstrcmpi(szArgVBuf, "/greNoCleanupOrphans"))
|
||||
sgProduct.greCleanupOrphans = FALSE;
|
||||
|
||||
#ifdef XXX_DEBUG
|
||||
itoa(i, szBuf, 10);
|
||||
@ -6707,6 +6906,11 @@ HRESULT ParseConfigIni(LPSTR lpszCmdLine)
|
||||
sgProduct.greType = GRE_SHARED;
|
||||
}
|
||||
|
||||
GetPrivateProfileString("General", "GRE Cleanup Orphans", "", szBuf, sizeof(szBuf), szFileIniConfig);
|
||||
if(lstrcmpi(szBuf, "TRUE") == 0)
|
||||
sgProduct.greCleanupOrphans = TRUE;
|
||||
|
||||
GetPrivateProfileString("General", "GRE Cleanup Orphans Message", "", sgProduct.greCleanupOrphansMessage, sizeof(sgProduct.greCleanupOrphansMessage), szFileIniConfig);
|
||||
GetPrivateProfileString("General", "GRE ID", "", sgProduct.greID, sizeof(sgProduct.greID), szFileIniConfig);
|
||||
GetPrivateProfileString("General", "GRE Private Key", "", szBuf, sizeof(szBuf), szFileIniConfig);
|
||||
if(*szBuf != '\0')
|
||||
@ -8089,6 +8293,18 @@ BOOL NeedReboot()
|
||||
return(diReboot.dwShowDialog);
|
||||
}
|
||||
|
||||
/* Function: IsInstallerProductGRE()
|
||||
* in: none.
|
||||
* out: Boolean value on whether or not the installer will be installing
|
||||
* the GRE.
|
||||
* purpose: The check to see if the product the installer will be installing
|
||||
* is GRE or not.
|
||||
*/
|
||||
BOOL IsInstallerProductGRE()
|
||||
{
|
||||
return(lstrcmpi(sgProduct.szProductNameInternal, "GRE") == 0 ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
/* Function: GreInstallerNeedsReboot()
|
||||
* in: none.
|
||||
* out: Boolean value on whether or not GRE installer needed a
|
||||
@ -8102,7 +8318,7 @@ BOOL GreInstallerNeedsReboot()
|
||||
|
||||
/* if this setup is not installing GRE *and* the GRE Setup has been run, then
|
||||
* check for GRE setup's exit value, if one exists */
|
||||
if((lstrcmpi(sgProduct.szProductNameInternal, "GRE") != 0) && gGreInstallerHasRun)
|
||||
if(!IsInstallerProductGRE() && gGreInstallerHasRun)
|
||||
{
|
||||
char status[MAX_BUF];
|
||||
|
||||
@ -8527,6 +8743,7 @@ void SaveInstallerFiles()
|
||||
* .exe file will automatically look for the .xpi files in a xpi subdir
|
||||
* off of the current working dir. */
|
||||
_snprintf(destInstallXpiDir, sizeof(destInstallXpiDir), "%sxpi\\", destInstallDir);
|
||||
destInstallXpiDir[sizeof(destInstallXpiDir) - 1] = '\0';
|
||||
CreateDirectoriesAll(destInstallXpiDir, ADD_TO_UNINSTALL_LOG);
|
||||
}
|
||||
else
|
||||
|
@ -229,6 +229,8 @@ void ReplacePrivateProfileStrCR(LPSTR aInputOutputStr);
|
||||
void UpdateGREAppInstallerProgress(int percent);
|
||||
BOOL IsPathWithinWindir();
|
||||
void CleanupOnUpgrade();
|
||||
BOOL IsInstallerProductGRE(void);
|
||||
HRESULT CleanupOrphanedGREs(void);
|
||||
|
||||
#endif /* _EXTRA_H_ */
|
||||
|
||||
|
@ -477,6 +477,8 @@ typedef struct setupStruct
|
||||
LPSTR szAppID;
|
||||
LPSTR szAppPath;
|
||||
LPSTR szRegPath;
|
||||
BOOL greCleanupOrphans;
|
||||
char greCleanupOrphansMessage[MAX_BUF];
|
||||
char greID[MAX_BUF];
|
||||
char grePrivateKey[MAX_BUF];
|
||||
} setupGen;
|
||||
|
Loading…
Reference in New Issue
Block a user