Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


SSL common.nsh   Sprache: unbekannt

 
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.


################################################################################
# Helper defines and macros for toolkit applications

/**
 * Avoid creating macros / functions that overwrite registers (see the
 * GetLongPath macro for one way to avoid this)!
 *
 * Before using the registers exchange the passed in params and save existing
 * register values to the stack.
 *
 * Exch $R9 ; exhange the original $R9 with the top of the stack
 * Exch 1   ; exchange the top of the stack with 1 below the top of the stack
 * Exch $R8 ; exchange the original $R8 with the top of the stack
 * Exch 2   ; exchange the top of the stack with 2 below the top of the stack
 * Exch $R7 ; exchange the original $R7 with the top of the stack
 * Push $R6 ; push the original $R6 onto the top of the stack
 * Push $R5 ; push the original $R5 onto the top of the stack
 * Push $R4 ; push the original $R4 onto the top of the stack
 *
 * <do stuff>
 *
 * ; Restore the values.
 * Pop $R4  ; restore the value for $R4 from the top of the stack
 * Pop $R5  ; restore the value for $R5 from the top of the stack
 * Pop $R6  ; restore the value for $R6 from the top of the stack
 * Exch $R7 ; exchange the new $R7 value with the top of the stack
 * Exch 2   ; exchange the top of the stack with 2 below the top of the stack
 * Exch $R8 ; exchange the new $R8 value with the top of the stack
 * Exch 1   ; exchange the top of the stack with 2 below the top of the stack
 * Exch $R9 ; exchange the new $R9 value with the top of the stack
 *
 *
 * When inserting macros in common.nsh from another macro in common.nsh that
 * can be used from the uninstaller _MOZFUNC_UN will be undefined when it is
 * inserted. Use the following to redefine _MOZFUNC_UN with its original value
 * (see the RegCleanMain macro for an example).
 *
 * !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
 * !insertmacro ${_MOZFUNC_UN_TMP}FileJoin
 * !insertmacro ${_MOZFUNC_UN_TMP}LineFind
 * !insertmacro ${_MOZFUNC_UN_TMP}TextCompareNoDetails
 * !insertmacro ${_MOZFUNC_UN_TMP}TrimNewLines
 * !undef _MOZFUNC_UN
 * !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
 * !undef _MOZFUNC_UN_TMP
 */

; When including a file provided by NSIS check if its verbose macro is defined
; to prevent loading the file a second time.
!ifmacrondef TEXTFUNC_VERBOSE
  !include TextFunc.nsh
!endif

!ifmacrondef FILEFUNC_VERBOSE
  !include FileFunc.nsh
!endif

!ifmacrondef LOGICLIB_VERBOSITY
  !include LogicLib.nsh
!endif

!ifndef WINMESSAGES_INCLUDED
  !include WinMessages.nsh
!endif

; When including WinVer.nsh check if ___WINVER__NSH___ is defined to prevent
; loading the file a second time.
!ifndef ___WINVER__NSH___
  !include WinVer.nsh
!endif

; When including x64.nsh check if ___X64__NSH___ is defined to prevent
; loading the file a second time.
!ifndef ___X64__NSH___
  !include x64.nsh
!endif

; NSIS provided macros that we have overridden.
!include overrides.nsh

!define SHORTCUTS_LOG "shortcuts_log.ini"
!define TO_BE_DELETED "tobedeleted"

; !define SHCNF_DWORD     0x0003
; !define SHCNF_FLUSH     0x1000
!ifndef SHCNF_DWORDFLUSH
  !define SHCNF_DWORDFLUSH 0x1003
!endif
!ifndef SHCNE_ASSOCCHANGED
  !define SHCNE_ASSOCCHANGED 0x08000000
!endif

################################################################################
# Macros for debugging

/**
 * The following two macros assist with verifying that a macro doesn't
 * overwrite any registers.
 *
 * Usage:
 * ${debugSetRegisters}
 * <do stuff>
 * ${debugDisplayRegisters}
 */

/**
 * Sets all register values to their name to assist with verifying that a macro
 * doesn't overwrite any registers.
 */
!macro debugSetRegisters
  StrCpy $0 "$$0"
  StrCpy $1 "$$1"
  StrCpy $2 "$$2"
  StrCpy $3 "$$3"
  StrCpy $4 "$$4"
  StrCpy $5 "$$5"
  StrCpy $6 "$$6"
  StrCpy $7 "$$7"
  StrCpy $8 "$$8"
  StrCpy $9 "$$9"
  StrCpy $R0 "$$R0"
  StrCpy $R1 "$$R1"
  StrCpy $R2 "$$R2"
  StrCpy $R3 "$$R3"
  StrCpy $R4 "$$R4"
  StrCpy $R5 "$$R5"
  StrCpy $R6 "$$R6"
  StrCpy $R7 "$$R7"
  StrCpy $R8 "$$R8"
  StrCpy $R9 "$$R9"
!macroend
!define debugSetRegisters "!insertmacro debugSetRegisters"

/**
 * Displays all register values to assist with verifying that a macro doesn't
 * overwrite any registers.
 */
!macro debugDisplayRegisters
  MessageBox MB_OK \
      "Register Values:$\n\
       $$0 = $0$\n$$1 = $1$\n$$2 = $2$\n$$3 = $3$\n$$4 = $4$\n\
       $$5 = $5$\n$$6 = $6$\n$$7 = $7$\n$$8 = $8$\n$$9 = $9$\n\
       $$R0 = $R0$\n$$R1 = $R1$\n$$R2 = $R2$\n$$R3 = $R3$\n$$R4 = $R4$\n\
       $$R5 = $R5$\n$$R6 = $R6$\n$$R7 = $R7$\n$$R8 = $R8$\n$$R9 = $R9"
!macroend
!define debugDisplayRegisters "!insertmacro debugDisplayRegisters"


################################################################################
# Modern User Interface (MUI) override macros

; Removed macros in nsis 2.33u (ported from nsis 2.22)
;  MUI_LANGUAGEFILE_DEFINE
;  MUI_LANGUAGEFILE_LANGSTRING_PAGE
;  MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE
;  MUI_LANGUAGEFILE_LANGSTRING_DEFINE
;  MUI_LANGUAGEFILE_UNLANGSTRING_PAGE

!macro MOZ_MUI_LANGUAGEFILE_DEFINE DEFINE NAME

  !ifndef "${DEFINE}"
    !define "${DEFINE}" "${${NAME}}"
  !endif
  !undef "${NAME}"

!macroend

!macro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE PAGE NAME

  !ifdef MUI_${PAGE}PAGE
    LangString "${NAME}" 0 "${${NAME}}"
    !undef "${NAME}"
  !else
    !undef "${NAME}"
  !endif

!macroend

!macro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE PAGE NAME

  !ifdef MUI_${PAGE}PAGE | MUI_UN${PAGE}PAGE
    LangString "${NAME}" 0 "${${NAME}}"
    !undef "${NAME}"
  !else
    !undef "${NAME}"
  !endif

!macroend

!macro MOZ_MUI_LANGUAGEFILE_LANGSTRING_DEFINE DEFINE NAME

  !ifdef "${DEFINE}"
    LangString "${NAME}" 0 "${${NAME}}"
  !endif
  !undef "${NAME}"

!macroend

!macro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE PAGE NAME

  !ifdef MUI_UNINSTALLER
    !ifdef MUI_UN${PAGE}PAGE
      LangString "${NAME}" 0 "${${NAME}}"
      !undef "${NAME}"
    !else
      !undef "${NAME}"
    !endif
  !else
    !undef "${NAME}"
  !endif

!macroend

; Modified version of the following MUI macros to support Mozilla localization.
; MUI_LANGUAGE
; MUI_LANGUAGEFILE_BEGIN
; MOZ_MUI_LANGUAGEFILE_END
; See <NSIS App Dir>/Contrib/Modern UI/System.nsh for more information
!define MUI_INSTALLOPTIONS_READ "!insertmacro MUI_INSTALLOPTIONS_READ"

!macro MOZ_MUI_LANGUAGE LANGUAGE
  !verbose push
  !verbose ${MUI_VERBOSE}
  !include "${LANGUAGE}.nsh"
  !verbose pop
