Source code

Revision control

Copy as Markdown

Other Tools

# 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