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
parent e1f404df97
commit f30a5ccefa
6 changed files with 319 additions and 96 deletions

View File

@ -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

View File

@ -293,7 +293,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

View File

@ -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
@ -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
* 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.
@ -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
* 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.
@ -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
* 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.
@ -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
* 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
@ -1899,103 +1911,104 @@ 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
/**
* If present removes the VirtualStore directory for this installation. Uses the
* program files directory path and the current install location to determine
* the sub-directory in the VirtualStore directory.
*/
*/
!macro CleanVirtualStore
!ifndef ${_MOZFUNC_UN}CleanVirtualStore
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
@ -2046,30 +2059,155 @@ Exch $R9 ; exchange the new $R9 value with the top of the stack
!macroend
!macro CleanVirtualStoreCall
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Call CleanVirtualStore
!verbose pop
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Call CleanVirtualStore
!verbose pop
!macroend
!macro un.CleanVirtualStoreCall
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Call un.CleanVirtualStore
!verbose pop
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Call un.CleanVirtualStore
!verbose pop
!macroend
!macro un.CleanVirtualStore
!ifndef un.CleanVirtualStore
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN
!define _MOZFUNC_UN "un."
!ifndef un.CleanVirtualStore
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!undef _MOZFUNC_UN
!define _MOZFUNC_UN "un."
!insertmacro CleanVirtualStore
!insertmacro CleanVirtualStore
!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

View File

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

View File

@ -589,6 +589,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 {

View File

@ -263,6 +263,7 @@ private:
static char* gSourcePath;
static ArchiveReader gArchiveReader;
static bool gSucceeded = FALSE;
static const char kWhitespace[] = " \t";
static const char kNL[] = "\r\n";
@ -1006,6 +1007,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
@ -1144,6 +1200,9 @@ int main(int argc, char **argv)
#ifdef XP_WIN
if (exefile)
CloseHandle(exefile);
if (gSucceeded)
LaunchWinPostProcess(argv[4]);
#endif
// 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;
}
if (status == OK)
gSucceeded = TRUE;
UpdateProgressUI(100.0f);
}