!macroend

!macro MOZ_MUI_LANGUAGEFILE_BEGIN LANGUAGE
  !insertmacro MUI_INSERT
  !ifndef "MUI_LANGUAGEFILE_${LANGUAGE}_USED"
    !define "MUI_LANGUAGEFILE_${LANGUAGE}_USED"
    LoadLanguageFile "${LANGUAGE}.nlf"
  !else
    !error "Modern UI language file ${LANGUAGE} included twice!"
  !endif
!macroend

; Custom version of MUI_LANGUAGEFILE_END. The macro to add the default MUI
; strings and the macros for several strings that are part of the NSIS MUI and
; not in our locale files have been commented out.
!macro MOZ_MUI_LANGUAGEFILE_END

#  !include "${NSISDIR}\Contrib\Modern UI\Language files\Default.nsh"
  !ifdef MUI_LANGUAGEFILE_DEFAULT_USED
    !undef MUI_LANGUAGEFILE_DEFAULT_USED
    !warning "${LANGUAGE} Modern UI language file version doesn't match. Using default English texts for missing strings."
  !endif

  !insertmacro MOZ_MUI_LANGUAGEFILE_DEFINE "MUI_${LANGUAGE}_LANGNAME" "MUI_LANGNAME"

  !ifndef MUI_LANGDLL_PUSHLIST
    !define MUI_LANGDLL_PUSHLIST "'${MUI_${LANGUAGE}_LANGNAME}' ${LANG_${LANGUAGE}} "
  !else
    !ifdef MUI_LANGDLL_PUSHLIST_TEMP
      !undef MUI_LANGDLL_PUSHLIST_TEMP
    !endif
    !define MUI_LANGDLL_PUSHLIST_TEMP "${MUI_LANGDLL_PUSHLIST}"
    !undef MUI_LANGDLL_PUSHLIST
    !define MUI_LANGDLL_PUSHLIST "'${MUI_${LANGUAGE}_LANGNAME}' ${LANG_${LANGUAGE}} ${MUI_LANGDLL_PUSHLIST_TEMP}"
  !endif

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE WELCOME "MUI_TEXT_WELCOME_INFO_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE WELCOME "MUI_TEXT_WELCOME_INFO_TEXT"

!ifdef MUI_TEXT_LICENSE_TITLE
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_TEXT_LICENSE_TITLE"
!endif
!ifdef MUI_TEXT_LICENSE_SUBTITLE
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_TEXT_LICENSE_SUBTITLE"
!endif
!ifdef MUI_INNERTEXT_LICENSE_TOP
  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_TOP"
!endif

#  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_BOTTOM"

!ifdef MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX"
!endif

!ifdef MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS"
!endif

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE COMPONENTS "MUI_TEXT_COMPONENTS_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE COMPONENTS "MUI_TEXT_COMPONENTS_SUBTITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE COMPONENTS "MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE COMPONENTS "MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO"

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE DIRECTORY "MUI_TEXT_DIRECTORY_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE DIRECTORY "MUI_TEXT_DIRECTORY_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_TEXT_STARTMENU_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_TEXT_STARTMENU_SUBTITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_INNERTEXT_STARTMENU_TOP"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_INNERTEXT_STARTMENU_CHECKBOX"

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_INSTALLING_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_INSTALLING_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_FINISH_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_FINISH_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_ABORT_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_ABORT_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_BUTTONTEXT_FINISH"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_INFO_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_INFO_TEXT"
  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_INFO_REBOOT"
  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_REBOOTNOW"
  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_REBOOTLATER"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_RUN"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_SHOWREADME"

; Support for using the existing MUI_TEXT_ABORTWARNING string
!ifdef MOZ_MUI_CUSTOM_ABORT
    LangString MOZ_MUI_TEXT_ABORTWARNING 0 "${MUI_TEXT_ABORTWARNING}"
!endif

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_DEFINE MUI_ABORTWARNING "MUI_TEXT_ABORTWARNING"


  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE WELCOME "MUI_UNTEXT_WELCOME_INFO_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE WELCOME "MUI_UNTEXT_WELCOME_INFO_TEXT"

  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE CONFIRM "MUI_UNTEXT_CONFIRM_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE CONFIRM "MUI_UNTEXT_CONFIRM_SUBTITLE"

#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNTEXT_LICENSE_TITLE"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNTEXT_LICENSE_SUBTITLE"

#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNINNERTEXT_LICENSE_BOTTOM"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS"

#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE COMPONENTS "MUI_UNTEXT_COMPONENTS_TITLE"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE COMPONENTS "MUI_UNTEXT_COMPONENTS_SUBTITLE"

#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE DIRECTORY "MUI_UNTEXT_DIRECTORY_TITLE"
#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE DIRECTORY  "MUI_UNTEXT_DIRECTORY_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_UNINSTALLING_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_UNINSTALLING_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_FINISH_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_FINISH_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_ABORT_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_ABORT_SUBTITLE"

  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE FINISH "MUI_UNTEXT_FINISH_INFO_TITLE"
  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE FINISH "MUI_UNTEXT_FINISH_INFO_TEXT"
  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE FINISH "MUI_UNTEXT_FINISH_INFO_REBOOT"

  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_DEFINE MUI_UNABORTWARNING "MUI_UNTEXT_ABORTWARNING"

  !ifndef MUI_LANGDLL_LANGUAGES
    !define MUI_LANGDLL_LANGUAGES "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' "
    !define MUI_LANGDLL_LANGUAGES_CP "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' '${LANG_${LANGUAGE}_CP}' "
  !else
    !ifdef MUI_LANGDLL_LANGUAGES_TEMP
      !undef MUI_LANGDLL_LANGUAGES_TEMP
    !endif
    !define MUI_LANGDLL_LANGUAGES_TEMP "${MUI_LANGDLL_LANGUAGES}"
    !undef MUI_LANGDLL_LANGUAGES

    !ifdef MUI_LANGDLL_LANGUAGES_CP_TEMP
      !undef MUI_LANGDLL_LANGUAGES_CP_TEMP
    !endif
    !define MUI_LANGDLL_LANGUAGES_CP_TEMP "${MUI_LANGDLL_LANGUAGES_CP}"
    !undef MUI_LANGDLL_LANGUAGES_CP

    !define MUI_LANGDLL_LANGUAGES "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' ${MUI_LANGDLL_LANGUAGES_TEMP}"
    !define MUI_LANGDLL_LANGUAGES_CP "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' '${LANG_${LANGUAGE}_CP}' ${MUI_LANGDLL_LANGUAGES_CP_TEMP}"
  !endif

!macroend

/**
 * Creates an InstallOptions file with a UTF-16LE BOM and adds the RTL value
 * to the Settings section.
 *
 * @param   _FILE
 *          The name of the file to be created in $PLUGINSDIR.
 */
!macro InitInstallOptionsFile _FILE
  Push $R9

  FileOpen $R9 "$PLUGINSDIR\${_FILE}" w
  FileWriteWord $R9 "65279"
  FileClose $R9
  WriteIniStr "$PLUGINSDIR\${_FILE}" "Settings" "RTL" "$(^RTL)"

  Pop $R9
!macroend


################################################################################
# Macros for handling files in use

/**
 * Checks for files in use in the $INSTDIR directory. To check files in
 * sub-directories this macro would need to be rewritten to create
 * sub-directories in the temporary directory used to backup the files that are
 * checked.
 *
 * Example usage:
 *
 *  ; The first string to be pushed onto the stack MUST be "end" to indicate
 *  ; that there are no more files in the $INSTDIR directory to check.
 *  Push "end"
 *  Push "freebl3.dll"
 *  ; The last file pushed should be the app's main exe so if it is in use this
 *  ; macro will return after the first check.
 *  Push "${FileMainEXE}"
 *  ${CheckForFilesInUse} $R9
 *
 * !IMPORTANT - this macro uses the $R7, $R8, and $R9 registers and makes no
 *              attempt to restore their original values.
 *
 * @return  _RESULT
 *          false if all of the files popped from the stack are not in use.
 *          True if any of the files popped from the stack are in use.
 * $R7 = Temporary backup directory where the files will be copied to.
 * $R8 = value popped from the stack. This will either be a file name for a file
 *       in the $INSTDIR directory or "end" to indicate that there are no
 *       additional files to check.
 * $R9 = _RESULT
 */
