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# CertCheck 8# InetBgDL 9# ShellLink 10# UAC 11 12; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs 13!verbose 3 14 15SetDatablockOptimize on 16SetCompress off 17CRCCheck on 18 19RequestExecutionLevel user 20 21Unicode true 22ManifestSupportedOS all 23ManifestDPIAware true 24 25!addplugindir ./ 26 27Var CheckboxSetAsDefault 28Var CheckboxShortcuts 29Var CheckboxSendPing 30Var CheckboxInstallMaintSvc 31Var CheckboxCleanupProfile 32 33Var FontFamilyName 34 35Var CanWriteToInstallDir 36Var HasRequiredSpaceAvailable 37Var IsDownloadFinished 38Var DownloadSizeBytes 39Var DownloadReset 40Var ExistingTopDir 41Var SpaceAvailableBytes 42Var InitialInstallDir 43Var HandleDownload 44Var CanSetAsDefault 45Var InstallCounterStep 46Var InstallTotalSteps 47Var ProgressCompleted 48Var UsingHighContrastMode 49 50Var ExitCode 51Var FirefoxLaunchCode 52 53Var StartDownloadPhaseTickCount 54; Since the Intro and Options pages can be displayed multiple times the total 55; seconds spent on each of these pages is reported. 56Var IntroPhaseSeconds 57Var OptionsPhaseSeconds 58; The tick count for the last download. 59Var StartLastDownloadTickCount 60; The number of seconds from the start of the download phase until the first 61; bytes are received. This is only recorded for first request so it is possible 62; to determine connection issues for the first request. 63Var DownloadFirstTransferSeconds 64; The last four tick counts are for the end of a phase in the installation page. 65Var EndDownloadPhaseTickCount 66Var EndPreInstallPhaseTickCount 67Var EndInstallPhaseTickCount 68Var EndFinishPhaseTickCount 69 70Var InitialInstallRequirementsCode 71Var ExistingProfile 72Var ExistingVersion 73Var ExistingBuildID 74Var DownloadedBytes 75Var DownloadRetryCount 76Var OpenedDownloadPage 77Var DownloadServerIP 78Var PostSigningData 79Var PreviousInstallDir 80Var ProfileCleanupPromptType 81Var AppLaunchWaitTickCount 82Var TimerHandle 83 84!define ARCH_X86 1 85!define ARCH_AMD64 2 86!define ARCH_AARCH64 3 87Var ArchToInstall 88 89; Uncomment the following to prevent pinging the metrics server when testing 90; the stub installer 91;!define STUB_DEBUG 92 93!define StubURLVersion "v8" 94 95; Successful install exit code 96!define ERR_SUCCESS 0 97 98/** 99 * The following errors prefixed with ERR_DOWNLOAD apply to the download phase. 100 */ 101; The download was cancelled by the user 102!define ERR_DOWNLOAD_CANCEL 10 103 104; Too many attempts to download. The maximum attempts is defined in 105; DownloadMaxRetries. 106!define ERR_DOWNLOAD_TOO_MANY_RETRIES 11 107 108/** 109 * The following errors prefixed with ERR_PREINSTALL apply to the pre-install 110 * check phase. 111 */ 112; Unable to acquire a file handle to the downloaded file 113!define ERR_PREINSTALL_INVALID_HANDLE 20 114 115; The downloaded file's certificate is not trusted by the certificate store. 116!define ERR_PREINSTALL_CERT_UNTRUSTED 21 117 118; The downloaded file's certificate attribute values were incorrect. 119!define ERR_PREINSTALL_CERT_ATTRIBUTES 22 120 121; The downloaded file's certificate is not trusted by the certificate store and 122; certificate attribute values were incorrect. 123!define ERR_PREINSTALL_CERT_UNTRUSTED_AND_ATTRIBUTES 23 124 125; Timed out while waiting for the certificate checks to run. 126!define ERR_PREINSTALL_CERT_TIMEOUT 24 127 128/** 129 * The following errors prefixed with ERR_INSTALL apply to the install phase. 130 */ 131; The installation timed out. The installation timeout is defined by the number 132; of progress steps defined in InstallTotalSteps and the install timer 133; interval defined in InstallIntervalMS 134!define ERR_INSTALL_TIMEOUT 30 135 136; Maximum times to retry the download before displaying an error 137!define DownloadMaxRetries 9 138 139; Interval before retrying to download. 3 seconds is used along with 10 140; attempted downloads (the first attempt along with 9 retries) to give a 141; minimum of 30 seconds or retrying before giving up. 142!define DownloadRetryIntervalMS 3000 143 144; Interval for the download timer 145!define DownloadIntervalMS 200 146 147; Timeout for the certificate check 148!define PreinstallCertCheckMaxWaitSec 30 149 150; Interval for the install timer 151!define InstallIntervalMS 100 152 153; Number of steps for the install progress. 154; This might not be enough when installing on a slow network drive so it will 155; fallback to downloading the full installer if it reaches this number. 156 157; Approximately 150 seconds with a 100 millisecond timer. 158!define InstallCleanTotalSteps 1500 159 160; Approximately 165 seconds with a 100 millisecond timer. 161!define InstallPaveOverTotalSteps 1650 162 163; Blurb duty cycle 164!define BlurbDisplayMS 19500 165!define BlurbBlankMS 500 166 167; Interval between checks for the application window and progress bar updates. 168!define AppLaunchWaitIntervalMS 100 169 170; Total time to wait for the application to start before just exiting. 171!define AppLaunchWaitTimeoutMS 10000 172 173; Maximum value of the download/install/launch progress bar, and the end values 174; for each individual stage. 175!define PROGRESS_BAR_TOTAL_STEPS 500 176!define PROGRESS_BAR_DOWNLOAD_END_STEP 300 177!define PROGRESS_BAR_INSTALL_END_STEP 475 178!define PROGRESS_BAR_APP_LAUNCH_END_STEP 500 179 180; Amount of physical memory required for the 64-bit build to be selected (2 GB). 181; Machines with this or less RAM get the 32-bit build, even with a 64-bit OS. 182!define RAM_NEEDED_FOR_64BIT 0x80000000 183 184; Attempt to elevate Standard Users in addition to users that 185; are a member of the Administrators group. 186!define NONADMIN_ELEVATE 187 188!define CONFIG_INI "config.ini" 189!define PARTNER_INI "$EXEDIR\partner.ini" 190 191!ifndef FILE_SHARE_READ 192 !define FILE_SHARE_READ 1 193!endif 194!ifndef GENERIC_READ 195 !define GENERIC_READ 0x80000000 196!endif 197!ifndef OPEN_EXISTING 198 !define OPEN_EXISTING 3 199!endif 200!ifndef INVALID_HANDLE_VALUE 201 !define INVALID_HANDLE_VALUE -1 202!endif 203 204!define DefaultInstDir32bit "$PROGRAMFILES32\${BrandFullName}" 205!define DefaultInstDir64bit "$PROGRAMFILES64\${BrandFullName}" 206 207!include "LogicLib.nsh" 208!include "FileFunc.nsh" 209!include "TextFunc.nsh" 210!include "WinVer.nsh" 211!include "WordFunc.nsh" 212 213!insertmacro GetParameters 214!insertmacro GetOptions 215!insertmacro LineFind 216!insertmacro StrFilter 217 218!include "locales.nsi" 219!include "branding.nsi" 220 221!include "defines.nsi" 222 223; Must be included after defines.nsi 224!include "locale-fonts.nsh" 225 226; The OFFICIAL define is a workaround to support different urls for Release and 227; Beta since they share the same branding when building with other branches that 228; set the update channel to beta. 229!ifdef OFFICIAL 230!ifdef BETA_UPDATE_CHANNEL 231!undef URLStubDownloadX86 232!undef URLStubDownloadAMD64 233!undef URLStubDownloadAArch64 234!define URLStubDownloadX86 "https://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-beta-latest" 235!define URLStubDownloadAMD64 "https://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-beta-latest" 236!define URLStubDownloadAArch64 "https://download.mozilla.org/?os=win64-aarch64&lang=${AB_CD}&product=firefox-beta-latest" 237!undef URLManualDownload 238!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=beta&installer_lang=${AB_CD}" 239!undef Channel 240!define Channel "beta" 241!endif 242!endif 243 244!include "common.nsh" 245 246!insertmacro CopyPostSigningData 247!insertmacro ElevateUAC 248!insertmacro GetLongPath 249!insertmacro GetPathFromString 250!insertmacro GetParent 251!insertmacro GetSingleInstallPath 252!insertmacro InitHashAppModelId 253!insertmacro IsUserAdmin 254!insertmacro RemovePrecompleteEntries 255!insertmacro SetBrandNameVars 256!insertmacro ITBL3Create 257!insertmacro UnloadUAC 258 259VIAddVersionKey "FileDescription" "${BrandShortName} Installer" 260VIAddVersionKey "OriginalFilename" "setup-stub.exe" 261 262Name "$BrandFullName" 263OutFile "setup-stub.exe" 264Icon "firefox64.ico" 265XPStyle on 266BrandingText " " 267ChangeUI IDD_INST "nsisui.exe" 268 269!ifdef ${AB_CD}_rtl 270 LoadLanguageFile "locale-rtl.nlf" 271!else 272 LoadLanguageFile "locale.nlf" 273!endif 274 275!include "nsisstrings.nlf" 276 277Caption "$(INSTALLER_WIN_CAPTION)" 278 279Page custom createProfileCleanup 280Page custom createInstall ; Download / Installation page 281 282Function .onInit 283 ; Remove the current exe directory from the search order. 284 ; This only effects LoadLibrary calls and not implicitly loaded DLLs. 285 System::Call 'kernel32::SetDllDirectoryW(w "")' 286 287 StrCpy $LANGUAGE 0 288 ; This macro is used to set the brand name variables but the ini file method 289 ; isn't supported for the stub installer. 290 ${SetBrandNameVars} "$PLUGINSDIR\ignored.ini" 291 292 ; Don't install on systems that don't support SSE2. The parameter value of 293 ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the 294 ; SSE2 instruction set is available. 295 System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7" 296 297 ; Windows NT 6.0 (Vista/Server 2008) and lower are not supported. 298 ${Unless} ${AtLeastWin7} 299 ${If} "$R7" == "0" 300 strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" 301 ${Else} 302 strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_MSG)" 303 ${EndIf} 304 MessageBox MB_OKCANCEL|MB_ICONSTOP "$R7" IDCANCEL +2 305 ExecShell "open" "${URLSystemRequirements}" 306 Quit 307 ${EndUnless} 308 309 ; SSE2 CPU support 310 ${If} "$R7" == "0" 311 MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_CPU_MSG)" IDCANCEL +2 312 ExecShell "open" "${URLSystemRequirements}" 313 Quit 314 ${EndIf} 315 316 Call GetArchToInstall 317 ${If} $ArchToInstall == ${ARCH_AARCH64} 318 ${OrIf} $ArchToInstall == ${ARCH_AMD64} 319 StrCpy $INSTDIR "${DefaultInstDir64bit}" 320 ${Else} 321 StrCpy $INSTDIR "${DefaultInstDir32bit}" 322 ${EndIf} 323 324 ; Require elevation if the user can elevate 325 ${ElevateUAC} 326 327 ; If we have any existing installation, use its location as the default 328 ; path for this install, even if it's not the same architecture. 329 SetRegView 32 330 SetShellVarContext all ; Set SHCTX to HKLM 331 ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9 332 333 ${If} "$R9" == "false" 334 ${If} ${IsNativeAMD64} 335 ${OrIf} ${IsNativeARM64} 336 SetRegView 64 337 ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9 338 ${EndIf} 339 ${EndIf} 340 341 ${If} "$R9" == "false" 342 SetShellVarContext current ; Set SHCTX to HKCU 343 ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9 344 ${EndIf} 345 346 StrCpy $PreviousInstallDir "" 347 ${If} "$R9" != "false" 348 StrCpy $PreviousInstallDir "$R9" 349 StrCpy $INSTDIR "$PreviousInstallDir" 350 ${EndIf} 351 352 ; Used to determine if the default installation directory was used. 353 StrCpy $InitialInstallDir "$INSTDIR" 354 355 ClearErrors 356 WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \ 357 "Write Test" 358 359 ; Only display set as default when there is write access to HKLM and on Win7 360 ; and below. 361 ${If} ${Errors} 362 ${OrIf} ${AtLeastWin8} 363 StrCpy $CanSetAsDefault "false" 364 ${Else} 365 DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" 366 StrCpy $CanSetAsDefault "true" 367 ${EndIf} 368 StrCpy $CheckboxSetAsDefault "0" 369 370 ; Initialize the majority of variables except those that need to be reset 371 ; when a page is displayed. 372 StrCpy $ExitCode "${ERR_DOWNLOAD_CANCEL}" 373 StrCpy $IntroPhaseSeconds "0" 374 StrCpy $OptionsPhaseSeconds "0" 375 StrCpy $EndPreInstallPhaseTickCount "0" 376 StrCpy $EndInstallPhaseTickCount "0" 377 StrCpy $StartDownloadPhaseTickCount "0" 378 StrCpy $EndDownloadPhaseTickCount "0" 379 StrCpy $InitialInstallRequirementsCode "" 380 StrCpy $IsDownloadFinished "" 381 StrCpy $FirefoxLaunchCode "0" 382 StrCpy $CheckboxShortcuts "1" 383 StrCpy $CheckboxSendPing "1" 384 StrCpy $CheckboxCleanupProfile "0" 385 StrCpy $ProgressCompleted "0" 386!ifdef MOZ_MAINTENANCE_SERVICE 387 ; We can only install the maintenance service if the user is an admin. 388 Call IsUserAdmin 389 Pop $0 390 ${If} "$0" == "true" 391 StrCpy $CheckboxInstallMaintSvc "1" 392 ${Else} 393 StrCpy $CheckboxInstallMaintSvc "0" 394 ${EndIf} 395!else 396 StrCpy $CheckboxInstallMaintSvc "0" 397!endif 398 399 StrCpy $FontFamilyName "" 400!ifdef FONT_FILE1 401 ${If} ${FileExists} "$FONTS\${FONT_FILE1}" 402 StrCpy $FontFamilyName "${FONT_NAME1}" 403 ${EndIf} 404!endif 405 406!ifdef FONT_FILE2 407 ${If} $FontFamilyName == "" 408 ${AndIf} ${FileExists} "$FONTS\${FONT_FILE2}" 409 StrCpy $FontFamilyName "${FONT_NAME2}" 410 ${EndIf} 411!endif 412 413 ${If} $FontFamilyName == "" 414 StrCpy $FontFamilyName "$(^Font)" 415 ${EndIf} 416 417 InitPluginsDir 418 File /oname=$PLUGINSDIR\bgstub.jpg "bgstub.jpg" 419 420 ; Detect whether the machine is running with a high contrast theme. 421 ; We'll hide our background images in that case, both because they don't 422 ; always render properly and also to improve the contrast. 423 System::Call '*(i 12, i 0, p 0) p . r0' 424 ; 0x42 == SPI_GETHIGHCONTRAST 425 System::Call 'user32::SystemParametersInfoW(i 0x42, i 0, p r0, i 0)' 426 System::Call '*$0(i, i . r1, p)' 427 System::Free $0 428 IntOp $UsingHighContrastMode $1 & 1 429 430 SetShellVarContext all ; Set SHCTX to All Users 431 ; If the user doesn't have write access to the installation directory set 432 ; the installation directory to a subdirectory of the user's local 433 ; application directory (e.g. non-roaming). 434 Call CanWrite 435 ${If} "$CanWriteToInstallDir" == "false" 436 ${GetLocalAppDataFolder} $0 437 StrCpy $INSTDIR "$0\${BrandFullName}\" 438 Call CanWrite 439 ${EndIf} 440 441 Call CheckSpace 442 443 ${If} ${FileExists} "$INSTDIR" 444 ; Always display the long path if the path exists. 445 ${GetLongPath} "$INSTDIR" $INSTDIR 446 ${EndIf} 447 448 ; Check whether the install requirements are satisfied using the default 449 ; values for metrics. 450 ${If} "$InitialInstallRequirementsCode" == "" 451 ${If} "$CanWriteToInstallDir" != "true" 452 ${AndIf} "$HasRequiredSpaceAvailable" != "true" 453 StrCpy $InitialInstallRequirementsCode "1" 454 ${ElseIf} "$CanWriteToInstallDir" != "true" 455 StrCpy $InitialInstallRequirementsCode "2" 456 ${ElseIf} "$HasRequiredSpaceAvailable" != "true" 457 StrCpy $InitialInstallRequirementsCode "3" 458 ${Else} 459 StrCpy $InitialInstallRequirementsCode "0" 460 ${EndIf} 461 ${EndIf} 462 463 Call CanWrite 464 ${If} "$CanWriteToInstallDir" == "false" 465 MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_WRITE_ACCESS_QUIT)$\n$\n$INSTDIR" 466 Quit 467 ${EndIf} 468 469 Call CheckSpace 470 ${If} "$HasRequiredSpaceAvailable" == "false" 471 MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_DISK_SPACE_QUIT)" 472 Quit 473 ${EndIf} 474 475 ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" 476 477 File /oname=$PLUGINSDIR\stub_common.css "stub_common.css" 478 File /oname=$PLUGINSDIR\stub_common.js "stub_common.js" 479FunctionEnd 480 481; .onGUIInit isn't needed except for RTL locales 482!ifdef ${AB_CD}_rtl 483Function .onGUIInit 484 ${MakeWindowRTL} $HWNDPARENT 485FunctionEnd 486!endif 487 488Function .onGUIEnd 489 Delete "$PLUGINSDIR\_temp" 490 Delete "$PLUGINSDIR\download.exe" 491 Delete "$PLUGINSDIR\${CONFIG_INI}" 492 493 ${UnloadUAC} 494FunctionEnd 495 496Function .onUserAbort 497 WebBrowser::CancelTimer $TimerHandle 498 499 ${If} "$IsDownloadFinished" != "" 500 ; Go ahead and cancel the download so it doesn't keep running while this 501 ; prompt is up. We'll resume it if the user decides to continue. 502 InetBgDL::Get /RESET /END 503 504 ${ShowTaskDialog} $(STUB_CANCEL_PROMPT_HEADING) \ 505 $(STUB_CANCEL_PROMPT_MESSAGE) \ 506 $(STUB_CANCEL_PROMPT_BUTTON_CONTINUE) \ 507 $(STUB_CANCEL_PROMPT_BUTTON_EXIT) 508 Pop $0 509 ${If} $0 == 1002 510 ; The cancel button was clicked 511 Call LaunchHelpPage 512 Call SendPing 513 ${Else} 514 ; Either the continue button was clicked or the dialog was dismissed 515 Call StartDownload 516 ${EndIf} 517 ${Else} 518 Call SendPing 519 ${EndIf} 520 521 ; Aborting the abort will allow SendPing to hide the installer window and 522 ; close the installer after it sends the metrics ping, or allow us to just go 523 ; back to installing if that's what the user selected. 524 Abort 525FunctionEnd 526 527!macro _RegisterAllCustomFunctions 528 GetFunctionAddress $0 getUIString 529 WebBrowser::RegisterCustomFunction $0 "getUIString" 530 531 GetFunctionAddress $0 getTextDirection 532 WebBrowser::RegisterCustomFunction $0 "getTextDirection" 533 534 GetFunctionAddress $0 getFontName 535 WebBrowser::RegisterCustomFunction $0 "getFontName" 536 537 GetFunctionAddress $0 getIsHighContrast 538 WebBrowser::RegisterCustomFunction $0 "getIsHighContrast" 539 540 GetFunctionAddress $0 gotoInstallPage 541 WebBrowser::RegisterCustomFunction $0 "gotoInstallPage" 542 543 GetFunctionAddress $0 getProgressBarPercent 544 WebBrowser::RegisterCustomFunction $0 "getProgressBarPercent" 545!macroend 546!define RegisterAllCustomFunctions "!insertmacro _RegisterAllCustomFunctions" 547 548!macro _StartTimer _INTERVAL_MS _FUNCTION_NAME 549 Push $0 550 GetFunctionAddress $0 ${_FUNCTION_NAME} 551 WebBrowser::CreateTimer $0 ${_INTERVAL_MS} 552 Pop $TimerHandle 553 Pop $0 554!macroend 555!define StartTimer "!insertmacro _StartTimer" 556 557Function gotoInstallPage 558 Pop $0 559 StrCpy $CheckboxCleanupProfile $0 560 561 StrCpy $R9 1 562 Call RelativeGotoPage 563 Push $0 564FunctionEnd 565 566Function getProgressBarPercent 567 ; Custom functions always get one parameter, which we don't use here. 568 ; But we will use $0 as a scratch accumulator register. 569 Pop $0 570 ; This math is getting the progess bar completion fraction and converting it 571 ; to a percentage, but we implement that with the operations in the reverse 572 ; of the intuitive order so that our integer math doesn't truncate to zero. 573 IntOp $0 $ProgressCompleted * 100 574 IntOp $0 $0 / ${PROGRESS_BAR_TOTAL_STEPS} 575 Push $0 576FunctionEnd 577 578Function getTextDirection 579 Pop $0 580 !ifdef ${AB_CD}_rtl 581 Push "rtl" 582 !else 583 Push "ltr" 584 !endif 585FunctionEnd 586 587Function getFontName 588 Pop $0 589 Push $FontFamilyName 590FunctionEnd 591 592Function getIsHighContrast 593 Pop $0 594 Push $UsingHighContrastMode 595FunctionEnd 596 597Function getUIString 598 Pop $0 599 ${Select} $0 600 ${Case} "cleanup_header" 601 ${If} $ProfileCleanupPromptType == 1 602 Push "$(STUB_CLEANUP_REINSTALL_HEADER2)" 603 ${Else} 604 Push "$(STUB_CLEANUP_PAVEOVER_HEADER2)" 605 ${EndIf} 606 ${Case} "cleanup_button" 607 ${If} $ProfileCleanupPromptType == 1 608 Push "$(STUB_CLEANUP_REINSTALL_BUTTON2)" 609 ${Else} 610 Push "$(STUB_CLEANUP_PAVEOVER_BUTTON2)" 611 ${EndIf} 612 ${Case} "cleanup_checkbox" 613 Push "$(STUB_CLEANUP_CHECKBOX_LABEL2)" 614 ${Case} "installing_header" 615 Push "$(STUB_INSTALLING_HEADLINE2)" 616 ${Case} "installing_label" 617 Push "$(STUB_INSTALLING_LABEL2)" 618 ${Case} "installing_content" 619 Push "$(STUB_INSTALLING_BODY2)" 620 ${Case} "installing_blurb_0" 621 Push "$(STUB_BLURB_FIRST1)" 622 ${Case} "installing_blurb_1" 623 Push "$(STUB_BLURB_SECOND1)" 624 ${Case} "installing_blurb_2" 625 Push "$(STUB_BLURB_THIRD1)" 626 ${Case} "global_footer" 627 Push "$(STUB_BLURB_FOOTER2)" 628 ${Default} 629 Push "" 630 ${EndSelect} 631FunctionEnd 632 633Function createProfileCleanup 634 Call ShouldPromptForProfileCleanup 635 636 ${If} $ProfileCleanupPromptType == 0 637 StrCpy $CheckboxCleanupProfile 0 638 Abort ; Skip this page 639 ${EndIf} 640 641 ${RegisterAllCustomFunctions} 642 643 File /oname=$PLUGINSDIR\profile_cleanup.html "profile_cleanup.html" 644 File /oname=$PLUGINSDIR\profile_cleanup_page.css "profile_cleanup_page.css" 645 File /oname=$PLUGINSDIR\profile_cleanup.js "profile_cleanup.js" 646 WebBrowser::ShowPage "$PLUGINSDIR\profile_cleanup.html" 647FunctionEnd 648 649Function createInstall 650 GetDlgItem $0 $HWNDPARENT 1 ; Install button 651 EnableWindow $0 0 652 ShowWindow $0 ${SW_HIDE} 653 654 GetDlgItem $0 $HWNDPARENT 3 ; Back button 655 EnableWindow $0 0 656 ShowWindow $0 ${SW_HIDE} 657 658 GetDlgItem $0 $HWNDPARENT 2 ; Cancel button 659 ; Hide the Cancel button, but don't disable it (or else it won't be possible 660 ; to close the window) 661 ShowWindow $0 ${SW_HIDE} 662 663 ; Get keyboard focus on the parent 664 System::Call "user32::SetFocus(p$HWNDPARENT)" 665 666 ; Set $DownloadReset to true so the first download tick count is measured. 667 StrCpy $DownloadReset "true" 668 StrCpy $IsDownloadFinished "false" 669 StrCpy $DownloadRetryCount "0" 670 StrCpy $DownloadedBytes "0" 671 StrCpy $StartLastDownloadTickCount "" 672 StrCpy $DownloadFirstTransferSeconds "" 673 StrCpy $OpenedDownloadPage "0" 674 675 ClearErrors 676 ReadINIStr $ExistingVersion "$INSTDIR\application.ini" "App" "Version" 677 ${If} ${Errors} 678 StrCpy $ExistingVersion "0" 679 ${EndIf} 680 681 ClearErrors 682 ReadINIStr $ExistingBuildID "$INSTDIR\application.ini" "App" "BuildID" 683 ${If} ${Errors} 684 StrCpy $ExistingBuildID "0" 685 ${EndIf} 686 687 ${GetLocalAppDataFolder} $0 688 ${If} ${FileExists} "$0\Mozilla\Firefox" 689 StrCpy $ExistingProfile "1" 690 ${Else} 691 StrCpy $ExistingProfile "0" 692 ${EndIf} 693 694 StrCpy $DownloadServerIP "" 695 696 System::Call "kernel32::GetTickCount()l .s" 697 Pop $StartDownloadPhaseTickCount 698 699 ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log" 700 StrCpy $InstallTotalSteps ${InstallPaveOverTotalSteps} 701 ${Else} 702 StrCpy $InstallTotalSteps ${InstallCleanTotalSteps} 703 ${EndIf} 704 705 ${ITBL3Create} 706 ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}" 707 708 ; Make sure the file we're about to try to download to doesn't already exist, 709 ; so we don't end up trying to "resume" on top of the wrong file. 710 Delete "$PLUGINSDIR\download.exe" 711 712 ${StartTimer} ${DownloadIntervalMS} StartDownload 713 714 ${RegisterAllCustomFunctions} 715 716 File /oname=$PLUGINSDIR\installing.html "installing.html" 717 File /oname=$PLUGINSDIR\installing_page.css "installing_page.css" 718 File /oname=$PLUGINSDIR\installing.js "installing.js" 719 WebBrowser::ShowPage "$PLUGINSDIR\installing.html" 720FunctionEnd 721 722Function StartDownload 723 WebBrowser::CancelTimer $TimerHandle 724 725 Call GetDownloadURL 726 Pop $0 727 InetBgDL::Get "$0" "$PLUGINSDIR\download.exe" \ 728 /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END 729 730 ${StartTimer} ${DownloadIntervalMS} OnDownload 731 732 ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}" 733 RmDir /r "$INSTDIR\${TO_BE_DELETED}" 734 ${EndIf} 735FunctionEnd 736 737Function SetProgressBars 738 ${ITBL3SetProgressValue} "$ProgressCompleted" "${PROGRESS_BAR_TOTAL_STEPS}" 739FunctionEnd 740 741Function OnDownload 742 InetBgDL::GetStats 743 # $0 = HTTP status code, 0=Completed 744 # $1 = Completed files 745 # $2 = Remaining files 746 # $3 = Number of downloaded bytes for the current file 747 # $4 = Size of current file (Empty string if the size is unknown) 748 # /RESET must be used if status $0 > 299 (e.g. failure), even if resuming 749 # When status is $0 =< 299 it is handled by InetBgDL 750 StrCpy $DownloadServerIP "$5" 751 ${If} $0 > 299 752 WebBrowser::CancelTimer $TimerHandle 753 IntOp $DownloadRetryCount $DownloadRetryCount + 1 754 ${If} $DownloadRetryCount >= ${DownloadMaxRetries} 755 StrCpy $ExitCode "${ERR_DOWNLOAD_TOO_MANY_RETRIES}" 756 ; Use a timer so the UI has a chance to update 757 ${StartTimer} ${InstallIntervalMS} DisplayDownloadError 758 Return 759 ${EndIf} 760 761 ; 1000 is a special code meaning InetBgDL lost the connection before it got 762 ; all the bytes it was expecting. We'll try to resume the transfer in that 763 ; case (assuming we aren't out of retries), so don't treat it as a reset 764 ; or clear the progress bar. 765 ${If} $0 != 1000 766 ${If} "$DownloadReset" != "true" 767 StrCpy $DownloadedBytes "0" 768 ${ITBL3SetProgressState} "${TBPF_INDETERMINATE}" 769 ${EndIf} 770 StrCpy $DownloadSizeBytes "" 771 StrCpy $DownloadReset "true" 772 Delete "$PLUGINSDIR\download.exe" 773 ${EndIf} 774 775 InetBgDL::Get /RESET /END 776 ${StartTimer} ${DownloadRetryIntervalMS} StartDownload 777 Return 778 ${EndIf} 779 780 ${If} "$DownloadReset" == "true" 781 System::Call "kernel32::GetTickCount()l .s" 782 Pop $StartLastDownloadTickCount 783 StrCpy $DownloadReset "false" 784 ; The seconds elapsed from the start of the download phase until the first 785 ; bytes are received are only recorded for the first request so it is 786 ; possible to determine connection issues for the first request. 787 ${If} "$DownloadFirstTransferSeconds" == "" 788 ; Get the seconds elapsed from the start of the download phase until the 789 ; first bytes are received. 790 ${GetSecondsElapsed} "$StartDownloadPhaseTickCount" "$StartLastDownloadTickCount" $DownloadFirstTransferSeconds 791 ${EndIf} 792 ${EndIf} 793 794 ${If} "$DownloadSizeBytes" == "" 795 ${AndIf} "$4" != "" 796 StrCpy $DownloadSizeBytes "$4" 797 StrCpy $ProgressCompleted 0 798 ${EndIf} 799 800 ; Don't update the status until after the download starts 801 ${If} $2 != 0 802 ${AndIf} "$4" == "" 803 Return 804 ${EndIf} 805 806 ${If} $IsDownloadFinished != "true" 807 ${If} $2 == 0 808 WebBrowser::CancelTimer $TimerHandle 809 StrCpy $IsDownloadFinished "true" 810 System::Call "kernel32::GetTickCount()l .s" 811 Pop $EndDownloadPhaseTickCount 812 813 ${If} "$DownloadSizeBytes" == "" 814 ; It's possible for the download to finish before we were able to 815 ; get the size while it was downloading, and InetBgDL doesn't report 816 ; it afterwards. Use the size of the finished file. 817 ClearErrors 818 FileOpen $5 "$PLUGINSDIR\download.exe" r 819 ${IfNot} ${Errors} 820 FileSeek $5 0 END $DownloadSizeBytes 821 FileClose $5 822 ${EndIf} 823 ${EndIf} 824 StrCpy $DownloadedBytes "$DownloadSizeBytes" 825 826 ; Update the progress bars first in the UI change so they take affect 827 ; before other UI changes. 828 StrCpy $ProgressCompleted "${PROGRESS_BAR_DOWNLOAD_END_STEP}" 829 Call SetProgressBars 830 831 ; Disable the Cancel button during the install 832 GetDlgItem $5 $HWNDPARENT 2 833 EnableWindow $5 0 834 835 ; Open a handle to prevent modification of the full installer 836 StrCpy $R9 "${INVALID_HANDLE_VALUE}" 837 System::Call 'kernel32::CreateFileW(w "$PLUGINSDIR\download.exe", \ 838 i ${GENERIC_READ}, \ 839 i ${FILE_SHARE_READ}, i 0, \ 840 i ${OPEN_EXISTING}, i 0, i 0) i .R9' 841 StrCpy $HandleDownload "$R9" 842 843 ${If} $HandleDownload == ${INVALID_HANDLE_VALUE} 844 StrCpy $ExitCode "${ERR_PREINSTALL_INVALID_HANDLE}" 845 System::Call "kernel32::GetTickCount()l .s" 846 Pop $EndPreInstallPhaseTickCount 847 ; Use a timer so the UI has a chance to update 848 ${StartTimer} ${InstallIntervalMS} DisplayDownloadError 849 ${Else} 850 CertCheck::CheckPETrustAndInfoAsync "$PLUGINSDIR\download.exe" \ 851 "${CertNameDownload}" "${CertIssuerDownload}" 852 ${StartTimer} ${DownloadIntervalMS} OnCertCheck 853 ${EndIf} 854 ${Else} 855 StrCpy $DownloadedBytes "$3" 856 System::Int64Op $DownloadedBytes * ${PROGRESS_BAR_DOWNLOAD_END_STEP} 857 Pop $ProgressCompleted 858 System::Int64Op $ProgressCompleted / $DownloadSizeBytes 859 Pop $ProgressCompleted 860 Call SetProgressBars 861 ${EndIf} 862 ${EndIf} 863FunctionEnd 864 865Function OnCertCheck 866 System::Call "kernel32::GetTickCount()l .s" 867 Pop $EndPreInstallPhaseTickCount 868 869 CertCheck::GetStatus 870 Pop $0 871 ${If} $0 == 0 872 ${GetSecondsElapsed} "$EndDownloadPhaseTickCount" "$EndPreInstallPhaseTickCount" $0 873 ${If} $0 >= ${PreinstallCertCheckMaxWaitSec} 874 WebBrowser::CancelTimer $TimerHandle 875 StrCpy $ExitCode "${ERR_PREINSTALL_CERT_TIMEOUT}" 876 ; Use a timer so the UI has a chance to update 877 ${StartTimer} ${InstallIntervalMS} DisplayDownloadError 878 ${EndIf} 879 Return 880 ${EndIf} 881 Pop $0 882 Pop $1 883 884 ${If} $0 == 0 885 ${AndIf} $1 == 0 886 StrCpy $ExitCode "${ERR_PREINSTALL_CERT_UNTRUSTED_AND_ATTRIBUTES}" 887 ${ElseIf} $0 == 0 888 StrCpy $ExitCode "${ERR_PREINSTALL_CERT_UNTRUSTED}" 889 ${ElseIf} $1 == 0 890 StrCpy $ExitCode "${ERR_PREINSTALL_CERT_ATTRIBUTES}" 891 ${EndIf} 892 893 WebBrowser::CancelTimer $TimerHandle 894 895 ${If} $0 == 0 896 ${OrIf} $1 == 0 897 ; Use a timer so the UI has a chance to update 898 ${StartTimer} ${InstallIntervalMS} DisplayDownloadError 899 Return 900 ${EndIf} 901 902 Call LaunchFullInstaller 903FunctionEnd 904 905Function LaunchFullInstaller 906 ; Instead of extracting the files we use the downloaded installer to 907 ; install in case it needs to perform operations that the stub doesn't 908 ; know about. 909 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "InstallDirectoryPath" "$INSTDIR" 910 ; Don't create the QuickLaunch or Taskbar shortcut from the launched installer 911 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "QuickLaunchShortcut" "false" 912 913 ; Always create a start menu shortcut, so the user always has some way 914 ; to access the application. 915 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "StartMenuShortcuts" "true" 916 917 ; Either avoid or force adding a taskbar pin and desktop shortcut 918 ; based on the checkbox value. 919 ${If} $CheckboxShortcuts == 0 920 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "false" 921 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "false" 922 ${Else} 923 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "true" 924 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "true" 925 ${EndIf} 926 927!ifdef MOZ_MAINTENANCE_SERVICE 928 ${If} $CheckboxInstallMaintSvc == 1 929 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "true" 930 ${Else} 931 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "false" 932 ${EndIf} 933!else 934 WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "MaintenanceService" "false" 935!endif 936 937 ; Delete the taskbar shortcut history to ensure we do the right thing based on 938 ; the config file above. 939 ${GetShortcutsLogPath} $0 940 Delete "$0" 941 942 ${RemovePrecompleteEntries} "false" 943 944 ; Delete the install.log and let the full installer create it. When the 945 ; installer closes it we can detect that it has completed. 946 Delete "$INSTDIR\install.log" 947 948 ; Delete firefox.exe.moz-upgrade and firefox.exe.moz-delete if it exists 949 ; since it being present will require an OS restart for the full 950 ; installer. 951 Delete "$INSTDIR\${FileMainEXE}.moz-upgrade" 952 Delete "$INSTDIR\${FileMainEXE}.moz-delete" 953 954 System::Call "kernel32::GetTickCount()l .s" 955 Pop $EndPreInstallPhaseTickCount 956 957 Exec "$\"$PLUGINSDIR\download.exe$\" /LaunchedFromStub /INI=$PLUGINSDIR\${CONFIG_INI}" 958 ${StartTimer} ${InstallIntervalMS} CheckInstall 959FunctionEnd 960 961Function SendPing 962 HideWindow 963 964 ${If} $CheckboxSendPing == 1 965 ; Get the tick count for the completion of all phases. 966 System::Call "kernel32::GetTickCount()l .s" 967 Pop $EndFinishPhaseTickCount 968 969 ; When the value of $IsDownloadFinished is false the download was started 970 ; but didn't finish. In this case the tick count stored in 971 ; $EndFinishPhaseTickCount is used to determine how long the download was 972 ; in progress. 973 ${If} "$IsDownloadFinished" == "false" 974 StrCpy $EndDownloadPhaseTickCount "$EndFinishPhaseTickCount" 975 ; Cancel the download in progress 976 InetBgDL::Get /RESET /END 977 ${EndIf} 978 979 980 ; When $DownloadFirstTransferSeconds equals an empty string the download 981 ; never successfully started so set the value to 0. It will be possible to 982 ; determine that the download didn't successfully start from the seconds for 983 ; the last download. 984 ${If} "$DownloadFirstTransferSeconds" == "" 985 StrCpy $DownloadFirstTransferSeconds "0" 986 ${EndIf} 987 988 ; When $StartLastDownloadTickCount equals an empty string the download never 989 ; successfully started so set the value to $EndDownloadPhaseTickCount to 990 ; compute the correct value. 991 ${If} $StartLastDownloadTickCount == "" 992 ; This could happen if the download never successfully starts 993 StrCpy $StartLastDownloadTickCount "$EndDownloadPhaseTickCount" 994 ${EndIf} 995 996 ; When $EndPreInstallPhaseTickCount equals 0 the installation phase was 997 ; never completed so set its value to $EndFinishPhaseTickCount to compute 998 ; the correct value. 999 ${If} "$EndPreInstallPhaseTickCount" == "0" 1000 StrCpy $EndPreInstallPhaseTickCount "$EndFinishPhaseTickCount" 1001 ${EndIf} 1002 1003 ; When $EndInstallPhaseTickCount equals 0 the installation phase was never 1004 ; completed so set its value to $EndFinishPhaseTickCount to compute the 1005 ; correct value. 1006 ${If} "$EndInstallPhaseTickCount" == "0" 1007 StrCpy $EndInstallPhaseTickCount "$EndFinishPhaseTickCount" 1008 ${EndIf} 1009 1010 ; Get the seconds elapsed from the start of the download phase to the end of 1011 ; the download phase. 1012 ${GetSecondsElapsed} "$StartDownloadPhaseTickCount" "$EndDownloadPhaseTickCount" $0 1013 1014 ; Get the seconds elapsed from the start of the last download to the end of 1015 ; the last download. 1016 ${GetSecondsElapsed} "$StartLastDownloadTickCount" "$EndDownloadPhaseTickCount" $1 1017 1018 ; Get the seconds elapsed from the end of the download phase to the 1019 ; completion of the pre-installation check phase. 1020 ${GetSecondsElapsed} "$EndDownloadPhaseTickCount" "$EndPreInstallPhaseTickCount" $2 1021 1022 ; Get the seconds elapsed from the end of the pre-installation check phase 1023 ; to the completion of the installation phase. 1024 ${GetSecondsElapsed} "$EndPreInstallPhaseTickCount" "$EndInstallPhaseTickCount" $3 1025 1026 ; Get the seconds elapsed from the end of the installation phase to the 1027 ; completion of all phases. 1028 ${GetSecondsElapsed} "$EndInstallPhaseTickCount" "$EndFinishPhaseTickCount" $4 1029 1030 ${If} $ArchToInstall == ${ARCH_AMD64} 1031 ${OrIf} $ArchToInstall == ${ARCH_AARCH64} 1032 StrCpy $R0 "1" 1033 ${Else} 1034 StrCpy $R0 "0" 1035 ${EndIf} 1036 1037 ${If} ${IsNativeAMD64} 1038 ${OrIf} ${IsNativeARM64} 1039 StrCpy $R1 "1" 1040 ${Else} 1041 StrCpy $R1 "0" 1042 ${EndIf} 1043 1044 ; Though these values are sometimes incorrect due to bug 444664 it happens 1045 ; so rarely it isn't worth working around it by reading the registry values. 1046 ${WinVerGetMajor} $5 1047 ${WinVerGetMinor} $6 1048 ${WinVerGetBuild} $7 1049 ${WinVerGetServicePackLevel} $8 1050 ${If} ${IsServerOS} 1051 StrCpy $9 "1" 1052 ${Else} 1053 StrCpy $9 "0" 1054 ${EndIf} 1055 1056 ${If} "$ExitCode" == "${ERR_SUCCESS}" 1057 ReadINIStr $R5 "$INSTDIR\application.ini" "App" "Version" 1058 ReadINIStr $R6 "$INSTDIR\application.ini" "App" "BuildID" 1059 ${Else} 1060 StrCpy $R5 "0" 1061 StrCpy $R6 "0" 1062 ${EndIf} 1063 1064 ; Whether installed into the default installation directory 1065 ${GetLongPath} "$INSTDIR" $R7 1066 ${GetLongPath} "$InitialInstallDir" $R8 1067 ${If} "$R7" == "$R8" 1068 StrCpy $R7 "1" 1069 ${Else} 1070 StrCpy $R7 "0" 1071 ${EndIf} 1072 1073 ClearErrors 1074 WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \ 1075 "Write Test" 1076 ${If} ${Errors} 1077 StrCpy $R8 "0" 1078 ${Else} 1079 DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" 1080 StrCpy $R8 "1" 1081 ${EndIf} 1082 1083 ${If} "$DownloadServerIP" == "" 1084 StrCpy $DownloadServerIP "Unknown" 1085 ${EndIf} 1086 1087 StrCpy $R2 "" 1088 SetShellVarContext current ; Set SHCTX to the current user 1089 ReadRegStr $R2 HKCU "Software\Classes\http\shell\open\command" "" 1090 ${If} $R2 != "" 1091 ${GetPathFromString} "$R2" $R2 1092 ${GetParent} "$R2" $R3 1093 ${GetLongPath} "$R3" $R3 1094 ${If} $R3 == $INSTDIR 1095 StrCpy $R2 "1" ; This Firefox install is set as default. 1096 ${Else} 1097 StrCpy $R2 "$R2" "" -11 # length of firefox.exe 1098 ${If} "$R2" == "${FileMainEXE}" 1099 StrCpy $R2 "2" ; Another Firefox install is set as default. 1100 ${Else} 1101 StrCpy $R2 "0" 1102 ${EndIf} 1103 ${EndIf} 1104 ${Else} 1105 StrCpy $R2 "0" ; Firefox is not set as default. 1106 ${EndIf} 1107 1108 ${If} "$R2" == "0" 1109 StrCpy $R3 "" 1110 ReadRegStr $R2 HKLM "Software\Classes\http\shell\open\command" "" 1111 ${If} $R2 != "" 1112 ${GetPathFromString} "$R2" $R2 1113 ${GetParent} "$R2" $R3 1114 ${GetLongPath} "$R3" $R3 1115 ${If} $R3 == $INSTDIR 1116 StrCpy $R2 "1" ; This Firefox install is set as default. 1117 ${Else} 1118 StrCpy $R2 "$R2" "" -11 # length of firefox.exe 1119 ${If} "$R2" == "${FileMainEXE}" 1120 StrCpy $R2 "2" ; Another Firefox install is set as default. 1121 ${Else} 1122 StrCpy $R2 "0" 1123 ${EndIf} 1124 ${EndIf} 1125 ${Else} 1126 StrCpy $R2 "0" ; Firefox is not set as default. 1127 ${EndIf} 1128 ${EndIf} 1129 1130 ${If} $CanSetAsDefault == "true" 1131 ${If} $CheckboxSetAsDefault == "1" 1132 StrCpy $R3 "2" 1133 ${Else} 1134 StrCpy $R3 "3" 1135 ${EndIf} 1136 ${Else} 1137 ${If} ${AtLeastWin8} 1138 StrCpy $R3 "1" 1139 ${Else} 1140 StrCpy $R3 "0" 1141 ${EndIf} 1142 ${EndIf} 1143 1144!ifdef STUB_DEBUG 1145 MessageBox MB_OK "${BaseURLStubPing} \ 1146 $\nStub URL Version = ${StubURLVersion}${StubURLVersionAppend} \ 1147 $\nBuild Channel = ${Channel} \ 1148 $\nUpdate Channel = ${UpdateChannel} \ 1149 $\nLocale = ${AB_CD} \ 1150 $\nFirefox x64 = $R0 \ 1151 $\nRunning x64 Windows = $R1 \ 1152 $\nMajor = $5 \ 1153 $\nMinor = $6 \ 1154 $\nBuild = $7 \ 1155 $\nServicePack = $8 \ 1156 $\nIsServer = $9 \ 1157 $\nExit Code = $ExitCode \ 1158 $\nFirefox Launch Code = $FirefoxLaunchCode \ 1159 $\nDownload Retry Count = $DownloadRetryCount \ 1160 $\nDownloaded Bytes = $DownloadedBytes \ 1161 $\nDownload Size Bytes = $DownloadSizeBytes \ 1162 $\nIntroduction Phase Seconds = $IntroPhaseSeconds \ 1163 $\nOptions Phase Seconds = $OptionsPhaseSeconds \ 1164 $\nDownload Phase Seconds = $0 \ 1165 $\nLast Download Seconds = $1 \ 1166 $\nDownload First Transfer Seconds = $DownloadFirstTransferSeconds \ 1167 $\nPreinstall Phase Seconds = $2 \ 1168 $\nInstall Phase Seconds = $3 \ 1169 $\nFinish Phase Seconds = $4 \ 1170 $\nInitial Install Requirements Code = $InitialInstallRequirementsCode \ 1171 $\nOpened Download Page = $OpenedDownloadPage \ 1172 $\nExisting Profile = $ExistingProfile \ 1173 $\nExisting Version = $ExistingVersion \ 1174 $\nExisting Build ID = $ExistingBuildID \ 1175 $\nNew Version = $R5 \ 1176 $\nNew Build ID = $R6 \ 1177 $\nDefault Install Dir = $R7 \ 1178 $\nHas Admin = $R8 \ 1179 $\nDefault Status = $R2 \ 1180 $\nSet As Sefault Status = $R3 \ 1181 $\nDownload Server IP = $DownloadServerIP \ 1182 $\nPost-Signing Data = $PostSigningData \ 1183 $\nProfile cleanup prompt shown = $ProfileCleanupPromptType \ 1184 $\nDid profile cleanup = $CheckboxCleanupProfile" 1185 ; The following will exit the installer 1186 SetAutoClose true 1187 StrCpy $R9 "2" 1188 Call RelativeGotoPage 1189!else 1190 ${StartTimer} ${DownloadIntervalMS} OnPing 1191 InetBgDL::Get "${BaseURLStubPing}/${StubURLVersion}${StubURLVersionAppend}/${Channel}/${UpdateChannel}/${AB_CD}/$R0/$R1/$5/$6/$7/$8/$9/$ExitCode/$FirefoxLaunchCode/$DownloadRetryCount/$DownloadedBytes/$DownloadSizeBytes/$IntroPhaseSeconds/$OptionsPhaseSeconds/$0/$1/$DownloadFirstTransferSeconds/$2/$3/$4/$InitialInstallRequirementsCode/$OpenedDownloadPage/$ExistingProfile/$ExistingVersion/$ExistingBuildID/$R5/$R6/$R7/$R8/$R2/$R3/$DownloadServerIP/$PostSigningData/$ProfileCleanupPromptType/$CheckboxCleanupProfile" \ 1192 "$PLUGINSDIR\_temp" /END 1193!endif 1194 ${Else} 1195 ${If} "$IsDownloadFinished" == "false" 1196 ; Cancel the download in progress 1197 InetBgDL::Get /RESET /END 1198 ${EndIf} 1199 ; The following will exit the installer 1200 SetAutoClose true 1201 StrCpy $R9 "2" 1202 Call RelativeGotoPage 1203 ${EndIf} 1204FunctionEnd 1205 1206Function OnPing 1207 InetBgDL::GetStats 1208 # $0 = HTTP status code, 0=Completed 1209 # $1 = Completed files 1210 # $2 = Remaining files 1211 # $3 = Number of downloaded bytes for the current file 1212 # $4 = Size of current file (Empty string if the size is unknown) 1213 # /RESET must be used if status $0 > 299 (e.g. failure) 1214 # When status is $0 =< 299 it is handled by InetBgDL 1215 ${If} $2 == 0 1216 ${OrIf} $0 > 299 1217 WebBrowser::CancelTimer $TimerHandle 1218 ${If} $0 > 299 1219 InetBgDL::Get /RESET /END 1220 ${EndIf} 1221 ; The following will exit the installer 1222 SetAutoClose true 1223 StrCpy $R9 "2" 1224 Call RelativeGotoPage 1225 ${EndIf} 1226FunctionEnd 1227 1228Function CheckInstall 1229 IntOp $InstallCounterStep $InstallCounterStep + 1 1230 ${If} $InstallCounterStep >= $InstallTotalSteps 1231 WebBrowser::CancelTimer $TimerHandle 1232 ; Close the handle that prevents modification of the full installer 1233 System::Call 'kernel32::CloseHandle(i $HandleDownload)' 1234 StrCpy $ExitCode "${ERR_INSTALL_TIMEOUT}" 1235 ; Use a timer so the UI has a chance to update 1236 ${StartTimer} ${InstallIntervalMS} DisplayDownloadError 1237 Return 1238 ${EndIf} 1239 1240 ${If} $ProgressCompleted < ${PROGRESS_BAR_INSTALL_END_STEP} 1241 IntOp $0 ${PROGRESS_BAR_INSTALL_END_STEP} - ${PROGRESS_BAR_DOWNLOAD_END_STEP} 1242 IntOp $0 $InstallCounterStep * $0 1243 IntOp $0 $0 / $InstallTotalSteps 1244 IntOp $ProgressCompleted ${PROGRESS_BAR_DOWNLOAD_END_STEP} + $0 1245 Call SetProgressBars 1246 ${EndIf} 1247 1248 ${If} ${FileExists} "$INSTDIR\install.log" 1249 Delete "$INSTDIR\install.tmp" 1250 CopyFiles /SILENT "$INSTDIR\install.log" "$INSTDIR\install.tmp" 1251 1252 ; The unfocus and refocus that happens approximately here is caused by the 1253 ; installer calling RefreshShellIcons to refresh the shortcut icons. 1254 1255 ; When the full installer completes the installation the install.log will no 1256 ; longer be in use. 1257 ClearErrors 1258 Delete "$INSTDIR\install.log" 1259 ${Unless} ${Errors} 1260 WebBrowser::CancelTimer $TimerHandle 1261 ; Close the handle that prevents modification of the full installer 1262 System::Call 'kernel32::CloseHandle(i $HandleDownload)' 1263 Rename "$INSTDIR\install.tmp" "$INSTDIR\install.log" 1264 Delete "$PLUGINSDIR\download.exe" 1265 Delete "$PLUGINSDIR\${CONFIG_INI}" 1266 System::Call "kernel32::GetTickCount()l .s" 1267 Pop $EndInstallPhaseTickCount 1268 Call FinishInstall 1269 ${EndUnless} 1270 ${EndIf} 1271FunctionEnd 1272 1273Function FinishInstall 1274 StrCpy $ProgressCompleted "${PROGRESS_BAR_INSTALL_END_STEP}" 1275 Call SetProgressBars 1276 1277 ${If} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-upgrade" 1278 Delete "$INSTDIR\${FileMainEXE}" 1279 Rename "$INSTDIR\${FileMainEXE}.moz-upgrade" "$INSTDIR\${FileMainEXE}" 1280 ${EndIf} 1281 1282 StrCpy $ExitCode "${ERR_SUCCESS}" 1283 1284 ${CopyPostSigningData} 1285 Pop $PostSigningData 1286 1287 Call LaunchApp 1288FunctionEnd 1289 1290Function RelativeGotoPage 1291 IntCmp $R9 0 0 Move Move 1292 StrCmp $R9 "X" 0 Move 1293 StrCpy $R9 "120" 1294 1295 Move: 1296 SendMessage $HWNDPARENT "0x408" "$R9" "" 1297FunctionEnd 1298 1299Function CheckSpace 1300 ${If} "$ExistingTopDir" != "" 1301 StrLen $0 "$ExistingTopDir" 1302 StrLen $1 "$INSTDIR" 1303 ${If} $0 <= $1 1304 StrCpy $2 "$INSTDIR" $3 1305 ${If} "$2" == "$ExistingTopDir" 1306 Return 1307 ${EndIf} 1308 ${EndIf} 1309 ${EndIf} 1310 1311 StrCpy $ExistingTopDir "$INSTDIR" 1312 ${DoUntil} ${FileExists} "$ExistingTopDir" 1313 ${GetParent} "$ExistingTopDir" $ExistingTopDir 1314 ${If} "$ExistingTopDir" == "" 1315 StrCpy $SpaceAvailableBytes "0" 1316 StrCpy $HasRequiredSpaceAvailable "false" 1317 Return 1318 ${EndIf} 1319 ${Loop} 1320 1321 ${GetLongPath} "$ExistingTopDir" $ExistingTopDir 1322 1323 ; GetDiskFreeSpaceExW requires a backslash. 1324 StrCpy $0 "$ExistingTopDir" "" -1 ; the last character 1325 ${If} "$0" != "\" 1326 StrCpy $0 "\" 1327 ${Else} 1328 StrCpy $0 "" 1329 ${EndIf} 1330 1331 System::Call 'kernel32::GetDiskFreeSpaceExW(w, *l, *l, *l) i("$ExistingTopDir$0", .r1, .r2, .r3) .' 1332 StrCpy $SpaceAvailableBytes "$1" 1333 1334 System::Int64Op $SpaceAvailableBytes / 1048576 1335 Pop $1 1336 System::Int64Op $1 > ${APPROXIMATE_REQUIRED_SPACE_MB} 1337 Pop $1 1338 ${If} $1 == 1 1339 StrCpy $HasRequiredSpaceAvailable "true" 1340 ${Else} 1341 StrCpy $HasRequiredSpaceAvailable "false" 1342 ${EndIf} 1343FunctionEnd 1344 1345Function CanWrite 1346 StrCpy $CanWriteToInstallDir "false" 1347 1348 StrCpy $0 "$INSTDIR" 1349 ; Use the existing directory when it exists 1350 ${Unless} ${FileExists} "$INSTDIR" 1351 ; Get the topmost directory that exists for new installs 1352 ${DoUntil} ${FileExists} "$0" 1353 ${GetParent} "$0" $0 1354 ${If} "$0" == "" 1355 Return 1356 ${EndIf} 1357 ${Loop} 1358 ${EndUnless} 1359 1360 GetTempFileName $2 "$0" 1361 Delete $2 1362 CreateDirectory "$2" 1363 1364 ${If} ${FileExists} "$2" 1365 ${If} ${FileExists} "$INSTDIR" 1366 GetTempFileName $3 "$INSTDIR" 1367 ${Else} 1368 GetTempFileName $3 "$2" 1369 ${EndIf} 1370 ${If} ${FileExists} "$3" 1371 Delete "$3" 1372 StrCpy $CanWriteToInstallDir "true" 1373 ${EndIf} 1374 RmDir "$2" 1375 ${EndIf} 1376FunctionEnd 1377 1378Function LaunchApp 1379 StrCpy $FirefoxLaunchCode "2" 1380 1381 ; Set the current working directory to the installation directory 1382 SetOutPath "$INSTDIR" 1383 ClearErrors 1384 ${GetParameters} $0 1385 ${GetOptions} "$0" "/UAC:" $1 1386 ${If} ${Errors} 1387 ${If} $CheckboxCleanupProfile == 1 1388 ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration -first-startup" 1389 ${Else} 1390 ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -first-startup" 1391 ${EndIf} 1392 ${Else} 1393 StrCpy $R1 $CheckboxCleanupProfile 1394 GetFunctionAddress $0 LaunchAppFromElevatedProcess 1395 UAC::ExecCodeSegment $0 1396 ${EndIf} 1397 1398 StrCpy $AppLaunchWaitTickCount 0 1399 ${StartTimer} ${AppLaunchWaitIntervalMS} WaitForAppLaunch 1400FunctionEnd 1401 1402Function LaunchAppFromElevatedProcess 1403 ; Set the current working directory to the installation directory 1404 SetOutPath "$INSTDIR" 1405 ${If} $R1 == 1 1406 ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -reset-profile -migration -first-startup" 1407 ${Else} 1408 ${ExecAndWaitForInputIdle} "$\"$INSTDIR\${FileMainEXE}$\" -first-startup" 1409 ${EndIf} 1410FunctionEnd 1411 1412Function WaitForAppLaunch 1413 FindWindow $0 "${MainWindowClass}" 1414 FindWindow $1 "${DialogWindowClass}" 1415 ${If} $0 <> 0 1416 ${OrIf} $1 <> 0 1417 WebBrowser::CancelTimer $TimerHandle 1418 StrCpy $ProgressCompleted "${PROGRESS_BAR_APP_LAUNCH_END_STEP}" 1419 Call SetProgressBars 1420 Call SendPing 1421 Return 1422 ${EndIf} 1423 1424 IntOp $AppLaunchWaitTickCount $AppLaunchWaitTickCount + 1 1425 IntOp $0 $AppLaunchWaitTickCount * ${AppLaunchWaitIntervalMS} 1426 ${If} $0 >= ${AppLaunchWaitTimeoutMS} 1427 ; We've waited an unreasonably long time, so just exit. 1428 WebBrowser::CancelTimer $TimerHandle 1429 Call SendPing 1430 Return 1431 ${EndIf} 1432 1433 ${If} $ProgressCompleted < ${PROGRESS_BAR_APP_LAUNCH_END_STEP} 1434 IntOp $ProgressCompleted $ProgressCompleted + 1 1435 Call SetProgressBars 1436 ${EndIf} 1437FunctionEnd 1438 1439Function DisplayDownloadError 1440 WebBrowser::CancelTimer $TimerHandle 1441 ; To better display the error state on the taskbar set the progress completed 1442 ; value to the total value. 1443 ${ITBL3SetProgressValue} "100" "100" 1444 ${ITBL3SetProgressState} "${TBPF_ERROR}" 1445 1446 MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD_CONT)" IDCANCEL +2 IDOK +1 1447 Call LaunchHelpPage 1448 Call SendPing 1449FunctionEnd 1450 1451Function LaunchHelpPage 1452 StrCpy $OpenedDownloadPage "1" ; Already initialized to 0 1453 ClearErrors 1454 ${GetParameters} $0 1455 ${GetOptions} "$0" "/UAC:" $1 1456 ${If} ${Errors} 1457 Call OpenManualDownloadURL 1458 ${Else} 1459 GetFunctionAddress $0 OpenManualDownloadURL 1460 UAC::ExecCodeSegment $0 1461 ${EndIf} 1462FunctionEnd 1463 1464Function OpenManualDownloadURL 1465 ClearErrors 1466 ReadINIStr $0 "${PARTNER_INI}" "DownloadURL" "FallbackPage" 1467 ${IfNot} ${Errors} 1468 ExecShell "open" "$0" 1469 ${Else} 1470 ExecShell "open" "${URLManualDownload}${URLManualDownloadAppend}" 1471 ${EndIf} 1472FunctionEnd 1473 1474Function ShouldPromptForProfileCleanup 1475 ; This will be our return value. 1476 StrCpy $ProfileCleanupPromptType 0 1477 1478 ; Only consider installations of the same architecture we're installing. 1479 ${If} $ArchToInstall == ${ARCH_AMD64} 1480 ${OrIf} $ArchToInstall == ${ARCH_AARCH64} 1481 SetRegView 64 1482 ${Else} 1483 SetRegView 32 1484 ${EndIf} 1485 1486 ; Make sure $APPDATA is the user's AppData and not ProgramData. 1487 ; We'll set this back to all at the end of the function. 1488 SetShellVarContext current 1489 1490 ${FindInstallSpecificProfile} 1491 Pop $R0 1492 1493 ${If} $R0 == "" 1494 ; We don't have an install-specific profile, so look for an old-style 1495 ; default profile instead by checking each numbered Profile section. 1496 StrCpy $0 0 1497 ${Do} 1498 ClearErrors 1499 ; Check if the section exists by reading a value that must be present. 1500 ReadINIStr $1 "$APPDATA\Mozilla\Firefox\profiles.ini" "Profile$0" "Path" 1501 ${If} ${Errors} 1502 ; We've run out of profile sections. 1503 ${Break} 1504 ${EndIf} 1505 1506 ClearErrors 1507 ReadINIStr $1 "$APPDATA\Mozilla\Firefox\profiles.ini" "Profile$0" "Default" 1508 ${IfNot} ${Errors} 1509 ${AndIf} $1 == "1" 1510 ; We've found the default profile 1511 ReadINIStr $1 "$APPDATA\Mozilla\Firefox\profiles.ini" "Profile$0" "Path" 1512 ReadINIStr $2 "$APPDATA\Mozilla\Firefox\profiles.ini" "Profile$0" "IsRelative" 1513 ${If} $2 == "1" 1514 StrCpy $R0 "$APPDATA\Mozilla\Firefox\$1" 1515 ${Else} 1516 StrCpy $R0 "$1" 1517 ${EndIf} 1518 ${Break} 1519 ${EndIf} 1520 1521 IntOp $0 $0 + 1 1522 ${Loop} 1523 ${EndIf} 1524 1525 GetFullPathName $R0 $R0 1526 1527 ${If} $R0 == "" 1528 ; No profile to clean up, so don't show the cleanup prompt. 1529 GoTo end 1530 ${EndIf} 1531 1532 ; We have at least one profile present. If we don't have any installations, 1533 ; then we need to show the re-install prompt. We'll say there's an 1534 ; installation present if HKCR\FirefoxURL* exists and points to a real path. 1535 StrCpy $0 0 1536 StrCpy $R9 "" 1537 ${Do} 1538 ClearErrors 1539 EnumRegKey $1 HKCR "" $0 1540 ${If} ${Errors} 1541 ${OrIf} $1 == "" 1542 ${Break} 1543 ${EndIf} 1544 ${WordFind} "$1" "-" "+1{" $2 1545 ${If} $2 == "FirefoxURL" 1546 ClearErrors 1547 ReadRegStr $2 HKCR "$1\DefaultIcon" "" 1548 ${IfNot} ${Errors} 1549 ${GetPathFromString} $2 $1 1550 ${If} ${FileExists} $1 1551 StrCpy $R9 $1 1552 ${Break} 1553 ${EndIf} 1554 ${EndIf} 1555 ${EndIf} 1556 IntOp $0 $0 + 1 1557 ${Loop} 1558 ${If} $R9 == "" 1559 StrCpy $ProfileCleanupPromptType 1 1560 GoTo end 1561 ${EndIf} 1562 1563 ; Okay, there's at least one install, let's see if it's for this channel. 1564 SetShellVarContext all 1565 ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $0 1566 ${If} $0 == "false" 1567 SetShellVarContext current 1568 ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $0 1569 ${If} $0 == "false" 1570 ; Existing installs are not for this channel. Don't show any prompt. 1571 GoTo end 1572 ${EndIf} 1573 ${EndIf} 1574 1575 ; Find out what version the default profile was last used on. 1576 ${If} ${FileExists} "$R0\compatibility.ini" 1577 ClearErrors 1578 ReadINIStr $0 "$R0\compatibility.ini" "Compatibility" "LastVersion" 1579 ${If} ${Errors} 1580 GoTo end 1581 ${EndIf} 1582 ${WordFind} $0 "." "+1{" $0 1583 1584 ; We don't know what version we're about to install because we haven't 1585 ; downloaded it yet. Find out what the latest version released on this 1586 ; channel is and assume we'll be installing that one. 1587 Call GetLatestReleasedVersion 1588 ${If} ${Errors} 1589 ; Use this stub installer's version as a fallback when we can't get the 1590 ; real current version; this may be behind, but it's better than nothing. 1591 StrCpy $1 ${AppVersion} 1592 ${EndIf} 1593 1594 ${WordFind} $1 "." "+1{" $1 1595 IntOp $1 $1 - 2 1596 1597 ${If} $1 > $0 1598 ; Default profile was last used more than two versions ago, so we need 1599 ; to show the paveover version of the profile cleanup prompt. 1600 StrCpy $ProfileCleanupPromptType 2 1601 ${EndIf} 1602 ${EndIf} 1603 1604 end: 1605 SetRegView lastused 1606 SetShellVarContext all 1607FunctionEnd 1608 1609Function GetLatestReleasedVersion 1610 ClearErrors 1611 Push $0 ; InetBgDl::GetStats uses $0 for the HTTP error code 1612 ; $1 is our return value, so don't save it 1613 Push $2 ; InetBgDl::GetStats uses $2 to tell us when the transfer is done 1614 Push $3 ; $3 - $5 are also set by InetBgDl::GetStats, but we don't use them 1615 Push $4 1616 Push $5 1617 Push $6 ; This is our response timeout counter 1618 1619 InetBgDL::Get /RESET /END 1620 InetBgDL::Get "https://product-details.mozilla.org/1.0/firefox_versions.json" \ 1621 "$PLUGINSDIR\firefox_versions.json" \ 1622 /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END 1623 1624 ; Wait for the response, but only give it half a second since this is on the 1625 ; installer startup path (we haven't even shown a window yet). 1626 StrCpy $6 0 1627 ${Do} 1628 Sleep 100 1629 InetBgDL::GetStats 1630 IntOp $6 $6 + 1 1631 1632 ${If} $2 == 0 1633 ${Break} 1634 ${ElseIf} $6 >= 5 1635 InetBgDL::Get /RESET /END 1636 SetErrors 1637 GoTo end 1638 ${EndIf} 1639 ${Loop} 1640 1641 StrCpy $1 0 1642 nsJSON::Set /file "$PLUGINSDIR\firefox_versions.json" 1643 IfErrors end 1644 ${Select} ${Channel} 1645 ${Case} "unofficial" 1646 StrCpy $1 "FIREFOX_NIGHTLY" 1647 ${Case} "nightly" 1648 StrCpy $1 "FIREFOX_NIGHTLY" 1649 ${Case} "aurora" 1650 StrCpy $1 "FIREFOX_DEVEDITION" 1651 ${Case} "beta" 1652 StrCpy $1 "LATEST_FIREFOX_RELEASED_DEVEL_VERSION" 1653 ${Case} "release" 1654 StrCpy $1 "LATEST_FIREFOX_VERSION" 1655 ${EndSelect} 1656 nsJSON::Get $1 /end 1657 1658 end: 1659 ${If} ${Errors} 1660 ${OrIf} $1 == 0 1661 SetErrors 1662 StrCpy $1 0 1663 ${Else} 1664 Pop $1 1665 ${EndIf} 1666 1667 Pop $6 1668 Pop $5 1669 Pop $4 1670 Pop $3 1671 Pop $2 1672 Pop $0 1673FunctionEnd 1674 1675; Determine which architecture build we should download and install. 1676; AArch64 is always selected if it's the native architecture of the machine. 1677; Otherwise, we check a few things to determine if AMD64 is appropriate: 1678; 1) Running a 64-bit OS (we've already checked the OS version). 1679; 2) An amount of RAM strictly greater than RAM_NEEDED_FOR_64BIT 1680; 3) No third-party products installed that cause issues with the 64-bit build. 1681; Currently this includes Lenovo OneKey Theater and Lenovo Energy Management. 1682; We also make sure that the partner.ini file contains a download URL for the 1683; selected architecture, when a partner.ini file eixsts. 1684; If any of those checks fail, the 32-bit x86 build is selected. 1685Function GetArchToInstall 1686 StrCpy $ArchToInstall ${ARCH_X86} 1687 1688 ${If} ${IsNativeARM64} 1689 StrCpy $ArchToInstall ${ARCH_AARCH64} 1690 GoTo downloadUrlCheck 1691 ${EndIf} 1692 1693 ${IfNot} ${IsNativeAMD64} 1694 Return 1695 ${EndIf} 1696 1697 System::Call "*(i 64, i, l 0, l, l, l, l, l, l)p.r1" 1698 System::Call "Kernel32::GlobalMemoryStatusEx(p r1)" 1699 System::Call "*$1(i, i, l.r2, l, l, l, l, l, l)" 1700 System::Free $1 1701 ${If} $2 L<= ${RAM_NEEDED_FOR_64BIT} 1702 Return 1703 ${EndIf} 1704 1705 ; Lenovo OneKey Theater can theoretically be in a directory other than this 1706 ; one, because some installer versions let you change it, but it's unlikely. 1707 ${If} ${FileExists} "$PROGRAMFILES32\Lenovo\Onekey Theater\windowsapihookdll64.dll" 1708 Return 1709 ${EndIf} 1710 1711 ${If} ${FileExists} "$PROGRAMFILES32\Lenovo\Energy Management\Energy Management.exe" 1712 Return 1713 ${EndIf} 1714 1715 StrCpy $ArchToInstall ${ARCH_AMD64} 1716 1717 downloadUrlCheck: 1718 ; If we've selected an architecture that doesn't have a download URL in the 1719 ; partner.ini, but there is a URL there for 32-bit x86, then fall back to 1720 ; 32-bit x86 on the theory that we should never use a non-partner build if 1721 ; we are configured as a partner installer, even if the only build that's 1722 ; provided is suboptimal for the machine. If there isn't even an x86 URL, 1723 ; then we won't force x86 and GetDownloadURL will stick with the built-in URL. 1724 ClearErrors 1725 ReadINIStr $1 "${PARTNER_INI}" "DownloadURL" "X86" 1726 ${IfNot} ${Errors} 1727 ${If} $ArchToInstall == ${ARCH_AMD64} 1728 ReadINIStr $1 "${PARTNER_INI}" "DownloadURL" "AMD64" 1729 ${If} ${Errors} 1730 StrCpy $ArchToInstall ${ARCH_X86} 1731 ${EndIf} 1732 ${ElseIf} $ArchToInstall == ${ARCH_AARCH64} 1733 ReadINIStr $1 "${PARTNER_INI}" "DownloadURL" "AArch64" 1734 ${If} ${Errors} 1735 StrCpy $ArchToInstall ${ARCH_X86} 1736 ${EndIf} 1737 ${EndIf} 1738 ${EndIf} 1739FunctionEnd 1740 1741Function GetDownloadURL 1742 Push $0 1743 Push $1 1744 1745 ; Start with the appropriate URL from our built-in branding info. 1746 ${If} $ArchToInstall == ${ARCH_AMD64} 1747 StrCpy $0 "${URLStubDownloadAMD64}${URLStubDownloadAppend}" 1748 ${ElseIf} $ArchToInstall == ${ARCH_AARCH64} 1749 StrCpy $0 "${URLStubDownloadAArch64}${URLStubDownloadAppend}" 1750 ${Else} 1751 StrCpy $0 "${URLStubDownloadX86}${URLStubDownloadAppend}" 1752 ${EndIf} 1753 1754 ; If we have a partner.ini file then use the URL from there instead. 1755 ClearErrors 1756 ${If} $ArchToInstall == ${ARCH_AMD64} 1757 ReadINIStr $1 "${PARTNER_INI}" "DownloadURL" "AMD64" 1758 ${ElseIf} $ArchToInstall == ${ARCH_AARCH64} 1759 ReadINIStr $1 "${PARTNER_INI}" "DownloadURL" "AArch64" 1760 ${Else} 1761 ReadINIStr $1 "${PARTNER_INI}" "DownloadURL" "X86" 1762 ${EndIf} 1763 ${IfNot} ${Errors} 1764 StrCpy $0 "$1" 1765 ${EndIf} 1766 1767 Pop $1 1768 Exch $0 1769FunctionEnd 1770 1771Section 1772SectionEnd 1773