Bug 1335857 - Synchronize the TB Maintenance Installer and Uninstaller with the Firefox version. r=jorgk

Referenced bugs:
Bug 778322 - Remove the prefetch deleted registry key from machines that contain it
Bug 775458 - Microsoft Security Essentials causes slow update fix
Bug 1025640 - Enable building and installing the x64bit maintenance service on x64
Bug 1334883 - Remove code NSIS pre-3.0a2 code from installer
Bug 1332496 - Fix 64-bit uninstaller failing to automatically remove maintenance service
This commit is contained in:
Richard Marti 2017-02-03 22:46:33 +01:00
Родитель efd80b963c
Коммит 901c0b415f
2 изменённых файлов: 209 добавлений и 144 удалений

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

@ -13,13 +13,9 @@ CRCCheck on
RequestExecutionLevel admin
; The commands inside this ifdef require NSIS 3.0a2 or greater so the ifdef can
; be removed after we require NSIS 3.0a2 or greater.
!ifdef NSIS_PACKEDVERSION
Unicode true
ManifestSupportedOS all
ManifestDPIAware true
!endif
Unicode true
ManifestSupportedOS all
ManifestDPIAware true
!addplugindir ./
@ -72,17 +68,16 @@ InstallDirRegKey HKLM "Software\Mozilla\MaintenanceService" ""
SetOverwrite on
; serviceinstall.cpp also uses this key, in case the path is changed, update
; there too.
!define MaintUninstallKey \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService"
; The HAVE_64BIT_BUILD define also means that we have an x64 build,
; not just an x64 OS.
!ifdef HAVE_64BIT_BUILD
; See below, we actually abort the install for x64 builds currently.
InstallDir "$PROGRAMFILES64\${MaintFullName}\"
!else
InstallDir "$PROGRAMFILES32\${MaintFullName}\"
!endif
; Always install into the 32-bit location even if we have a 64-bit build.
; This is because we use only 1 service for all Firefox channels.
; Allow either x86 and x64 builds to exist at this location, depending on
; what is the latest build.
InstallDir "$PROGRAMFILES32\${MaintFullName}\"
ShowUnInstDetails nevershow
################################################################################
@ -120,12 +115,6 @@ Function .onInit
System::Call 'kernel32::SetDllDirectoryW(w "")'
SetSilent silent
!ifdef HAVE_64BIT_BUILD
; We plan to eventually enable 64bit native builds to use the maintenance
; service, but for the initial release, to reduce testing and development,
; 64-bit builds will not install the maintenanceservice.
Abort
!endif
${Unless} ${AtLeastWin7}
Abort
@ -178,14 +167,28 @@ Section "MaintenanceService"
${GetParameters} $0
${GetOptions} "$0" "/Upgrade" $0
${If} ${Errors}
nsExec::Exec '"$INSTDIR\$TempMaintServiceName" install'
ExecWait '"$INSTDIR\$TempMaintServiceName" install'
${Else}
; The upgrade cmdline is the same as install except
; It will fail if the service isn't already installed.
nsExec::Exec '"$INSTDIR\$TempMaintServiceName" upgrade'
ExecWait '"$INSTDIR\$TempMaintServiceName" upgrade'
${EndIf}
WriteUninstaller "$INSTDIR\Uninstall.exe"
; Since the Maintenance service can be installed either x86 or x64,
; always use the 64-bit registry.
${If} ${RunningX64}
; Previous versions always created the uninstall key in the 32-bit registry.
; Clean those old entries out if they still exist.
SetRegView 32
DeleteRegKey HKLM "${MaintUninstallKey}"
; Preserve the lastused value before we switch to 64.
SetRegView lastused
SetRegView 64
${EndIf}
WriteRegStr HKLM "${MaintUninstallKey}" "DisplayName" "${MaintFullName}"
WriteRegStr HKLM "${MaintUninstallKey}" "UninstallString" \
'"$INSTDIR\uninstall.exe"'
@ -193,8 +196,7 @@ Section "MaintenanceService"
"$INSTDIR\Uninstall.exe,0"
WriteRegStr HKLM "${MaintUninstallKey}" "DisplayVersion" "${AppVersion}"
WriteRegStr HKLM "${MaintUninstallKey}" "Publisher" "Mozilla"
WriteRegStr HKLM "${MaintUninstallKey}" "Comments" \
"${BrandFullName} ${AppVersion} (${ARCH} ${AB_CD})"
WriteRegStr HKLM "${MaintUninstallKey}" "Comments" "${BrandFullName}"
WriteRegDWORD HKLM "${MaintUninstallKey}" "NoModify" 1
${GetSize} "$INSTDIR" "/S=0K" $R2 $R3 $R4
WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2
@ -204,13 +206,9 @@ Section "MaintenanceService"
; want to install once on the first upgrade to maintenance service.
; Also write out that we are currently installed, preferences will check
; this value to determine if we should show the service update pref.
; Since the Maintenance service can be installed either x86 or x64,
; always use the 64-bit registry for checking if an attempt was made.
${If} ${RunningX64}
SetRegView 64
${EndIf}
WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Attempted" 1
WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Installed" 1
DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "FFPrefetchDisabled"
; Included here for debug purposes only.
; These keys are used to bypass the installation dir is a valid installation
@ -242,7 +240,7 @@ FunctionEnd
Section "Uninstall"
; Delete the service so that no updates will be attempted
nsExec::Exec '"$INSTDIR\maintenanceservice.exe" uninstall'
ExecWait '"$INSTDIR\maintenanceservice.exe" uninstall'
Push "$INSTDIR\updater.ini"
Call un.RenameDelete
@ -254,14 +252,75 @@ Section "Uninstall"
Call un.RenameDelete
Push "$INSTDIR\Uninstall.exe"
Call un.RenameDelete
Push "$INSTDIR\update\updater.ini"
Call un.RenameDelete
Push "$INSTDIR\update\updater.exe"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-1.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-2.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-3.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-4.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-5.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-6.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-7.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-8.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-9.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-10.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-install.log"
Call un.RenameDelete
Push "$INSTDIR\logs\maintenanceservice-uninstall.log"
Call un.RenameDelete
SetShellVarContext all
Push "$APPDATA\Mozilla\logs\maintenanceservice.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-1.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-2.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-3.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-4.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-5.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-6.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-7.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-8.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-9.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-10.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-install.log"
Call un.RenameDelete
Push "$APPDATA\Mozilla\logs\maintenanceservice-uninstall.log"
Call un.RenameDelete
RMDir /REBOOTOK "$APPDATA\Mozilla\logs"
RMDir /REBOOTOK "$APPDATA\Mozilla"
RMDir /REBOOTOK "$INSTDIR\logs"
RMDir /REBOOTOK "$INSTDIR\update"
RMDir /REBOOTOK "$INSTDIR"
DeleteRegKey HKLM "${MaintUninstallKey}"
${If} ${RunningX64}
SetRegView 64
${EndIf}
DeleteRegKey HKLM "${MaintUninstallKey}"
DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "Installed"
DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "FFPrefetchDisabled"
DeleteRegKey HKLM "${FallbackKey}\"
${If} ${RunningX64}
SetRegView lastused

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