!macro CheckForFilesInUse

  !ifndef ${_MOZFUNC_UN}CheckForFilesInUse
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}CheckForFilesInUse "!insertmacro ${_MOZFUNC_UN}CheckForFilesInUseCall"

    Function ${_MOZFUNC_UN}CheckForFilesInUse
      ; Create a temporary backup directory.
      GetTempFileName $R7 "$INSTDIR"
      Delete "$R7"
      SetOutPath "$R7"
      StrCpy $R9 "false"

      Pop $R8
      ${While} $R8 != "end"
        ${Unless} ${FileExists} "$INSTDIR\$R8"
          Pop $R8 ; get next file to check before continuing
          ${Continue}
        ${EndUnless}

        ClearErrors
        CopyFiles /SILENT "$INSTDIR\$R8" "$R7\$R8" ; try to copy
        ${If} ${Errors}
          ; File is in use
          StrCpy $R9 "true"
          ${Break}
        ${EndIf}

        Delete "$INSTDIR\$R8" ; delete original
        ${If} ${Errors}
          ; File is in use
          StrCpy $R9 "true"
          Delete "$R7\$R8" ; delete temp copy
          ${Break}
        ${EndIf}

        Pop $R8 ; get next file to check
      ${EndWhile}

      ; clear stack
      ${While} $R8 != "end"
        Pop $R8
      ${EndWhile}

      ; restore everything
      SetOutPath "$INSTDIR"
      CopyFiles /SILENT "$R7\*" "$INSTDIR\"
      RmDir /r "$R7"
      SetOutPath "$EXEDIR"
      ClearErrors

      Push $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro CheckForFilesInUseCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call CheckForFilesInUse
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.CheckForFilesInUseCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call un.CheckForFilesInUse
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.CheckForFilesInUse
  !ifndef un.CheckForFilesInUse
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro CheckForFilesInUse

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

!macro GetCommonDirectory

  !ifndef ${_MOZFUNC_UN}GetCommonDirectory
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}GetCommonDirectory "!insertmacro ${_MOZFUNC_UN}GetCommonDirectoryCall"

    Function ${_MOZFUNC_UN}GetCommonDirectory
      Push $0   ; Save $0

      ; This gets C:\ProgramData or the equivalent.
      ${GetCommonAppDataFolder} $0

      ; Add our subdirectory, this is hardcoded as grandparent of the update directory in
      ; several other places.
      StrCpy $0 "$0\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38"

      Exch $0   ; Restore original $0 and put our $0 on the stack.
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro GetCommonDirectoryCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call GetCommonDirectory
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetCommonDirectoryCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call un.GetCommonDirectory
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetCommonDirectory
  !ifndef un.GetCommonDirectory
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro GetCommonDirectory

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * The macros below will automatically prepend un. to the function names when
 * they are defined (e.g. !define un.RegCleanMain).
 */
!verbose push
!verbose 3
!ifndef _MOZFUNC_VERBOSE
  !define _MOZFUNC_VERBOSE 3
!endif
!verbose ${_MOZFUNC_VERBOSE}
!define MOZFUNC_VERBOSE "!insertmacro MOZFUNC_VERBOSE"
!define _MOZFUNC_UN
!define _MOZFUNC_S
!verbose pop

!macro MOZFUNC_VERBOSE _VERBOSE
  !verbose push
  !verbose 3
  !undef _MOZFUNC_VERBOSE
  !define _MOZFUNC_VERBOSE ${_VERBOSE}
  !verbose pop
!macroend

/**
 * Displays a MessageBox and then calls abort to prevent continuing to the
 * next page when the specified Window Class is found.
 *
 * @param   _WINDOW_CLASS
 *          The Window Class to search for with FindWindow.
 * @param   _MSG
 *          The message text to display in the message box.
 *
 * $R7 = return value from FindWindow
 * $R8 = _WINDOW_CLASS
 * $R9 = _MSG
 */
!macro ManualCloseAppPrompt

  !ifndef ${_MOZFUNC_UN}ManualCloseAppPrompt
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}ManualCloseAppPrompt "!insertmacro ${_MOZFUNC_UN}ManualCloseAppPromptCall"

    Function ${_MOZFUNC_UN}ManualCloseAppPrompt
      Exch $R9
      Exch 1
      Exch $R8
      Push $R7

      FindWindow $R7 "$R8"
      ${If} $R7 <> 0 ; integer comparison
        MessageBox MB_OK|MB_ICONQUESTION "$R9"
        Abort
      ${EndIf}

      Pop $R7
      Exch $R8
      Exch 1
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro ManualCloseAppPromptCall _WINDOW_CLASS _MSG
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_WINDOW_CLASS}"
  Push "${_MSG}"
  Call ManualCloseAppPrompt
  !verbose pop
!macroend

!macro un.ManualCloseAppPromptCall _WINDOW_CLASS _MSG
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_WINDOW_CLASS}"
  Push "${_MSG}"
  Call un.ManualCloseAppPrompt
  !verbose pop
!macroend

!macro un.ManualCloseAppPrompt
  !ifndef un.ManualCloseAppPrompt
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro ManualCloseAppPrompt

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend


################################################################################
# Macros for working with the registry

/**
 * Writes a registry string using SHCTX and the supplied params and logs the
 * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
 *
 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
 *
 * @param   _ROOT
 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
 *          This will only be used for logging.
 * @param   _KEY
 *          The subkey in relation to the key root.
 * @param   _NAME
 *          The key value name to write to.
 * @param   _STR
 *          The string to write to the key value name.
 * @param   _LOG_UNINSTALL
 *          0 = don't add to uninstall log, 1 = add to uninstall log.
 *
 * $R5 = _ROOT
 * $R6 = _KEY
 * $R7 = _NAME
 * $R8 = _STR
 * $R9 = _LOG_UNINSTALL
 */
!macro WriteRegStr2

  !ifndef ${_MOZFUNC_UN}WriteRegStr2
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}WriteRegStr2 "!insertmacro ${_MOZFUNC_UN}WriteRegStr2Call"

    Function ${_MOZFUNC_UN}WriteRegStr2
      Exch $R9
      Exch 1
      Exch $R8
      Exch 2
      Exch $R7
      Exch 3
      Exch $R6
      Exch 4
      Exch $R5

      ClearErrors
      WriteRegStr SHCTX "$R6" "$R7" "$R8"

      !ifndef NO_LOG
        ${If} ${Errors}
          ${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
        ${Else}
          ${If} $R9 == 1 ; add to the uninstall log?
            ${LogUninstall} "RegVal: $R5 | $R6 | $R7"
          ${EndIf}
          ${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
        ${EndIf}
      !endif

      Exch $R5
      Exch 4
      Exch $R6
      Exch 3
      Exch $R7
      Exch 2
      Exch $R8
      Exch 1
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro WriteRegStr2Call _ROOT _KEY _NAME _STR _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_NAME}"
  Push "${_STR}"
  Push "${_LOG_UNINSTALL}"
  Call WriteRegStr2
  !verbose pop
!macroend

!macro un.WriteRegStr2Call _ROOT _KEY _NAME _STR _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_NAME}"
  Push "${_STR}"
  Push "${_LOG_UNINSTALL}"
  Call un.WriteRegStr2
  !verbose pop
!macroend

!macro un.WriteRegStr2
  !ifndef un.WriteRegStr2
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro WriteRegStr2

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * Writes a registry dword using SHCTX and the supplied params and logs the
 * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
 *
 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
 *
 * @param   _ROOT
 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
 *          This will only be used for logging.
 * @param   _KEY
 *          The subkey in relation to the key root.
 * @param   _NAME
 *          The key value name to write to.
 * @param   _DWORD
 *          The dword to write to the key value name.
 * @param   _LOG_UNINSTALL
 *          0 = don't add to uninstall log, 1 = add to uninstall log.
 *
 * $R5 = _ROOT
 * $R6 = _KEY
 * $R7 = _NAME
 * $R8 = _DWORD
 * $R9 = _LOG_UNINSTALL
 */
