tor-browser

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

installer.nsi (70227B)


      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 # AccessControl
      7 #   https://nsis.sourceforge.io/AccessControl_plug-in
      8 # AppAssocReg
      9 #   http://nsis.sourceforge.net/Application_Association_Registration_plug-in
     10 # ApplicationID
     11 #   http://nsis.sourceforge.net/ApplicationID_plug-in
     12 # CityHash
     13 #   http://searchfox.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash
     14 # nsJSON
     15 #   http://nsis.sourceforge.net/NsJSON_plug-in
     16 # ShellLink
     17 #   http://nsis.sourceforge.net/ShellLink_plug-in
     18 # UAC
     19 #   http://nsis.sourceforge.net/UAC_plug-in
     20 # ServicesHelper
     21 #   Mozilla specific plugin that is located in /other-licenses/nsis
     22 
     23 ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
     24 !verbose 3
     25 
     26 ; 7-Zip provides better compression than the lzma from NSIS so we add the files
     27 ; uncompressed and use 7-Zip to create a SFX archive of it
     28 SetDatablockOptimize on
     29 SetCompress off
     30 CRCCheck on
     31 
     32 RequestExecutionLevel user
     33 
     34 Unicode true
     35 ManifestSupportedOS all
     36 ManifestDPIAware true
     37 
     38 !addplugindir ./
     39 
     40 Var TmpVal
     41 Var InstallType
     42 Var AddStartMenuSC
     43 Var AddTaskbarSC
     44 Var AddDesktopSC
     45 Var AddDesktopLauncher
     46 Var AddPrivateBrowsingSC
     47 Var InstallMaintenanceService
     48 Var InstallOptionalExtensions
     49 Var ExtensionRecommender
     50 Var PageName
     51 Var PreventRebootRequired
     52 Var RegisterDefaultAgent
     53 ; Will be the registry hive that we are going to write things like class keys
     54 ; into. This will generally be HKLM if running with elevation, otherwise HKCU.
     55 Var RegHive
     56 
     57 ; Telemetry ping fields
     58 Var SetAsDefault
     59 Var HadOldInstall
     60 Var InstallExisted
     61 Var DefaultInstDir
     62 Var IntroPhaseStart
     63 Var OptionsPhaseStart
     64 Var InstallPhaseStart
     65 Var FinishPhaseStart
     66 Var FinishPhaseEnd
     67 Var InstallResult
     68 Var LaunchedNewApp
     69 Var PostSigningData
     70 
     71 ; By defining NO_STARTMENU_DIR an installer that doesn't provide an option for
     72 ; an application's Start Menu PROGRAMS directory and doesn't define the
     73 ; StartMenuDir variable can use the common InstallOnInitCommon macro.
     74 !define NO_STARTMENU_DIR
     75 
     76 ; Attempt to elevate Standard Users in addition to users that
     77 ; are a member of the Administrators group.
     78 !define NONADMIN_ELEVATE
     79 
     80 !define AbortSurveyURL "http://www.kampyle.com/feedback_form/ff-feedback-form.php?site_code=8166124&form_id=12116&url="
     81 
     82 ; Other included files may depend upon these includes!
     83 ; The following includes are provided by NSIS.
     84 !include FileFunc.nsh
     85 !include LogicLib.nsh
     86 !include MUI.nsh
     87 !include WinMessages.nsh
     88 !include WinVer.nsh
     89 !include WordFunc.nsh
     90 
     91 !insertmacro GetOptions
     92 !insertmacro GetParameters
     93 !insertmacro GetSize
     94 !insertmacro StrFilter
     95 !insertmacro WordFind
     96 !insertmacro WordReplace
     97 
     98 ; The following includes are custom.
     99 !include branding.nsi
    100 !include defines.nsi
    101 !include common.nsh
    102 !include locales.nsi
    103 
    104 VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
    105 VIAddVersionKey "OriginalFilename" "setup.exe"
    106 
    107 ; Must be inserted before other macros that use logging
    108 !insertmacro _LoggingCommon
    109 
    110 !insertmacro AddDisabledDDEHandlerValues
    111 !insertmacro ChangeMUIHeaderImage
    112 !insertmacro ChangeMUISidebarImage
    113 !insertmacro CheckForFilesInUse
    114 !insertmacro CleanMaintenanceServiceLogs
    115 !insertmacro CopyFilesFromDir
    116 !insertmacro CopyPostSigningData
    117 !insertmacro CreateRegKey
    118 !insertmacro GetFirstInstallPath
    119 !insertmacro GetLongPath
    120 !insertmacro GetPathFromString
    121 !insertmacro GetParent
    122 !insertmacro InitHashAppModelId
    123 !insertmacro IsHandlerForInstallDir
    124 !insertmacro IsPinnedToTaskBar
    125 !insertmacro IsUserAdmin
    126 !insertmacro LogDesktopShortcut
    127 !insertmacro LogQuickLaunchShortcut
    128 !insertmacro LogStartMenuShortcut
    129 !insertmacro ManualCloseAppPrompt
    130 !insertmacro PinnedToStartMenuLnkCount
    131 !insertmacro RegCleanAppHandler
    132 !insertmacro RegCleanMain
    133 !insertmacro RegCleanUninstall
    134 !insertmacro RemovePrecompleteEntries
    135 !insertmacro SetAppLSPCategories
    136 !insertmacro SetBrandNameVars
    137 !insertmacro UpdateShortcutAppModelIDs
    138 !insertmacro UnloadUAC
    139 !insertmacro WriteRegStr2
    140 !insertmacro WriteRegDWORD2
    141 
    142 !include shared.nsh
    143 
    144 ; Helper macros for ui callbacks. Insert these after shared.nsh
    145 !insertmacro CheckCustomCommon
    146 !insertmacro InstallEndCleanupCommon
    147 !insertmacro InstallOnInitCommon
    148 !insertmacro InstallStartCleanupCommon
    149 !insertmacro LeaveDirectoryCommon
    150 !insertmacro LeaveOptionsCommon
    151 !insertmacro OnEndCommon
    152 !insertmacro PreDirectoryCommon
    153 
    154 Name "${BrandFullName}"
    155 OutFile "setup.exe"
    156 !ifdef HAVE_64BIT_BUILD
    157  InstallDir "$PROGRAMFILES64\${BrandFullName}\"
    158 !else
    159  InstallDir "$PROGRAMFILES32\${BrandFullName}\"
    160 !endif
    161 ShowInstDetails nevershow
    162 
    163 ################################################################################
    164 # Modern User Interface - MUI
    165 
    166 !define MOZ_MUI_CUSTOM_ABORT
    167 !define MUI_CUSTOMFUNCTION_ABORT "CustomAbort"
    168 !define MUI_ICON setup.ico
    169 !define MUI_UNICON setup.ico
    170 !define MUI_WELCOMEPAGE_TITLE_3LINES
    171 !define MUI_HEADERIMAGE
    172 !define MUI_HEADERIMAGE_RIGHT
    173 !define MUI_WELCOMEFINISHPAGE_BITMAP wizWatermark.bmp
    174 ; By default MUI_BGCOLOR is hardcoded to FFFFFF, which is only correct if the
    175 ; Windows theme or high-contrast mode hasn't changed it, so we need to
    176 ; override that with GetSysColor(COLOR_WINDOW) (this string ends up getting
    177 ; passed to SetCtlColors, which uses this custom syntax to mean that).
    178 !define MUI_BGCOLOR SYSCLR:WINDOW
    179 
    180 ; Use a right to left header image when the language is right to left
    181 !ifdef ${AB_CD}_rtl
    182 !define MUI_HEADERIMAGE_BITMAP_RTL wizHeaderRTL.bmp
    183 !else
    184 !define MUI_HEADERIMAGE_BITMAP wizHeader.bmp
    185 !endif
    186 
    187 /**
    188 * Installation Pages
    189 */
    190 ; Welcome Page
    191 !define MUI_PAGE_CUSTOMFUNCTION_PRE preWelcome
    192 !define MUI_PAGE_CUSTOMFUNCTION_SHOW showWelcome
    193 !define MUI_PAGE_CUSTOMFUNCTION_LEAVE leaveWelcome
    194 !insertmacro MUI_PAGE_WELCOME
    195 
    196 ; Custom Options Page
    197 Page custom preOptions leaveOptions
    198 
    199 ; Select Install Directory Page
    200 !define MUI_PAGE_CUSTOMFUNCTION_PRE preDirectory
    201 !define MUI_PAGE_CUSTOMFUNCTION_LEAVE leaveDirectory
    202 !define MUI_DIRECTORYPAGE_VERIFYONLEAVE
    203 !insertmacro MUI_PAGE_DIRECTORY
    204 
    205 ; Custom Components Page
    206 !ifdef MOZ_MAINTENANCE_SERVICE
    207 Page custom preComponents leaveComponents
    208 !endif
    209 
    210 ; Custom Shortcuts Page
    211 Page custom preShortcuts leaveShortcuts
    212 
    213 ; Custom Extensions Page
    214 !ifdef MOZ_OPTIONAL_EXTENSIONS
    215 Page custom preExtensions leaveExtensions
    216 !endif
    217 
    218 ; Custom Summary Page
    219 Page custom preSummary leaveSummary
    220 
    221 ; Install Files Page
    222 !insertmacro MUI_PAGE_INSTFILES
    223 
    224 ; Finish Page
    225 !define MUI_FINISHPAGE_TITLE_3LINES
    226 !define MUI_FINISHPAGE_RUN
    227 !define MUI_FINISHPAGE_RUN_FUNCTION LaunchApp
    228 !define MUI_FINISHPAGE_RUN_TEXT $(LAUNCH_TEXT)
    229 !define MUI_PAGE_CUSTOMFUNCTION_PRE preFinish
    230 !define MUI_PAGE_CUSTOMFUNCTION_SHOW showFinish
    231 !define MUI_PAGE_CUSTOMFUNCTION_LEAVE postFinish
    232 !insertmacro MUI_PAGE_FINISH
    233 
    234 ; Use the default dialog for IDD_VERIFY for a simple Banner
    235 ChangeUI IDD_VERIFY "${NSISDIR}\Contrib\UIs\default.exe"
    236 
    237 ################################################################################
    238 # Install Sections
    239 
    240 ; Cleanup operations to perform at the start of the installation.
    241 Section "-InstallStartCleanup"
    242  System::Call "kernel32::GetTickCount()l .s"
    243  Pop $InstallPhaseStart
    244 
    245  SetDetailsPrint both
    246  DetailPrint $(STATUS_CLEANUP)
    247  SetDetailsPrint none
    248 
    249  SetOutPath "$INSTDIR"
    250  ${StartInstallLog} "${BrandFullName}" "${AB_CD}" "${AppVersion}" "${GREVersion}"
    251 
    252  StrCpy $R9 "true"
    253  StrCpy $PreventRebootRequired "false"
    254  ${GetParameters} $R8
    255  ${GetOptions} "$R8" "/INI=" $R7
    256  ${Unless} ${Errors}
    257    ; The configuration file must also exist
    258    ${If} ${FileExists} "$R7"
    259      ReadINIStr $R9 $R7 "Install" "RemoveDistributionDir"
    260      ReadINIStr $R8 $R7 "Install" "PreventRebootRequired"
    261      ${If} $R8 == "true"
    262        StrCpy $PreventRebootRequired "true"
    263      ${EndIf}
    264    ${EndIf}
    265  ${EndUnless}
    266 
    267  ${GetParameters} $R8
    268  ${InstallGetOption} $R8 "RemoveDistributionDir" $R9
    269  ${If} $R9 == "0"
    270    StrCpy $R9 "false"
    271  ${EndIf}
    272  ${InstallGetOption} $R8 "PreventRebootRequired" $PreventRebootRequired
    273  ${If} $PreventRebootRequired == "1"
    274    StrCpy $PreventRebootRequired "true"
    275  ${EndIf}
    276 
    277  ; Remove directories and files we always control before parsing the uninstall
    278  ; log so empty directories can be removed.
    279  ${If} ${FileExists} "$INSTDIR\updates"
    280    RmDir /r "$INSTDIR\updates"
    281  ${EndIf}
    282  ${If} ${FileExists} "$INSTDIR\updated"
    283    RmDir /r "$INSTDIR\updated"
    284  ${EndIf}
    285  ${If} ${FileExists} "$INSTDIR\defaults\shortcuts"
    286    RmDir /r "$INSTDIR\defaults\shortcuts"
    287  ${EndIf}
    288  ${If} ${FileExists} "$INSTDIR\distribution"
    289  ${AndIf} $R9 != "false"
    290    RmDir /r "$INSTDIR\distribution"
    291  ${EndIf}
    292 
    293  Call CheckIfInstallExisted
    294 
    295  ; Delete the app exe if present to prevent launching the app while we are
    296  ; installing.
    297  ClearErrors
    298  ${DeleteFile} "$INSTDIR\${FileMainEXE}"
    299  ${If} ${Errors}
    300    ; If the user closed the application it can take several seconds for it to
    301    ; shut down completely. If the application is being used by another user we
    302    ; can rename the file and then delete is when the system is restarted.
    303    Sleep 5000
    304    ${DeleteFile} "$INSTDIR\${FileMainEXE}"
    305    ClearErrors
    306  ${EndIf}
    307 
    308  ; setup the application model id registration value
    309  ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs"
    310 
    311  ; Clean up old maintenance service logs
    312  ${CleanMaintenanceServiceLogs} "Mozilla\Firefox"
    313 
    314  ${RemoveDeprecatedFiles}
    315  ${RemovePrecompleteEntries} "false"
    316 
    317  ${If} ${FileExists} "$INSTDIR\defaults\pref\channel-prefs.js"
    318    Delete "$INSTDIR\defaults\pref\channel-prefs.js"
    319  ${EndIf}
    320  ${If} ${FileExists} "$INSTDIR\defaults\pref"
    321    RmDir "$INSTDIR\defaults\pref"
    322  ${EndIf}
    323  ${If} ${FileExists} "$INSTDIR\defaults"
    324    RmDir "$INSTDIR\defaults"
    325  ${EndIf}
    326  ${If} ${FileExists} "$INSTDIR\uninstall"
    327    ; Remove the uninstall directory that we control
    328    RmDir /r "$INSTDIR\uninstall"
    329  ${EndIf}
    330  ${If} ${FileExists} "$INSTDIR\update-settings.ini"
    331    Delete "$INSTDIR\update-settings.ini"
    332  ${EndIf}
    333  ${If} ${FileExists} "$INSTDIR\installation_telemetry.json"
    334    Delete "$INSTDIR\installation_telemetry.json"
    335  ${EndIf}
    336 
    337  ; Explicitly remove empty webapprt dir in case it exists (bug 757978).
    338  RmDir "$INSTDIR\webapprt\components"
    339  RmDir "$INSTDIR\webapprt"
    340 
    341  ${InstallStartCleanupCommon}
    342 SectionEnd
    343 
    344 Section "-Application" APP_IDX
    345  ${StartUninstallLog}
    346 
    347  SetDetailsPrint both
    348  DetailPrint $(STATUS_INSTALL_APP)
    349  SetDetailsPrint none
    350 
    351  ${LogHeader} "Installing Main Files"
    352  ${CopyFilesFromDir} "$EXEDIR\core" "$INSTDIR" \
    353                      "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
    354                      "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
    355 
    356  ; Register DLLs
    357  ; XXXrstrong - AccessibleMarshal.dll can be used by multiple applications but
    358  ; is only registered for the last application installed. When the last
    359  ; application installed is uninstalled AccessibleMarshal.dll will no longer be
    360  ; registered. bug 338878
    361  ${LogHeader} "DLL Registration"
    362  ClearErrors
    363  ${RegisterDLL} "$INSTDIR\AccessibleMarshal.dll"
    364  ${If} ${Errors}
    365    ${LogMsg} "** ERROR Registering: $INSTDIR\AccessibleMarshal.dll **"
    366  ${Else}
    367    ${LogUninstall} "DLLReg: \AccessibleMarshal.dll"
    368    ${LogMsg} "Registered: $INSTDIR\AccessibleMarshal.dll"
    369  ${EndIf}
    370 
    371  ClearErrors
    372 
    373  ; Record the Windows Error Reporting module
    374  WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\Windows Error Reporting\RuntimeExceptionHelperModules" "$INSTDIR\mozwer.dll" 0
    375  ${If} ${Errors}
    376    ${LogMsg} "** ERROR Recording: $INSTDIR\mozwer.dll **"
    377  ${Else}
    378    ${LogMsg} "Recorded: $INSTDIR\mozwer.dll"
    379  ${EndIf}
    380 
    381  ClearErrors
    382 
    383  ; Apply LPAC permissions to install directory.
    384  ${LogHeader} "File access permissions"
    385  Push "Marker"
    386  AccessControl::GrantOnFile \
    387    "$INSTDIR" "(${LpacFirefoxInstallFilesSid})" "GenericRead + GenericExecute"
    388  Pop $TmpVal ; get "Marker" or error msg
    389  ${If} $TmpVal == "Marker"
    390    ${LogMsg} "Granted access for LPAC to $INSTDIR"
    391  ${Else}
    392    ${LogMsg} "** Error granting access for LPAC to $INSTDIR : $TmpVal **"
    393    Pop $TmpVal ; get "Marker"
    394  ${EndIf}
    395 
    396  ClearErrors
    397 
    398  ; Default for creating Start Menu shortcut
    399  ; (1 = create, 0 = don't create)
    400  ${If} $AddStartMenuSC == ""
    401    StrCpy $AddStartMenuSC "1"
    402  ${EndIf}
    403 
    404  ${If} $AddPrivateBrowsingSC == ""
    405    StrCpy $AddPrivateBrowsingSC "1"
    406  ${EndIf}
    407 
    408  ; Default for creating Desktop shortcut (1 = create, 0 = don't create)
    409  ${If} $AddDesktopSC == ""
    410    StrCpy $AddDesktopSC "1"
    411  ${EndIf}
    412 
    413  ; Default for adding a Taskbar pin (1 = pin, 0 = don't pin)
    414  ${If} $AddTaskbarSC == ""
    415    ${GetPinningSupportedByWindowsVersionWithoutSystemPopup} $AddTaskbarSC
    416  ${EndIf}
    417 
    418  ${LogHeader} "Adding Registry Entries"
    419  SetShellVarContext current  ; Set SHCTX to HKCU
    420  ${RegCleanMain} "Software\Mozilla"
    421  ${RegCleanUninstall}
    422  ${UpdateProtocolHandlers}
    423 
    424  ClearErrors
    425  WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
    426  ${If} ${Errors}
    427    StrCpy $RegHive "HKCU"
    428  ${Else}
    429    SetShellVarContext all  ; Set SHCTX to HKLM
    430    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
    431    StrCpy $RegHive "HKLM"
    432    ${RegCleanMain} "Software\Mozilla"
    433    ${RegCleanUninstall}
    434    ${UpdateProtocolHandlers}
    435 
    436    ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion"
    437    ${If} "$0" != "${GREVersion}"
    438      WriteRegStr HKLM "Software\mozilla.org\Mozilla" "CurrentVersion" "${GREVersion}"
    439    ${EndIf}
    440  ${EndIf}
    441 
    442  ${RemoveDeprecatedKeys}
    443  ${Set32to64DidMigrateReg}
    444 
    445  ; The previous installer adds several regsitry values to both HKLM and HKCU.
    446  ; We now try to add to HKLM and if that fails to HKCU
    447 
    448  ; The order that reg keys and values are added is important if you use the
    449  ; uninstall log to remove them on uninstall. When using the uninstall log you
    450  ; MUST add children first so they will be removed first on uninstall so they
    451  ; will be empty when the key is deleted. This allows the uninstaller to
    452  ; specify that only empty keys will be deleted.
    453  ${SetAppKeys}
    454 
    455  ${FixClassKeys}
    456 
    457  ; Uninstall keys can only exist under HKLM on some versions of windows. Since
    458  ; it doesn't cause problems always add them.
    459  ${SetUninstallKeys}
    460 
    461  ; On install always add the FirefoxHTML-, FirefoxPDF-, and FirefoxURL- keys.
    462  ; An empty string is used for the 5th param because FirefoxHTML- is not a
    463  ; protocol handler.
    464  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
    465  StrCpy $2 "$\"$8$\" -osint -url $\"%1$\""
    466 
    467  ; In Win8, the delegate execute handler picks up the value in FirefoxURL- and
    468  ; FirefoxHTML- to launch the desktop browser when it needs to.
    469  ${AddDisabledDDEHandlerValues} "FirefoxHTML-$AppUserModelID" "$2" "$8,${IDI_DOCUMENT_ZERO_BASED}" \
    470                                 "${AppRegName} HTML Document" ""
    471  ${AddDisabledDDEHandlerValues} "FirefoxPDF-$AppUserModelID" "$2" "$8,${IDI_DOCUMENT_PDF_ZERO_BASED}" \
    472                                 "${AppRegName} PDF Document" ""
    473  ${AddDisabledDDEHandlerValues} "FirefoxURL-$AppUserModelID" "$2" "$8,${IDI_DOCUMENT_ZERO_BASED}" \
    474                                 "${AppRegName} URL" "true"
    475 
    476  ; The keys below can be set in HKCU if needed.
    477  ${If} $RegHive == "HKLM"
    478    ; Set the Start Menu Internet and Registered App HKLM registry keys.
    479    ${SetStartMenuInternet} "HKLM"
    480    ${FixShellIconHandler} "HKLM"
    481  ${Else}
    482    ; Set the Start Menu Internet and Registered App HKCU registry keys.
    483    ${SetStartMenuInternet} "HKCU"
    484    ${FixShellIconHandler} "HKCU"
    485  ${EndIf}
    486 
    487 !ifdef MOZ_MAINTENANCE_SERVICE
    488  ; If the maintenance service page was displayed then a value was already
    489  ; explicitly selected for installing the maintenance service and
    490  ; and so InstallMaintenanceService will already be 0 or 1.
    491  ; If the maintenance service page was not displayed then
    492  ; InstallMaintenanceService will be equal to "".
    493  ${If} $InstallMaintenanceService == ""
    494    Call IsUserAdmin
    495    Pop $R0
    496    ${If} $R0 == "true"
    497    ; Only proceed if we have HKLM write access
    498    ${AndIf} $RegHive == "HKLM"
    499      ; The user is an admin, so we should default to installing the service.
    500      StrCpy $InstallMaintenanceService "1"
    501    ${Else}
    502      ; The user is not admin, so we can't install the service.
    503      StrCpy $InstallMaintenanceService "0"
    504    ${EndIf}
    505  ${EndIf}
    506 
    507  ${If} $InstallMaintenanceService == "1"
    508    ; The user wants to install the maintenance service, so execute
    509    ; the pre-packaged maintenance service installer.
    510    ; This option can only be turned on if the user is an admin so there
    511    ; is no need to use ExecShell w/ verb runas to enforce elevated.
    512    nsExec::Exec "$\"$INSTDIR\maintenanceservice_installer.exe$\""
    513  ${EndIf}
    514 !endif
    515 
    516  ; These need special handling on uninstall since they may be overwritten by
    517  ; an install into a different location.
    518  StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}"
    519  ${WriteRegStr2} $RegHive "$0" "" "$INSTDIR\${FileMainEXE}" 0
    520  ${WriteRegStr2} $RegHive "$0" "Path" "$INSTDIR" 0
    521 
    522  StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\$R9"
    523  ${CreateRegKey} "$RegHive" "$0" 0
    524  StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe"
    525  ${CreateRegKey} "$RegHive" "$0" 0
    526 
    527  ${If} $RegHive == "HKLM"
    528    ; Set the permitted LSP Categories
    529    ${SetAppLSPCategories} ${LSP_CATEGORIES}
    530  ${EndIf}
    531 
    532 !ifdef MOZ_LAUNCHER_PROCESS
    533  ; Launcher telemetry is opt-out, so we always enable it by default in new
    534  ; installs. We always use HKCU because this value is a reflection of a pref
    535  ; from the user profile. While this is not a perfect abstraction (given the
    536  ; possibility of multiple Firefox profiles owned by the same Windows user), it
    537  ; is more accurate than a machine-wide setting, and should be accurate in the
    538  ; majority of cases.
    539  WriteRegDWORD HKCU ${MOZ_LAUNCHER_SUBKEY} "$INSTDIR\${FileMainEXE}|Telemetry" 1
    540 !endif
    541 
    542  ${WriteToastNotificationRegistration} $RegHive
    543 
    544  ; Create shortcuts
    545  ${LogHeader} "Adding Shortcuts"
    546 
    547  ; Remove the start menu shortcuts and directory if the SMPROGRAMS section
    548  ; exists in the shortcuts_log.ini and the SMPROGRAMS. The installer's shortcut
    549  ; creation code will create the shortcut in the root of the Start Menu
    550  ; Programs directory.
    551  ${RemoveStartMenuDir}
    552 
    553  ; Always add the application's shortcuts to the shortcuts log ini file. The
    554  ; DeleteShortcuts macro will do the right thing on uninstall if the
    555  ; shortcuts don't exist.
    556  ${LogStartMenuShortcut} "${BrandShortName}.lnk"
    557  ${LogQuickLaunchShortcut} "${BrandShortName}.lnk"
    558  ${LogDesktopShortcut} "${BrandShortName}.lnk"
    559 
    560  ; Best effort to update the Win7 taskbar and start menu shortcut app model
    561  ; id's. The possible contexts are current user / system and the user that
    562  ; elevated the installer.
    563  Call FixShortcutAppModelIDs
    564  ; If the current context is all also perform Win7 taskbar and start menu link
    565  ; maintenance for the current user context.
    566  ${If} $RegHive == "HKLM"
    567    SetShellVarContext current  ; Set SHCTX to HKCU
    568    Call FixShortcutAppModelIDs
    569    SetShellVarContext all  ; Set SHCTX to HKLM
    570  ${EndIf}
    571 
    572  ; If running elevated also perform Win7 taskbar and start menu link
    573  ; maintenance for the unelevated user context in case that is different than
    574  ; the current user.
    575  ClearErrors
    576  ${GetParameters} $0
    577  ${GetOptions} "$0" "/UAC:" $0
    578  ${Unless} ${Errors}
    579    GetFunctionAddress $0 FixShortcutAppModelIDs
    580    UAC::ExecCodeSegment $0
    581  ${EndUnless}
    582 
    583  ; UAC only allows elevating to an Admin account so there is no need to add
    584  ; the Start Menu or Desktop shortcuts from the original unelevated process
    585  ; since this will either add it for the user if unelevated or All Users if
    586  ; elevated.
    587  ${If} $AddStartMenuSC == 1
    588    ; See if there's an existing shortcut for this installation using the old
    589    ; name that we should just rename, instead of creating a new shortcut.
    590    ; We could do this renaming even when $AddStartMenuSC is false; the idea
    591    ; behind not doing that is to interpret "false" as "don't do anything
    592    ; involving start menu shortcuts at all." We could also try to do this for
    593    ; both shell contexts, but that won't typically accomplish anything.
    594    ${If} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk"
    595      ShellLink::GetShortCutTarget "$SMPROGRAMS\${BrandFullName}.lnk"
    596      Pop $0
    597      ${GetLongPath} "$0" $0
    598      ${If} $0 == "$INSTDIR\${FileMainEXE}"
    599      ${AndIfNot} ${FileExists} "$SMPROGRAMS\${BrandShortName}.lnk"
    600        Rename "$SMPROGRAMS\${BrandFullName}.lnk" \
    601               "$SMPROGRAMS\${BrandShortName}.lnk"
    602        ${LogMsg} "Renamed existing shortcut to $SMPROGRAMS\${BrandShortName}.lnk"
    603      ${EndIf}
    604    ${Else}
    605      CreateShortCut "$SMPROGRAMS\${BrandShortName}.lnk" "$INSTDIR\${FileMainEXE}"
    606      ${If} ${FileExists} "$SMPROGRAMS\${BrandShortName}.lnk"
    607        ShellLink::SetShortCutDescription "$SMPROGRAMS\${BrandShortName}.lnk" "$(BRIEF_APP_DESC)"
    608        ShellLink::SetShortCutWorkingDirectory "$SMPROGRAMS\${BrandShortName}.lnk" \
    609                                               "$INSTDIR"
    610        ${If} "$AppUserModelID" != ""
    611          ApplicationID::Set "$SMPROGRAMS\${BrandShortName}.lnk" \
    612                             "$AppUserModelID" "true"
    613        ${EndIf}
    614        ${LogMsg} "Added Shortcut: $SMPROGRAMS\${BrandShortName}.lnk"
    615      ${Else}
    616        ${LogMsg} "** ERROR Adding Shortcut: $SMPROGRAMS\${BrandShortName}.lnk"
    617      ${EndIf}
    618    ${EndIf}
    619  ${EndIf}
    620 
    621  ; This is always added if it doesn't already exist to ensure that Windows'
    622  ; native "Pin to Taskbar" functionality can find an appropriate shortcut.
    623  ; See https://bugzilla.mozilla.org/show_bug.cgi?id=1762994 for additional
    624  ; background.
    625  ${If} $AddPrivateBrowsingSC == 1
    626    ${AddPrivateBrowsingShortcut}
    627  ${EndIf}
    628 
    629  ; Update lastwritetime of the Start Menu shortcut to clear the tile cache.
    630  ; Do this for both shell contexts in case the user has shortcuts in multiple
    631  ; locations, then restore the previous context at the end.
    632  SetShellVarContext all
    633  ${TouchStartMenuShortcut}
    634  SetShellVarContext current
    635  ${TouchStartMenuShortcut}
    636  ${If} $RegHive == "HKLM"
    637    SetShellVarContext all
    638  ${ElseIf} $RegHive == "HKCU"
    639    SetShellVarContext current
    640  ${EndIf}
    641 
    642  ${If} $AddDesktopLauncher == 1
    643    ; Entry point for installing launcher when Firefox is being installed
    644    Call OnInstallDesktopLauncherHandler
    645  ${ElseIf} $AddDesktopSC == 1
    646    ${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
    647      ShellLink::GetShortCutTarget "$DESKTOP\${BrandFullName}.lnk"
    648      Pop $0
    649      ${GetLongPath} "$0" $0
    650      ${If} $0 == "$INSTDIR\${FileMainEXE}"
    651      ${AndIfNot} ${FileExists} "$DESKTOP\${BrandShortName}.lnk"
    652        Rename "$DESKTOP\${BrandFullName}.lnk" "$DESKTOP\${BrandShortName}.lnk"
    653        ${LogMsg} "Renamed existing shortcut to $DESKTOP\${BrandShortName}.lnk"
    654      ${EndIf}
    655    ${Else}
    656      CreateShortCut "$DESKTOP\${BrandShortName}.lnk" "$INSTDIR\${FileMainEXE}"
    657      ${If} ${FileExists} "$DESKTOP\${BrandShortName}.lnk"
    658        ShellLink::SetShortCutDescription "$DESKTOP\${BrandShortName}.lnk" "$(BRIEF_APP_DESC)"
    659        ShellLink::SetShortCutWorkingDirectory "$DESKTOP\${BrandShortName}.lnk" \
    660                                              "$INSTDIR"
    661        ${If} "$AppUserModelID" != ""
    662          ApplicationID::Set "$DESKTOP\${BrandShortName}.lnk" \
    663                            "$AppUserModelID" "true"
    664        ${EndIf}
    665        ${LogMsg} "Added Shortcut: $DESKTOP\${BrandShortName}.lnk"
    666      ${Else}
    667        ${LogMsg} "** ERROR Adding Shortcut: $DESKTOP\${BrandShortName}.lnk"
    668      ${EndIf}
    669    ${EndIf}
    670  ${EndIf}
    671 
    672 !ifdef MOZ_OPTIONAL_EXTENSIONS
    673  ${If} ${FileExists} "$INSTDIR\distribution\optional-extensions"
    674    ${LogHeader} "Installing optional extensions if requested"
    675 
    676    ${If} $InstallOptionalExtensions != "0"
    677    ${AndIf} ${FileExists} "$INSTDIR\distribution\setup.ini"
    678      ${Unless} ${FileExists} "$INSTDIR\distribution\extensions"
    679        CreateDirectory "$INSTDIR\distribution\extensions"
    680      ${EndUnless}
    681 
    682      StrCpy $0 0
    683      ${Do}
    684        ClearErrors
    685        ReadINIStr $1 "$INSTDIR\distribution\setup.ini" "OptionalExtensions" \
    686                                                        "extension.$0.id"
    687        ${If} ${Errors}
    688          ${ExitDo}
    689        ${EndIf}
    690 
    691        ReadINIStr $2 "$INSTDIR\distribution\setup.ini" "OptionalExtensions" \
    692                                                        "extension.$0.checked"
    693        ${If} $2 != ${BST_UNCHECKED}
    694          ${LogMsg} "Installing optional extension: $1"
    695          CopyFiles /SILENT "$INSTDIR\distribution\optional-extensions\$1.xpi" \
    696                            "$INSTDIR\distribution\extensions"
    697        ${EndIf}
    698 
    699        IntOp $0 $0 + 1
    700      ${Loop}
    701    ${EndIf}
    702 
    703    ${LogMsg} "Removing the optional-extensions directory"
    704    RMDir /r /REBOOTOK "$INSTDIR\distribution\optional-extensions"
    705  ${EndIf}
    706 !endif
    707 
    708 !ifdef MOZ_MAINTENANCE_SERVICE
    709  ${If} $RegHive == "HKLM"
    710    ; Add the registry keys for allowed certificates.
    711    ${AddMaintCertKeys}
    712  ${EndIf}
    713 !endif
    714 
    715 !ifdef MOZ_DEFAULT_BROWSER_AGENT
    716  ${If} $RegisterDefaultAgent != "0"
    717    ExecWait '"$INSTDIR\default-browser-agent.exe" register-task $AppUserModelID' $0
    718 
    719    ${If} $0 == 0x80070534 ; HRESULT_FROM_WIN32(ERROR_NONE_MAPPED)
    720      ; The agent sometimes returns this error from trying to register the task
    721      ; when we're running out of the MSI. The error is cryptic, but I believe
    722      ; the cause is the fact that the MSI service runs us as SYSTEM, so
    723      ; proxying the invocation through the shell gets the task registered as
    724      ; the interactive user, which is what we want.
    725      ; We use ExecInExplorer only as a fallback instead of always, because it
    726      ; doesn't work in all environments; see bug 1602726.
    727      ExecInExplorer::Exec "$INSTDIR\default-browser-agent.exe" \
    728                           /cmdargs "register-task $AppUserModelID"
    729      ; We don't need Exec's return value, but don't leave it on the stack.
    730      Pop $0
    731    ${EndIf}
    732 
    733    ${If} $RegisterDefaultAgent == ""
    734      ; If the variable was unset, force it to a good value.
    735      StrCpy $RegisterDefaultAgent 1
    736    ${EndIf}
    737  ${EndIf}
    738  ; Remember whether we were told to skip registering the agent, so that updates
    739  ; won't try to create a registration when they don't find an existing one.
    740  WriteRegDWORD HKCU "Software\Mozilla\${AppName}\Installer\$AppUserModelID" \
    741                     "DidRegisterDefaultBrowserAgent" $RegisterDefaultAgent
    742 !endif
    743 
    744 ; Return value is saved to an unused variable to prevent the the error flag
    745 ; from being set.
    746 Var /GLOBAL UnusedExecCatchReturn
    747 ExecWait '"$INSTDIR\${FileMainEXE}" --backgroundtask install' $UnusedExecCatchReturn
    748 SectionEnd
    749 
    750 ; Cleanup operations to perform at the end of the installation.
    751 Section "-InstallEndCleanup"
    752  SetDetailsPrint both
    753  DetailPrint "$(STATUS_CLEANUP)"
    754  SetDetailsPrint none
    755 
    756  ; Maybe copy the post-signing data?
    757  StrCpy $PostSigningData ""
    758  ${GetParameters} $0
    759  ClearErrors
    760  ; We don't get post-signing data from the MSI.
    761  ${GetOptions} $0 "/LaunchedFromMSI" $1
    762  ${If} ${Errors}
    763    ; The stub will handle copying the data if it ran us.
    764    ClearErrors
    765    ${GetOptions} $0 "/LaunchedFromStub" $1
    766    ${If} ${Errors}
    767      ; We're being run standalone, copy the data.
    768      ${CopyPostSigningData}
    769      Pop $PostSigningData
    770    ${EndIf}
    771  ${EndIf}
    772 
    773  ; Adds a pinned Task Bar shortcut (see MigrateTaskBarShortcut for details).
    774  ${MigrateTaskBarShortcut} "$AddTaskbarSC"
    775 
    776  ; Add the Firewall entries during install
    777  Call AddFirewallEntries
    778 
    779  ; Refresh desktop icons
    780  ${RefreshShellIcons}
    781 
    782  ; Remove old unsupported firefox and firefox-private extension protocol
    783  ; handlers which were added in FX122 for the dual browser extension, since
    784  ; renamed to FirefoxBridge
    785  Push $1
    786  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $1
    787  ${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox"
    788  ${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox-private"
    789  Pop $1
    790 
    791  ${InstallEndCleanupCommon}
    792 
    793  ${If} $PreventRebootRequired == "true"
    794    SetRebootFlag false
    795  ${EndIf}
    796 
    797  ${If} ${RebootFlag}
    798    ; Admin is required to delete files on reboot so only add the moz-delete if
    799    ; the user is an admin. After calling UAC::IsAdmin $0 will equal 1 if the
    800    ; user is an admin.
    801    UAC::IsAdmin
    802    ${If} "$0" == "1"
    803      ; When a reboot is required give RefreshShellIcons time to finish the
    804      ; refreshing the icons so the OS doesn't display the icons from helper.exe
    805      Sleep 10000
    806      ${LogHeader} "Reboot Required To Finish Installation"
    807      ; ${FileMainEXE}.moz-upgrade should never exist but just in case...
    808      ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-upgrade"
    809        Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-upgrade"
    810      ${EndUnless}
    811 
    812      ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
    813        ClearErrors
    814        Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-delete"
    815        ${Unless} ${Errors}
    816          Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete"
    817        ${EndUnless}
    818      ${EndIf}
    819 
    820      ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
    821        CopyFiles /SILENT "$INSTDIR\uninstall\helper.exe" "$INSTDIR"
    822        FileOpen $0 "$INSTDIR\${FileMainEXE}" w
    823        FileWrite $0 "Will be deleted on restart"
    824        Rename /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-upgrade" "$INSTDIR\${FileMainEXE}"
    825        FileClose $0
    826        Delete "$INSTDIR\${FileMainEXE}"
    827        Rename "$INSTDIR\helper.exe" "$INSTDIR\${FileMainEXE}"
    828      ${EndUnless}
    829    ${EndIf}
    830  ${EndIf}
    831 
    832  Call WriteInstallationTelemetryData
    833 
    834  StrCpy $InstallResult "success"
    835 
    836  ; When we're using the GUI, .onGUIEnd sends the ping, but of course that isn't
    837  ; invoked when we're running silently.
    838  ${If} ${Silent}
    839    Call SendPing
    840  ${EndIf}
    841 SectionEnd
    842 
    843 ################################################################################
    844 # Install Abort Survey Functions
    845 
    846 Function CustomAbort
    847  ${If} "${AB_CD}" == "en-US"
    848  ${AndIf} "$PageName" != ""
    849  ${AndIf} ${FileExists} "$EXEDIR\core\distribution\distribution.ini"
    850    ReadINIStr $0 "$EXEDIR\core\distribution\distribution.ini" "Global" "about"
    851    ClearErrors
    852    ${WordFind} "$0" "Funnelcake" "E#" $1
    853    ${Unless} ${Errors}
    854      ; Yes = fill out the survey and exit, No = don't fill out survey and exit,
    855      ; Cancel = don't exit.
    856      MessageBox MB_YESNO|MB_ICONEXCLAMATION \
    857                 "Would you like to tell us why you are canceling this installation?" \
    858                 IDYes +1 IDNO CustomAbort_finish
    859      ${If} "$PageName" == "Welcome"
    860          GetFunctionAddress $0 AbortSurveyWelcome
    861      ${ElseIf} "$PageName" == "Options"
    862          GetFunctionAddress $0 AbortSurveyOptions
    863      ${ElseIf} "$PageName" == "Directory"
    864          GetFunctionAddress $0 AbortSurveyDirectory
    865      ${ElseIf} "$PageName" == "Shortcuts"
    866          GetFunctionAddress $0 AbortSurveyShortcuts
    867      ${ElseIf} "$PageName" == "Summary"
    868          GetFunctionAddress $0 AbortSurveySummary
    869      ${EndIf}
    870      ClearErrors
    871      ${GetParameters} $1
    872      ${GetOptions} "$1" "/UAC:" $2
    873      ${If} ${Errors}
    874        Call $0
    875      ${Else}
    876        UAC::ExecCodeSegment $0
    877      ${EndIf}
    878 
    879      CustomAbort_finish:
    880      Return
    881    ${EndUnless}
    882  ${EndIf}
    883 
    884  MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(MOZ_MUI_TEXT_ABORTWARNING)" \
    885             IDYES +1 IDNO +2
    886  Return
    887  Abort
    888 FunctionEnd
    889 
    890 Function AbortSurveyWelcome
    891  ExecShell "open" "${AbortSurveyURL}step1"
    892 FunctionEnd
    893 
    894 Function AbortSurveyOptions
    895  ExecShell "open" "${AbortSurveyURL}step2"
    896 FunctionEnd
    897 
    898 Function AbortSurveyDirectory
    899  ExecShell "open" "${AbortSurveyURL}step3"
    900 FunctionEnd
    901 
    902 Function AbortSurveyShortcuts
    903  ExecShell "open" "${AbortSurveyURL}step4"
    904 FunctionEnd
    905 
    906 Function AbortSurveySummary
    907  ExecShell "open" "${AbortSurveyURL}step5"
    908 FunctionEnd
    909 
    910 ################################################################################
    911 # Helper Functions
    912 
    913 Function CheckExistingInstall
    914  ; If there is a pending file copy from a previous upgrade don't allow
    915  ; installing until after the system has rebooted.
    916  IfFileExists "$INSTDIR\${FileMainEXE}.moz-upgrade" +1 +4
    917  MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(WARN_RESTART_REQUIRED_UPGRADE)" IDNO +2
    918  Reboot
    919  Quit
    920 
    921  ; If there is a pending file deletion from a previous uninstall don't allow
    922  ; installing until after the system has rebooted.
    923  IfFileExists "$INSTDIR\${FileMainEXE}.moz-delete" +1 +4
    924  MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(WARN_RESTART_REQUIRED_UNINSTALL)" IDNO +2
    925  Reboot
    926  Quit
    927 
    928  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
    929    ; Disable the next, cancel, and back buttons
    930    GetDlgItem $0 $HWNDPARENT 1 ; Next button
    931    EnableWindow $0 0
    932    GetDlgItem $0 $HWNDPARENT 2 ; Cancel button
    933    EnableWindow $0 0
    934    GetDlgItem $0 $HWNDPARENT 3 ; Back button
    935    EnableWindow $0 0
    936 
    937    Banner::show /NOUNLOAD "$(BANNER_CHECK_EXISTING)"
    938 
    939    ${If} "$TmpVal" == "FoundAppWindow"
    940      Sleep 5000
    941    ${EndIf}
    942 
    943    ${PushFilesToCheck}
    944 
    945    ; Store the return value in $TmpVal so it is less likely to be accidentally
    946    ; overwritten elsewhere.
    947    ${CheckForFilesInUse} $TmpVal
    948 
    949    Banner::destroy
    950 
    951    ; Enable the next, cancel, and back buttons
    952    GetDlgItem $0 $HWNDPARENT 1 ; Next button
    953    EnableWindow $0 1
    954    GetDlgItem $0 $HWNDPARENT 2 ; Cancel button
    955    EnableWindow $0 1
    956    GetDlgItem $0 $HWNDPARENT 3 ; Back button
    957    EnableWindow $0 1
    958 
    959    ; If there are files in use $TmpVal will be "true"
    960    ${If} "$TmpVal" == "true"
    961      ; If it finds a window of the right class, then ManualCloseAppPrompt will
    962      ; abort leaving the value of $TmpVal set to "FoundAppWindow".
    963      StrCpy $TmpVal "FoundAppWindow"
    964      ${ManualCloseAppPrompt} "${MainWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
    965      ${ManualCloseAppPrompt} "${DialogWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
    966      StrCpy $TmpVal "true"
    967    ${EndIf}
    968  ${EndIf}
    969 FunctionEnd
    970 
    971 Function LaunchApp
    972  ClearErrors
    973  ${GetParameters} $0
    974  ${GetOptions} "$0" "/UAC:" $1
    975  ${If} ${Errors}
    976    ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -first-startup"
    977  ${Else}
    978    GetFunctionAddress $0 LaunchAppFromElevatedProcess
    979    UAC::ExecCodeSegment $0
    980  ${EndIf}
    981 
    982  StrCpy $LaunchedNewApp true
    983 FunctionEnd
    984 
    985 Function LaunchAppFromElevatedProcess
    986  ; Set our current working directory to the application's install directory
    987  ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
    988  SetOutPath "$INSTDIR"
    989  ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -first-startup"
    990 FunctionEnd
    991 
    992 Function SendPing
    993  ${GetParameters} $0
    994  ${GetOptions} $0 "/LaunchedFromStub" $0
    995  ${IfNot} ${Errors}
    996    Return
    997  ${EndIf}
    998 
    999  ; Create a GUID to use as the unique document ID.
   1000  System::Call "rpcrt4::UuidCreate(g . r0)i"
   1001  ; StringFromGUID2 (which is what System::Call uses internally to stringify
   1002  ; GUIDs) includes braces in its output, and we don't want those.
   1003  StrCpy $0 $0 -1 1
   1004 
   1005  ; Configure the HTTP request for the ping
   1006  nsJSON::Set /tree ping /value "{}"
   1007  nsJSON::Set /tree ping "Url" /value \
   1008    '"${TELEMETRY_BASE_URL}/${TELEMETRY_NAMESPACE}/${TELEMETRY_INSTALL_PING_DOCTYPE}/${TELEMETRY_INSTALL_PING_VERSION}/$0"'
   1009  nsJSON::Set /tree ping "Verb" /value '"POST"'
   1010  nsJSON::Set /tree ping "DataType" /value '"JSON"'
   1011  nsJSON::Set /tree ping "AccessType" /value '"PreConfig"'
   1012 
   1013  ; Fill in the ping payload
   1014  nsJSON::Set /tree ping "Data" /value "{}"
   1015  nsJSON::Set /tree ping "Data" "installer_type" /value '"full"'
   1016  nsJSON::Set /tree ping "Data" "installer_version" /value '"${AppVersion}"'
   1017  nsJSON::Set /tree ping "Data" "build_channel" /value '"${Channel}"'
   1018  nsJSON::Set /tree ping "Data" "update_channel" /value '"${UpdateChannel}"'
   1019  nsJSON::Set /tree ping "Data" "locale" /value '"${AB_CD}"'
   1020 
   1021  ReadINIStr $0 "$INSTDIR\application.ini" "App" "Version"
   1022  nsJSON::Set /tree ping "Data" "version" /value '"$0"'
   1023  ReadINIStr $0 "$INSTDIR\application.ini" "App" "BuildID"
   1024  nsJSON::Set /tree ping "Data" "build_id" /value '"$0"'
   1025 
   1026  ; Capture the distribution ID and version if they exist.
   1027  StrCpy $1 "$INSTDIR\distribution\distribution.ini"
   1028  ${If} ${FileExists} "$1"
   1029    ReadINIStr $0 "$1" "Global" "id"
   1030    nsJSON::Set /tree ping "Data" "distribution_id" /value '"$0"'
   1031    ReadINIStr $0 "$1" "Global" "version"
   1032    nsJSON::Set /tree ping "Data" "distribution_version" /value '"$0"'
   1033  ${EndIf}
   1034 
   1035  ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "UBR"
   1036  ${If} ${Errors}
   1037    StrCpy $0 "-1" ; Assign -1 if an error occured during registry read
   1038  ${EndIf}
   1039  
   1040  nsJSON::Set /tree ping "Data" "windows_ubr" /value '$0'
   1041 
   1042  ${GetParameters} $0
   1043  ${GetOptions} $0 "/LaunchedFromMSI" $0
   1044  ${IfNot} ${Errors}
   1045    nsJSON::Set /tree ping "Data" "from_msi" /value true
   1046  ${EndIf}
   1047 
   1048  !ifdef HAVE_64BIT_BUILD
   1049    nsJSON::Set /tree ping "Data" "64bit_build" /value true
   1050  !else
   1051    nsJSON::Set /tree ping "Data" "64bit_build" /value false
   1052  !endif
   1053 
   1054  ${If} ${RunningX64}
   1055    nsJSON::Set /tree ping "Data" "64bit_os" /value true
   1056  ${Else}
   1057    nsJSON::Set /tree ping "Data" "64bit_os" /value false
   1058  ${EndIf}
   1059 
   1060  ; Though these values are sometimes incorrect due to bug 444664 it happens
   1061  ; so rarely it isn't worth working around it by reading the registry values.
   1062  ${WinVerGetMajor} $0
   1063  ${WinVerGetMinor} $1
   1064  ${WinVerGetBuild} $2
   1065  nsJSON::Set /tree ping "Data" "os_version" /value '"$0.$1.$2"'
   1066  ${If} ${IsServerOS}
   1067    nsJSON::Set /tree ping "Data" "server_os" /value true
   1068  ${Else}
   1069    nsJSON::Set /tree ping "Data" "server_os" /value false
   1070  ${EndIf}
   1071 
   1072  ClearErrors
   1073  WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \
   1074                   "Write Test"
   1075  ${If} ${Errors}
   1076    nsJSON::Set /tree ping "Data" "admin_user" /value false
   1077  ${Else}
   1078    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
   1079    nsJSON::Set /tree ping "Data" "admin_user" /value true
   1080  ${EndIf}
   1081 
   1082  ${If} $DefaultInstDir == $INSTDIR
   1083    nsJSON::Set /tree ping "Data" "default_path" /value true
   1084  ${Else}
   1085    nsJSON::Set /tree ping "Data" "default_path" /value false
   1086  ${EndIf}
   1087 
   1088  nsJSON::Set /tree ping "Data" "set_default" /value "$SetAsDefault"
   1089 
   1090  nsJSON::Set /tree ping "Data" "new_default" /value false
   1091  nsJSON::Set /tree ping "Data" "old_default" /value false
   1092 
   1093  AppAssocReg::QueryCurrentDefault "http" "protocol" "effective"
   1094  Pop $0
   1095  ReadRegStr $0 HKCR "$0\shell\open\command" ""
   1096  ${If} $0 != ""
   1097    ${GetPathFromString} "$0" $0
   1098    ${GetParent} "$0" $1
   1099    ${GetLongPath} "$1" $1
   1100    ${If} $1 == $INSTDIR
   1101      nsJSON::Set /tree ping "Data" "new_default" /value true
   1102    ${Else}
   1103      StrCpy $0 "$0" "" -11 # 11 == length of "firefox.exe"
   1104      ${If} "$0" == "${FileMainEXE}"
   1105        nsJSON::Set /tree ping "Data" "old_default" /value true
   1106      ${EndIf}
   1107    ${EndIf}
   1108  ${EndIf}
   1109 
   1110  nsJSON::Set /tree ping "Data" "had_old_install" /value "$HadOldInstall"
   1111 
   1112  ${If} ${Silent}
   1113    ; In silent mode, only the install phase is executed, and the GUI events
   1114    ; that initialize most of the phase times are never called; only
   1115    ; $InstallPhaseStart and $FinishPhaseStart have usable values.
   1116    ${GetSecondsElapsed} $InstallPhaseStart $FinishPhaseStart $0
   1117 
   1118    nsJSON::Set /tree ping "Data" "intro_time" /value 0
   1119    nsJSON::Set /tree ping "Data" "options_time" /value 0
   1120    nsJSON::Set /tree ping "Data" "install_time" /value "$0"
   1121    nsJSON::Set /tree ping "Data" "finish_time" /value 0
   1122  ${Else}
   1123    ; In GUI mode, all we can be certain of is that the intro phase has started;
   1124    ; the user could have canceled at any time and phases after that won't
   1125    ; have run at all. So we have to be prepared for anything after
   1126    ; $IntroPhaseStart to be uninitialized. For anything that isn't filled in
   1127    ; yet we'll use the current tick count. That means that any phases that
   1128    ; weren't entered at all will get 0 for their times because the start and
   1129    ; end tick counts will be the same.
   1130    System::Call "kernel32::GetTickCount()l .s"
   1131    Pop $0
   1132 
   1133    ${If} $OptionsPhaseStart == 0
   1134      StrCpy $OptionsPhaseStart $0
   1135    ${EndIf}
   1136    ${GetSecondsElapsed} $IntroPhaseStart $OptionsPhaseStart $1
   1137    nsJSON::Set /tree ping "Data" "intro_time" /value "$1"
   1138 
   1139    ${If} $InstallPhaseStart == 0
   1140      StrCpy $InstallPhaseStart $0
   1141    ${EndIf}
   1142    ${GetSecondsElapsed} $OptionsPhaseStart $InstallPhaseStart $1
   1143    nsJSON::Set /tree ping "Data" "options_time" /value "$1"
   1144 
   1145    ${If} $FinishPhaseStart == 0
   1146      StrCpy $FinishPhaseStart $0
   1147    ${EndIf}
   1148    ${GetSecondsElapsed} $InstallPhaseStart $FinishPhaseStart $1
   1149    nsJSON::Set /tree ping "Data" "install_time" /value "$1"
   1150 
   1151    ${If} $FinishPhaseEnd == 0
   1152      StrCpy $FinishPhaseEnd $0
   1153    ${EndIf}
   1154    ${GetSecondsElapsed} $FinishPhaseStart $FinishPhaseEnd $1
   1155    nsJSON::Set /tree ping "Data" "finish_time" /value "$1"
   1156  ${EndIf}
   1157 
   1158  ; $PostSigningData should only be empty if we didn't try to copy the
   1159  ; postSigningData file at all. If we did try and the file was missing
   1160  ; or empty, this will be "0", and for consistency with the stub we will
   1161  ; still submit it.
   1162  ${If} $PostSigningData != ""
   1163    nsJSON::Quote /always $PostSigningData
   1164    Pop $0
   1165    nsJSON::Set /tree ping "Data" "attribution" /value $0
   1166  ${EndIf}
   1167 
   1168  nsJSON::Set /tree ping "Data" "new_launched" /value "$LaunchedNewApp"
   1169 
   1170  nsJSON::Set /tree ping "Data" "succeeded" /value false
   1171  ${If} $InstallResult == "cancel"
   1172    nsJSON::Set /tree ping "Data" "user_cancelled" /value true
   1173  ${ElseIf} $InstallResult == "success"
   1174    nsJSON::Set /tree ping "Data" "succeeded" /value true
   1175  ${EndIf}
   1176 
   1177  ${If} ${Silent}
   1178    nsJSON::Set /tree ping "Data" "silent" /value true
   1179  ${Else}
   1180    nsJSON::Set /tree ping "Data" "silent" /value false
   1181  ${EndIf}
   1182 
   1183  ; Send the ping request. This call will block until a response is received,
   1184  ; but we shouldn't have any windows still open, so we won't jank anything.
   1185  nsJSON::Set /http ping
   1186 FunctionEnd
   1187 
   1188 ; Record data about this installation for use in in-app Telemetry pings.
   1189 ;
   1190 ; This should be run only after a successful installation, as it will
   1191 ; pull data from $INSTDIR\application.ini.
   1192 ;
   1193 ; Unlike the install ping or post-signing data, which is only sent/written by
   1194 ; the full installer when it is not run by the stub (since the stub has more
   1195 ; information), this will always be recorded by the full installer, to reduce
   1196 ; duplication and ensure consistency.
   1197 ;
   1198 ; Note: Should be assumed to clobber all $0, $1, etc registers.
   1199 !define JSONSet `nsJSON::Set /tree installation_data`
   1200 Function WriteInstallationTelemetryData
   1201  ${JSONSet} /value "{}"
   1202 
   1203  ReadINIStr $0 "$INSTDIR\application.ini" "App" "Version"
   1204  ${JSONSet} "version" /value '"$0"'
   1205  ReadINIStr $0 "$INSTDIR\application.ini" "App" "BuildID"
   1206  ${JSONSet} "build_id" /value '"$0"'
   1207 
   1208  ; Check for write access to HKLM, if successful then report this user
   1209  ; as an (elevated) admin.
   1210  ClearErrors
   1211  WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \
   1212                   "Write Test"
   1213  ${If} ${Errors}
   1214    StrCpy $1 "false"
   1215  ${Else}
   1216    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
   1217    StrCpy $1 "true"
   1218  ${EndIf}
   1219  ${JSONSet} "admin_user" /value $1
   1220 
   1221  ; Note: This is not the same as $HadOldInstall, which looks for any install
   1222  ; in the registry. $InstallExisted is true only if this run of the installer
   1223  ; is replacing an existing main EXE.
   1224  ${If} $InstallExisted != ""
   1225    ${JSONSet} "install_existed" /value $InstallExisted
   1226  ${EndIf}
   1227 
   1228  ; Check for top-level profile directory
   1229  ; Note: This is the same check used to set $ExistingProfile in stub.nsi
   1230  ${GetLocalAppDataFolder} $0
   1231  ${If} ${FileExists} "$0\Mozilla\Firefox"
   1232    StrCpy $1 "true"
   1233  ${Else}
   1234    StrCpy $1 "false"
   1235  ${EndIf}
   1236  ${JSONSet} "profdir_existed" /value $1
   1237 
   1238  ${GetParameters} $0
   1239  ${GetOptions} $0 "/LaunchedFromStub" $1
   1240  ${IfNot} ${Errors}
   1241    ${JSONSet} "installer_type" /value '"stub"'
   1242  ${Else}
   1243    ; Not launched from stub
   1244    ${JSONSet} "installer_type" /value '"full"'
   1245 
   1246    ; Include additional info relevant when the full installer is run directly
   1247 
   1248    ${If} ${Silent}
   1249      StrCpy $1 "true"
   1250    ${Else}
   1251      StrCpy $1 "false"
   1252    ${EndIf}
   1253    ${JSONSet} "silent" /value $1
   1254 
   1255    ${GetOptions} $0 "/LaunchedFromMSI" $1
   1256    ${IfNot} ${Errors}
   1257      StrCpy $1 "true"
   1258    ${Else}
   1259      StrCpy $1 "false"
   1260    ${EndIf}
   1261    ${JSONSet} "from_msi" /value $1
   1262 
   1263    ; NOTE: for non-admin basic installs, or reinstalls, $DefaultInstDir may not
   1264    ; reflect the actual default path.
   1265    ${If} $DefaultInstDir == $INSTDIR
   1266      StrCpy $1 "true"
   1267    ${Else}
   1268      StrCpy $1 "false"
   1269    ${EndIf}
   1270    ${JSONSet} "default_path" /value $1
   1271  ${EndIf}
   1272 
   1273  ; Timestamp, to allow app to detect a new install.
   1274  ; As a 64-bit integer isn't valid JSON, quote as a string.
   1275  System::Call "kernel32::GetSystemTimeAsFileTime(*l.r0)"
   1276  ${JSONSet} "install_timestamp" /value '"$0"'
   1277 
   1278  nsJSON::Serialize /tree installation_data /file /unicode "$INSTDIR\installation_telemetry.json"
   1279 FunctionEnd
   1280 !undef JSONSet
   1281 
   1282 ; Set $InstallExisted (if not yet set) by checking for the EXE.
   1283 ; Should be called before trying to delete the EXE when install begins.
   1284 Function CheckIfInstallExisted
   1285  ${If} $InstallExisted == ""
   1286    ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
   1287      StrCpy $InstallExisted true
   1288    ${Else}
   1289      StrCpy $InstallExisted false
   1290    ${EndIf}
   1291  ${EndIf}
   1292 FunctionEnd
   1293 
   1294 ################################################################################
   1295 # Language
   1296 
   1297 !insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
   1298 !verbose push
   1299 !verbose 3
   1300 !include "overrideLocale.nsh"
   1301 !include "customLocale.nsh"
   1302 !ifdef MOZ_OPTIONAL_EXTENSIONS
   1303 !include "extensionsLocale.nsh"
   1304 !endif
   1305 !verbose pop
   1306 
   1307 ; Set this after the locale files to override it if it is in the locale
   1308 ; using " " for BrandingText will hide the "Nullsoft Install System..." branding
   1309 BrandingText " "
   1310 
   1311 ################################################################################
   1312 # Page pre, show, and leave functions
   1313 
   1314 Function preWelcome
   1315  StrCpy $PageName "Welcome"
   1316  ${If} ${FileExists} "$EXEDIR\core\distribution\modern-wizard.bmp"
   1317    Delete "$PLUGINSDIR\modern-wizard.bmp"
   1318    CopyFiles /SILENT "$EXEDIR\core\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
   1319  ${EndIf}
   1320 
   1321  ; We don't want the header bitmap showing on the welcome page.
   1322  GetDlgItem $0 $HWNDPARENT 1046
   1323  ShowWindow $0 ${SW_HIDE}
   1324 
   1325  System::Call "kernel32::GetTickCount()l .s"
   1326  Pop $IntroPhaseStart
   1327 FunctionEnd
   1328 
   1329 Function showWelcome
   1330  ; The welcome and finish pages don't get the correct colors for their labels
   1331  ; like the other pages do, presumably because they're built by filling in an
   1332  ; InstallOptions .ini file instead of from a dialog resource like the others.
   1333  ; Field 2 is the header and Field 3 is the body text.
   1334  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 2" "HWND"
   1335  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1336  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 3" "HWND"
   1337  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1338 
   1339  ; We need to overwrite the sidebar image so that we get it drawn with proper
   1340  ; scaling if the display is scaled at anything above 100%.
   1341  ${ChangeMUISidebarImage} "$PLUGINSDIR\modern-wizard.bmp"
   1342 FunctionEnd
   1343 
   1344 Function leaveWelcome
   1345  ; Bring back the header bitmap for the next pages.
   1346  GetDlgItem $0 $HWNDPARENT 1046
   1347  ShowWindow $0 ${SW_SHOW}
   1348 FunctionEnd
   1349 
   1350 Function preOptions
   1351  System::Call "kernel32::GetTickCount()l .s"
   1352  Pop $OptionsPhaseStart
   1353 
   1354  ; The header and subheader on the wizard pages don't get the correct text
   1355  ; color by default for some reason, even though the other controls do.
   1356  GetDlgItem $0 $HWNDPARENT 1037
   1357  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1358  GetDlgItem $0 $HWNDPARENT 1038
   1359  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1360 
   1361  StrCpy $PageName "Options"
   1362  ${If} ${FileExists} "$EXEDIR\core\distribution\modern-header.bmp"
   1363    Delete "$PLUGINSDIR\modern-header.bmp"
   1364    CopyFiles /SILENT "$EXEDIR\core\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
   1365  ${EndIf}
   1366  ${ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
   1367  !insertmacro MUI_HEADER_TEXT "$(OPTIONS_PAGE_TITLE)" "$(OPTIONS_PAGE_SUBTITLE)"
   1368  !insertmacro MUI_INSTALLOPTIONS_DISPLAY "options.ini"
   1369 FunctionEnd
   1370 
   1371 Function leaveOptions
   1372  ${MUI_INSTALLOPTIONS_READ} $0 "options.ini" "Settings" "State"
   1373  ${If} $0 != 0
   1374    Abort
   1375  ${EndIf}
   1376  ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 2" "State"
   1377  StrCmp $R0 "1" +1 +2
   1378  StrCpy $InstallType ${INSTALLTYPE_BASIC}
   1379  ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 3" "State"
   1380  StrCmp $R0 "1" +1 +2
   1381  StrCpy $InstallType ${INSTALLTYPE_CUSTOM}
   1382 
   1383  ${LeaveOptionsCommon}
   1384 
   1385  ${If} $InstallType == ${INSTALLTYPE_BASIC}
   1386    Call CheckExistingInstall
   1387  ${EndIf}
   1388 FunctionEnd
   1389 
   1390 Function preDirectory
   1391  StrCpy $PageName "Directory"
   1392  ${PreDirectoryCommon}
   1393 
   1394  StrCpy $DefaultInstDir $INSTDIR
   1395 FunctionEnd
   1396 
   1397 Function leaveDirectory
   1398  ${If} $InstallType == ${INSTALLTYPE_BASIC}
   1399    Call CheckExistingInstall
   1400  ${EndIf}
   1401  ${LeaveDirectoryCommon} "$(WARN_DISK_SPACE)" "$(WARN_WRITE_ACCESS)"
   1402 FunctionEnd
   1403 
   1404 Function preShortcuts
   1405  StrCpy $PageName "Shortcuts"
   1406  ${CheckCustomCommon}
   1407  !insertmacro MUI_HEADER_TEXT "$(SHORTCUTS_PAGE_TITLE)" "$(SHORTCUTS_PAGE_SUBTITLE)"
   1408  !insertmacro MUI_INSTALLOPTIONS_DISPLAY "shortcuts.ini"
   1409 FunctionEnd
   1410 
   1411 Function leaveShortcuts
   1412  ${MUI_INSTALLOPTIONS_READ} $0 "shortcuts.ini" "Settings" "State"
   1413  ${If} $0 != 0
   1414    Abort
   1415  ${EndIf}
   1416  ${MUI_INSTALLOPTIONS_READ} $AddDesktopSC "shortcuts.ini" "Field 2" "State"
   1417  ${MUI_INSTALLOPTIONS_READ} $AddStartMenuSC "shortcuts.ini" "Field 3" "State"
   1418 
   1419 
   1420  ${If} ${IsPinningSupportedByWindowsVersionWithoutSystemPopup}
   1421    ${MUI_INSTALLOPTIONS_READ} $AddTaskbarSC "shortcuts.ini" "Field 4" "State"
   1422  ${EndIf}
   1423 
   1424  ${If} $InstallType == ${INSTALLTYPE_CUSTOM}
   1425    Call CheckExistingInstall
   1426  ${EndIf}
   1427 FunctionEnd
   1428 
   1429 !ifdef MOZ_MAINTENANCE_SERVICE
   1430 Function preComponents
   1431  ; If the service already exists, don't show this page
   1432  ServicesHelper::IsInstalled "MozillaMaintenance"
   1433  Pop $R9
   1434  ${If} $R9 == 1
   1435    ; The service already exists so don't show this page.
   1436    Abort
   1437  ${EndIf}
   1438 
   1439  ; Don't show the custom components page if the
   1440  ; user is not an admin
   1441  Call IsUserAdmin
   1442  Pop $R9
   1443  ${If} $R9 != "true"
   1444    Abort
   1445  ${EndIf}
   1446 
   1447  ; Only show the maintenance service page if we have write access to HKLM
   1448  ClearErrors
   1449  WriteRegStr HKLM "Software\Mozilla" \
   1450              "${BrandShortName}InstallerTest" "Write Test"
   1451  ${If} ${Errors}
   1452    ClearErrors
   1453    Abort
   1454  ${Else}
   1455    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
   1456  ${EndIf}
   1457 
   1458  StrCpy $PageName "Components"
   1459  ${CheckCustomCommon}
   1460  !insertmacro MUI_HEADER_TEXT "$(COMPONENTS_PAGE_TITLE)" "$(COMPONENTS_PAGE_SUBTITLE)"
   1461  !insertmacro MUI_INSTALLOPTIONS_DISPLAY "components.ini"
   1462 FunctionEnd
   1463 
   1464 Function leaveComponents
   1465  ${MUI_INSTALLOPTIONS_READ} $0 "components.ini" "Settings" "State"
   1466  ${If} $0 != 0
   1467    Abort
   1468  ${EndIf}
   1469  ${MUI_INSTALLOPTIONS_READ} $InstallMaintenanceService "components.ini" "Field 2" "State"
   1470  ${If} $InstallType == ${INSTALLTYPE_CUSTOM}
   1471    Call CheckExistingInstall
   1472  ${EndIf}
   1473 FunctionEnd
   1474 !endif
   1475 
   1476 !ifdef MOZ_OPTIONAL_EXTENSIONS
   1477 Function preExtensions
   1478  StrCpy $PageName "Extensions"
   1479  ${CheckCustomCommon}
   1480 
   1481  ; Abort if no optional extensions configured in distribution/setup.ini
   1482  ${If} ${FileExists} "$EXEDIR\core\distribution\setup.ini"
   1483    ClearErrors
   1484    ReadINIStr $ExtensionRecommender "$EXEDIR\core\distribution\setup.ini" \
   1485      "OptionalExtensions" "Recommender.${AB_CD}"
   1486    ${If} ${Errors}
   1487      ClearErrors
   1488      ReadINIStr $ExtensionRecommender "$EXEDIR\core\distribution\setup.ini" \
   1489        "OptionalExtensions" "Recommender"
   1490    ${EndIf}
   1491 
   1492    ${If} ${Errors}
   1493      ClearErrors
   1494      Abort
   1495    ${EndIf}
   1496  ${Else}
   1497    Abort
   1498  ${EndIf}
   1499 
   1500  !insertmacro MUI_HEADER_TEXT "$(EXTENSIONS_PAGE_TITLE)" "$(EXTENSIONS_PAGE_SUBTITLE)"
   1501  !insertmacro MUI_INSTALLOPTIONS_DISPLAY "extensions.ini"
   1502 FunctionEnd
   1503 
   1504 Function leaveExtensions
   1505  ${MUI_INSTALLOPTIONS_READ} $0 "extensions.ini" "Settings" "NumFields"
   1506  ${MUI_INSTALLOPTIONS_READ} $1 "extensions.ini" "Settings" "State"
   1507 
   1508  ; $0 is count of checkboxes
   1509  IntOp $0 $0 - 1
   1510 
   1511  ${If} $1 > $0
   1512    Abort
   1513  ${ElseIf} $1 == 0
   1514    ; $1 is count of selected optional extension(s)
   1515    StrCpy $1 0
   1516 
   1517    StrCpy $2 2
   1518    ${Do}
   1519      ${MUI_INSTALLOPTIONS_READ} $3 "extensions.ini" "Field $2" "State"
   1520      ${If} $3 == ${BST_CHECKED}
   1521        IntOp $1 $1 + 1
   1522      ${EndIf}
   1523 
   1524      IntOp $4 $2 - 2
   1525      WriteINIStr "$EXEDIR\core\distribution\setup.ini" \
   1526        "OptionalExtensions" "extension.$4.checked" "$3"
   1527 
   1528      ${If} $0 == $2
   1529        ${ExitDo}
   1530      ${Else}
   1531        IntOp $2 $2 + 1
   1532      ${EndIf}
   1533    ${Loop}
   1534 
   1535    ; Different from state of field 1, "0" means no optional extensions selected
   1536    ${If} $1 > 0
   1537      StrCpy $InstallOptionalExtensions "1"
   1538    ${Else}
   1539      StrCpy $InstallOptionalExtensions "0"
   1540    ${EndIf}
   1541 
   1542    ${If} $InstallType == ${INSTALLTYPE_CUSTOM}
   1543      Call CheckExistingInstall
   1544    ${EndIf}
   1545  ${ElseIf} $1 == 1
   1546    ; Check/uncheck all optional extensions with field 1
   1547    ${MUI_INSTALLOPTIONS_READ} $1 "extensions.ini" "Field 1" "State"
   1548 
   1549    StrCpy $2 2
   1550    ${Do}
   1551      ${MUI_INSTALLOPTIONS_READ} $3 "extensions.ini" "Field $2" "HWND"
   1552      SendMessage $3 ${BM_SETCHECK} $1 0
   1553 
   1554      ${If} $0 == $2
   1555        ${ExitDo}
   1556      ${Else}
   1557        IntOp $2 $2 + 1
   1558      ${EndIf}
   1559    ${Loop}
   1560 
   1561    Abort
   1562  ${ElseIf} $1 > 1
   1563    StrCpy $1 ${BST_CHECKED}
   1564 
   1565    StrCpy $2 2
   1566    ${Do}
   1567      ${MUI_INSTALLOPTIONS_READ} $3 "extensions.ini" "Field $2" "State"
   1568      ${If} $3 == ${BST_UNCHECKED}
   1569        StrCpy $1 ${BST_UNCHECKED}
   1570        ${ExitDo}
   1571      ${EndIf}
   1572 
   1573      ${If} $0 == $2
   1574        ${ExitDo}
   1575      ${Else}
   1576        IntOp $2 $2 + 1
   1577      ${EndIf}
   1578    ${Loop}
   1579 
   1580    ; Check field 1 only if all optional extensions are selected
   1581    ${MUI_INSTALLOPTIONS_READ} $3 "extensions.ini" "Field 1" "HWND"
   1582    SendMessage $3 ${BM_SETCHECK} $1 0
   1583 
   1584    Abort
   1585  ${EndIf}
   1586 FunctionEnd
   1587 !endif
   1588 
   1589 Function preSummary
   1590  StrCpy $PageName "Summary"
   1591  ; Setup the summary.ini file for the Custom Summary Page
   1592  WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NumFields "3"
   1593 
   1594  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Type   "label"
   1595  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Text   "$(SUMMARY_INSTALLED_TO)"
   1596  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Left   "0"
   1597  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Right  "-1"
   1598  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Top    "5"
   1599  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Bottom "15"
   1600 
   1601  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Type   "text"
   1602  ; The contents of this control must be set as follows in the pre function
   1603  ; ${MUI_INSTALLOPTIONS_READ} $1 "summary.ini" "Field 2" "HWND"
   1604  ; SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR"
   1605  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" state  ""
   1606  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Left   "0"
   1607  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Right  "-1"
   1608  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Top    "17"
   1609  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" Bottom "30"
   1610  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 2" flags  "READONLY"
   1611 
   1612  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Type   "label"
   1613  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Left   "0"
   1614  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Right  "-1"
   1615  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Top    "130"
   1616  WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Bottom "150"
   1617 
   1618  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
   1619    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Text "$(SUMMARY_UPGRADE_CLICK)"
   1620    WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NextButtonText "$(UPGRADE_BUTTON)"
   1621  ${Else}
   1622    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 3" Text "$(SUMMARY_INSTALL_CLICK)"
   1623    DeleteINIStr "$PLUGINSDIR\summary.ini" "Settings" NextButtonText
   1624  ${EndIf}
   1625 
   1626  ${If} "$TmpVal" == "true"
   1627    WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NumFields "4"
   1628 
   1629    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Type   "label"
   1630    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Text   "$(SUMMARY_REBOOT_REQUIRED_INSTALL)"
   1631    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Left   "0"
   1632    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Right  "-1"
   1633    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Top    "35"
   1634    WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Bottom "50"
   1635  ${EndIf}
   1636 
   1637  !insertmacro MUI_HEADER_TEXT "$(SUMMARY_PAGE_TITLE)" "$(SUMMARY_PAGE_SUBTITLE)"
   1638 
   1639  ; The Summary custom page has a textbox that will automatically receive
   1640  ; focus. This sets the focus to the Install button instead.
   1641  !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "summary.ini"
   1642  GetDlgItem $0 $HWNDPARENT 1
   1643  System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i"
   1644  ${MUI_INSTALLOPTIONS_READ} $1 "summary.ini" "Field 2" "HWND"
   1645  SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR"
   1646  !insertmacro MUI_INSTALLOPTIONS_SHOW
   1647 FunctionEnd
   1648 
   1649 Function leaveSummary
   1650  Call CheckIfInstallExisted
   1651 
   1652  ; Try to delete the app executable and if we can't delete it try to find the
   1653  ; app's message window and prompt the user to close the app. This allows
   1654  ; running an instance that is located in another directory. If for whatever
   1655  ; reason there is no message window we will just rename the app's files and
   1656  ; then remove them on restart.
   1657  ClearErrors
   1658  ${DeleteFile} "$INSTDIR\${FileMainEXE}"
   1659  ${If} ${Errors}
   1660    ${ManualCloseAppPrompt} "${MainWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
   1661    ${ManualCloseAppPrompt} "${DialogWindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
   1662  ${EndIf}
   1663 FunctionEnd
   1664 
   1665 ; When we add an optional action to the finish page the cancel button is
   1666 ; enabled. This disables it and leaves the finish button as the only choice.
   1667 Function preFinish
   1668  System::Call "kernel32::GetTickCount()l .s"
   1669  Pop $FinishPhaseStart
   1670 
   1671  StrCpy $PageName ""
   1672  ${EndInstallLog} "${BrandFullName}"
   1673  !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
   1674 
   1675  ; We don't want the header bitmap showing on the finish page.
   1676  GetDlgItem $0 $HWNDPARENT 1046
   1677  ShowWindow $0 ${SW_HIDE}
   1678 FunctionEnd
   1679 
   1680 Function showFinish
   1681  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 2" "HWND"
   1682  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1683 
   1684  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 3" "HWND"
   1685  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1686 
   1687  ; We need to overwrite the sidebar image so that we get it drawn with proper
   1688  ; scaling if the display is scaled at anything above 100%.
   1689  ${ChangeMUISidebarImage} "$PLUGINSDIR\modern-wizard.bmp"
   1690 
   1691  ; Field 4 is the launch checkbox. Since it's a checkbox, we need to
   1692  ; clear the theme from it before we can set its background color.
   1693  ReadINIStr $0 "$PLUGINSDIR\ioSpecial.ini" "Field 4" "HWND"
   1694  System::Call 'uxtheme::SetWindowTheme(i $0, w " ", w " ")'
   1695  SetCtlColors $0 SYSCLR:WINDOWTEXT SYSCLR:WINDOW
   1696 FunctionEnd
   1697 
   1698 Function postFinish
   1699  System::Call "kernel32::GetTickCount()l .s"
   1700  Pop $FinishPhaseEnd
   1701 FunctionEnd
   1702 
   1703 ################################################################################
   1704 # Initialization Functions
   1705 
   1706 Function .onInit
   1707  ; Remove the current exe directory from the search order.
   1708  ; This only effects LoadLibrary calls and not implicitly loaded DLLs.
   1709  System::Call 'kernel32::SetDllDirectoryW(w "")'
   1710 
   1711  ; Initialize the variables used for telemetry
   1712  StrCpy $SetAsDefault true
   1713  StrCpy $HadOldInstall false
   1714  StrCpy $InstallExisted ""
   1715  StrCpy $DefaultInstDir $INSTDIR
   1716  StrCpy $IntroPhaseStart 0
   1717  StrCpy $OptionsPhaseStart 0
   1718  StrCpy $InstallPhaseStart 0
   1719  StrCpy $FinishPhaseStart 0
   1720  StrCpy $FinishPhaseEnd 0
   1721  StrCpy $InstallResult "cancel"
   1722  StrCpy $LaunchedNewApp false
   1723 
   1724  StrCpy $PageName ""
   1725  StrCpy $LANGUAGE 0
   1726  ${SetBrandNameVars} "$EXEDIR\core\distribution\setup.ini"
   1727 
   1728  ; Don't install on systems that don't support SSE2. The parameter value of
   1729  ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the
   1730  ; SSE2 instruction set is available. Result returned in $R7.
   1731  System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7"
   1732 
   1733  ; Windows 8.1/Server 2012 R2 and lower are not supported.
   1734  ${Unless} ${AtLeastWin10}
   1735    ${If} "$R7" == "0"
   1736      strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG2)"
   1737    ${Else}
   1738      strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_MSG2)"
   1739    ${EndIf}
   1740    MessageBox MB_OKCANCEL|MB_ICONSTOP "$R7" IDCANCEL +2
   1741    ExecShell "open" "${URLSystemRequirements}"
   1742    Quit
   1743  ${EndUnless}
   1744 
   1745  ; SSE2 CPU support
   1746  ${If} "$R7" == "0"
   1747    MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_CPU_MSG)" IDCANCEL +2
   1748    ExecShell "open" "${URLSystemRequirements}"
   1749    Quit
   1750  ${EndIf}
   1751 
   1752 !ifdef HAVE_64BIT_BUILD
   1753  ${If} "${ARCH}" == "AArch64"
   1754    ${IfNot} ${IsNativeARM64}
   1755      MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_OSVER_MSG2)" IDCANCEL +2
   1756      ExecShell "open" "${URLSystemRequirements}"
   1757      Quit
   1758    ${EndIf}
   1759  ${ElseIfNot} ${RunningX64}
   1760    MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_OSVER_MSG2)" IDCANCEL +2
   1761    ExecShell "open" "${URLSystemRequirements}"
   1762    Quit
   1763  ${EndIf}
   1764  SetRegView 64
   1765 !endif
   1766 
   1767  SetShellVarContext all
   1768  ${GetFirstInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $0
   1769  ${If} "$0" == "false"
   1770    SetShellVarContext current
   1771    ${GetFirstInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $0
   1772    ${If} "$0" == "false"
   1773      StrCpy $HadOldInstall false
   1774    ${Else}
   1775      StrCpy $HadOldInstall true
   1776    ${EndIf}
   1777  ${Else}
   1778    StrCpy $HadOldInstall true
   1779  ${EndIf}
   1780 
   1781  ${InstallOnInitCommon} "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG2)"
   1782 
   1783  !insertmacro InitInstallOptionsFile "options.ini"
   1784  !insertmacro InitInstallOptionsFile "shortcuts.ini"
   1785  !insertmacro InitInstallOptionsFile "components.ini"
   1786  !insertmacro InitInstallOptionsFile "extensions.ini"
   1787  !insertmacro InitInstallOptionsFile "summary.ini"
   1788 
   1789  WriteINIStr "$PLUGINSDIR\options.ini" "Settings" NumFields "5"
   1790 
   1791  WriteINIStr "$PLUGINSDIR\options.ini" "Field 1" Type   "label"
   1792  WriteINIStr "$PLUGINSDIR\options.ini" "Field 1" Text   "$(OPTIONS_SUMMARY)"
   1793  WriteINIStr "$PLUGINSDIR\options.ini" "Field 1" Left   "0"
   1794  WriteINIStr "$PLUGINSDIR\options.ini" "Field 1" Right  "-1"
   1795  WriteINIStr "$PLUGINSDIR\options.ini" "Field 1" Top    "0"
   1796  WriteINIStr "$PLUGINSDIR\options.ini" "Field 1" Bottom "10"
   1797 
   1798  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Type   "RadioButton"
   1799  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Text   "$(OPTION_STANDARD_RADIO)"
   1800  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Left   "0"
   1801  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Right  "-1"
   1802  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Top    "25"
   1803  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Bottom "35"
   1804  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" State  "1"
   1805  WriteINIStr "$PLUGINSDIR\options.ini" "Field 2" Flags  "GROUP"
   1806 
   1807  WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Type   "RadioButton"
   1808  WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Text   "$(OPTION_CUSTOM_RADIO)"
   1809  WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Left   "0"
   1810  WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Right  "-1"
   1811  WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Top    "55"
   1812  WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" Bottom "65"
   1813  WriteINIStr "$PLUGINSDIR\options.ini" "Field 3" State  "0"
   1814 
   1815  WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Type   "label"
   1816  WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Text   "$(OPTION_STANDARD_DESC)"
   1817  WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Left   "15"
   1818  WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Right  "-1"
   1819  WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Top    "37"
   1820  WriteINIStr "$PLUGINSDIR\options.ini" "Field 4" Bottom "57"
   1821 
   1822  WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Type   "label"
   1823  WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Text   "$(OPTION_CUSTOM_DESC)"
   1824  WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Left   "15"
   1825  WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Right  "-1"
   1826  WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Top    "67"
   1827  WriteINIStr "$PLUGINSDIR\options.ini" "Field 5" Bottom "87"
   1828 
   1829  ${If} ${IsPinningSupportedByWindowsVersionWithoutSystemPopup}
   1830    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Settings" NumFields "4"
   1831  ${Else}
   1832    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Settings" NumFields "3"
   1833  ${EndIf}
   1834 
   1835  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 1" Type   "label"
   1836  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 1" Text   "$(CREATE_ICONS_DESC)"
   1837  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 1" Left   "0"
   1838  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 1" Right  "-1"
   1839  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 1" Top    "5"
   1840  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 1" Bottom "15"
   1841 
   1842  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Type   "checkbox"
   1843  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Text   "$(ICONS_DESKTOP)"
   1844  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Left   "0"
   1845  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Right  "-1"
   1846  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Top    "20"
   1847  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Bottom "30"
   1848  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" State  "1"
   1849  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 2" Flags  "GROUP"
   1850 
   1851  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Type   "checkbox"
   1852  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Text   "$(ICONS_STARTMENU)"
   1853  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Left   "0"
   1854  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Right  "-1"
   1855  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Top    "40"
   1856  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" Bottom "50"
   1857  WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 3" State  "1"
   1858 
   1859  ${If} ${IsPinningSupportedByWindowsVersionWithoutSystemPopup}
   1860    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Type   "checkbox"
   1861    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Text   "$(ICONS_TASKBAR)"
   1862    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left   "0"
   1863    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Right  "-1"
   1864    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Top    "60"
   1865    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Bottom "70"
   1866    WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State  "1"
   1867  ${EndIf}
   1868 
   1869  ; Setup the components.ini file for the Components Page
   1870  WriteINIStr "$PLUGINSDIR\components.ini" "Settings" NumFields "2"
   1871 
   1872  WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Type   "label"
   1873  WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Text   "$(OPTIONAL_COMPONENTS_DESC)"
   1874  WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Left   "0"
   1875  WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Right  "-1"
   1876  WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Top    "5"
   1877  WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Bottom "25"
   1878 
   1879  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Type   "checkbox"
   1880  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Text   "$(MAINTENANCE_SERVICE_CHECKBOX_DESC)"
   1881  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Left   "0"
   1882  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Right  "-1"
   1883  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Top    "27"
   1884  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Bottom "37"
   1885  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" State  "1"
   1886  WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Flags  "GROUP"
   1887 
   1888  ; Setup the extensions.ini file for the Custom Extensions Page
   1889  StrCpy $R9 0
   1890  StrCpy $R8 ${BST_CHECKED}
   1891 
   1892  ${If} ${FileExists} "$EXEDIR\core\distribution\setup.ini"
   1893    ${Do}
   1894      IntOp $R7 $R9 + 2
   1895 
   1896      ClearErrors
   1897      ReadINIStr $R6 "$EXEDIR\core\distribution\setup.ini" \
   1898        "OptionalExtensions" "extension.$R9.name.${AB_CD}"
   1899      ${If} ${Errors}
   1900        ClearErrors
   1901        ReadINIStr $R6 "$EXEDIR\core\distribution\setup.ini" \
   1902          "OptionalExtensions" "extension.$R9.name"
   1903      ${EndIf}
   1904 
   1905      ${If} ${Errors}
   1906        ${ExitDo}
   1907      ${EndIf}
   1908 
   1909      ; Each row moves down by 13 DLUs
   1910      IntOp $R2 $R9 * 13
   1911      IntOp $R2 $R2 + 21
   1912      IntOp $R1 $R2 + 10
   1913 
   1914      ClearErrors
   1915      ReadINIStr $R0 "$EXEDIR\core\distribution\setup.ini" \
   1916        "OptionalExtensions" "extension.$R9.checked"
   1917      ${If} ${Errors}
   1918        StrCpy $R0 ${BST_CHECKED}
   1919      ${ElseIf} $R0 == "0"
   1920        StrCpy $R8 ${BST_UNCHECKED}
   1921      ${EndIf}
   1922 
   1923      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" Type   "checkbox"
   1924      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" Text   "$R6"
   1925      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" Left   "11"
   1926      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" Right  "-1"
   1927      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" Top    "$R2"
   1928      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" Bottom "$R1"
   1929      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" State  "$R0"
   1930      WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R7" Flags  "NOTIFY"
   1931 
   1932      IntOp $R9 $R9 + 1
   1933    ${Loop}
   1934  ${EndIf}
   1935 
   1936  IntOp $R9 $R9 + 2
   1937 
   1938  WriteINIStr "$PLUGINSDIR\extensions.ini" "Settings" NumFields "$R9"
   1939 
   1940  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" Type   "checkbox"
   1941  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" Text   "$(OPTIONAL_EXTENSIONS_CHECKBOX_DESC)"
   1942  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" Left   "0"
   1943  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" Right  "-1"
   1944  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" Top    "5"
   1945  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" Bottom "15"
   1946  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" State  "$R8"
   1947  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field 1" Flags  "GROUP|NOTIFY"
   1948 
   1949  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R9" Type   "label"
   1950  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R9" Text   "$(OPTIONAL_EXTENSIONS_DESC)"
   1951  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R9" Left   "0"
   1952  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R9" Right  "-1"
   1953  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R9" Top    "-23"
   1954  WriteINIStr "$PLUGINSDIR\extensions.ini" "Field $R9" Bottom "-5"
   1955 
   1956  ; There must always be a core directory.
   1957  ${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8
   1958  SectionSetSize ${APP_IDX} $R5
   1959 
   1960  ; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
   1961  ; the user clicks the back button
   1962  StrCpy $hHeaderBitmap ""
   1963 FunctionEnd
   1964 
   1965 Function .onGUIEnd
   1966  ${OnEndCommon}
   1967  Call SendPing
   1968 FunctionEnd