# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. /** * Called from the uninstaller's .onInit function not to be confused with the * installer's .onInit or the uninstaller's un.onInit functions. */ !macro UninstallOnInitCommon !ifndef UninstallOnInitCommon !insertmacro ElevateUAC !insertmacro GetLongPath !insertmacro GetOptions !insertmacro GetParameters !insertmacro GetParent !insertmacro UnloadUAC !insertmacro UpdateShortcutAppModelIDs !insertmacro UpdateUninstallLog !verbose push !verbose ${_MOZFUNC_VERBOSE} !define UninstallOnInitCommon "!insertmacro UninstallOnInitCommonCall" Function UninstallOnInitCommon ; Prevents breaking apps that don't use SetBrandNameVars !ifdef SetBrandNameVars ${SetBrandNameVars} "$EXEDIR\distribution\setup.ini" !endif ; Prevent launching the application when a reboot is required and this ; executable is the main application executable IfFileExists "$EXEDIR\${FileMainEXE}.moz-upgrade" +1 +4 MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(WARN_RESTART_REQUIRED_UPGRADE)" IDNO +2 Reboot Quit ; Nothing initialized so no need to call OnEndCommon ${GetParent} "$EXEDIR" $INSTDIR ${GetLongPath} "$INSTDIR" $INSTDIR IfFileExists "$INSTDIR\${FileMainEXE}" +2 +1 Quit ; Nothing initialized so no need to call OnEndCommon !ifmacrodef InitHashAppModelId ; setup the application model id registration value !ifdef AppName ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" !endif !endif ; Prevents breaking apps that don't use SetBrandNameVars !ifdef SetBrandNameVars ${SetBrandNameVars} "$INSTDIR\distribution\setup.ini" !endif ; Application update uses a directory named tobedeleted in the $INSTDIR to ; delete files on OS reboot when they are in use. Try to delete this ; directory if it exists. ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}" RmDir /r "$INSTDIR\${TO_BE_DELETED}" ${EndIf} ; Prevent all operations (e.g. set as default, postupdate, etc.) when a ; reboot is required and the executable launched is helper.exe IfFileExists "$INSTDIR\${FileMainEXE}.moz-upgrade" +1 +4 MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(WARN_RESTART_REQUIRED_UPGRADE)" IDNO +2 Reboot Quit ; Nothing initialized so no need to call OnEndCommon !ifdef HAVE_64BIT_BUILD SetRegView 64 !endif ${GetParameters} $R0 ${Unless} ${Silent} ; Manually check for /S in the command line due to Bug 506867 ClearErrors ${GetOptions} "$R0" "/S" $R2 ${Unless} ${Errors} SetSilent silent ${Else} ; Support for the deprecated -ms command line argument. ClearErrors ${GetOptions} "$R0" "-ms" $R2 ${Unless} ${Errors} SetSilent silent ${EndUnless} ${EndUnless} ${EndUnless} StrCmp "$R0" "" continue hideshortcuts ; Require elevation if the user can elevate hideshortcuts: ClearErrors ${GetOptions} "$R0" "/HideShortcuts" $R2 IfErrors showshortcuts +1 !ifndef NONADMIN_ELEVATE ${ElevateUAC} !endif ${HideShortcuts} GoTo finish ; Require elevation if the user can elevate showshortcuts: ClearErrors ${GetOptions} "$R0" "/ShowShortcuts" $R2 IfErrors defaultappuser +1 !ifndef NONADMIN_ELEVATE ${ElevateUAC} !endif ${ShowShortcuts} GoTo finish ; Require elevation if the the StartMenuInternet registry keys require ; updating and the user can elevate defaultappuser: ClearErrors ${GetOptions} "$R0" "/SetAsDefaultAppUser" $R2 IfErrors defaultappglobal +1 ${SetAsDefaultAppUser} GoTo finish ; Require elevation if the user can elevate defaultappglobal: ClearErrors ${GetOptions} "$R0" "/SetAsDefaultAppGlobal" $R2 IfErrors postupdate +1 ${ElevateUAC} ${SetAsDefaultAppGlobal} GoTo finish ; Do not attempt to elevate. The application launching this executable is ; responsible for elevation if it is required. postupdate: ${WordReplace} "$R0" "$\"" "" "+" $R0 ClearErrors ${GetOptions} "$R0" "/PostUpdate" $R2 IfErrors continue +1 ; If the uninstall.log does not exist don't perform post update ; operations. This prevents updating the registry for zip builds. IfFileExists "$EXEDIR\uninstall.log" +2 +1 Quit ; Nothing initialized so no need to call OnEndCommon ${PostUpdate} ClearErrors ${GetOptions} "$R0" "/UninstallLog=" $R2 IfErrors updateuninstalllog +1 StrCmp "$R2" "" finish +1 GetFullPathName $R3 "$R2" IfFileExists "$R3" +1 finish Delete "$INSTDIR\uninstall\*wizard*" Delete "$INSTDIR\uninstall\uninstall.log" CopyFiles /SILENT /FILESONLY "$R3" "$INSTDIR\uninstall\" ${GetParent} "$R3" $R4 Delete "$R3" RmDir "$R4" GoTo finish ; Do not attempt to elevate. The application launching this executable is ; responsible for elevation if it is required. updateuninstalllog: ${UpdateUninstallLog} finish: ${UnloadUAC} ${RefreshShellIcons} Quit ; Nothing initialized so no need to call OnEndCommon continue: ; If the uninstall.log does not exist don't perform uninstall ; operations. This prevents running the uninstaller for zip builds. IfFileExists "$INSTDIR\uninstall\uninstall.log" +2 +1 Quit ; Nothing initialized so no need to call OnEndCommon ; When silent, try to avoid elevation if we have a chance to succeed. We ; can succeed when we can write to (hence delete from) the install ; directory and when we can clean up all registry entries. Now, the ; installer when elevated writes privileged registry entries for the use ; of the Maintenance Service, even when the service is not and will not be ; installed. (In fact, even when a service installed in the future will ; never update the installation, for example due to not being in a ; privileged location.) In practice this means we can only truly silently ; remove an unelevated install: an elevated installer writing to an ; unprivileged install directory will still write privileged registry ; entries, requiring an elevated uninstaller to completely clean up. ; ; This avoids a wrinkle, whereby an uninstaller which runs unelevated will ; never itself launch the Maintenance Service uninstaller, because it will ; fail to remove its own service registration (removing the relevant ; registry key would require elevation). Therefore the check for the ; service being unused will fail, which will prevent running the service ; uninstaller. That's both subtle and possibly leaves the service ; registration hanging around, which might be a security risk. ; ; That is why we look for a privileged service registration for this ; installation when deciding to elevate, and elevate unconditionally if we ; find one, regardless of the result of the write check that would avoid ; elevation. ; The reason for requiring elevation, or "" for not required. StrCpy $R4 "" ${IfNot} ${Silent} ; In normal operation, require elevation if the user can elevate so that ; we are most likely to succeed. StrCpy $R4 "not silent" ${EndIf} GetTempFileName $R6 "$INSTDIR" FileOpen $R5 "$R6" w FileWrite $R5 "Write Access Test" FileClose $R5 Delete $R6 ${If} ${Errors} StrCpy $R4 "write" ${EndIf} !ifdef MOZ_MAINTENANCE_SERVICE ; We don't necessarily have $MaintCertKey, so use temporary registers. ServicesHelper::PathToUniqueRegistryPath "$INSTDIR" Pop $R5 ${If} $R5 != "" ; Always use the 64bit registry for certs on 64bit systems. ${If} ${RunningX64} ${OrIf} ${IsNativeARM64} SetRegView 64 ${EndIf} EnumRegKey $R6 HKLM $R5 0 ClearErrors ${If} ${RunningX64} ${OrIf} ${IsNativeARM64} SetRegView lastused ${EndIf} ${IfNot} "$R6" == "" StrCpy $R4 "mms" ${EndIf} ${EndIf} !endif ${If} "$R4" != "" ; In the future, we might not try to elevate to remain truly silent. Or ; we might add a command line arguments to specify behaviour. One ; reason to not do that immediately is that we have no great way to ; signal that we exited without taking action. ${ElevateUAC} ${EndIf} ; Now we've elevated, try the write access test again. ClearErrors GetTempFileName $R6 "$INSTDIR" FileOpen $R5 "$R6" w FileWrite $R5 "Write Access Test" FileClose $R5 Delete $R6 ${If} ${Errors} ; Nothing initialized so no need to call OnEndCommon Quit ${EndIf} !ifdef MOZ_MAINTENANCE_SERVICE ; And verify that if we need to, we're going to clean up the registry ; correctly. ${If} "$R4" == "mms" WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test" ${If} ${Errors} ; Nothing initialized so no need to call OnEndCommon Quit ${Endif} DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" ${EndIf} !endif ; If we made it this far then this installer is being used as an uninstaller. WriteUninstaller "$EXEDIR\uninstaller.exe" ${If} ${Silent} StrCpy $R1 "$\"$EXEDIR\uninstaller.exe$\" /S" ${Else} StrCpy $R1 "$\"$EXEDIR\uninstaller.exe$\"" ${EndIf} ; When the uninstaller is launched it copies itself to the temp directory ; so it won't be in use so it can delete itself. ExecWait $R1 ${DeleteFile} "$EXEDIR\uninstaller.exe" ${UnloadUAC} SetErrorLevel 0 Quit ; Nothing initialized so no need to call OnEndCommon FunctionEnd !verbose pop !endif !macroend !macro PostUpdate ; PostUpdate is called from both session 0 and from the user session ; for service updates, make sure that we only register with the user session ; Otherwise ApplicationID::Set can fail intermittently with a file in use error. System::Call "kernel32::GetCurrentProcessId() i.r0" System::Call "kernel32::ProcessIdToSessionId(i $0, *i ${NSIS_MAX_STRLEN} r9)" ${CreateShortcutsLog} ; Remove registry entries for non-existent apps and for apps that point to our ; install location in the Software\Mozilla key and uninstall registry entries ; that point to our install location for both HKCU and HKLM. SetShellVarContext current ; Set SHCTX to the current user (e.g. HKCU) ${RegCleanMain} "Software\Mozilla" ${RegCleanUninstall} ${UpdateProtocolHandlers} ; setup the application model id registration value ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" ; Upgrade the copies of the MAPI DLL's ${UpgradeMapiDLLs} ClearErrors WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test" ${If} ${Errors} StrCpy $RegHive "HKCU" ${Else} SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM) DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" StrCpy $RegHive "HKLM" ${RegCleanMain} "Software\Mozilla" ${RegCleanUninstall} ${UpdateProtocolHandlers} ${SetAppLSPCategories} ${LSP_CATEGORIES} ; Only update the Clients\Mail registry key values if they don't exist or ; this installation is the same as the one set in those keys. ReadRegStr $0 HKLM "Software\Clients\Mail\${ClientsRegName}\DefaultIcon" "" ${GetPathFromString} "$0" $0 ${GetParent} "$0" $0 ${If} ${FileExists} "$0" ${GetLongPath} "$0" $0 ${EndIf} ${If} "$0" == "$INSTDIR" ${SetClientsMail} "HKLM" ${EndIf} ; Only update the Clients\News registry key values if they don't exist or ; this installation is the same as the one set in those keys. ReadRegStr $0 HKLM "Software\Clients\News\${ClientsRegName}\DefaultIcon" "" ${GetPathFromString} "$0" $0 ${GetParent} "$0" $0 ${If} ${FileExists} "$0" ${GetLongPath} "$0" $0 ${EndIf} ${If} "$0" == "$INSTDIR" ${SetClientsNews} "HKLM" ${EndIf} ; Only update the Clients\Calendar registry key values if they don't exist or ; this installation is the same as the one set in those keys. ReadRegStr $0 HKLM "Software\Clients\Calendar\${ClientsRegName}\DefaultIcon" "" ${GetPathFromString} "$0" $0 ${GetParent} "$0" $0 ${If} ${FileExists} "$0" ${GetLongPath} "$0" $0 ${EndIf} ${If} "$0" == "$INSTDIR" ${SetClientsCalendar} "HKLM" ${EndIf} ${EndIf} ; Update the name/icon/AppModelID of our shortcuts as needed, then update the ; lastwritetime of the Start Menu shortcut to clear the tile icon cache. ; Do this for both shell contexts in case the user has shortcuts in multiple ; locations, then restore the previous context at the end. SetShellVarContext all ${UpdateShortcutsBranding} ${TouchStartMenuShortcut} Call FixShortcutAppModelIDs SetShellVarContext current ${UpdateShortcutsBranding} ${TouchStartMenuShortcut} Call FixShortcutAppModelIDs ${If} $RegHive == "HKLM" SetShellVarContext all ${ElseIf} $RegHive == "HKCU" SetShellVarContext current ${EndIf} ${RemoveDeprecatedKeys} ${Set32to64DidMigrateReg} ${SetAppKeys} ${SetUninstallKeys} ; Remove files that may be left behind by the application in the ; VirtualStore directory. ${CleanVirtualStore} RmDir /r /REBOOTOK "$INSTDIR\${TO_BE_DELETED}" ; Register AccessibleMarshal.dll with COM (this requires write access to HKLM) ${RegisterAccessibleMarshal} ; Record the Windows Error Reporting module WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\Windows Error Reporting\RuntimeExceptionHelperModules" "$INSTDIR\mozwer.dll" 0 !ifdef MOZ_MAINTENANCE_SERVICE Call IsUserAdmin Pop $R0 ${If} $R0 == "true" ; Only proceed if we have HKLM write access ${AndIf} $RegHive == "HKLM" ; We check to see if the maintenance service install was already attempted. ; 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} ${OrIf} ${IsNativeARM64} SetRegView 64 ${EndIf} ReadRegDWORD $5 HKLM "Software\Mozilla\MaintenanceService" "Attempted" ClearErrors ${If} ${RunningX64} ${OrIf} ${IsNativeARM64} SetRegView lastused ${EndIf} ; Add the registry keys for allowed certificates. ${AddMaintCertKeys} ; If the maintenance service is already installed, do nothing. ; The maintenance service will launch: ; maintenanceservice_installer.exe /Upgrade to upgrade the maintenance ; service if necessary. If the update was done from updater.exe without ; the service (i.e. service is failing), updater.exe will do the update of ; the service. The reasons we do not do it here is because we don't want ; to have to prompt for limited user accounts when the service isn't used ; and we currently call the PostUpdate twice, once for the user and once ; for the SYSTEM account. Also, this would stop the maintenance service ; and we need a return result back to the service when run that way. ${If} $5 == "" ; An install of maintenance service was never attempted. ; We know we are an Admin and that we have write access into HKLM ; based on the above checks, so attempt to just run the EXE. ; In the worst case, in case there is some edge case with the ; IsAdmin check and the permissions check, the maintenance service ; will just fail to be attempted to be installed. nsExec::Exec "$\"$INSTDIR\maintenanceservice_installer.exe$\"" ${EndIf} ${EndIf} !endif ${WriteToastNotificationRegistration} $RegHive !macroend !define PostUpdate "!insertmacro PostUpdate"