!macro WriteRegDWORD2

  !ifndef ${_MOZFUNC_UN}WriteRegDWORD2
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}WriteRegDWORD2 "!insertmacro ${_MOZFUNC_UN}WriteRegDWORD2Call"

    Function ${_MOZFUNC_UN}WriteRegDWORD2
      Exch $R9
      Exch 1
      Exch $R8
      Exch 2
      Exch $R7
      Exch 3
      Exch $R6
      Exch 4
      Exch $R5

      ClearErrors
      WriteRegDWORD SHCTX "$R6" "$R7" "$R8"

      !ifndef NO_LOG
        ${If} ${Errors}
          ${LogMsg} "** ERROR Adding Registry DWord: $R5 | $R6 | $R7 | $R8 **"
        ${Else}
          ${If} $R9 == 1 ; add to the uninstall log?
            ${LogUninstall} "RegVal: $R5 | $R6 | $R7"
          ${EndIf}
          ${LogMsg} "Added Registry DWord: $R5 | $R6 | $R7 | $R8"
        ${EndIf}
      !endif

      Exch $R5
      Exch 4
      Exch $R6
      Exch 3
      Exch $R7
      Exch 2
      Exch $R8
      Exch 1
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro WriteRegDWORD2Call _ROOT _KEY _NAME _DWORD _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_NAME}"
  Push "${_DWORD}"
  Push "${_LOG_UNINSTALL}"
  Call WriteRegDWORD2
  !verbose pop
!macroend

!macro un.WriteRegDWORD2Call _ROOT _KEY _NAME _DWORD _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_NAME}"
  Push "${_DWORD}"
  Push "${_LOG_UNINSTALL}"
  Call un.WriteRegDWORD2
  !verbose pop
!macroend

!macro un.WriteRegDWORD2
  !ifndef un.WriteRegDWORD2
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro WriteRegDWORD2

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * Writes a registry string to HKCR using the supplied params and logs the
 * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
 *
 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
 *
 * @param   _ROOT
 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
 *          This will only be used for logging.
 * @param   _KEY
 *          The subkey in relation to the key root.
 * @param   _NAME
 *          The key value name to write to.
 * @param   _STR
 *          The string to write to the key value name.
 * @param   _LOG_UNINSTALL
 *          0 = don't add to uninstall log, 1 = add to uninstall log.
 *
 * $R5 = _ROOT
 * $R6 = _KEY
 * $R7 = _NAME
 * $R8 = _STR
 * $R9 = _LOG_UNINSTALL
 */
!macro WriteRegStrHKCR

  !ifndef ${_MOZFUNC_UN}WriteRegStrHKCR
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}WriteRegStrHKCR "!insertmacro ${_MOZFUNC_UN}WriteRegStrHKCRCall"

    Function ${_MOZFUNC_UN}WriteRegStrHKCR
      Exch $R9
      Exch 1
      Exch $R8
      Exch 2
      Exch $R7
      Exch 3
      Exch $R6
      Exch 4
      Exch $R5

      ClearErrors
      WriteRegStr HKCR "$R6" "$R7" "$R8"

      !ifndef NO_LOG
        ${If} ${Errors}
          ${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
        ${Else}
          ${If} $R9 == 1 ; add to the uninstall log?
            ${LogUninstall} "RegVal: $R5 | $R6 | $R7"
          ${EndIf}
          ${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
        ${EndIf}
      !endif

      Exch $R5
      Exch 4
      Exch $R6
      Exch 3
      Exch $R7
      Exch 2
      Exch $R8
      Exch 1
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro WriteRegStrHKCRCall _ROOT _KEY _NAME _STR _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_NAME}"
  Push "${_STR}"
  Push "${_LOG_UNINSTALL}"
  Call WriteRegStrHKCR
  !verbose pop
!macroend

!macro un.WriteRegStrHKCRCall _ROOT _KEY _NAME _STR _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_NAME}"
  Push "${_STR}"
  Push "${_LOG_UNINSTALL}"
  Call un.WriteRegStrHKCR
  !verbose pop
!macroend

!macro un.WriteRegStrHKCR
  !ifndef un.WriteRegStrHKCR
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro WriteRegStrHKCR

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

!ifndef KEY_SET_VALUE
  !define KEY_SET_VALUE 0x0002
!endif
!ifndef KEY_WOW64_64KEY
  !define KEY_WOW64_64KEY 0x0100
!endif
!ifndef HAVE_64BIT_BUILD
  !define CREATE_KEY_SAM ${KEY_SET_VALUE}
!else
  !define CREATE_KEY_SAM ${KEY_SET_VALUE}|${KEY_WOW64_64KEY}
!endif

/**
 * Creates a registry key. This will log the actions to the install and
 * uninstall logs. Alternatively you can set a registry value to create the key
 * and then delete the value.
 *
 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
 *
 * @param   _ROOT
 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
 * @param   _KEY
 *          The subkey in relation to the key root.
 * @param   _LOG_UNINSTALL
 *          0 = don't add to uninstall log, 1 = add to uninstall log.
 *
 * $R4 = [out] handle to newly created registry key. If this is not a key
 *       located in one of the predefined registry keys this must be closed
 *       with RegCloseKey (this should not be needed unless someone decides to
 *       do something extremely squirrelly with NSIS).
 * $R5 = return value from RegCreateKeyExW (represented by R5 in the system call).
 * $R6 = [in] hKey passed to RegCreateKeyExW.
 * $R7 = _ROOT
 * $R8 = _KEY
 * $R9 = _LOG_UNINSTALL
 */
!macro CreateRegKey

  !ifndef ${_MOZFUNC_UN}CreateRegKey
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}CreateRegKey "!insertmacro ${_MOZFUNC_UN}CreateRegKeyCall"

    Function ${_MOZFUNC_UN}CreateRegKey
      Exch $R9
      Exch 1
      Exch $R8
      Exch 2
      Exch $R7
      Push $R6
      Push $R5
      Push $R4

      StrCmp $R7 "HKCR" +1 +2
      StrCpy $R6 "0x80000000"
      StrCmp $R7 "HKCU" +1 +2
      StrCpy $R6 "0x80000001"
      StrCmp $R7 "HKLM" +1 +2
      StrCpy $R6 "0x80000002"

      ; see definition of RegCreateKey
      System::Call "Advapi32::RegCreateKeyExW(i R6, w R8, i 0, i 0, i 0,\
                                              i ${CREATE_KEY_SAM}, i 0, *i .R4,\
                                              i 0) i .R5"

      !ifndef NO_LOG
        ; if $R5 is not 0 then there was an error creating the registry key.
        ${If} $R5 <> 0
          ${LogMsg} "** ERROR Adding Registry Key: $R7 | $R8 **"
        ${Else}
          ${If} $R9 == 1 ; add to the uninstall log?
            ${LogUninstall} "RegKey: $R7 | $R8"
          ${EndIf}
          ${LogMsg} "Added Registry Key: $R7 | $R8"
        ${EndIf}
      !endif

      StrCmp $R5 0 +1 +2
      System::Call "Advapi32::RegCloseKey(iR4)"

      Pop $R4
      Pop $R5
      Pop $R6
      Exch $R7
      Exch 2
      Exch $R8
      Exch 1
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro CreateRegKeyCall _ROOT _KEY _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_LOG_UNINSTALL}"
  Call CreateRegKey
  !verbose pop
!macroend

!macro un.CreateRegKeyCall _ROOT _KEY _LOG_UNINSTALL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_ROOT}"
  Push "${_KEY}"
  Push "${_LOG_UNINSTALL}"
  Call un.CreateRegKey
  !verbose pop
!macroend

!macro un.CreateRegKey
  !ifndef un.CreateRegKey
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro CreateRegKey

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * Helper for checking for the existence of a registry key.
 * SHCTX is the root key to search.
 *
 * @param   _MAIN_KEY
 *          Sub key to iterate for the key in question
 * @param   _KEY
 *          Key name to search for
 * @return  _RESULT
 *          'true' / 'false' result
 */
