From b4bd3644a712866b844cf54ec14d7aafb7b7094c Mon Sep 17 00:00:00 2001 From: "rob_strong%exchangecode.com" Date: Sat, 8 Sep 2007 23:31:17 +0000 Subject: [PATCH] Bug 368587 - avoid the second UAC prompt for helper.exe on software update by launching it directly from the elevated updater.exe process. r=bsmedberg, a1.8.1.7=dveditz for release-drivers git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_BRANCH@235414 18797224-902f-48f8-a5cc-f745e15eee43 --- .../installer/windows/nsis/uninstaller.nsi | 11 +- mozilla/browser/locales/Makefile.in | 3 +- .../mozapps/installer/windows/nsis/common.nsh | 287 +++++++++++++----- .../mozapps/update/src/nsPostUpdateWin.js | 10 + .../mozapps/update/src/updater/updater.cpp | 68 +++++ 5 files changed, 301 insertions(+), 78 deletions(-) diff --git a/mozilla/browser/installer/windows/nsis/uninstaller.nsi b/mozilla/browser/installer/windows/nsis/uninstaller.nsi index 1f22478803e..b51a1a104bb 100755 --- a/mozilla/browser/installer/windows/nsis/uninstaller.nsi +++ b/mozilla/browser/installer/windows/nsis/uninstaller.nsi @@ -62,9 +62,13 @@ Var TmpVal !include WordFunc.nsh !include MUI.nsh +!insertmacro FileJoin !insertmacro GetOptions !insertmacro GetParameters +!insertmacro LineFind !insertmacro StrFilter +!insertmacro TextCompare +!insertmacro TrimNewLines !insertmacro WordFind !insertmacro WordReplace @@ -86,6 +90,7 @@ VIAddVersionKey "FileDescription" "${BrandShortName} Helper" !insertmacro AddHandlerValues !insertmacro RegCleanMain !insertmacro RegCleanUninstall +!insertmacro UpdateUninstallLog !insertmacro WriteRegStr2 !insertmacro WriteRegDWORD2 @@ -228,7 +233,7 @@ Section "Uninstall" ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log" ; Copy the uninstall log file to a temporary file GetTempFileName $TmpVal - CopyFiles "$INSTDIR\uninstall\uninstall.log" "$TmpVal" + CopyFiles /SILENT /FILESONLY "$INSTDIR\uninstall\uninstall.log" "$TmpVal" ; Unregister DLL's ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.UnRegDLLsCallback" @@ -471,7 +476,7 @@ Function .onInit ${If} ${FileExists} "$R3" Delete "$INSTDIR\uninstall\*wizard*" Delete "$INSTDIR\uninstall\uninstall.log" - CopyFiles /SILENT "$R3" "$INSTDIR\uninstall\" + CopyFiles /SILENT /FILESONLY "$R3" "$INSTDIR\uninstall\" Push $R3 ${GetParentDir} Pop $R4 @@ -479,6 +484,8 @@ Function .onInit RmDir "$R4" ${EndIf} ${EndUnless} + ${Else} + ${UpdateUninstallLog} ${EndUnless} StrCpy $R1 "true" ${EndUnless} diff --git a/mozilla/browser/locales/Makefile.in b/mozilla/browser/locales/Makefile.in index 41f9909a882..69a9983343f 100644 --- a/mozilla/browser/locales/Makefile.in +++ b/mozilla/browser/locales/Makefile.in @@ -292,7 +292,8 @@ endif ifdef MOZ_UPDATER libs:: $(addprefix $(LOCALE_SRCDIR)/,updater/updater.ini) ifeq ($(OS_ARCH),WINNT) - iconv -f UTF-8 -t $(WIN_INSTALLER_CHARSET) $< > $(FINAL_TARGET)/updater.ini + cat $< $(srcdir)/../installer/windows/nsis/updater_append.ini | \ + iconv -f UTF-8 -t $(WIN_INSTALLER_CHARSET) > $(FINAL_TARGET)/updater.ini else ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) $(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/updater.app/Contents/MacOS diff --git a/mozilla/toolkit/mozapps/installer/windows/nsis/common.nsh b/mozilla/toolkit/mozapps/installer/windows/nsis/common.nsh index d50e70ce174..f60f7dbae01 100755 --- a/mozilla/toolkit/mozapps/installer/windows/nsis/common.nsh +++ b/mozilla/toolkit/mozapps/installer/windows/nsis/common.nsh @@ -389,11 +389,11 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack !macroend !macro GetParentDir - Exch $R0 - Push $R1 - Push $R2 - Push $R3 - StrLen $R3 $R0 + Exch $R0 + Push $R1 + Push $R2 + Push $R3 + StrLen $R3 $R0 ${DoWhile} 1 > 0 IntOp $R1 $R1 - 1 ${If} $R1 <= -$R3 @@ -1081,6 +1081,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack /** * Writes a registry string using SHCTX and the supplied params and logs the * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1. + * + * Define NO_LOG to prevent all logging when calling this from the uninstaller. + * * @param _ROOT * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * This will only be used for logging. @@ -1186,6 +1189,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack /** * Writes a registry dword using SHCTX and the supplied params and logs the * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1. + * + * Define NO_LOG to prevent all logging when calling this from the uninstaller. + * * @param _ROOT * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * This will only be used for logging. @@ -1291,6 +1297,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack /** * Writes a registry string to HKCR using the supplied params and logs the * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1. + * + * Define NO_LOG to prevent all logging when calling this from the uninstaller. + * * @param _ROOT * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * This will only be used for logging. @@ -1409,6 +1418,9 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack * Creates a registry key. This will log the actions to the install and * uninstall logs. Alternatively you can set a registry value to create the key * and then delete the value. + * + * Define NO_LOG to prevent all logging when calling this from the uninstaller. + * * @param _ROOT * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * @param _KEY @@ -1910,95 +1922,220 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack */ !macro GetPathFromString - !ifndef ${_MOZFUNC_UN}GetPathFromString - !verbose push - !verbose ${_MOZFUNC_VERBOSE} - !define ${_MOZFUNC_UN}GetPathFromString "!insertmacro ${_MOZFUNC_UN}GetPathFromStringCall" + !ifndef ${_MOZFUNC_UN}GetPathFromString + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !define ${_MOZFUNC_UN}GetPathFromString "!insertmacro ${_MOZFUNC_UN}GetPathFromStringCall" - Function ${_MOZFUNC_UN}GetPathFromString - Exch $R8 - Push $R7 - Push $R6 - ClearErrors + Function ${_MOZFUNC_UN}GetPathFromString + Exch $R8 + Push $R7 + Push $R6 + ClearErrors - StrCpy $R9 $R8 - StrCpy $R6 0 ; Set the counter to 0. + StrCpy $R9 $R8 + StrCpy $R6 0 ; Set the counter to 0. - ClearErrors - ; Handle quoted paths with arguments. - StrCpy $R7 $R9 1 ; Copy the first char. - StrCmp $R7 '"' +2 +1 ; Is it a "? - StrCmp $R7 "'" +1 +9 ; Is it a '? - StrCpy $R9 $R9 "" 1 ; Remove the first char. - IntOp $R6 $R6 + 1 ; Increment the counter. - StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char. - StrCmp $R7 "" end ; Are there no more chars? - StrCmp $R7 '"' +2 +1 ; Is it a " char? - StrCmp $R7 "'" +1 -4 ; Is it a ' char? - StrCpy $R9 $R9 $R6 ; Copy chars up to the counter. - GoTo end + ClearErrors + ; Handle quoted paths with arguments. + StrCpy $R7 $R9 1 ; Copy the first char. + StrCmp $R7 '"' +2 +1 ; Is it a "? + StrCmp $R7 "'" +1 +9 ; Is it a '? + StrCpy $R9 $R9 "" 1 ; Remove the first char. + IntOp $R6 $R6 + 1 ; Increment the counter. + StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char. + StrCmp $R7 "" end ; Are there no more chars? + StrCmp $R7 '"' +2 +1 ; Is it a " char? + StrCmp $R7 "'" +1 -4 ; Is it a ' char? + StrCpy $R9 $R9 $R6 ; Copy chars up to the counter. + GoTo end - ; Handle DefaultIcon paths. DefaultIcon paths are not quoted and end with - ; a , and a number. - IntOp $R6 $R6 - 1 ; Decrement the counter. - StrCpy $R7 $R9 1 $R6 ; Copy one char from the end minus the counter. - StrCmp $R7 '' +4 ; Are there no more chars? - StrCmp $R7 ',' +1 -3 ; Is it a , char? - StrCpy $R9 $R9 $R6 ; Copy chars up to the end minus the counter. - GoTo end + ; Handle DefaultIcon paths. DefaultIcon paths are not quoted and end with + ; a , and a number. + IntOp $R6 $R6 - 1 ; Decrement the counter. + StrCpy $R7 $R9 1 $R6 ; Copy one char from the end minus the counter. + StrCmp $R7 '' +4 ; Are there no more chars? + StrCmp $R7 ',' +1 -3 ; Is it a , char? + StrCpy $R9 $R9 $R6 ; Copy chars up to the end minus the counter. + GoTo end - ; Handle unquoted paths with arguments. An unquoted path with arguments - ; must be an 8dot3 path. - StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0. - IntOp $R6 $R6 + 1 ; Increment the counter. - StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char. - StrCmp $R7 "" end ; Are there no more chars? - StrCmp $R7 " " +1 -3 ; Is it a space char? - StrCpy $R9 $R9 $R6 ; Copy chars up to the counter. + ; Handle unquoted paths with arguments. An unquoted path with arguments + ; must be an 8dot3 path. + StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0. + IntOp $R6 $R6 + 1 ; Increment the counter. + StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char. + StrCmp $R7 "" end ; Are there no more chars? + StrCmp $R7 " " +1 -3 ; Is it a space char? + StrCpy $R9 $R9 $R6 ; Copy chars up to the counter. - end: + end: - Pop $R6 - Pop $R7 - Exch $R8 - Push $R9 - FunctionEnd + Pop $R6 + Pop $R7 + Exch $R8 + Push $R9 + FunctionEnd - !verbose pop - !endif + !verbose pop + !endif !macroend !macro GetPathFromStringCall _STRING _RESULT - !verbose push - !verbose ${_MOZFUNC_VERBOSE} - Push "${_STRING}" - Call GetPathFromString - Pop ${_RESULT} - !verbose pop + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_STRING}" + Call GetPathFromString + Pop ${_RESULT} + !verbose pop !macroend !macro un.GetPathFromStringCall _STRING _RESULT - !verbose push - !verbose ${_MOZFUNC_VERBOSE} - Push "${_STRING}" - Call un.GetPathFromString - Pop ${_RESULT} - !verbose pop + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Push "${_STRING}" + Call un.GetPathFromString + Pop ${_RESULT} + !verbose pop !macroend !macro un.GetPathFromString - !ifndef un.GetPathFromString - !verbose push - !verbose ${_MOZFUNC_VERBOSE} - !undef _MOZFUNC_UN - !define _MOZFUNC_UN "un." + !ifndef un.GetPathFromString + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !undef _MOZFUNC_UN + !define _MOZFUNC_UN "un." - !insertmacro GetPathFromString + !insertmacro GetPathFromString - !undef _MOZFUNC_UN - !define _MOZFUNC_UN - !verbose pop - !endif + !undef _MOZFUNC_UN + !define _MOZFUNC_UN + !verbose pop + !endif +!macroend + +/** + * Updates the uninstall.log with new files added by software update. + * + * Requires FileJoin, LineFind, TextCompare, and TrimNewLines. + * + * IMPORTANT! The LineFind docs claim that it uses all registers except $R0-$R3. + * Though it appears that this is not true all registers besides + * $R0-$R3 may be overwritten so protect yourself! + */ +!macro UpdateUninstallLog + + !ifndef ${_MOZFUNC_UN}UpdateUninstallLog + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !define ${_MOZFUNC_UN}UpdateUninstallLog "!insertmacro ${_MOZFUNC_UN}UpdateUninstallLogCall" + + Function ${_MOZFUNC_UN}UpdateUninstallLog + Push $R3 + Push $R2 + Push $R1 + Push $R0 + + ClearErrors + + GetFullPathName $R3 "$INSTDIR\uninstall" + IfFileExists "$R3\uninstall.update" +2 0 + Return + + ${${_MOZFUNC_UN}LineFind} "$R3\uninstall.update" "" "1:-1" "${_MOZFUNC_UN}CleanupUpdateLog" + + GetTempFileName $R2 "$R3" + FileOpen $R1 $R2 w + ${${_MOZFUNC_UN}TextCompare} "$R3\uninstall.update" "$R3\uninstall.log" "SlowDiff" "${_MOZFUNC_UN}CreateUpdateDiff" + FileClose $R1 + + IfErrors +2 0 + ${${_MOZFUNC_UN}FileJoin} "$R3\uninstall.log" "$R2" "$R3\uninstall.log" + + ${DeleteFile} "$R2" + + ClearErrors + + Pop $R0 + Pop $R1 + Pop $R2 + Pop $R3 + FunctionEnd + + ; This callback MUST use labels vs. relative line numbers. + Function ${_MOZFUNC_UN}CleanupUpdateLog + StrCpy $R2 "$R9" 12 + StrCmp "$R2" "EXECUTE ADD " 0 skip + StrCpy $R9 "$R9" "" 12 + + Push $R6 + Push $R5 + Push $R4 + StrCpy $R4 "" ; Initialize to an empty string. + StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0. + + loop: + IntOp $R6 $R6 + 1 ; Increment the counter. + StrCpy $R5 $R9 1 $R6 ; Starting from the counter copy the next char. + StrCmp $R5 "" copy ; Are there no more chars? + StrCmp $R5 "/" 0 +2 ; Is the char a /? + StrCpy $R5 "\" ; Replace the char with a \. + + StrCpy $R4 "$R4$R5" + GoTo loop + + copy: + StrCpy $R9 "File: \$R4" + Pop $R6 + Pop $R5 + Pop $R4 + GoTo end + + skip: + StrCpy $0 "SkipWrite" + + end: + Push $0 + FunctionEnd + + Function ${_MOZFUNC_UN}CreateUpdateDiff + ${${_MOZFUNC_UN}TrimNewLines} "$9" "$9" + StrCmp $9 "" +2 0 + FileWrite $R1 "$9$\r$\n" + + Push 0 + FunctionEnd + + !verbose pop + !endif +!macroend + +!macro UpdateUninstallLogCall + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Call UpdateUninstallLog + !verbose pop +!macroend + +!macro un.UpdateUninstallLogCall + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + Call un.UpdateUninstallLog + !verbose pop +!macroend + +!macro un.UpdateUninstallLog + !ifndef un.UpdateUninstallLog + !verbose push + !verbose ${_MOZFUNC_VERBOSE} + !undef _MOZFUNC_UN + !define _MOZFUNC_UN "un." + + !insertmacro UpdateUninstallLog + + !undef _MOZFUNC_UN + !define _MOZFUNC_UN + !verbose pop + !endif !macroend /** diff --git a/mozilla/toolkit/mozapps/update/src/nsPostUpdateWin.js b/mozilla/toolkit/mozapps/update/src/nsPostUpdateWin.js index c0d9138697f..984670e2c57 100644 --- a/mozilla/toolkit/mozapps/update/src/nsPostUpdateWin.js +++ b/mozilla/toolkit/mozapps/update/src/nsPostUpdateWin.js @@ -594,6 +594,16 @@ nsPostUpdateWin.prototype = { }, run: function() { + // When uninstall/uninstall.update exists the uninstaller has already + // updated the uninstall.log with the files added by software update. + var updateUninstallFile = getFile(KEY_APPDIR); + updateUninstallFile.append("uninstall"); + updateUninstallFile.append("uninstall.update"); + if (updateUninstallFile.exists()) { + LOG("nothing to do, uninstall.log has already been updated"); + return; + } + try { installLogWriter = new InstallLogWriter(); try { diff --git a/mozilla/toolkit/mozapps/update/src/updater/updater.cpp b/mozilla/toolkit/mozapps/update/src/updater/updater.cpp index ff80bcf268c..fd1d41b0f5d 100644 --- a/mozilla/toolkit/mozapps/update/src/updater/updater.cpp +++ b/mozilla/toolkit/mozapps/update/src/updater/updater.cpp @@ -263,6 +263,9 @@ private: static char* gSourcePath; static ArchiveReader gArchiveReader; +#ifdef XP_WIN +static bool gSucceeded = FALSE; +#endif static const char kWhitespace[] = " \t"; static const char kNL[] = "\r\n"; @@ -1006,6 +1009,61 @@ PatchIfFile::Finish(int status) #ifdef XP_WIN #include "nsWindowsRestart.cpp" + +static void +LaunchWinPostProcess(const char *appExe) +{ + // Launch helper.exe to perform post processing (e.g. registry and log file + // modifications) for the update. + char inifile[MAXPATHLEN]; + strcpy(inifile, appExe); + + char *slash = strrchr(inifile, '\\'); + if (!slash) + return; + + strcpy(slash + 1, "updater.ini"); + + char exefile[MAXPATHLEN]; + char exearg[MAXPATHLEN]; + if (!GetPrivateProfileString("PostUpdateWin", "ExeRelPath", NULL, exefile, + sizeof(exefile), inifile)) + return; + + if (!GetPrivateProfileString("PostUpdateWin", "ExeArg", NULL, exearg, + sizeof(exearg), inifile)) + return; + + char exefullpath[MAXPATHLEN]; + strcpy(exefullpath, appExe); + + slash = strrchr(exefullpath, '\\'); + strcpy(slash + 1, exefile); + + char dlogFile[MAXPATHLEN]; + strcpy(dlogFile, exefullpath); + + slash = strrchr(dlogFile, '\\'); + strcpy(slash + 1, "uninstall.update"); + + char slogFile[MAXPATHLEN]; + snprintf(slogFile, MAXPATHLEN, "%s/update.log", gSourcePath); + + // We want to launch the post update helper app to update the Windows + // registry even if there is a failure with removing the uninstall.update + // file or copying the update.log file. + ensure_remove(dlogFile); + copy_file(slogFile, dlogFile); + + static int argc = 2; + static char **argv = (char**) malloc(sizeof(char*) * (argc + 1)); + argv[0] = "argv0ignoredbywinlaunchchild"; + argv[1] = exearg; + argv[2] = "\0"; + + WinLaunchChild(exefullpath, argc, argv, 1); + free(argv); +} #endif static void @@ -1128,6 +1186,11 @@ int main(int argc, char **argv) LogFinish(); +#ifdef XP_WIN + if (gSucceeded) + LaunchWinPostProcess(argv[4]); +#endif + // The callback to execute is given as the last N arguments of our command // line. The first of those arguments specifies the working directory for // the callback. @@ -1233,6 +1296,11 @@ ActionList::Finish(int status) a = a->mNext; } +#ifdef XP_WIN + if (status == OK) + gSucceeded = TRUE; +#endif + UpdateProgressUI(100.0f); }