@ -4,7 +4,7 @@
# Required Plugins:
# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in
# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash
# CityHash http://dxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash
# ShellLink http://nsis.sourceforge.net/ShellLink_plug-in
# UAC http://nsis.sourceforge.net/UAC_plug-in
@ -19,13 +19,9 @@ CRCCheck on
RequestExecutionLevel user
; The commands inside this ifdef require NSIS 3.0a2 or greater so the ifdef can
; be removed after we require NSIS 3.0a2 or greater.
!ifdef NSIS_PACKEDVERSION
Unicode true
ManifestSupportedOS all
ManifestDPIAware true
!endif
Unicode true
ManifestSupportedOS all
ManifestDPIAware true
!addplugindir ./
@ -52,10 +48,8 @@ Var MaintCertKey
!include WordFunc.nsh
!insertmacro GetSize
!insertmacro GetOptions
!insertmacro GetParameters
!insertmacro GetParent
!insertmacro WordFind
!insertmacro StrFilter
!insertmacro WordReplace
!insertmacro un.GetParent
@ -67,12 +61,9 @@ Var MaintCertKey
; This is named BrandShortName helper because we use this for software update
; post update cleanup.
VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
VIAddVersionKey "OriginalFilename" "helper.exe"
; Most commonly used macros for managing shortcuts
!insertmacro _LoggingShortcutsCommon
!insertmacro AddHandlerValues
!insertmacro CleanVirtualStore
!insertmacro ElevateUAC
@ -86,17 +77,19 @@ VIAddVersionKey "OriginalFilename" "helper.exe"
!insertmacro LogQuickLaunchShortcut
!insertmacro LogStartMenuShortcut
!insertmacro PinnedToStartMenuLnkCount
!insertmacro RegCleanAppHandler
!insertmacro RegCleanMain
!insertmacro RegCleanUninstall
!insertmacro SetAppLSPCategories
!insertmacro SetBrandNameVars
!insertmacro UnloadUAC
!insertmacro UpdateShortcutAppModelIDs
!insertmacro UnloadUAC
!insertmacro WriteRegDWORD2
!insertmacro WriteRegStr2
!insertmacro un.ChangeMUIHeaderImage
!insertmacro un.CheckForFilesInUse
!insertmacro un.CleanUpdatesDir
!insertmacro un.CleanUpdateDirectories
!insertmacro un.CleanVirtualStore
!insertmacro un.DeleteShortcuts
!insertmacro un.GetLongPath
@ -107,9 +100,11 @@ VIAddVersionKey "OriginalFilename" "helper.exe"
!insertmacro un.RegCleanAppHandler
!insertmacro un.RegCleanFileHandler
!insertmacro un.RegCleanMain
!insertmacro un.RegCleanProtocolHandler
!insertmacro un.RegCleanUninstall
!insertmacro un.RegCleanProtocolHandler
!insertmacro un.RemoveQuotesFromPath
!insertmacro un.RemovePrecompleteEntries
!insertmacro un.SetAppLSPCategories
!insertmacro un.SetBrandNameVars
!include shared.nsh
@ -157,7 +152,7 @@ ShowUnInstDetails nevershow
!insertmacro MUI_UNPAGE_WELCOME
; Custom Uninstall Confirm Page
UninstPage custom un.preConfirm un.leaveConfirm
UninstPage custom un.preConfirm
; Remove Files Page
!insertmacro MUI_UNPAGE_INSTFILES
@ -169,6 +164,66 @@ UninstPage custom un.preConfirm un.leaveConfirm
; Use the default dialog for IDD_VERIFY for a simple Banner
ChangeUI IDD_VERIFY "${NSISDIR}\Contrib\UIs\default.exe"
################################################################################
# Helper Functions
; This function is used to uninstall the maintenance service if the
; application currently being uninstalled is the last application to use the
; maintenance service.
Function un.UninstallServiceIfNotUsed
; $0 will store if a subkey exists
; $1 will store the first subkey if it exists or an empty string if it doesn't
; Backup the old values
Push $0
Push $1
; The maintenance service always uses the 64-bit registry on x64 systems
${If} ${RunningX64}
SetRegView 64
${EndIf}
; Figure out the number of subkeys
StrCpy $0 0
${Do}
EnumRegKey $1 HKLM "Software\Mozilla\MaintenanceService" $0
${If} "$1" == ""
${ExitDo}
${EndIf}
IntOp $0 $0 + 1
${Loop}
; Restore back the registry view
${If} ${RunningX64}
SetRegView lastUsed
${EndIf}
${If} $0 == 0
; Get the path of the maintenance service uninstaller.
; Look in both the 32-bit and 64-bit registry views.
SetRegView 32
ReadRegStr $1 HKLM ${MaintUninstallKey} "UninstallString"
SetRegView lastused
${If} $1 == ""
${AndIf} ${RunningX64}
SetRegView 64
ReadRegStr $1 HKLM ${MaintUninstallKey} "UninstallString"
SetRegView lastused
${EndIf}
; If the uninstall string does not exist, skip executing it
${If} $1 != ""
; $1 is already a quoted string pointing to the install path
; so we're already protected against paths with spaces
nsExec::Exec "$1 /S"
${EndIf}
${EndIf}
; Restore the old value of $1 and $0
Pop $1
Pop $0
FunctionEnd
################################################################################
# Install Sections
; Empty section required for the installer to compile as an uninstaller
@ -203,6 +258,19 @@ Section "Uninstall"
${un.RegCleanUninstall}
${un.DeleteShortcuts}
; Unregister resources associated with Win7 taskbar jump lists.
${If} ${AtLeastWin7}
${AndIf} "$AppUserModelID" != ""
ApplicationID::UninstallJumpLists "$AppUserModelID"
${EndIf}
; Remove the updates directory
${un.CleanUpdateDirectories} "Thunderbird" "Thunderbird\updates"
; Remove any app model id's stored in the registry for this install path
DeleteRegValue HKCU "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR"
DeleteRegValue HKLM "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR"
ClearErrors
WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
${If} ${Errors}
@ -224,16 +292,6 @@ Section "Uninstall"
${un.RegCleanProtocolHandler} "nntp"
${un.RegCleanProtocolHandler} "snews"
; Unregister resources associated with Win7 taskbar jump lists.
${If} "$AppUserModelID" != ""
${AndIf} ${AtLeastWin7}
ApplicationID::UninstallJumpLists "$AppUserModelID"
${EndIf}
; Remove any app model id's stored in the registry for this install path
DeleteRegValue HKCU "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR"
DeleteRegValue HKLM "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR"
ClearErrors
ReadRegStr $R9 HKCR "ThunderbirdEML" ""
; Don't clean up the file handlers if the ThunderbirdEML key still exists
@ -313,9 +371,6 @@ Section "Uninstall"
Delete /REBOOTOK "$INSTDIR\mozMapi32_InUse.dll"
${EndIf}
; Remove the updates directory
${un.CleanUpdatesDir} "Thunderbird"
; Remove files that may be left behind by the application in the
; VirtualStore directory.
${un.CleanVirtualStore}
@ -328,19 +383,25 @@ Section "Uninstall"
RmDir /r /REBOOTOK "$INSTDIR\uninstall"
; Remove the installation directory if it is empty
${RemoveDir} "$INSTDIR"
RmDir "$INSTDIR"
; If thunderbird.exe was successfully deleted yet we still need to restart to
; remove other files create a dummy thunderbird.exe.moz-delete to prevent the
; installer from allowing an install without restart when it is required
; to complete an uninstall.
${If} ${RebootFlag}
${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-delete"
FileOpen $0 "$INSTDIR\${FileMainEXE}.moz-delete" w
FileWrite $0 "Will be deleted on restart"
Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete"
FileClose $0
${EndUnless}
; Admin is required to delete files on reboot so only add the moz-delete if
; the user is an admin. After calling UAC::IsAdmin $0 will equal 1 if the
; user is an admin.
UAC::IsAdmin
${If} "$0" == "1"
${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-delete"
FileOpen $0 "$INSTDIR\${FileMainEXE}.moz-delete" w
FileWrite $0 "Will be deleted on restart"
Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete"
FileClose $0
${EndUnless}
${EndIf}
${EndIf}
; Refresh desktop icons otherwise the start menu internet item won't be
@ -354,67 +415,20 @@ Section "Uninstall"
ServicesHelper::PathToUniqueRegistryPath "$INSTDIR"
Pop $MaintCertKey
${If} $MaintCertKey != ""
; We always use the 64bit registry for certs
; This call is ignored on 32-bit systems.
SetRegView 64
DeleteRegKey HKLM "$MaintCertKey\"
SetRegView lastused
; Always use the 64bit registry for certs on 64bit systems.
${If} ${RunningX64}
SetRegView 64
${EndIf}
DeleteRegKey HKLM "$MaintCertKey"
${If} ${RunningX64}
SetRegView lastused
${EndIf}
${EndIf}
Call un.UninstallServiceIfNotUsed
!endif
SectionEnd
################################################################################
# Helper Functions
; This function is used to uninstall the maintenance service if the
; application currently being uninstalled is the last application to use the
; maintenance service.
Function un.UninstallServiceIfNotUsed
; $0 will store if a subkey exists
; $1 will store the first subkey if it exists or an empty string if it doesn't
; Backup the old values
Push $0
Push $1
; The maintenance service always uses the 64-bit registry on x64 systems
${If} ${RunningX64}
SetRegView 64
${EndIf}
; Figure out the number of subkeys
StrCpy $0 0
${Do}
EnumRegKey $1 HKLM "Software\Mozilla\MaintenanceService" $0
${If} "$1" == ""
${ExitDo}
${EndIf}
IntOp $0 $0 + 1
${Loop}
; Restore back the registry view
${If} ${RunningX64}
SetRegView lastUsed
${EndIf}
${If} $0 == 0
; Get the path of the maintenance service uninstaller
ReadRegStr $1 HKLM ${MaintUninstallKey} "UninstallString"
; If the uninstall string does not exist, skip executing it
StrCmp $1 "" doneUninstall
; $1 is already a quoted string pointing to the install path
; so we're already protected against paths with spaces
nsExec::Exec "$1 /S"
doneUninstall:
${EndIf}
; Restore the old value of $1 and $0
Pop $1
Pop $0
FunctionEnd
################################################################################
# Language
@ -443,6 +457,8 @@ Function un.leaveWelcome
${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
Banner::show /NOUNLOAD "$(BANNER_CHECK_EXISTING)"
; If the message window has been found previously give the app an additional
; five seconds to close.
${If} "$TmpVal" == "FoundMessageWindow"
Sleep 5000
${EndIf}
@ -453,9 +469,14 @@ Function un.leaveWelcome
Banner::destroy
; If there are files in use $TmpVal will be "true"
${If} "$TmpVal" == "true"
; If the message window is found the call to ManualCloseAppPrompt will
; abort leaving the value of $TmpVal set to "FoundMessageWindow".
StrCpy $TmpVal "FoundMessageWindow"
${un.ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)"
; If the message window is not found set $TmpVal to "true" so the restart
; required message is displayed.
StrCpy $TmpVal "true"
${EndIf}
${EndIf}
@ -469,6 +490,7 @@ Function un.preConfirm
${un.ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
${EndIf}
; Setup the unconfirm.ini file for the Custom Uninstall Confirm Page
WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "3"
WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Type "label"
@ -518,19 +540,6 @@ Function un.preConfirm
!insertmacro MUI_INSTALLOPTIONS_SHOW
FunctionEnd
Function un.leaveConfirm
; Try to delete the app executable and if we can't delete it try to find the
; app's message window and prompt the user to close the app. This allows
; running an instance that is located in another directory. If for whatever
; reason there is no message window we will just rename the app's files and
; then remove them on restart if they are in use.
ClearErrors
${DeleteFile} "$INSTDIR\${FileMainEXE}"
${If} ${Errors}
${un.ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)"
${EndIf}
FunctionEnd
################################################################################
# Initialization Functions
@ -540,9 +549,6 @@ Function .onInit
System::Call 'kernel32::SetDllDirectoryW(w "")'
; We need this set up for most of the helper.exe operations.
!ifdef AppName
${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs"
!endif
${UninstallOnInitCommon}
FunctionEnd