!macro CheckIfRegistryKeyExists
  !ifndef CheckIfRegistryKeyExists
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define CheckIfRegistryKeyExists "!insertmacro CheckIfRegistryKeyExistsCall"

    Function CheckIfRegistryKeyExists
      ; stack: main key, key
      Exch $R9 ; main key, stack: old R9, key
      Exch 1   ; stack: key, old R9
      Exch $R8 ; key, stack: old R8, old R9
      Push $R7
      Push $R6
      Push $R5

      StrCpy $R5 "false"
      StrCpy $R7 "0" # loop index
      ${Do}
        EnumRegKey $R6 SHCTX "$R9" "$R7"
        ${If} "$R6" == "$R8"
          StrCpy $R5 "true"
          ${Break}
        ${EndIf}
        IntOp $R7 $R7 + 1
      ${LoopWhile} $R6 != ""
      ClearErrors

      StrCpy $R9 $R5

      Pop $R5
      Pop $R6
      Pop $R7 ; stack: old R8, old R9
      Pop $R8 ; stack: old R9
      Exch $R9 ; stack: result
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro CheckIfRegistryKeyExistsCall _MAIN_KEY _KEY _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Push "${_MAIN_KEY}"
  Call CheckIfRegistryKeyExists
  Pop ${_RESULT}
  !verbose pop
!macroend

/**
 * Read the value of an installer pref that's been set by the product.
 *
 * @param   _KEY ($R1)
 *          Sub key containing all the installer prefs
 *          Usually "Software\Mozilla\${AppName}"
 * @param   _PREF ($R2)
 *          Name of the pref to look up
 * @return  _RESULT ($R3)
 *          'true' or 'false' (only boolean prefs are supported)
 *          If no value exists for the requested pref, the result is 'false'
 */
!macro GetInstallerRegistryPref
  !ifndef ${_MOZFUNC_UN}GetInstallerRegistryPref
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}GetInstallerRegistryPref "!insertmacro GetInstallerRegistryPrefCall"

    Function ${_MOZFUNC_UN}GetInstallerRegistryPref
      ; stack: key, pref
      Exch $R1 ; key, stack: old R1, pref
      Exch 1   ; stack: pref, old R1
      Exch $R2 ; pref, stack: old R2, old R1
      Push $R3

      StrCpy $R3 0

      ; These prefs are always stored in the native registry.
      SetRegView 64

      ClearErrors
      ReadRegDWORD $R3 HKCU "$R1\Installer\$AppUserModelID" "$R2"

      SetRegView lastused

      ${IfNot} ${Errors}
      ${AndIf} $R3 != 0
        StrCpy $R1 "true"
      ${Else}
        StrCpy $R1 "false"
      ${EndIf}

      ; stack: old R3, old R2, old R1
      Pop $R3 ; stack: old R2, old R1
      Pop $R2 ; stack: old R1
      Exch $R1 ; stack: result
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro GetInstallerRegistryPrefCall _KEY _PREF _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_PREF}"
  Push "${_KEY}"
  Call GetInstallerRegistryPref
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetInstallerRegistryPrefCall _KEY _PREF _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_PREF}"
  Push "${_KEY}"
  Call un.GetInstallerRegistryPref
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetInstallerRegistryPref
  !ifndef un.GetInstallerRegistryPref
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro GetInstallerRegistryPref

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

################################################################################
# Macros for adding file and protocol handlers

/**
 * Writes common registry values for a handler using SHCTX.
 *
 * @param   _KEY
 *          The subkey in relation to the key root.
 * @param   _VALOPEN
 *          The path and args to launch the application.
 * @param   _VALICON
 *          The path to the binary that contains the icon group for the default icon
 *          followed by a comma and either the icon group's resource index or the icon
 *          group's resource id prefixed with a minus sign
 * @param   _DISPNAME
 *          The display name for the handler. If emtpy no value will be set.
 * @param   _ISPROTOCOL
 *          Sets protocol handler specific registry values when "true".
 *          Deletes protocol handler specific registry values when "delete".
 *          Otherwise doesn't touch handler specific registry values.
 * @param   _ISDDE
 *          Sets DDE specific registry values when "true".
 *
 * $R3 = string value of the current registry key path.
 * $R4 = _KEY
 * $R5 = _VALOPEN
 * $R6 = _VALICON
 * $R7 = _DISPNAME
 * $R8 = _ISPROTOCOL
 * $R9 = _ISDDE
 */
!macro AddHandlerValues

  !ifndef ${_MOZFUNC_UN}AddHandlerValues
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}AddHandlerValues "!insertmacro ${_MOZFUNC_UN}AddHandlerValuesCall"

    Function ${_MOZFUNC_UN}AddHandlerValues
      Exch $R9
      Exch 1
      Exch $R8
      Exch 2
      Exch $R7
      Exch 3
      Exch $R6
      Exch 4
      Exch $R5
      Exch 5
      Exch $R4
      Push $R3

      StrCmp "$R7" "" +6 +1
      ReadRegStr $R3 SHCTX "$R4" "FriendlyTypeName"

      StrCmp "$R3" "" +1 +3
      WriteRegStr SHCTX "$R4" "" "$R7"
      WriteRegStr SHCTX "$R4" "FriendlyTypeName" "$R7"

      StrCmp "$R8" "true" +1 +2
      WriteRegStr SHCTX "$R4" "URL Protocol" ""
      StrCmp "$R8" "delete" +1 +2
      DeleteRegValue SHCTX "$R4" "URL Protocol"
      StrCpy $R3 ""
      ReadRegDWord $R3 SHCTX "$R4" "EditFlags"
      StrCmp $R3 "" +1 +3  ; Only add EditFlags if a value doesn't exist
      DeleteRegValue SHCTX "$R4" "EditFlags"
      WriteRegDWord SHCTX "$R4" "EditFlags" 0x00000002

      StrCmp "$R6" "" +2 +1
      WriteRegStr SHCTX "$R4\DefaultIcon" "" "$R6"

      StrCmp "$R5" "" +2 +1
      WriteRegStr SHCTX "$R4\shell\open\command" "" "$R5"

!ifdef DDEApplication
      StrCmp "$R9" "true" +1 +11
      WriteRegStr SHCTX "$R4\shell\open\ddeexec" "" "$\"%1$\",,0,0,,,,"
      WriteRegStr SHCTX "$R4\shell\open\ddeexec" "NoActivateHandler" ""
      WriteRegStr SHCTX "$R4\shell\open\ddeexec\Application" "" "${DDEApplication}"
      WriteRegStr SHCTX "$R4\shell\open\ddeexec\Topic" "" "WWW_OpenURL"
      ; The ifexec key may have been added by another application so try to
      ; delete it to prevent it from breaking this app's shell integration.
      ; Also, IE 6 and below doesn't remove this key when it sets itself as the
      ; default handler and if this key exists IE's shell integration breaks.
      DeleteRegKey HKLM "$R4\shell\open\ddeexec\ifexec"
      DeleteRegKey HKCU "$R4\shell\open\ddeexec\ifexec"
!endif

      ClearErrors

      Pop $R3
      Exch $R4
      Exch 5
      Exch $R5
      Exch 4
      Exch $R6
      Exch 3
      Exch $R7
      Exch 2
      Exch $R8
      Exch 1
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro AddHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _ISDDE
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Push "${_VALOPEN}"
  Push "${_VALICON}"
  Push "${_DISPNAME}"
  Push "${_ISPROTOCOL}"
  Push "${_ISDDE}"
  Call AddHandlerValues
  !verbose pop
!macroend

!macro un.AddHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _ISDDE
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Push "${_VALOPEN}"
  Push "${_VALICON}"
  Push "${_DISPNAME}"
  Push "${_ISPROTOCOL}"
  Push "${_ISDDE}"
  Call un.AddHandlerValues
  !verbose pop
!macroend

