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, a=mconnor

This commit is contained in:
rob_strong@exchangecode.com 2007-07-30 13:16:56 -07:00
Родитель e1f404df97
Коммит f30a5ccefa
6 изменённых файлов: 319 добавлений и 96 удалений

Просмотреть файл

@ -0,0 +1,12 @@
; IMPORTANT: This file should always start with a newline in case a locale
; provided updater.ini does not end with a newline.
; Application to launch after an update has been successfully applied. This
; must be in the same directory or a sub-directory of the directory of the
; application executable that initiated the software update.
[PostUpdateWin]
; ExeRelPath is the path to the PostUpdateWin executable relative to the
; application executable.
ExeRelPath=uninstall\helper.exe
; ExeArg is the argument to pass to the PostUpdateWin exe
ExeArg=/PostUpdate

Просмотреть файл

@ -293,7 +293,8 @@ endif
ifdef MOZ_UPDATER ifdef MOZ_UPDATER
libs:: $(addprefix $(LOCALE_SRCDIR)/,updater/updater.ini) libs:: $(addprefix $(LOCALE_SRCDIR)/,updater/updater.ini)
ifeq ($(OS_ARCH),WINNT) 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 else
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/updater.app/Contents/MacOS $(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/updater.app/Contents/MacOS

Просмотреть файл

@ -389,11 +389,11 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!macroend !macroend
!macro GetParentDir !macro GetParentDir
Exch $R0 Exch $R0
Push $R1 Push $R1
Push $R2 Push $R2
Push $R3 Push $R3
StrLen $R3 $R0 StrLen $R3 $R0
${DoWhile} 1 > 0 ${DoWhile} 1 > 0
IntOp $R1 $R1 - 1 IntOp $R1 $R1 - 1
${If} $R1 <= -$R3 ${If} $R1 <= -$R3
@ -1071,6 +1071,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 * 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. * 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 * @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* This will only be used for logging. * This will only be used for logging.
@ -1176,6 +1179,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 * 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. * 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 * @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* This will only be used for logging. * This will only be used for logging.
@ -1280,6 +1286,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 * 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. * 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 * @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* This will only be used for logging. * This will only be used for logging.
@ -1398,6 +1407,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 * 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 * uninstall logs. Alternatively you can set a registry value to create the key
* and then delete the value. * and then delete the value.
*
* Define NO_LOG to prevent all logging when calling this from the uninstaller.
*
* @param _ROOT * @param _ROOT
* The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.). * The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
* @param _KEY * @param _KEY
@ -1899,103 +1911,104 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
*/ */
!macro GetPathFromString !macro GetPathFromString
!ifndef ${_MOZFUNC_UN}GetPathFromString !ifndef ${_MOZFUNC_UN}GetPathFromString
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
!define ${_MOZFUNC_UN}GetPathFromString "!insertmacro ${_MOZFUNC_UN}GetPathFromStringCall" !define ${_MOZFUNC_UN}GetPathFromString "!insertmacro ${_MOZFUNC_UN}GetPathFromStringCall"
Function ${_MOZFUNC_UN}GetPathFromString Function ${_MOZFUNC_UN}GetPathFromString
Exch $R8 Exch $R8
Push $R7 Push $R7
Push $R6 Push $R6
ClearErrors ClearErrors
StrCpy $R9 $R8 StrCpy $R9 $R8
StrCpy $R6 0 ; Set the counter to 0. StrCpy $R6 0 ; Set the counter to 0.
ClearErrors ClearErrors
; Handle quoted paths with arguments. ; Handle quoted paths with arguments.
StrCpy $R7 $R9 1 ; Copy the first char. StrCpy $R7 $R9 1 ; Copy the first char.
StrCmp $R7 '"' +2 +1 ; Is it a "? StrCmp $R7 '"' +2 +1 ; Is it a "?
StrCmp $R7 "'" +1 +9 ; Is it a '? StrCmp $R7 "'" +1 +9 ; Is it a '?
StrCpy $R9 $R9 "" 1 ; Remove the first char. StrCpy $R9 $R9 "" 1 ; Remove the first char.
IntOp $R6 $R6 + 1 ; Increment the counter. IntOp $R6 $R6 + 1 ; Increment the counter.
StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char. StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char.
StrCmp $R7 "" end ; Are there no more chars? StrCmp $R7 "" end ; Are there no more chars?
StrCmp $R7 '"' +2 +1 ; Is it a " char? StrCmp $R7 '"' +2 +1 ; Is it a " char?
StrCmp $R7 "'" +1 -4 ; Is it a ' char? StrCmp $R7 "'" +1 -4 ; Is it a ' char?
StrCpy $R9 $R9 $R6 ; Copy chars up to the counter. StrCpy $R9 $R9 $R6 ; Copy chars up to the counter.
GoTo end GoTo end
; Handle DefaultIcon paths. DefaultIcon paths are not quoted and end with ; Handle DefaultIcon paths. DefaultIcon paths are not quoted and end with
; a , and a number. ; a , and a number.
IntOp $R6 $R6 - 1 ; Decrement the counter. IntOp $R6 $R6 - 1 ; Decrement the counter.
StrCpy $R7 $R9 1 $R6 ; Copy one char from the end minus 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 '' +4 ; Are there no more chars?
StrCmp $R7 ',' +1 -3 ; Is it a , char? StrCmp $R7 ',' +1 -3 ; Is it a , char?
StrCpy $R9 $R9 $R6 ; Copy chars up to the end minus the counter. StrCpy $R9 $R9 $R6 ; Copy chars up to the end minus the counter.
GoTo end GoTo end
; Handle unquoted paths with arguments. An unquoted path with arguments ; Handle unquoted paths with arguments. An unquoted path with arguments
; must be an 8dot3 path. ; must be an 8dot3 path.
StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0. StrCpy $R6 -1 ; Set the counter to -1 so it will start at 0.
IntOp $R6 $R6 + 1 ; Increment the counter. IntOp $R6 $R6 + 1 ; Increment the counter.
StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char. StrCpy $R7 $R9 1 $R6 ; Starting from the counter copy the next char.
StrCmp $R7 "" end ; Are there no more chars? StrCmp $R7 "" end ; Are there no more chars?
StrCmp $R7 " " +1 -3 ; Is it a space char? StrCmp $R7 " " +1 -3 ; Is it a space char?
StrCpy $R9 $R9 $R6 ; Copy chars up to the counter. StrCpy $R9 $R9 $R6 ; Copy chars up to the counter.
end: end:
Pop $R6 Pop $R6
Pop $R7 Pop $R7
Exch $R8 Exch $R8
Push $R9 Push $R9
FunctionEnd FunctionEnd
!verbose pop !verbose pop
!endif !endif
!macroend !macroend
!macro GetPathFromStringCall _STRING _RESULT !macro GetPathFromStringCall _STRING _RESULT
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
Push "${_STRING}" Push "${_STRING}"
Call GetPathFromString Call GetPathFromString
Pop ${_RESULT} Pop ${_RESULT}
!verbose pop !verbose pop
!macroend !macroend
!macro un.GetPathFromStringCall _STRING _RESULT !macro un.GetPathFromStringCall _STRING _RESULT
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
Push "${_STRING}" Push "${_STRING}"
Call un.GetPathFromString Call un.GetPathFromString
Pop ${_RESULT} Pop ${_RESULT}
!verbose pop !verbose pop
!macroend !macroend
!macro un.GetPathFromString !macro un.GetPathFromString
!ifndef un.GetPathFromString !ifndef un.GetPathFromString
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN !undef _MOZFUNC_UN
!define _MOZFUNC_UN "un." !define _MOZFUNC_UN "un."
!insertmacro GetPathFromString !insertmacro GetPathFromString
!undef _MOZFUNC_UN !undef _MOZFUNC_UN
!define _MOZFUNC_UN !define _MOZFUNC_UN
!verbose pop !verbose pop
!endif !endif
!macroend !macroend
/** /**
* If present removes the VirtualStore directory for this installation. Uses the * If present removes the VirtualStore directory for this installation. Uses the
* program files directory path and the current install location to determine * program files directory path and the current install location to determine
* the sub-directory in the VirtualStore directory. * the sub-directory in the VirtualStore directory.
*/ */
!macro CleanVirtualStore !macro CleanVirtualStore
!ifndef ${_MOZFUNC_UN}CleanVirtualStore !ifndef ${_MOZFUNC_UN}CleanVirtualStore
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
@ -2046,30 +2059,155 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!macroend !macroend
!macro CleanVirtualStoreCall !macro CleanVirtualStoreCall
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
Call CleanVirtualStore Call CleanVirtualStore
!verbose pop !verbose pop
!macroend !macroend
!macro un.CleanVirtualStoreCall !macro un.CleanVirtualStoreCall
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
Call un.CleanVirtualStore Call un.CleanVirtualStore
!verbose pop !verbose pop
!macroend !macroend
!macro un.CleanVirtualStore !macro un.CleanVirtualStore
!ifndef un.CleanVirtualStore !ifndef un.CleanVirtualStore
!verbose push !verbose push
!verbose ${_MOZFUNC_VERBOSE} !verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN !undef _MOZFUNC_UN
!define _MOZFUNC_UN "un." !define _MOZFUNC_UN "un."
!insertmacro CleanVirtualStore !insertmacro CleanVirtualStore
!undef _MOZFUNC_UN !undef _MOZFUNC_UN
!define _MOZFUNC_UN !define _MOZFUNC_UN
!verbose pop !verbose pop
!endif !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 !macroend

