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