!macro un.AddHandlerValues
  !ifndef un.AddHandlerValues
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro AddHandlerValues

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * Writes common registry values for a handler that DOES NOT use DDE using SHCTX.
 *
 * @param   _KEY
 *          The key name in relation to the HKCR root. SOFTWARE\Classes is
 *          prefixed to this value when using SHCTX.
 * @param   _VALOPEN
 *          The path and args to launch the application.
 * @param   _VALICON
 *          The path to the binary that contains the icon group for the default icon
 *          followed by a comma and either the icon group's resource index or the icon
 *          group's resource id prefixed with a minus sign
 * @param   _DISPNAME
 *          The display name for the handler. If emtpy no value will be set.
 * @param   _ISPROTOCOL
 *          Sets protocol handler specific registry values when "true".
 *          Deletes protocol handler specific registry values when "delete".
 *          Otherwise doesn't touch handler specific registry values.
 *
 * $R3 = storage for SOFTWARE\Classes
 * $R4 = string value of the current registry key path.
 * $R5 = _KEY
 * $R6 = _VALOPEN
 * $R7 = _VALICON
 * $R8 = _DISPNAME
 * $R9 = _ISPROTOCOL
 */
!macro AddDisabledDDEHandlerValues

  !ifndef ${_MOZFUNC_UN}AddDisabledDDEHandlerValues
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}AddDisabledDDEHandlerValues "!insertmacro ${_MOZFUNC_UN}AddDisabledDDEHandlerValuesCall"

    Function ${_MOZFUNC_UN}AddDisabledDDEHandlerValues
      Exch $R9 ; _ISPROTOCOL
      Exch 1
      Exch $R8 ; FriendlyTypeName
      Exch 2
      Exch $R7 ; icon index
      Exch 3
      Exch $R6 ; shell\open\command
      Exch 4
      Exch $R5 ; reg key
      Push $R4 ;
      Push $R3 ; base reg class

      StrCpy $R3 "SOFTWARE\Classes"
      StrCmp "$R8" "" +6 +1
      ReadRegStr $R4 SHCTX "$R5" "FriendlyTypeName"

      StrCmp "$R4" "" +1 +3
      WriteRegStr SHCTX "$R3\$R5" "" "$R8"
      WriteRegStr SHCTX "$R3\$R5" "FriendlyTypeName" "$R8"

      StrCmp "$R9" "true" +1 +2
      WriteRegStr SHCTX "$R3\$R5" "URL Protocol" ""
      StrCmp "$R9" "delete" +1 +2
      DeleteRegValue SHCTX "$R3\$R5" "URL Protocol"
      StrCpy $R4 ""
      ReadRegDWord $R4 SHCTX "$R3\$R5" "EditFlags"
      StrCmp $R4 "" +1 +3  ; Only add EditFlags if a value doesn't exist
      DeleteRegValue SHCTX "$R3\$R5" "EditFlags"
      WriteRegDWord SHCTX "$R3\$R5" "EditFlags" 0x00000002

      StrCmp "$R7" "" +2 +1
      WriteRegStr SHCTX "$R3\$R5\DefaultIcon" "" "$R7"

      ; Main command handler for the app
      WriteRegStr SHCTX "$R3\$R5\shell" "" "open"
      WriteRegStr SHCTX "$R3\$R5\shell\open\command" "" "$R6"

      ; Drop support for DDE (bug 491947), and remove old dde entries if
      ; they exist.
      ;
      ; Note, changes in SHCTX should propegate to hkey classes root when
      ; current user or local machine entries are written. Windows will also
      ; attempt to propegate entries when a handler is used. CR entries are a
      ; combination of LM and CU, with CU taking priority.
      ;
      ; To disable dde, an empty shell/ddeexec key must be created in current
      ; user or local machine. Unfortunately, settings have various different
      ; behaviors depending on the windows version. The following code attempts
      ; to address these differences.
      ;
      ; IE does not configure ddeexec, so issues with left over ddeexec keys
      ; in LM are reduced. We configure an empty ddeexec key with an empty default
      ; string in CU to be sure.
      ;
      DeleteRegKey SHCTX "SOFTWARE\Classes\$R5\shell\open\ddeexec"
      WriteRegStr SHCTX "SOFTWARE\Classes\$R5\shell\open\ddeexec" "" ""

      ClearErrors

      Pop $R3
      Pop $R4
      Exch $R5
      Exch 4
      Exch $R6
      Exch 3
      Exch $R7
      Exch 2
      Exch $R8
      Exch 1
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro AddDisabledDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Push "${_VALOPEN}"
  Push "${_VALICON}"
  Push "${_DISPNAME}"
  Push "${_ISPROTOCOL}"
  Call AddDisabledDDEHandlerValues
  !verbose pop
!macroend

!macro un.AddDisabledDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Push "${_VALOPEN}"
  Push "${_VALICON}"
  Push "${_DISPNAME}"
  Push "${_ISPROTOCOL}"
  Call un.AddDisabledDDEHandlerValues
  !verbose pop
!macroend

!macro un.AddDisabledDDEHandlerValues
  !ifndef un.AddDisabledDDEHandlerValues
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro AddDisabledDDEHandlerValues

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend


################################################################################
# Macros for handling DLL registration

!macro RegisterDLL DLL

  ; The x64 regsvr32.exe registers x86 DLL's properly so just use it
  ; when installing on an x64 systems even when installing an x86 application.
  ${If} ${RunningX64}
  ${OrIf} ${IsNativeARM64}
    ${DisableX64FSRedirection}
    ExecWait '"$SYSDIR\regsvr32.exe" /s "${DLL}"'
    ${EnableX64FSRedirection}
  ${Else}
    RegDLL "${DLL}"
  ${EndIf}

!macroend

!macro UnregisterDLL DLL

  ; The x64 regsvr32.exe registers x86 DLL's properly so just use it
  ; when installing on an x64 systems even when installing an x86 application.
  ${If} ${RunningX64}
  ${OrIf} ${IsNativeARM64}
    ${DisableX64FSRedirection}
    ExecWait '"$SYSDIR\regsvr32.exe" /s /u "${DLL}"'
    ${EnableX64FSRedirection}
  ${Else}
    UnRegDLL "${DLL}"
  ${EndIf}

!macroend

!define RegisterDLL "!insertmacro RegisterDLL"
!define UnregisterDLL "!insertmacro UnregisterDLL"


################################################################################
# Macros for retrieving special folders

/**
 * These macro get special folder paths directly, without depending on
 * SetShellVarContext.
 *
 * Usage:
 * ${GetProgramsFolder} $0
 * ${GetLocalAppDataFolder} $0
 * ${GetCommonAppDataFolder} $0
 *
 */
