tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

uninstaller.nsi (42606B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this
      3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 # Required Plugins:
      6 # AppAssocReg
      7 #   http://nsis.sourceforge.net/Application_Association_Registration_plug-in
      8 # BitsUtils
      9 #   http://searchfox.org/mozilla-central/source/other-licenses/nsis/Contrib/BitsUtils
     10 # CityHash
     11 #   http://searchfox.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash
     12 # HttpPostFile
     13 #   http://searchfox.org/mozilla-central/source/other-licenses/nsis/Contrib/HttpPostFile
     14 # ShellLink
     15 #   http://nsis.sourceforge.net/ShellLink_plug-in
     16 # UAC
     17 #   http://nsis.sourceforge.net/UAC_plug-in
     18 
     19 ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
     20 !verbose 3
     21 
     22 ; 7-Zip provides better compression than the lzma from NSIS so we add the files
     23 ; uncompressed and use 7-Zip to create a SFX archive of it
     24 SetDatablockOptimize on
     25 SetCompress off
     26 CRCCheck on
     27 
     28 RequestExecutionLevel user
     29 
     30 Unicode true
     31 ManifestSupportedOS all
     32 ManifestDPIAware true
     33 
     34 !addplugindir ./
     35 
     36 ; Attempt to elevate Standard Users in addition to users that
     37 ; are a member of the Administrators group.
     38 !define NONADMIN_ELEVATE
     39 
     40 ; prevents compiling of the reg write logging.
     41 !define NO_LOG
     42 
     43 !define MaintUninstallKey \
     44 "Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService"
     45 
     46 Var TmpVal
     47 Var MaintCertKey
     48 Var ShouldOpenSurvey
     49 Var ShouldSendPing
     50 Var InstalledVersion
     51 Var InstalledBuildID
     52 Var ShouldPromptForRefresh
     53 Var RefreshRequested
     54 ; AddTaskbarSC is defined here in order to silence warnings from inside
     55 ; MigrateTaskBarShortcut and is not intended to be used here.
     56 ; See Bug 1329869 for more.
     57 Var AddTaskbarSC
     58 ; Will be the registry hive that we are going to write things like class keys
     59 ; into. This will generally be HKLM if running with elevation, otherwise HKCU.
     60 Var RegHive
     61 
     62 ; Other included files may depend upon these includes!
     63 ; The following includes are provided by NSIS.
     64 !include FileFunc.nsh
     65 !include InstallOptions.nsh
     66 !include LogicLib.nsh
     67 !include MUI.nsh
     68 !include WinMessages.nsh
     69 !include WinVer.nsh
     70 !include WordFunc.nsh
     71 
     72 !insertmacro GetSize
     73 !insertmacro StrFilter
     74 !insertmacro WordReplace
     75 
     76 !insertmacro un.GetParent
     77 
     78 ; The following includes are custom.
     79 !include branding.nsi
     80 !include defines.nsi
     81 !include common.nsh
     82 !include locales.nsi
     83 
     84 ; This is named BrandShortName helper because we use this for software update
     85 ; post update cleanup.
     86 VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
     87 VIAddVersionKey "OriginalFilename" "helper.exe"
     88 
     89 !insertmacro AddDisabledDDEHandlerValues
     90 !insertmacro CleanVirtualStore
     91 !insertmacro ElevateUAC
     92 !insertmacro GetLongPath
     93 !insertmacro GetPathFromString
     94 !insertmacro InitHashAppModelId
     95 !insertmacro IsHandlerForInstallDir
     96 !insertmacro IsPinnedToTaskBar
     97 !insertmacro IsUserAdmin
     98 !insertmacro LogDesktopShortcut
     99 !insertmacro LogQuickLaunchShortcut
    100 !insertmacro LogStartMenuShortcut
    101 !insertmacro PinnedToStartMenuLnkCount
    102 !insertmacro RegCleanAppHandler
    103 !insertmacro RegCleanMain
    104 !insertmacro RegCleanUninstall
    105 !insertmacro SetAppLSPCategories
    106 !insertmacro SetBrandNameVars
    107 !insertmacro UpdateShortcutAppModelIDs
    108 !insertmacro UnloadUAC
    109 !insertmacro WriteRegDWORD2
    110 !insertmacro WriteRegStr2
    111 
    112 !insertmacro un.ChangeMUIHeaderImage
    113 !insertmacro un.ChangeMUISidebarImage
    114 !insertmacro un.CheckForFilesInUse
    115 !insertmacro un.CleanMaintenanceServiceLogs
    116 !insertmacro un.CleanVirtualStore
    117 !insertmacro un.DeleteShortcuts
    118 !insertmacro un.GetCommonDirectory
    119 !insertmacro un.GetLongPath
    120 !insertmacro un.GetSecondInstallPath
    121 !insertmacro un.InitHashAppModelId
    122 !insertmacro un.ManualCloseAppPrompt
    123 !insertmacro un.RegCleanAppHandler
    124 !insertmacro un.RegCleanFileHandler
    125 !insertmacro un.RegCleanMain
    126 !insertmacro un.RegCleanPrefs
    127 !insertmacro un.RegCleanUninstall
    128 !insertmacro un.RegCleanProtocolHandler
    129 !insertmacro un.RemoveQuotesFromPath
    130 !insertmacro un.RemovePrecompleteEntries
    131 !insertmacro un.SetAppLSPCategories
    132 !insertmacro un.SetBrandNameVars
    133 
    134 !include shared.nsh
    135 
    136 ; Helper macros for ui callbacks. Insert these after shared.nsh
    137 !insertmacro OnEndCommon
    138 !insertmacro UninstallOnInitCommon
    139 
    140 !insertmacro un.OnEndCommon
    141 !insertmacro un.UninstallUnOnInitCommon
    142 
    143 Name "${BrandFullName}"
    144 OutFile "helper.exe"
    145 !ifdef HAVE_64BIT_BUILD
    146  InstallDir "$PROGRAMFILES64\${BrandFullName}\"
    147 !else
    148  InstallDir "$PROGRAMFILES32\${BrandFullName}\"
    149 !endif
    150 ShowUnInstDetails nevershow
    151 
    152 !define URLUninstallSurvey "https://qsurvey.mozilla.com/s3/FF-Desktop-Post-Uninstall?channel=${UpdateChannel}&version=${AppVersion}&osversion="
    153 
    154 ; Support for the profile refresh feature
    155 !define URLProfileRefreshHelp "https://support.mozilla.org/kb/refresh-firefox-reset-add-ons-and-settings"
    156 
    157 ; Arguments to add to the command line when launching FileMainEXE for profile refresh
    158 !define ArgsProfileRefresh "-reset-profile -migration -uninstaller-profile-refresh"
    159 
    160 ################################################################################
    161 # Modern User Interface - MUI
    162 
    163 !define MUI_ABORTWARNING
    164 !define MUI_ICON setup.ico
    165 !define MUI_UNICON setup.ico
    166 !define MUI_WELCOMEPAGE_TITLE_3LINES
    167 !define MUI_HEADERIMAGE
    168 !define MUI_HEADERIMAGE_RIGHT
    169 !define MUI_UNWELCOMEFINISHPAGE_BITMAP wizWatermark.bmp
    170 ; By default MUI_BGCOLOR is hardcoded to FFFFFF, which is only correct if the
    171 ; the Windows theme or high-contrast mode hasn't changed it, so we need to
    172 ; override that with GetSysColor(COLOR_WINDOW) (this string ends up getting
    173 ; passed to SetCtlColors, which uses this custom syntax to mean that).
    174 !define MUI_BGCOLOR SYSCLR:WINDOW
    175 
    176 ; Use a right to left header image when the language is right to left
    177 !ifdef ${AB_CD}_rtl
    178 !define MUI_HEADERIMAGE_BITMAP_RTL wizHeaderRTL.bmp
    179 !else
    180 !define MUI_HEADERIMAGE_BITMAP wizHeader.bmp
    181 !endif
    182 
    183 !define MUI_CUSTOMFUNCTION_UNGUIINIT un.GUIInit
    184 
    185 /**
    186 * Uninstall Pages
    187 */
    188 ; Welcome Page
    189 !define MUI_PAGE_CUSTOMFUNCTION_PRE un.preWelcome
    190 !define MUI_PAGE_CUSTOMFUNCTION_SHOW un.showWelcome
    191 !define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.leaveWelcome
    192 !insertmacro MUI_UNPAGE_WELCOME
    193 
    194 ; Custom Uninstall Confirm Page
    195 UninstPage custom un.preConfirm
    196 
    197 ; Remove Files Page
    198 !insertmacro MUI_UNPAGE_INSTFILES
    199 
    200 ; Finish Page
    201 !define MUI_FINISHPAGE_SHOWREADME
    202 !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
    203 !define MUI_FINISHPAGE_SHOWREADME_TEXT $(UN_SURVEY_CHECKBOX_LABEL)
    204 !define MUI_FINISHPAGE_SHOWREADME_FUNCTION un.Survey
    205 !define MUI_PAGE_CUSTOMFUNCTION_PRE un.preFinish
    206 !define MUI_PAGE_CUSTOMFUNCTION_SHOW un.showFinish
    207 !insertmacro MUI_UNPAGE_FINISH
    208 
    209 ; Use the default dialog for IDD_VERIFY for a simple Banner
    210 ChangeUI IDD_VERIFY "${NSISDIR}\Contrib\UIs\default.exe"
    211 
    212 ################################################################################
    213 # Helper Functions
    214 
    215 Function un.Survey
    216  ; We can't actually call ExecInExplorer here because it's going to have to
    217  ; make some marshalled COM calls and those are not allowed from within a
    218  ; synchronous message handler (where we currently are); we'll be thrown
    219  ; RPC_E_CANTCALLOUT_ININPUTSYNCCALL if we try. So all we can do is record
    220  ; that we need to make the call later, which we'll do from un.onGUIEnd.
    221  StrCpy $ShouldOpenSurvey "1"
    222 FunctionEnd
    223 
    224 ; This function is used to uninstall the maintenance service if the
    225 ; application currently being uninstalled is the last application to use the
    226 ; maintenance service.
    227 Function un.UninstallServiceIfNotUsed
    228  ; $0 will store if a subkey exists
    229  ; $1 will store the first subkey if it exists or an empty string if it doesn't
    230  ; Backup the old values
    231  Push $0
    232  Push $1
    233 
    234  ; The maintenance service always uses the 64-bit registry on x64 systems
    235  ${If} ${RunningX64}
    236  ${OrIf} ${IsNativeARM64}
    237    SetRegView 64
    238  ${EndIf}
    239 
    240  ; Figure out the number of subkeys
    241  StrCpy $0 0
    242  ${Do}
    243    EnumRegKey $1 HKLM "Software\Mozilla\MaintenanceService" $0
    244    ${If} "$1" == ""
    245      ${ExitDo}
    246    ${EndIf}
    247    IntOp $0 $0 + 1
    248  ${Loop}
    249 
    250  ; Restore back the registry view
    251  ${If} ${RunningX64}
    252  ${OrIf} ${IsNativeARM64}
    253    SetRegView lastused
    254  ${EndIf}
    255 
    256  ${If} $0 == 0
    257    ; Get the path of the maintenance service uninstaller.
    258    ; Look in both the 32-bit and 64-bit registry views.
    259    SetRegView 32
    260    ReadRegStr $1 HKLM ${MaintUninstallKey} "UninstallString"
    261    SetRegView lastused
    262 
    263    ${If} ${RunningX64}
    264    ${OrIf} ${IsNativeARM64}
    265      ${If} $1 == ""
    266        SetRegView 64
    267        ReadRegStr $1 HKLM ${MaintUninstallKey} "UninstallString"
    268        SetRegView lastused
    269      ${EndIf}
    270    ${EndIf}
    271 
    272    ; If the uninstall string does not exist, skip executing it
    273    ${If} $1 != ""
    274      ; $1 is already a quoted string pointing to the install path
    275      ; so we're already protected against paths with spaces
    276      nsExec::Exec "$1 /S"
    277    ${EndIf}
    278  ${EndIf}
    279 
    280  ; Restore the old value of $1 and $0
    281  Pop $1
    282  Pop $0
    283 FunctionEnd
    284 
    285 Function un.LaunchAppForRefresh
    286  Push $0
    287  Push $1
    288  ; Set the current working directory to the installation directory
    289  SetOutPath "$INSTDIR"
    290  ClearErrors
    291  ${GetParameters} $0
    292  ${GetOptions} "$0" "/UAC:" $1
    293  ${If} ${Errors}
    294    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" ${ArgsProfileRefresh}"
    295  ${Else}
    296    GetFunctionAddress $0 un.LaunchAppForRefreshFromElevatedProcess
    297    UAC::ExecCodeSegment $0
    298  ${EndIf}
    299  Pop $1
    300  Pop $0
    301 FunctionEnd
    302 
    303 Function un.LaunchAppForRefreshFromElevatedProcess
    304  ; Set the current working directory to the installation directory
    305  SetOutPath "$INSTDIR"
    306  ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" ${ArgsProfileRefresh}"
    307 FunctionEnd
    308 
    309 Function un.LaunchRefreshHelpPage
    310  Push $0
    311  Push $1
    312  ClearErrors
    313  ${GetParameters} $0
    314  ${GetOptions} "$0" "/UAC:" $1
    315  ${If} ${Errors}
    316    Call un.OpenRefreshHelpURL
    317  ${Else}
    318    GetFunctionAddress $0 un.OpenRefreshHelpURL
    319    UAC::ExecCodeSegment $0
    320  ${EndIf}
    321  Pop $1
    322  Pop $0
    323 FunctionEnd
    324 
    325 Function un.OpenRefreshHelpURL
    326  ExecShell "open" "${URLProfileRefreshHelp}"
    327 FunctionEnd
    328 
    329 Function un.SendUninstallPing
    330  ; Notably, we only check the non-private AUMID here. There's no good reason
    331  ; to send the uninstall ping twice.
    332  ${If} $AppUserModelID == ""
    333    Return
    334  ${EndIf}
    335 
    336  Push $0   ; $0 = Find handle
    337  Push $1   ; $1 = Found ping file name
    338  Push $2   ; $2 = Directory containing the pings
    339  Push $3   ; $3 = Ping file name filespec
    340  Push $4   ; $4 = Offset of ID in file name
    341  Push $5   ; $5 = URL, POST result
    342  Push $6   ; $6 = Full path to the ping file
    343 
    344  Call un.GetCommonDirectory
    345  Pop $2
    346 
    347  ; The ping ID is in the file name, so that we can get it for the submission URL
    348  ; without having to parse the ping. Since we don't know the exact name, use FindFirst
    349  ; to locate the file.
    350  ; Format is uninstall_ping_$AppUserModelID_$PingUUID.json
    351 
    352  ; File name base
    353  StrCpy $3 "uninstall_ping_$AppUserModelID_"
    354  ; Get length of the fixed prefix, this is the offset of ping ID in the file name
    355  StrLen $4 $3
    356  ; Finish building filespec
    357  StrCpy $3 "$2\$3*.json"
    358 
    359  ClearErrors
    360  FindFirst $0 $1 $3
    361  ; Build the full path
    362  StrCpy $6 "$2\$1"
    363 
    364  ${IfNot} ${Errors}
    365    ; Copy the ping ID, starting after $AppUserModelID_, ending 5 from the end to remove .json
    366    StrCpy $5 $1 -5 $4
    367 
    368    ; Build the full submission URL from the ID
    369    ; https://docs.telemetry.mozilla.org/concepts/pipeline/http_edge_spec.html#special-handling-for-firefox-desktop-telemetry
    370    ; It's possible for the path components to disagree with the contents of the ping,
    371    ; but this should be rare, and shouldn't affect the collection.
    372    StrCpy $5 "${TELEMETRY_BASE_URL}/${TELEMETRY_UNINSTALL_PING_NAMESPACE}/$5/${TELEMETRY_UNINSTALL_PING_DOCTYPE}/${AppName}/$InstalledVersion/${UpdateChannel}/$InstalledBuildID?v=4"
    373 
    374    HttpPostFile::Post $6 "Content-Type: application/json$\r$\n" $5
    375    ; Pop the result. This could indicate an error if it's something other than
    376    ; "success", but we don't have any recovery path here anyway.
    377    Pop $5
    378 
    379    ${Do}
    380      Delete $6
    381 
    382      ; Continue to delete any other pings from this install. Only the first found will be sent:
    383      ; there should only be one ping, if there are more than one then something has gone wrong,
    384      ; it seems preferable to not try to send them all.
    385      ClearErrors
    386      FindNext $0 $1
    387      ; Build the full path
    388      StrCpy $6 "$2\$1"
    389    ${LoopUntil} ${Errors}
    390 
    391    FindClose $0
    392  ${Endif}
    393 
    394  Pop $6
    395  Pop $5
    396  Pop $4
    397  Pop $3
    398  Pop $2
    399  Pop $1
    400  Pop $0
    401 FunctionEnd
    402 
    403 ################################################################################
    404 # Install Sections
    405 ; Empty section required for the installer to compile as an uninstaller
    406 Section ""
    407 SectionEnd
    408 
    409 ################################################################################
    410 # Uninstall Sections
    411 
    412 Section "Uninstall"
    413  SetDetailsPrint textonly
    414  DetailPrint $(STATUS_UNINSTALL_MAIN)
    415  SetDetailsPrint none
    416 
    417  ; Some system cleanup is most easily handled when XPCOM functionality is
    418  ; available - e.g. removing notifications from Window's Action Center. We
    419  ; handle this in the `uninstall` background task.
    420  ;
    421  ; Return value is saved to an unused variable to prevent the the error flag
    422  ; from being set.
    423  Var /GLOBAL UnusedExecCatchReturn
    424  ExecWait '"$INSTDIR\${FileMainEXE}" --backgroundtask uninstall' $UnusedExecCatchReturn
    425 
    426  ; Uninstall the default browser agent scheduled task and all other scheduled
    427  ; tasks registered by Firefox.
    428  ; This also removes the registry entries that the WDBA creates.
    429  ; One of the scheduled tasks that this will remove is the Background Update
    430  ; Task. Ideally, this will eventually be changed so that it doesn't rely on
    431  ; the WDBA. See Bug 1710143.
    432  ExecWait '"$INSTDIR\default-browser-agent.exe" uninstall $AppUserModelID'
    433  ${RemoveDefaultBrowserAgentShortcut}
    434 
    435  ; Delete the app exe to prevent launching the app while we are uninstalling.
    436  ClearErrors
    437  ${DeleteFile} "$INSTDIR\${FileMainEXE}"
    438  ${If} ${Errors}
    439    ; If the user closed the application it can take several seconds for it to
    440    ; shut down completely. If the application is being used by another user we
    441    ; can still delete the files when the system is restarted.
    442    Sleep 5000
    443    ${DeleteFile} "$INSTDIR\${FileMainEXE}"
    444    ClearErrors
    445  ${EndIf}
    446 
    447  ReadRegDWORD $R4 HKCU "Software\Mozilla\${BrandFullNameInternal}" DesktopLauncherAppInstalled
    448  ${IfNot} ${Errors}
    449  ${AndIf} $R4 == "1"
    450    ; The current user had a desktop launcher at some point, so remove it.
    451    SetShellVarContext current
    452    Delete "$DESKTOP\${BrandShortName}.exe"
    453    ${IfNot} ${Errors}
    454      DeleteRegValue HKCU "Software\Mozilla\${BrandFullNameInternal}" DesktopLauncherAppInstalled
    455    ${EndIf}
    456  ${EndIf}
    457  ClearErrors
    458 
    459  SetShellVarContext current  ; Set SHCTX to HKCU
    460  ${un.RegCleanMain} "Software\Mozilla"
    461  ${un.RegCleanPrefs} "Software\Mozilla\${AppName}"
    462  ${un.RegCleanUninstall}
    463  ${un.DeleteShortcuts}
    464 
    465  ${If} "$AppUserModelID" != ""
    466    ; Unregister resources associated with taskbar jump lists.
    467    ApplicationID::UninstallJumpLists "$AppUserModelID"
    468    ; Remove the update sync manager's multi-instance lock file
    469    Call un.GetCommonDirectory
    470    Pop $0
    471    Delete /REBOOTOK "$0\UpdateLock-$AppUserModelID"
    472  ${EndIf}
    473 
    474  ${If} "$AppUserModelIDPrivate" != ""
    475    ApplicationID::UninstallJumpLists "$AppUserModelIDPrivate"
    476  ${EndIf}
    477 
    478  ; Clean up old maintenance service logs
    479  ${un.CleanMaintenanceServiceLogs} "Mozilla\Firefox"
    480 
    481  ; Remove any app model id's stored in the registry for this install path
    482  DeleteRegValue HKCU "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR"
    483  DeleteRegValue HKLM "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR"
    484 
    485  ClearErrors
    486  WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
    487  ${If} ${Errors}
    488    StrCpy $RegHive "HKCU"
    489  ${Else}
    490    SetShellVarContext all  ; Set SHCTX to HKLM
    491    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
    492    StrCpy $RegHive "HKLM"
    493    ${un.RegCleanMain} "Software\Mozilla"
    494    ${un.RegCleanUninstall}
    495    ${un.DeleteShortcuts}
    496    ${un.SetAppLSPCategories}
    497  ${EndIf}
    498 
    499  ${un.RegCleanAppHandler} "FirefoxHTML-$AppUserModelID"
    500  ${un.RegCleanAppHandler} "FirefoxPDF-$AppUserModelID"
    501  ${un.RegCleanAppHandler} "FirefoxURL-$AppUserModelID"
    502  ${un.RegCleanProtocolHandler} "http"
    503  ${un.RegCleanProtocolHandler} "https"
    504  ${un.RegCleanProtocolHandler} "mailto"
    505  ${un.RegCleanFileHandler}  ".htm"   "FirefoxHTML-$AppUserModelID"
    506  ${un.RegCleanFileHandler}  ".html"  "FirefoxHTML-$AppUserModelID"
    507  ${un.RegCleanFileHandler}  ".shtml" "FirefoxHTML-$AppUserModelID"
    508  ${un.RegCleanFileHandler}  ".xht"   "FirefoxHTML-$AppUserModelID"
    509  ${un.RegCleanFileHandler}  ".xhtml" "FirefoxHTML-$AppUserModelID"
    510  ${un.RegCleanFileHandler}  ".oga"   "FirefoxHTML-$AppUserModelID"
    511  ${un.RegCleanFileHandler}  ".ogg"   "FirefoxHTML-$AppUserModelID"
    512  ${un.RegCleanFileHandler}  ".ogv"   "FirefoxHTML-$AppUserModelID"
    513  ${un.RegCleanFileHandler}  ".webm"  "FirefoxHTML-$AppUserModelID"
    514  ${un.RegCleanFileHandler}  ".svg"   "FirefoxHTML-$AppUserModelID"
    515  ${un.RegCleanFileHandler}  ".webp"  "FirefoxHTML-$AppUserModelID"
    516  ${un.RegCleanFileHandler}  ".avif"  "FirefoxHTML-$AppUserModelID"
    517 
    518  ${un.RegCleanFileHandler}  ".pdf"   "FirefoxPDF-$AppUserModelID"
    519 
    520  SetShellVarContext all  ; Set SHCTX to HKLM
    521  ${un.GetSecondInstallPath} "Software\Mozilla" $R9
    522  ${If} $R9 == "false"
    523    SetShellVarContext current  ; Set SHCTX to HKCU
    524    ${un.GetSecondInstallPath} "Software\Mozilla" $R9
    525  ${EndIf}
    526 
    527  DeleteRegKey HKLM "Software\Clients\StartMenuInternet\${AppRegName}-$AppUserModelID"
    528  DeleteRegValue HKLM "Software\RegisteredApplications" "${AppRegName}-$AppUserModelID"
    529 
    530  DeleteRegKey HKCU "Software\Clients\StartMenuInternet\${AppRegName}-$AppUserModelID"
    531  DeleteRegValue HKCU "Software\RegisteredApplications" "${AppRegName}-$AppUserModelID"
    532 
    533  ; Clean up "launch on login" registry key for this installation.
    534  DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "Mozilla-${AppName}-$AppUserModelID"
    535 
    536  ; Remove FirefoxBridge extension protocol handlers
    537  Push $1
    538  ${un.GetLongPath} "$INSTDIR\${FileMainEXE}" $1
    539  ${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox-bridge"
    540  ${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox-private-bridge"
    541  Pop $1
    542 
    543  ; Remove old protocol handler and StartMenuInternet keys without install path
    544  ; hashes, but only if they're for this installation.  We've never supported
    545  ; bare FirefoxPDF.
    546  ReadRegStr $0 HKLM "Software\Classes\FirefoxHTML\DefaultIcon" ""
    547  StrCpy $0 $0 -2
    548  ${If} $0 == "$INSTDIR\${FileMainEXE}"
    549    DeleteRegKey HKLM "Software\Classes\FirefoxHTML"
    550    DeleteRegKey HKLM "Software\Classes\FirefoxURL"
    551    ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
    552    DeleteRegKey HKLM "Software\Clients\StartMenuInternet\$R9"
    553    DeleteRegValue HKLM "Software\RegisteredApplications" "$R9"
    554    DeleteRegValue HKLM "Software\RegisteredApplications" "${AppRegName}"
    555  ${EndIf}
    556  ReadRegStr $0 HKCU "Software\Classes\FirefoxHTML\DefaultIcon" ""
    557  StrCpy $0 $0 -2
    558  ${If} $0 == "$INSTDIR\${FileMainEXE}"
    559    DeleteRegKey HKCU "Software\Classes\FirefoxHTML"
    560    DeleteRegKey HKCU "Software\Classes\FirefoxURL"
    561    ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
    562    DeleteRegKey HKCU "Software\Clients\StartMenuInternet\$R9"
    563    DeleteRegValue HKCU "Software\RegisteredApplications" "$R9"
    564    DeleteRegValue HKCU "Software\RegisteredApplications" "${AppRegName}"
    565  ${EndIf}
    566 
    567  StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}"
    568  ${If} $R9 == "false"
    569    DeleteRegKey HKLM "$0"
    570    DeleteRegKey HKCU "$0"
    571    StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\${FileMainEXE}"
    572    DeleteRegKey HKLM "$0"
    573    DeleteRegKey HKCU "$0"
    574    StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe"
    575    DeleteRegKey HKLM "$0"
    576    DeleteRegKey HKCU "$0"
    577    StrCpy $0 "Software\Classes\MIME\Database\Content Type\application/x-xpinstall;app=firefox"
    578    DeleteRegKey HKLM "$0"
    579    DeleteRegKey HKCU "$0"
    580  ${Else}
    581    ReadRegStr $R1 HKLM "$0" ""
    582    ${un.RemoveQuotesFromPath} "$R1" $R1
    583    ${un.GetParent} "$R1" $R1
    584    ${If} "$INSTDIR" == "$R1"
    585      WriteRegStr HKLM "$0" "" "$R9"
    586      ${un.GetParent} "$R9" $R1
    587      WriteRegStr HKLM "$0" "Path" "$R1"
    588    ${EndIf}
    589  ${EndIf}
    590 
    591  ; Remove our HKCR/Applications key, if it's for this installation.
    592  ReadRegStr $0 HKLM "Software\Classes\Applications\${FileMainEXE}\DefaultIcon" ""
    593  StrCpy $0 $0 -2
    594  ${If} $0 == "$INSTDIR\${FileMainEXE}"
    595    DeleteRegKey HKLM "Software\Classes\Applications\${FileMainEXE}"
    596  ${EndIf}
    597  ReadRegStr $0 HKCU "Software\Classes\Applications\${FileMainEXE}\DefaultIcon" ""
    598  StrCpy $0 $0 -2
    599  ${If} $0 == "$INSTDIR\${FileMainEXE}"
    600    DeleteRegKey HKCU "Software\Classes\Applications\${FileMainEXE}"
    601  ${EndIf}
    602 
    603  ; Remove directories and files we always control before parsing the uninstall
    604  ; log so empty directories can be removed.
    605  ${If} ${FileExists} "$INSTDIR\updates"
    606    RmDir /r /REBOOTOK "$INSTDIR\updates"
    607  ${EndIf}
    608  ${If} ${FileExists} "$INSTDIR\updated"
    609    RmDir /r /REBOOTOK "$INSTDIR\updated"
    610  ${EndIf}
    611  ${If} ${FileExists} "$INSTDIR\defaults\shortcuts"
    612    RmDir /r /REBOOTOK "$INSTDIR\defaults\shortcuts"
    613  ${EndIf}
    614  ${If} ${FileExists} "$INSTDIR\distribution"
    615    RmDir /r /REBOOTOK "$INSTDIR\distribution"
    616  ${EndIf}
    617 
    618  ; Remove files that may be left behind by the application in the
    619  ; VirtualStore directory.
    620  ${un.CleanVirtualStore}
    621 
    622  ; Only unregister the dll if the registration points to this installation
    623  ReadRegStr $R1 HKCR "CLSID\{0D68D6D0-D93D-4D08-A30D-F00DD1F45B24}\InProcServer32" ""
    624  ${If} "$INSTDIR\AccessibleMarshal.dll" == "$R1"
    625    ${UnregisterDLL} "$INSTDIR\AccessibleMarshal.dll"
    626  ${EndIf}
    627 
    628  ${If} ${FileExists} "$INSTDIR\AccessibleHandler.dll"
    629    ${UnregisterDLL} "$INSTDIR\AccessibleHandler.dll"
    630  ${EndIf}
    631 
    632  ; Remove the Windows Reporter Module entry
    633  DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows\Windows Error Reporting\RuntimeExceptionHelperModules" "$INSTDIR\mozwer.dll"
    634 
    635 !ifdef MOZ_LAUNCHER_PROCESS
    636  DeleteRegValue HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Launcher"
    637  DeleteRegValue HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Browser"
    638  DeleteRegValue HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Image"
    639  DeleteRegValue HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Telemetry"
    640 !endif
    641 
    642  ; Remove Toast Notification registration.
    643  ; Find any GUID used for this installation.
    644  ClearErrors
    645  ReadRegStr $0 HKLM "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "CustomActivator"
    646 
    647  DeleteRegValue HKLM "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "CustomActivator"
    648  DeleteRegValue HKLM "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "DisplayName"
    649  DeleteRegValue HKLM "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "IconUri"
    650  DeleteRegKey HKLM "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID"
    651  ${If} "$0" != ""
    652    DeleteRegValue HKLM "Software\Classes\AppID\$0" "DllSurrogate"
    653    DeleteRegKey HKLM "Software\Classes\AppID\$0"
    654    DeleteRegValue HKLM "Software\Classes\CLSID\$0" "AppID"
    655    DeleteRegValue HKLM "Software\Classes\CLSID\$0\InProcServer32" ""
    656    DeleteRegKey HKLM "Software\Classes\CLSID\$0\InProcServer32"
    657    DeleteRegKey HKLM "Software\Classes\CLSID\$0"
    658  ${EndIf}
    659 
    660  ClearErrors
    661  ReadRegStr $0 HKCU "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "CustomActivator"
    662 
    663  DeleteRegValue HKCU "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "CustomActivator"
    664  DeleteRegValue HKCU "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "DisplayName"
    665  DeleteRegValue HKCU "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID" "IconUri"
    666  DeleteRegKey HKCU "Software\Classes\AppUserModelId\${ToastAumidPrefix}$AppUserModelID"
    667  ${If} "$0" != ""
    668    DeleteRegValue HKCU "Software\Classes\AppID\$0" "DllSurrogate"
    669    DeleteRegKey HKCU "Software\Classes\AppID\$0"
    670    DeleteRegValue HKCU "Software\Classes\CLSID\$0" "AppID"
    671    DeleteRegValue HKCU "Software\Classes\CLSID\$0\InProcServer32" ""
    672    DeleteRegKey HKCU "Software\Classes\CLSID\$0\InProcServer32"
    673    DeleteRegKey HKCU "Software\Classes\CLSID\$0"
    674  ${EndIf}
    675 
    676  ${un.RemovePrecompleteEntries} "false"
    677 
    678  ${If} ${FileExists} "$INSTDIR\defaults\pref\channel-prefs.js"
    679    Delete /REBOOTOK "$INSTDIR\defaults\pref\channel-prefs.js"
    680  ${EndIf}
    681  RmDir "$INSTDIR\defaults\pref"
    682  RmDir "$INSTDIR\defaults"
    683  ${If} ${FileExists} "$INSTDIR\uninstall"
    684    ; Remove the uninstall directory that we control
    685    RmDir /r /REBOOTOK "$INSTDIR\uninstall"
    686  ${EndIf}
    687  ${If} ${FileExists} "$INSTDIR\install.log"
    688    Delete /REBOOTOK "$INSTDIR\install.log"
    689  ${EndIf}
    690  ${If} ${FileExists} "$INSTDIR\update-settings.ini"
    691    Delete /REBOOTOK "$INSTDIR\update-settings.ini"
    692  ${EndIf}
    693  ${If} ${FileExists} "$INSTDIR\installation_telemetry.json"
    694    Delete /REBOOTOK "$INSTDIR\installation_telemetry.json"
    695  ${EndIf}
    696  ${If} ${FileExists} "$INSTDIR\postSigningData"
    697    Delete /REBOOTOK "$INSTDIR\postSigningData"
    698  ${EndIf}
    699 
    700  ; Explicitly remove empty webapprt dir in case it exists (bug 757978).
    701  RmDir "$INSTDIR\webapprt\components"
    702  RmDir "$INSTDIR\webapprt"
    703 
    704  ; Remove the installation directory if it is empty
    705  RmDir "$INSTDIR"
    706 
    707  ; If firefox.exe was successfully deleted yet we still need to restart to
    708  ; remove other files create a dummy firefox.exe.moz-delete to prevent the
    709  ; installer from allowing an install without restart when it is required
    710  ; to complete an uninstall.
    711  ${If} ${RebootFlag}
    712    ; Admin is required to delete files on reboot so only add the moz-delete if
    713    ; the user is an admin. After calling UAC::IsAdmin $0 will equal 1 if the
    714    ; user is an admin.
    715    UAC::IsAdmin
    716    ${If} "$0" == "1"
    717      ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-delete"
    718        FileOpen $0 "$INSTDIR\${FileMainEXE}.moz-delete" w
    719        FileWrite $0 "Will be deleted on restart"
    720        Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete"
    721        FileClose $0
    722      ${EndUnless}
    723    ${EndIf}
    724  ${EndIf}
    725 
    726  ; Refresh desktop icons otherwise the start menu internet item won't be
    727  ; removed and other ugly things will happen like recreation of the app's
    728  ; clients registry key by the OS under some conditions.
    729  ${RefreshShellIcons}
    730 
    731  ; Users who uninstall then reinstall expecting Firefox to use a clean profile
    732  ; may be surprised during first-run. This key is checked during startup of Firefox and
    733  ; subsequently deleted after checking. If the value is found during startup
    734  ; the browser will offer to Reset Firefox. We use the UpdateChannel to match
    735  ; uninstalls of Firefox-release with reinstalls of Firefox-release, for example.
    736  WriteRegStr HKCU "Software\Mozilla\Firefox" "Uninstalled-${UpdateChannel}" "True"
    737 
    738 !ifdef MOZ_MAINTENANCE_SERVICE
    739  ; Get the path the allowed cert is at and remove it
    740  ; Keep this block of code last since it modfies the reg view
    741  ServicesHelper::PathToUniqueRegistryPath "$INSTDIR"
    742  Pop $MaintCertKey
    743  ${If} $MaintCertKey != ""
    744    ; Always use the 64bit registry for certs on 64bit systems.
    745    ${If} ${RunningX64}
    746    ${OrIf} ${IsNativeARM64}
    747      SetRegView 64
    748    ${EndIf}
    749    DeleteRegKey HKLM "$MaintCertKey"
    750    ${If} ${RunningX64}
    751    ${OrIf} ${IsNativeARM64}
    752      SetRegView lastused
    753    ${EndIf}
    754  ${EndIf}
    755  Call un.UninstallServiceIfNotUsed
    756 !endif
    757 
    758 !ifdef MOZ_BITS_DOWNLOAD
    759  BitsUtils::CancelBitsJobsByName "MozillaUpdate $AppUserModelID"
    760  Pop $0
    761 !endif
    762 
    763  ${un.IsFirewallSvcRunning}
    764  Pop $0
    765  ${If} "$0" == "true"
    766    liteFirewallW::RemoveRule "$INSTDIR\${FileMainEXE}" "${BrandShortName} ($INSTDIR)"
    767  ${EndIf}
    768 SectionEnd
    769 
    770 ################################################################################
    771 # Language
    772 
    773 !insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
    774 !verbose push
    775 !verbose 3
    776 !include "overrideLocale.nsh"
    777 !include "customLocale.nsh"
    778 !verbose pop
    779 
    780 ; Set this after the locale files to override it if it is in the locale. Using
    781 ; " " for BrandingText will hide the "Nullsoft Install System..." branding.
    782 BrandingText " "
    783 
    784 ################################################################################
    785 # Page pre, show, and leave functions
    786 
    787 Function un.preWelcome
    788  ${If} ${FileExists} "$INSTDIR\distribution\modern-wizard.bmp"
    789    Delete "$PLUGINSDIR\modern-wizard.bmp"
    790    CopyFiles /SILENT "$INSTDIR\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
    791  ${EndIf}
    792 !ifdef MOZ_BITS_DOWNLOAD
    793  BitsUtils::StartBitsServiceBackground
    794 !endif
    795 
    796  ; We don't want the header bitmap showing on the welcome page.
    797  GetDlgItem $0 $HWNDPARENT 1046
    798  ShowWindow $0 ${SW_HIDE}
    799 
    800  ${If} $ShouldPromptForRefresh == "1"
    801    ; Note: INI strings added here (rather than overwriting an existing value)
    802    ; should be removed in un.leaveWelcome, since ioSpecial.ini is reused
    803    ; for the Finish page.
    804 
    805    ; Replace title and body text
    806    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 2" Text "$(UN_REFRESH_PAGE_TITLE)"
    807    ; Convert to translate newlines, this includes $PLUGINSDIR internally.
    808    !insertmacro INSTALLOPTIONS_WRITE_UNCONVERT "ioSpecial.ini" "Field 3" Text "$(UN_REFRESH_PAGE_EXPLANATION)"
    809 
    810    ; Make room for the link and button
    811    StrCpy $0 "148"
    812    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 3" Bottom  $0
    813 
    814    ; Show the help link
    815    IntOp $1 $0 + 14
    816    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Type    "link"
    817    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Text    "$(UN_REFRESH_LEARN_MORE)"
    818    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Left    "120"
    819    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Top     $0
    820    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Right   "315"
    821    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Bottom  $1
    822    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Flags   "NOTIFY"
    823 
    824    ; Show the refresh button.
    825    IntOp $2 $1 + 14
    826    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 5" Type    "button"
    827    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 5" Text    "$(UN_REFRESH_BUTTON)"
    828    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 5" Left    "120"
    829    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 5" Top     $1
    830    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 5" Right   "240"
    831    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 5" Bottom  $2
    832    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 5" Flags   "NOTIFY"
    833 
    834    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Settings" NumFields 5
    835  ${EndIf}
    836 FunctionEnd
    837 
    838 Function un.ShowWelcome
    839  ; The welcome and finish pages don't get the correct colors for their labels
    840  ; like the other pages do, presumably because they're built by filling in an
    841  ; InstallOptions .ini file instead of from a dialog resource like the others.
    842  ; Field 2 is the header and Field 3 is the body text.
    843  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 2" "HWND"
    844  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
    845 
    846  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 3" "HWND"
    847  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
    848 
    849  ${If} $ShouldPromptForRefresh == "1"
    850    ; Field 4 is the profile refresh help link
    851    ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 4" "HWND"
    852    SetCtlColors $0 SYSCLR:HOTLIGHT SYSCLR:WINDOW
    853  ${EndIf}
    854 
    855  ; We need to overwrite the sidebar image so that we get it drawn with proper
    856  ; scaling if the display is scaled at anything above 100%.
    857  ${un.ChangeMUISidebarImage} "$PLUGINSDIR\modern-wizard.bmp"
    858 FunctionEnd
    859 
    860 Function un.leaveWelcome
    861  StrCpy $RefreshRequested "0"
    862 
    863  ${If} $ShouldPromptForRefresh == "1"
    864    ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Settings" "State"
    865    ${If} $0 == "5"
    866      ; Refresh button
    867      StrCpy $RefreshRequested "1"
    868    ${ElseIf} $0 == "4"
    869      ; Launch refresh help link, stay on this page
    870      Call un.LaunchRefreshHelpPage
    871      Abort
    872    ${EndIf}
    873  ${EndIf}
    874 
    875  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
    876    Banner::show /NOUNLOAD "$(BANNER_CHECK_EXISTING)"
    877 
    878    ; If we already found a window once and we're checking again, wait for an
    879    ; additional five seconds for the app to close.
    880    ${If} "$TmpVal" == "FoundAppWindow"
    881      Sleep 5000
    882    ${EndIf}
    883 
    884    ${PushFilesToCheck}
    885 
    886    ${un.CheckForFilesInUse} $TmpVal
    887 
    888    Banner::destroy
    889 
    890    ; If there are files in use $TmpVal will be "true"
    891    ${If} "$TmpVal" == "true"
    892      ; If it finds a window of the right class, then ManualCloseAppPrompt will
    893      ; abort leaving the value of $TmpVal set to "FoundAppWindow".
    894      StrCpy $TmpVal "FoundAppWindow"
    895 
    896      ${If} $RefreshRequested == "1"
    897        ${un.ManualCloseAppPrompt} "${MainWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_REFRESH)"
    898        ${un.ManualCloseAppPrompt} "${DialogWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_REFRESH)"
    899      ${Else}
    900        ${un.ManualCloseAppPrompt} "${MainWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)"
    901        ${un.ManualCloseAppPrompt} "${DialogWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)"
    902      ${EndIf}
    903      ; If the message window is not found set $TmpVal to "true" so the restart
    904      ; required message is displayed.
    905      ; In the case of a refresh request the restart required message will not be displayed;
    906      ; we're not trying to change the installation, so files in use only matter if the
    907      ; window is shown.
    908      StrCpy $TmpVal "true"
    909    ${EndIf}
    910  ${EndIf}
    911 
    912  ${If} $RefreshRequested == "1"
    913    Call un.LaunchAppForRefresh
    914    Quit
    915  ${EndIf}
    916 
    917  ${If} $ShouldPromptForRefresh == "1"
    918    ; Remove the custom controls.
    919    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Settings" NumFields 3
    920    DeleteIniSec "$PLUGINSDIR\ioSpecial.ini" "Field 4"
    921    DeleteIniSec "$PLUGINSDIR\ioSpecial.ini" "Field 5"
    922  ${EndIf}
    923 
    924  ; Bring back the header bitmap for the next pages.
    925  GetDlgItem $0 $HWNDPARENT 1046
    926  ShowWindow $0 ${SW_SHOW}
    927 FunctionEnd
    928 
    929 Function un.preConfirm
    930  ; The header on the wizard pages doesn't get the correct text
    931  ; color by default for some reason, even though the other controls do.
    932  GetDlgItem $0 $HWNDPARENT 1037
    933  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
    934  ; Hide unused subheader (to avoid overlapping moved header)
    935  GetDlgItem $0 $HWNDPARENT 1038
    936  ShowWindow $0 ${SW_HIDE}
    937 
    938  ${If} ${FileExists} "$INSTDIR\distribution\modern-header.bmp"
    939    Delete "$PLUGINSDIR\modern-header.bmp"
    940    CopyFiles /SILENT "$INSTDIR\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
    941  ${EndIf}
    942  ${un.ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
    943 
    944  ; Setup the unconfirm.ini file for the Custom Uninstall Confirm Page
    945  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "3"
    946 
    947  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Type   "label"
    948  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Text   "$(UN_CONFIRM_UNINSTALLED_FROM)"
    949  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Left   "0"
    950  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Right  "-1"
    951  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Top    "5"
    952  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Bottom "15"
    953 
    954  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Type   "text"
    955  ; The contents of this control must be set as follows in the pre function
    956  ; ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 2" "HWND"
    957  ; SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR"
    958  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" State  ""
    959  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Left   "0"
    960  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Right  "-1"
    961  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Top    "17"
    962  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Bottom "30"
    963  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" flags  "READONLY"
    964 
    965  ${If} "$TmpVal" == "true"
    966    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Type   "label"
    967    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Text   "$(SUMMARY_REBOOT_REQUIRED_UNINSTALL)"
    968    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Left   "0"
    969    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Right  "-1"
    970    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Top    "35"
    971    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Bottom "45"
    972 
    973    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "3"
    974  ${EndIf}
    975 
    976  !insertmacro MUI_HEADER_TEXT "$(UN_CONFIRM_PAGE_TITLE)" ""
    977 
    978  ; The Summary custom page has a textbox that will automatically receive
    979  ; focus. This sets the focus to the Install button instead.
    980  !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "unconfirm.ini"
    981  GetDlgItem $0 $HWNDPARENT 1
    982  System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i"
    983  ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 2" "HWND"
    984  SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR"
    985  !insertmacro MUI_INSTALLOPTIONS_SHOW
    986 FunctionEnd
    987 
    988 Function un.onUninstSuccess
    989  ; Send a ping at un.onGUIEnd, to avoid freezing the GUI.
    990  StrCpy $ShouldSendPing "1"
    991 
    992  ${If} ${Silent}
    993    ; If this is a silent uninstall then un.onGUIEnd doesn't run, so do it now.
    994    Call un.SendUninstallPing
    995  ${EndIf}
    996 FunctionEnd
    997 
    998 Function un.preFinish
    999  ; Need to give the survey (readme) checkbox a few extra DU's of height
   1000  ; to accommodate a potentially multi-line label. If the reboot flag is set,
   1001  ; then we're not showing the survey checkbox and Field 4 is the "reboot now"
   1002  ; radio button; setting it to go from 90 to 120 (instead of 90 to 100) would
   1003  ; cover up Field 5 which is "reboot later", running from 110 to 120. For
   1004  ; whatever reason child windows get created at the bottom of the z-order, so
   1005  ; 4 overlaps 5.
   1006  ${IfNot} ${RebootFlag}
   1007    WriteINIStr "$PLUGINSDIR\ioSpecial.ini" "Field 4" Bottom "120"
   1008  ${EndIf}
   1009 
   1010  ; We don't want the header bitmap showing on the finish page.
   1011  GetDlgItem $0 $HWNDPARENT 1046
   1012  ShowWindow $0 ${SW_HIDE}
   1013 FunctionEnd
   1014 
   1015 Function un.ShowFinish
   1016  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 2" "HWND"
   1017  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1018 
   1019  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 3" "HWND"
   1020  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1021 
   1022  ; We need to overwrite the sidebar image so that we get it drawn with proper
   1023  ; scaling if the display is scaled at anything above 100%.
   1024  ${un.ChangeMUISidebarImage} "$PLUGINSDIR\modern-wizard.bmp"
   1025 
   1026  ; Either Fields 4 and 5 are the reboot option radio buttons, or Field 4 is
   1027  ; the survey checkbox and Field 5 doesn't exist. Either way, we need to
   1028  ; clear the theme from them before we can set their background colors.
   1029  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 4" "HWND"
   1030  System::Call 'uxtheme::SetWindowTheme(i $0, w " ", w " ")'
   1031  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1032 
   1033  ClearErrors
   1034  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 5" "HWND"
   1035  ${IfNot} ${Errors}
   1036    System::Call 'uxtheme::SetWindowTheme(i $0, w " ", w " ")'
   1037    SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1038  ${EndIf}
   1039 FunctionEnd
   1040 
   1041 ################################################################################
   1042 # Initialization Functions
   1043 
   1044 Function .onInit
   1045  ; Remove the current exe directory from the search order.
   1046  ; This only effects LoadLibrary calls and not implicitly loaded DLLs.
   1047  System::Call 'kernel32::SetDllDirectoryW(w "")'
   1048 
   1049  ; We need this set up for most of the helper.exe operations.
   1050  ${UninstallOnInitCommon}
   1051 FunctionEnd
   1052 
   1053 Function un.onInit
   1054  ; Remove the current exe directory from the search order.
   1055  ; This only effects LoadLibrary calls and not implicitly loaded DLLs.
   1056  System::Call 'kernel32::SetDllDirectoryW(w "")'
   1057 
   1058  StrCpy $LANGUAGE 0
   1059  StrCpy $ShouldOpenSurvey "0"
   1060 
   1061  ${un.UninstallUnOnInitCommon}
   1062 
   1063  ; setup the application model id registration value
   1064  ${un.InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs"
   1065 
   1066  ; Find a default profile for this install.
   1067  SetShellVarContext current
   1068  ${un.FindInstallSpecificProfile}
   1069  Pop $1
   1070  GetFullPathName $1 $1
   1071 
   1072  ; If there is an existing default profile, offer profile refresh.
   1073  StrCpy $ShouldPromptForRefresh "0"
   1074  StrCpy $RefreshRequested "0"
   1075  ${If} $1 != ""
   1076    StrCpy $ShouldPromptForRefresh "1"
   1077  ${EndIf}
   1078 
   1079  ; Load version info for uninstall ping (sent after uninstall is complete)
   1080  ReadINIStr $InstalledVersion "$INSTDIR\application.ini" "App" "Version"
   1081  ReadINIStr $InstalledBuildID "$INSTDIR\application.ini" "App" "BuildID"
   1082 
   1083  !insertmacro InitInstallOptionsFile "unconfirm.ini"
   1084 FunctionEnd
   1085 
   1086 Function un.GUIInit
   1087  ; Move header text down, roughly vertically centered in the header.
   1088  ; Even if we're not changing the X, we can't set Y without also setting X.
   1089  ; Child window positions have to be set in client coordinates, and these are
   1090  ; left-to-right mirrored for RTL.
   1091  GetDlgItem $0 $HWNDPARENT 1037
   1092  ; Get current rect in screen coordinates
   1093  System::Call "*(i 0, i 0, i 0, i 0) i .r2"
   1094  System::Call "user32::GetWindowRect(p $0, p $2)"
   1095  ; Convert screen coordinates to client coordinates (handles RTL mirroring)
   1096  System::Call "user32::MapWindowPoints(p 0, p $HWNDPARENT, p $2, i 2)"
   1097  System::Call "*$2(i . r3, i . r4, i, i)"
   1098  System::Free $2
   1099  ; Move down
   1100  ${DialogUnitsToPixels} 8 Y $1
   1101  IntOp $4 $4 + $1
   1102  ; Set position, 0x0015 is SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE
   1103  System::Call "user32::SetWindowPos(p $0, p 0, i $3, i $4, i 0, i 0, i 0x0015)"
   1104 FunctionEnd
   1105 
   1106 Function .onGUIEnd
   1107  ${OnEndCommon}
   1108 FunctionEnd
   1109 
   1110 Function un.onGUIEnd
   1111  ${un.OnEndCommon}
   1112 
   1113  ${If} $ShouldOpenSurvey == "1"
   1114    ; Though these values are sometimes incorrect due to bug 444664 it happens
   1115    ; so rarely it isn't worth working around it by reading the registry values.
   1116    ${WinVerGetMajor} $0
   1117    ${WinVerGetMinor} $1
   1118    ${WinVerGetBuild} $2
   1119    ${WinVerGetServicePackLevel} $3
   1120    StrCpy $R1 "${URLUninstallSurvey}$0.$1.$2.$3"
   1121 
   1122    ; We can't just open the URL normally because we are most likely running
   1123    ; elevated without an unelevated process to redirect through, and we're
   1124    ; not going to go around starting elevated web browsers. But to start an
   1125    ; unelevated process directly from here we need a pretty nasty hack; see
   1126    ; the ExecInExplorer plugin code itself for the details.
   1127    ; If we were the default browser and we've now been uninstalled, we need
   1128    ; to take steps to make sure the user doesn't see an "open with" dialog;
   1129    ; they're helping us out by answering this survey, they don't need more
   1130    ; friction.
   1131    ; Windows 10 always seems to just clear the default browser, so for it
   1132    ; we'll manually invoke Edge using Edge's custom URI scheme.
   1133    ExecInExplorer::Exec "microsoft-edge:$R1"
   1134  ${EndIf}
   1135 
   1136  ; Finally send the ping, there's no GUI to freeze in case it is slow.
   1137  ${If} $ShouldSendPing == "1"
   1138    Call un.SendUninstallPing
   1139  ${EndIf}
   1140 FunctionEnd