Просмотреть файл

@ -42,7 +42,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk include $(DEPTH)/config/autoconf.mk
MODULE = extensions MODULE = update
ifdef MOZ_UPDATER ifdef MOZ_UPDATER
DIRS = updater DIRS = updater

Просмотреть файл

@ -589,6 +589,16 @@ nsPostUpdateWin.prototype = {
}, },
run: function() { 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 { try {
installLogWriter = new InstallLogWriter(); installLogWriter = new InstallLogWriter();
try { try {

Просмотреть файл

@ -263,6 +263,7 @@ private:
static char* gSourcePath; static char* gSourcePath;
static ArchiveReader gArchiveReader; static ArchiveReader gArchiveReader;
static bool gSucceeded = FALSE;
static const char kWhitespace[] = " \t"; static const char kWhitespace[] = " \t";
static const char kNL[] = "\r\n"; static const char kNL[] = "\r\n";
@ -1006,6 +1007,61 @@ PatchIfFile::Finish(int status)
#ifdef XP_WIN #ifdef XP_WIN
#include "nsWindowsRestart.cpp" #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 #endif
static void static void
@ -1144,6 +1200,9 @@ int main(int argc, char **argv)
#ifdef XP_WIN #ifdef XP_WIN
if (exefile) if (exefile)
CloseHandle(exefile); CloseHandle(exefile);
if (gSucceeded)
LaunchWinPostProcess(argv[4]);
#endif #endif
// The callback to execute is given as the last N arguments of our command // The callback to execute is given as the last N arguments of our command
@ -1251,6 +1310,9 @@ ActionList::Finish(int status)
a = a->mNext; a = a->mNext;
} }
if (status == OK)
gSucceeded = TRUE;
UpdateProgressUI(100.0f); UpdateProgressUI(100.0f);
} }