!macro GetSpecialFolder _ID _RESULT
  ; This system call gets the directory path. The arguments are:
  ;   A null ptr for hwnd
  ;   t.s puts the output string on the NSIS stack
  ;   id indicates which dir to get
  ;   false for fCreate (i.e. Do not create the folder if it doesn't exist)
  System::Call "Shell32::SHGetSpecialFolderPathW(p 0, t.s, i ${_ID}, i 0)"
  Pop ${_RESULT}
!macroend

!define CSIDL_PROGRAMS          0x0002
!define CSIDL_LOCAL_APPDATA     0x001c
!define CSIDL_COMMON_APPDATA    0x0023

; Current User's Start Menu Programs
!define GetProgramsFolder       "!insertmacro GetSpecialFolder ${CSIDL_PROGRAMS}"

; Current User's Local App Data (e.g. C:\Users\<user>\AppData\Local)
!define GetLocalAppDataFolder   "!insertmacro GetSpecialFolder ${CSIDL_LOCAL_APPDATA}"

; Common App Data (e.g. C:\ProgramData)
!define GetCommonAppDataFolder  "!insertmacro GetSpecialFolder ${CSIDL_COMMON_APPDATA}"

################################################################################
# Macros for retrieving existing install paths

/**
 * Finds a second installation of the application so we can make informed
 * decisions about registry operations. This uses SHCTX to determine the
 * registry hive so you must call SetShellVarContext first.
 *
 * @param   _KEY
 *          The registry subkey (typically this will be Software\Mozilla).
 * @return  _RESULT
 *          false if a second install isn't found, path to the main exe if a
 *          second install is found.
 *
 * $R3 = stores the long path to $INSTDIR
 * $R4 = counter for the outer loop's EnumRegKey
 * $R5 = return value from ReadRegStr and RemoveQuotesFromPath
 * $R6 = return value from GetParent
 * $R7 = return value from the loop's EnumRegKey
 * $R8 = storage for _KEY
 * $R9 = _KEY and _RESULT
 */
!macro GetSecondInstallPath

  !ifndef ${_MOZFUNC_UN}GetSecondInstallPath
    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
    !insertmacro ${_MOZFUNC_UN_TMP}RemoveQuotesFromPath
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
    !undef _MOZFUNC_UN_TMP

    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}GetSecondInstallPath "!insertmacro ${_MOZFUNC_UN}GetSecondInstallPathCall"

    Function ${_MOZFUNC_UN}GetSecondInstallPath
      Exch $R9
      Push $R8
      Push $R7
      Push $R6
      Push $R5
      Push $R4
      Push $R3

      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R3

      StrCpy $R4 0       ; set the counter for the loop to 0
      StrCpy $R8 "$R9"   ; Registry key path to search
      StrCpy $R9 "false" ; default return value

      loop:
      EnumRegKey $R7 SHCTX $R8 $R4
      StrCmp $R7 "" end +1  ; if empty there are no more keys to enumerate
      IntOp $R4 $R4 + 1     ; increment the loop's counter
      ClearErrors
      ReadRegStr $R5 SHCTX "$R8\$R7\bin" "PathToExe"
      IfErrors loop

      ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R5" $R5

      IfFileExists "$R5" +1 loop
      ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
      ${${_MOZFUNC_UN}GetParent} "$R5" $R6
      StrCmp "$R6" "$R3" loop +1
      StrCmp "$R6\${FileMainEXE}" "$R5" +1 loop
      StrCpy $R9 "$R5"

      end:
      ClearErrors

      Pop $R3
      Pop $R4
      Pop $R5
      Pop $R6
      Pop $R7
      Pop $R8
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro GetSecondInstallPathCall _KEY _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Call GetSecondInstallPath
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetSecondInstallPathCall _KEY _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Call un.GetSecondInstallPath
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetSecondInstallPath
  !ifndef un.GetSecondInstallPath
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro GetSecondInstallPath

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * Finds an existing installation path for the application based on the
 * application's executable name so we can default to using this path for the
 * install. If there is zero or more than one installation of the application
 * then we default to the default installation path. This uses SHCTX to
 * determine the registry hive to read from so you must call SetShellVarContext
 * first.
 *
 * @param   _KEY
 *          The registry subkey (typically this will be Software\Mozilla\App Name).
 * @return  _RESULT
 *          false if a single install location for this app name isn't found,
 *          path to the install directory if a single install location is found.
 *
 * $R5 = counter for the loop's EnumRegKey
 * $R6 = return value from EnumRegKey
 * $R7 = return value from ReadRegStr
 * $R8 = storage for _KEY
 * $R9 = _KEY and _RESULT
 */
!macro GetSingleInstallPath

  !ifndef ${_MOZFUNC_UN}GetSingleInstallPath
    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
    !insertmacro ${_MOZFUNC_UN_TMP}RemoveQuotesFromPath
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
    !undef _MOZFUNC_UN_TMP

    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}GetSingleInstallPath "!insertmacro ${_MOZFUNC_UN}GetSingleInstallPathCall"

    Function ${_MOZFUNC_UN}GetSingleInstallPath
      Exch $R9
      Push $R8
      Push $R7
      Push $R6
      Push $R5

      StrCpy $R8 $R9
      StrCpy $R9 "false"
      StrCpy $R5 0  ; set the counter for the loop to 0

      loop:
      ClearErrors
      EnumRegKey $R6 SHCTX $R8 $R5
      IfErrors cleanup
      StrCmp $R6 "" cleanup +1  ; if empty there are no more keys to enumerate
      IntOp $R5 $R5 + 1         ; increment the loop's counter
      ClearErrors
      ReadRegStr $R7 SHCTX "$R8\$R6\Main" "PathToExe"
      IfErrors loop
      ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R7" $R7
      GetFullPathName $R7 "$R7"
      IfErrors loop

      StrCmp "$R9" "false" +1 +3
      StrCpy $R9 "$R7"
      GoTo Loop

      StrCpy $R9 "false"

      cleanup:
      StrCmp $R9 "false" end +1
      ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
      ${${_MOZFUNC_UN}GetParent} "$R9" $R9

      end:
      ClearErrors

      Pop $R5
      Pop $R6
      Pop $R7
      Pop $R8
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro GetSingleInstallPathCall _KEY _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Call GetSingleInstallPath
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetSingleInstallPathCall _KEY _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Call un.GetSingleInstallPath
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.GetSingleInstallPath
  !ifndef un.GetSingleInstallPath
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro GetSingleInstallPath

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * Find the first existing installation for the application.
 * This is similar to GetSingleInstallPath, except that it always returns the
 * first path it finds, instead of an error when more than one path exists.
 *
 * The shell context and the registry view should already have been set.
 *
 * @param   _KEY
 *          The registry subkey (typically Software\Mozilla\App Name).
 * @return  _RESULT
 *          path to the install directory of the first location found, or
 *          the string "false" if no existing installation was found.
 *
 * $R5 = counter for the loop's EnumRegKey
 * $R6 = return value from EnumRegKey
 * $R7 = return value from ReadRegStr
 * $R8 = storage for _KEY
 * $R9 = _KEY and _RESULT
 */
!macro GetFirstInstallPath
  !ifndef ${_MOZFUNC_UN}GetFirstInstallPath
    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
    !insertmacro ${_MOZFUNC_UN_TMP}RemoveQuotesFromPath
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
    !undef _MOZFUNC_UN_TMP

    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}GetFirstInstallPath "!insertmacro ${_MOZFUNC_UN}__GetFirstInstallPathCall"

    Function ${_MOZFUNC_UN}__GetFirstInstallPath
      Exch $R9
      Push $R8
      Push $R7
      Push $R6
      Push $R5

      StrCpy $R8 $R9
      StrCpy $R9 "false"
      StrCpy $R5 0

      ${Do}
        ClearErrors
        EnumRegKey $R6 SHCTX $R8 $R5
        ${If} ${Errors}
        ${OrIf} $R6 == ""
          ${Break}
        ${EndIf}

        IntOp $R5 $R5 + 1

        ReadRegStr $R7 SHCTX "$R8\$R6\Main" "PathToExe"
        ${If} ${Errors}
          ${Continue}
        ${EndIf}

        ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R7" $R7
        GetFullPathName $R7 "$R7"
        ${If} ${Errors}
          ${Continue}
        ${EndIf}

        StrCpy $R9 "$R7"
        ${Break}
      ${Loop}

      ${If} $R9 != "false"
        ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
        ${${_MOZFUNC_UN}GetParent} "$R9" $R9
      ${EndIf}

      Pop $R5
      Pop $R6
      Pop $R7
      Pop $R8
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro __GetFirstInstallPathCall _KEY _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Call __GetFirstInstallPath
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.__GetFirstInstallPathCall _KEY _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Push "${_KEY}"
  Call un.__GetFirstInstallPath
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.__GetFirstInstallPath
  !ifndef un.__GetFirstInstallPath
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro __GetFirstInstallPath

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend


################################################################################
# Macros for working with the file system

/**
 * Attempts to delete a file if it exists. This will fail if the file is in use.
 *
 * @param   _FILE
 *          The path to the file that is to be deleted.
 */
!macro DeleteFile _FILE
  ${If} ${FileExists} "${_FILE}"
    Delete "${_FILE}"
  ${EndIf}
!macroend
!define DeleteFile "!insertmacro DeleteFile"

/**
 * Removes a directory if it exists and is empty.
 *
 * @param   _DIR
 *          The path to the directory that is to be removed.
 */
!macro RemoveDir _DIR
  ${If} ${FileExists} "${_DIR}"
    RmDir "${_DIR}"
  ${EndIf}
!macroend
!define RemoveDir "!insertmacro RemoveDir"

/**
 * Checks whether it is possible to create and delete a directory and a file in
 * the install directory. Creation and deletion of files and directories are
 * checked since a user may have rights for one and not the other. If creation
 * and deletion of a file and a directory are successful this macro will return
 * true... if not, this it return false.
 *
 * @return  _RESULT
 *          true if files and directories can be created and deleted in the
 *          install directory otherwise false.
 *
 * $R8 = temporary filename in the installation directory returned from
 *       GetTempFileName.
 * $R9 = _RESULT
 */
!macro CanWriteToInstallDir

  !ifndef ${_MOZFUNC_UN}CanWriteToInstallDir
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}CanWriteToInstallDir "!insertmacro ${_MOZFUNC_UN}CanWriteToInstallDirCall"

    Function ${_MOZFUNC_UN}CanWriteToInstallDir
      Push $R9
      Push $R8

      StrCpy $R9 "true"

      ; IfFileExists returns false for $INSTDIR when $INSTDIR is the root of a
      ; UNC path so always try to create $INSTDIR
      CreateDirectory "$INSTDIR\"
      GetTempFileName $R8 "$INSTDIR\"

      ${Unless} ${FileExists} $R8 ; Can files be created?
        StrCpy $R9 "false"
        Goto done
      ${EndUnless}

      Delete $R8
      ${If} ${FileExists} $R8 ; Can files be deleted?
        StrCpy $R9 "false"
        Goto done
      ${EndIf}

      CreateDirectory $R8
      ${Unless} ${FileExists} $R8  ; Can directories be created?
        StrCpy $R9 "false"
        Goto done
      ${EndUnless}

      RmDir $R8
      ${If} ${FileExists} $R8  ; Can directories be deleted?
        StrCpy $R9 "false"
        Goto done
      ${EndIf}

      done:

      RmDir "$INSTDIR\" ; Only remove $INSTDIR if it is empty
      ClearErrors

      Pop $R8
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro CanWriteToInstallDirCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call CanWriteToInstallDir
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.CanWriteToInstallDirCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call un.CanWriteToInstallDir
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.CanWriteToInstallDir
  !ifndef un.CanWriteToInstallDir
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro CanWriteToInstallDir

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
 * Checks whether there is sufficient free space available for the installation
 * directory using GetDiskFreeSpaceExW which respects disk quotas. This macro
 * will calculate the size of all sections that are selected, compare that with
 * the free space available, and if there is sufficient free space it will
 * return true... if not, it will return false.
 *
 * @return  _RESULT
 *          "true" if there is sufficient free space otherwise "false".
 *
 * $R5 = return value from SectionGetSize
 * $R6 = return value from SectionGetFlags
 *       return value from an 'and' comparison of SectionGetFlags (1=selected)
 *       return value for lpFreeBytesAvailable from GetDiskFreeSpaceExW
 *       return value for System::Int64Op $R6 / 1024
 *       return value for System::Int64Op $R6 > $R8
 * $R7 = the counter for enumerating the sections
 *       the temporary file name for the directory created under $INSTDIR passed
 *       to GetDiskFreeSpaceExW.
 * $R8 = sum in KB of all selected sections
 * $R9 = _RESULT
 */
!macro CheckDiskSpace

  !ifndef ${_MOZFUNC_UN}CheckDiskSpace
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}CheckDiskSpace "!insertmacro ${_MOZFUNC_UN}CheckDiskSpaceCall"

    Function ${_MOZFUNC_UN}CheckDiskSpace
      Push $R9
      Push $R8
      Push $R7
      Push $R6
      Push $R5

      ClearErrors

      StrCpy $R9 "true" ; default return value
      StrCpy $R8 "0"    ; sum in KB of all selected sections
      StrCpy $R7 "0"    ; counter for enumerating sections

      ; Enumerate the sections and sum up the sizes of the sections that are
      ; selected.
      SectionGetFlags $R7 $R6
      IfErrors +7 +1
      IntOp $R6 ${SF_SELECTED} & $R6
      IntCmp $R6 0 +3 +1 +1
      SectionGetSize $R7 $R5
      IntOp $R8 $R8 + $R5
      IntOp $R7 $R7 + 1
      GoTo -7

      ; The directory passed to GetDiskFreeSpaceExW must exist for the call to
      ; succeed.  Since the CanWriteToInstallDir macro is called prior to this
      ; macro the call to CreateDirectory will always succeed.

      ; IfFileExists returns false for $INSTDIR when $INSTDIR is the root of a
      ; UNC path so always try to create $INSTDIR
      CreateDirectory "$INSTDIR\"
      GetTempFileName $R7 "$INSTDIR\"
      Delete "$R7"
      CreateDirectory "$R7"

      System::Call 'kernel32::GetDiskFreeSpaceExW(w, *l, *l, *l) i(R7, .R6, ., .) .'

      ; Convert to KB for comparison with $R8 which is in KB
      System::Int64Op $R6 / 1024
      Pop $R6

      System::Int64Op $R6 > $R8
      Pop $R6

      IntCmp $R6 1 end +1 +1
      StrCpy $R9 "false"

      end:
      RmDir "$R7"
      RmDir "$INSTDIR\" ; Only remove $INSTDIR if it is empty

      ClearErrors

      Pop $R5
      Pop $R6
      Pop $R7
      Pop $R8
      Exch $R9
    FunctionEnd

    !verbose pop
  !endif
!macroend

!macro CheckDiskSpaceCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call CheckDiskSpace
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.CheckDiskSpaceCall _RESULT
  !verbose push
  !verbose ${_MOZFUNC_VERBOSE}
  Call un.CheckDiskSpace
  Pop ${_RESULT}
  !verbose pop
!macroend

!macro un.CheckDiskSpace
  !ifndef un.CheckDiskSpace
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN "un."

    !insertmacro CheckDiskSpace

    !undef _MOZFUNC_UN
    !define _MOZFUNC_UN
    !verbose pop
  !endif
!macroend

/**
* Returns the path found within a passed in string. The path is quoted or not
* with the exception of an unquoted non 8dot3 path without arguments that is
* also not a DefaultIcon path, is a 8dot3 path or not, has command line
* arguments, or is a registry DefaultIcon path (e.g. <path to binary>,# where #
* is the icon's resuorce id). The string does not need to be a valid path or
* exist. It is up to the caller to pass in a string of one of the forms noted
* above and to verify existence if necessary.
*
* Examples:
* In:  C:\PROGRA~1\MOZILL~1\FIREFOX.EXE -flag "%1"
* In:  C:\PROGRA~1\MOZILL~1\FIREFOX.EXE,0
* In:  C:\PROGRA~1\MOZILL~1\FIREFOX.EXE
* In:  "C:\PROGRA~1\MOZILL~1\FIREFOX.EXE"
* In:  "C:\PROGRA~1\MOZILL~1\FIREFOX.EXE" -flag "%1"
* Out: C:\PROGRA~1\MOZILL~1\FIREFOX.EXE
*
* In:  "C:\Program Files\Mozilla Firefox\firefox.exe" -flag "%1"
* In:  C:\Program Files\Mozilla Firefox\firefox.exe,0
* In:  "C:\Program Files\Mozilla Firefox\firefox.exe"
* Out: C:\Program Files\Mozilla Firefox\firefox.exe
*
* @param   _IN_PATH
*          The string containing the path.
* @param   _OUT_PATH
*          The register to store the path to.
*
* $R7 = counter for the outer loop's EnumRegKey
* $R8 = return value from ReadRegStr
* $R9 = _IN_PATH and _OUT_PATH
*/
!macro GetPathFromString

  !ifndef ${_MOZFUNC_UN}GetPathFromString
    !verbose push
    !verbose ${_MOZFUNC_VERBOSE}
    !define ${_MOZFUNC_UN}GetPathFromString "!insertmacro ${_MOZFUNC_UN}GetPathFromStringCall"

    Function ${_MOZFUNC_UN}GetPathFromString
      Exch $R9
      Push $R8
      Push $R7

      StrCpy $R7 0          ; Set the counter to 0.

      ; Handle quoted paths with arguments.
      StrCpy $R8 $R9 1      ; Copy the first char.
      StrCmp $R8 '"' +2 +1  ; Is it a "?
      StrCmp $R8 "'" +1 +9  ; Is it a '?
      StrCpy $R9 $R9 "" 1   ; Remove the first char.
      IntOp $R7 $R7 + 1     ; Increment the counter.
      StrCpy $R8 $R9 1 $R7  ; Starting from the counter copy the next char.
      StrCmp $R8 "" end +1  ; Are there no more chars?
--> --------------------

--> maximum size reached

--> --------------------

[ Verzeichnis aufwärts0.41unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge