summaryrefslogtreecommitdiffstats
path: root/packaging/win32/macros
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:29:01 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:29:01 +0000
commit35a96bde514a8897f6f0fcc41c5833bf63df2e2a (patch)
tree657d15a03cc46bd099fc2c6546a7a4ad43815d9f /packaging/win32/macros
parentInitial commit. (diff)
downloadinkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.tar.xz
inkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.zip
Adding upstream version 1.0.2.upstream/1.0.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'packaging/win32/macros')
-rw-r--r--packaging/win32/macros/AdvUninstLog.nsh437
-rw-r--r--packaging/win32/macros/AdvUninstLog.txt121
-rw-r--r--packaging/win32/macros/RequireLatestNSIS.nsh4
-rw-r--r--packaging/win32/macros/SHMessageBoxCheck.nsh94
-rw-r--r--packaging/win32/macros/ifexist.nsh36
5 files changed, 692 insertions, 0 deletions
diff --git a/packaging/win32/macros/AdvUninstLog.nsh b/packaging/win32/macros/AdvUninstLog.nsh
new file mode 100644
index 0000000..a932aa8
--- /dev/null
+++ b/packaging/win32/macros/AdvUninstLog.nsh
@@ -0,0 +1,437 @@
+ ;_____________________________ HEADER FILE BEGIN ____________________________
+
+ # Advanced Uninstall Log NSIS header
+ # Version 1.0 2007-01-31
+ # By Red Wine (http://nsis.sf.net/User:Red_Wine)
+
+ # Usage: See included examples Uninstall_Log_Default_UI.nsi - Uninstall_Log_Modern_UI.nsi
+
+!verbose push
+ !verbose 3
+
+!ifndef ADVANCED_UNINSTALL.LOG_NSH
+ !define ADVANCED_UNINSTALL.LOG_NSH
+
+!ifndef INSTDIR_REG_ROOT | INSTDIR_REG_KEY
+ !error "You must properly define both INSTDIR_REG_ROOT and INSTDIR_REG_KEY"
+!endif
+
+!ifndef UNINSTALL_LOG
+ !define UNINSTALL_LOG "Uninstall"
+!endif
+
+!ifndef UNINST_LOG_VERBOSE
+ !define UNINST_LOG_VERBOSE "3"
+!endif
+
+!verbose pop
+
+!echo "Advanced Uninstall Log NSIS header v1.0 2007-01-31 by Red Wine (http://nsis.sf.net/User:Red_Wine)"
+
+!verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+!define UNINST_EXE "$INSTDIR\${UNINSTALL_LOG}.exe"
+!define UNINST_DAT "$INSTDIR\${UNINSTALL_LOG}.dat"
+!define UNLOG_PART "$PLUGINSDIR\part."
+!define UNLOG_TEMP "$PLUGINSDIR\unlog.tmp"
+!define EXCLU_LIST "$PLUGINSDIR\exclude.tmp"
+!define UNLOG_HEAD "=========== Uninstaller Log please do not edit this file ==========="
+
+ var unlog_tmp_0
+ var unlog_tmp_1
+ var unlog_tmp_2
+ var unlog_tmp_3
+ var unlog_error
+
+!include FileFunc.nsh
+!include TextFunc.nsh
+
+!insertmacro Locate
+!insertmacro un.Locate
+!insertmacro DirState
+!insertmacro un.DirState
+!insertmacro FileJoin
+!insertmacro TrimNewLines
+!insertmacro un.TrimNewLines
+
+;.............................. Uninstaller Macros ..............................
+
+!macro UNINSTALL.LOG_BEGIN_UNINSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ IfFileExists "${UNINST_DAT}" +3
+ MessageBox MB_ICONSTOP|MB_OK "${UNINST_DAT} not found, unable to perform uninstall." /SD IDOK
+ Quit
+
+ StrCmp "$PLUGINSDIR" "" 0 +2
+ InitPluginsDir
+
+ CopyFiles "${UNINST_DAT}" "${UNLOG_TEMP}"
+ FileOpen $unlog_tmp_2 "${UNLOG_TEMP}" r
+
+ !verbose pop
+!macroend
+
+
+!macro UNINSTALL.LOG_END_UNINSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ FileClose $unlog_tmp_2
+ DeleteRegValue ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}" "${UNINSTALL_LOG}.dat"
+ DeleteRegValue ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}" "${UNINSTALL_LOG}Directory"
+
+ !verbose pop
+!macroend
+
+
+!macro UNINSTALL.LOG_UNINSTALL TargetDir
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ !ifndef INTERACTIVE_UNINSTALL & UNATTENDED_UNINSTALL
+ !error "You must insert either Interactive or Unattended Uninstall neither both, neither none."
+ !endif
+
+ !ifdef INTERACTIVE_UNINSTALL
+ GetTempFileName $unlog_tmp_5 "$PLUGINSDIR"
+ FileOpen $unlog_tmp_4 "$unlog_tmp_5" a
+ !endif
+
+ ${PerfomUninstall} "${TargetDir}" "${UnLog_Uninstall_CallBackFunc}"
+
+ !ifdef INTERACTIVE_UNINSTALL
+ FileClose $unlog_tmp_4
+ !endif
+
+ !verbose pop
+!macroend
+
+
+!define PerfomUninstall "!insertmacro PERFORMUNINSTALL"
+
+!macro PERFORMUNINSTALL TargetDir UninstCallBackFunc
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ !define ID ${__LINE__}
+
+ ${un.Locate} "${TargetDir}" "/L=F" "${UninstCallBackFunc}"
+
+ loop_${ID}:
+
+ StrCpy $unlog_tmp_1 0
+
+ ${un.Locate} "${TargetDir}" "/L=DE" "${UninstCallBackFunc}"
+ StrCmp $unlog_tmp_1 "0" 0 loop_${ID}
+
+ ${un.DirState} "${TargetDir}" $unlog_tmp_0
+ StrCmp "$unlog_tmp_0" "0" 0 +2
+ RmDir "${TargetDir}"
+
+ IfErrors 0 +2
+ MessageBox MB_ICONEXCLAMATION|MB_OK "${UNINSTALL_LOG} Log error" /SD IDOK
+
+ !undef ID
+
+ !verbose pop
+!macroend
+
+
+!macro INTERACTIVE_UNINSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ !ifdef INTERACTIVE_UNINSTALL
+ !error "INTERACTIVE_UNINSTALL is already defined"
+ !endif
+
+ var unlog_tmp_4
+ var unlog_tmp_5
+
+ !define INTERACTIVE_UNINSTALL
+
+ !ifdef INTERACTIVE_UNINSTALL & UNATTENDED_UNINSTALL
+ !error "You must insert either Interactive or Unattended Uninstall neither both, neither none."
+ !endif
+
+ !ifdef UnLog_Uninstall_CallBackFunc
+ !undef UnLog_Uninstall_CallBackFunc
+ !endif
+
+ !ifndef UnLog_Uninstall_CallBackFunc
+ !insertmacro UNINSTALL.LOG_UNINSTALL_INTERACTIVE
+ !define UnLog_Uninstall_CallBackFunc "un._LocateCallBack_Function_Interactive"
+ !endif
+
+ !verbose pop
+!macroend
+
+
+!macro UNATTENDED_UNINSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ !ifdef UNATTENDED_UNINSTALL
+ !error "UNATTENDED_UNINSTALL is already defined"
+ !endif
+
+ !define UNATTENDED_UNINSTALL
+
+ !ifdef INTERACTIVE_UNINSTALL & UNATTENDED_UNINSTALL
+ !error "You must insert either Interactive or Unattended Uninstall neither both, neither none."
+ !endif
+
+ !ifdef UnLog_Uninstall_CallBackFunc
+ !undef UnLog_Uninstall_CallBackFunc
+ !endif
+
+ !ifndef UnLog_Uninstall_CallBackFunc
+ !insertmacro UNINSTALL.LOG_UNINSTALL_UNATTENDED
+ !define UnLog_Uninstall_CallBackFunc "un._LocateCallBack_Function_Unattended"
+ !endif
+
+ !verbose pop
+!macroend
+
+
+!macro UNINSTALL.LOG_UNINSTALL_UNATTENDED
+
+ Function un._LocateCallBack_Function_Unattended
+ start:
+ FileRead $unlog_tmp_2 "$unlog_tmp_3" ${NSIS_MAX_STRLEN}
+ ${un.TrimNewLines} "$unlog_tmp_3" "$unlog_tmp_3"
+ StrCmp "$unlog_tmp_3" "$R9" islog
+ IfErrors nolog
+ goto start
+
+ islog:
+ IfFileExists "$R9\*.*" isdir
+
+ isfile:
+ Delete "$R9"
+ goto end
+
+ isdir:
+ RmDir "$R9"
+ IntOp $unlog_tmp_1 $unlog_tmp_1 + 1
+ goto end
+
+ nolog:
+ ClearErrors
+ StrCmp "$R9" "${UNINST_EXE}" isfile
+ StrCmp "$R9" "${UNINST_DAT}" isfile
+
+ end:
+ FileSeek $unlog_tmp_2 0 SET
+ Push $unlog_tmp_0
+ FunctionEnd
+
+!macroend
+
+
+!macro UNINSTALL.LOG_UNINSTALL_INTERACTIVE
+
+ Function un._LocateCallBack_Function_Interactive
+ start:
+ FileRead $unlog_tmp_2 "$unlog_tmp_3" ${NSIS_MAX_STRLEN}
+ ${un.TrimNewLines} "$unlog_tmp_3" "$unlog_tmp_3"
+ StrCmp "$unlog_tmp_3" "$R9" islog
+ IfErrors nolog
+ goto start
+
+ islog:
+ IfFileExists "$R9\*.*" isdir
+
+ isfile:
+ Delete "$R9"
+ goto end
+
+ isdir:
+ RmDir "$R9"
+ IntOp $unlog_tmp_1 $unlog_tmp_1 + 1
+ goto end
+
+ nolog:
+ ClearErrors
+ FileSeek $unlog_tmp_4 0 SET
+ read:
+ FileRead $unlog_tmp_4 "$unlog_tmp_3"
+ ${un.TrimNewLines} "$unlog_tmp_3" "$unlog_tmp_3"
+ StrCmp "$unlog_tmp_3" "$R9" end
+ IfErrors +2
+ goto read
+ ClearErrors
+ StrCmp "$R9" "${UNINST_EXE}" isfile
+ StrCmp "$R9" "${UNINST_DAT}" isfile
+ IfFileExists "$R9\*.*" msgdir
+
+ MessageBox MB_ICONQUESTION|MB_YESNO \
+ 'Delete File "$R9"?' /SD IDNO IDYES isfile IDNO nodel
+
+ msgdir:
+ MessageBox MB_ICONQUESTION|MB_YESNO \
+ 'Delete Directory "$R9"?' /SD IDNO IDYES isdir IDNO nodel
+
+ nodel:
+ FileSeek $unlog_tmp_4 0 END
+ FileWrite $unlog_tmp_4 "$R9$\r$\n"
+
+ end:
+ FileSeek $unlog_tmp_2 0 SET
+ Push $unlog_tmp_0
+ FunctionEnd
+
+!macroend
+
+;................................. Installer Macros .................................
+
+!macro UNINSTALL.LOG_INSTALL_UNATTENDED
+
+ Function _LocateCallBack_Function_Install
+ loop:
+ FileRead $unlog_tmp_2 "$unlog_tmp_3" ${NSIS_MAX_STRLEN}
+ ${TrimNewLines} "$unlog_tmp_3" "$unlog_tmp_3"
+ IfErrors 0 +4
+ ClearErrors
+ FileSeek $unlog_tmp_2 0 SET
+ goto next
+ StrCmp "$R9" "$unlog_tmp_3" end
+ goto loop
+ next:
+ FileWrite $unlog_tmp_1 "$R9$\r$\n"
+ end:
+ Push $unlog_tmp_0
+ FunctionEnd
+
+!macroend
+
+
+!ifdef UnLog_Install_Func_CallBack
+ !undef UnLog_Install_Func_CallBack
+!endif
+
+!ifndef UnLog_Install_Func_CallBack
+ !insertmacro UNINSTALL.LOG_INSTALL_UNATTENDED
+ !define UnLog_Install_Func_CallBack "_LocateCallBack_Function_Install"
+!endif
+
+
+!macro UNINSTALL.LOG_PREPARE_INSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ Push $0
+ Push $1
+ ClearErrors
+ ReadRegStr "$0" ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}" "${UNINSTALL_LOG}Directory"
+ IfErrors next
+ ${DirState} "$0" $1
+ StrCmp "$1" "-1" next
+ StrCmp "$1" "0" next
+ IfFileExists "$0\${UNINSTALL_LOG}.dat" next
+ MessageBox MB_ICONEXCLAMATION|MB_OK \
+ "Previous installation detected at $0.$\n\
+ Required file ${UNINSTALL_LOG}.dat is missing.$\n$\nIt is highly recommended \
+ to select an empty directory and perform a fresh installation." /SD IDOK
+ StrCpy $unlog_error "error"
+
+ next:
+ ClearErrors
+ StrCmp "$PLUGINSDIR" "" 0 +2
+ InitPluginsDir
+
+ GetTempFileName "$1"
+ FileOpen $0 "$1" w
+ FileWrite $0 "${UNLOG_HEAD}$\r$\n"
+ FileClose $0
+ Rename "$1" "${UNLOG_TEMP}"
+ Pop $1
+ Pop $0
+
+ !verbose pop
+!macroend
+
+
+!macro UNINSTALL.LOG_UPDATE_INSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ Delete "${UNINST_DAT}"
+ Rename "${UNLOG_TEMP}" "${UNINST_DAT}"
+ WriteUninstaller "${UNINST_EXE}"
+ WriteRegStr ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}" "${UNINSTALL_LOG}.dat" "${UNINST_DAT}"
+ WriteRegStr ${INSTDIR_REG_ROOT} "${INSTDIR_REG_KEY}" "${UNINSTALL_LOG}Directory" "$INSTDIR"
+
+ !verbose pop
+!macroend
+
+
+!define uninstall.log_install "!insertmacro UNINSTALL.LOG_INSTALL"
+
+!macro UNINSTALL.LOG_INSTALL FileOpenWrite FileOpenRead TargetDir
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ FileOpen $unlog_tmp_1 "${FileOpenWrite}" w
+ FileOpen $unlog_tmp_2 "${FileOpenRead}" r
+
+ ${Locate} "${TargetDir}" "/L=FD" "${UnLog_Install_Func_CallBack}"
+
+ StrCmp $unlog_error "error" 0 +2
+ ClearErrors
+
+ IfErrors 0 +2
+ MessageBox MB_ICONEXCLAMATION|MB_OK "Error creating ${UNINSTALL_LOG} Log." /SD IDOK
+
+ FileClose $unlog_tmp_1
+ FileClose $unlog_tmp_2
+
+ !verbose pop
+!macroend
+
+
+!define uninstall.log_mergeID "!insertmacro UNINSTALL.LOG_MERGE"
+
+!macro UNINSTALL.LOG_MERGE UnlogPart
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ ${FileJoin} "${UNLOG_TEMP}" "${UnlogPart}" "${UNLOG_TEMP}"
+
+ !verbose pop
+!macroend
+
+
+!macro UNINSTALL.LOG_OPEN_INSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ StrCmp $unlog_error "error" +2
+ ${uninstall.log_install} "${EXCLU_LIST}" "${UNINST_DAT}" "$OUTDIR"
+
+ !verbose pop
+!macroend
+
+
+!macro UNINSTALL.LOG_CLOSE_INSTALL
+ !verbose push
+ !verbose ${UNINST_LOG_VERBOSE}
+
+ !define ID ${__LINE__}
+
+ ${uninstall.log_install} "${UNLOG_PART}${ID}" "${EXCLU_LIST}" "$OUTDIR"
+ ${uninstall.log_mergeID} "${UNLOG_PART}${ID}"
+
+ !undef ID
+
+ !verbose pop
+!macroend
+
+!endif
+
+!verbose pop
+ ;_____________________________ HEADER FILE END ____________________________
+
diff --git a/packaging/win32/macros/AdvUninstLog.txt b/packaging/win32/macros/AdvUninstLog.txt
new file mode 100644
index 0000000..74cd509
--- /dev/null
+++ b/packaging/win32/macros/AdvUninstLog.txt
@@ -0,0 +1,121 @@
+Overview
+
+Advanced Uninstall Log for NSIS was born in the need to cover a specific gap.
+It's been discussed fairly enough that the File /r command is very useful
+in cases when developers want to add a huge amount of sub directories and
+files, nevertheless it has the disadvantage that such an installation should
+be uninstalled with RmDir /r which is risky and removes also data that has
+been added/created later within the installation folder.
+
+
+
+
+About Advanced Uninstall Log.
+
+Advanced Uninstall Log is a macro system provided in a NSIS header that
+is able to monitor an installation and build an uninstall log file which
+is used by the uninstaller to uninstall files/directories that have been
+added within specific installation blocks.
+
+This means that files which have been installed outside these blocks,
+or added later either by the user or application's activities, ignored
+by the uninstaller.
+
+Moreover files that might exist into the target directory prior the current
+installation, ignored as well.
+
+Advanced Uninstall Log creates an uninstall log that removes only files that
+have been installed and optionally interacts with users for every other file
+and/or directory has found in installation folder and requires permission to
+remove these files/directories.
+
+It is enhanced as well to support updates, e.g. if the installer later would
+update the installation by adding new data, the uninstaller would remove the
+new data that has been added by the installer, without bothering users about.
+
+
+
+
+Features
+
+If target installation folder exists and contains files and/or directories
+they all preserved from being uninstalled.
+
+Uninstaller removes data that has been added within specific installation
+blocks, preserving all other data that has been created/added outside of
+these installation blocks. See included examples for details.
+
+Supports unlimited updates/reinstallations.
+
+Supports two uninstaller modes. Interactive mode requires confirmation
+to remove every other file except those files that have been installed.
+Unattended mode leaves intact every other file without bothering users.
+
+In case when uninstall log (uninstall.dat) has been removed manually instead
+of execute uninstaller, if users attempt to run the installer later, a warning
+issued that they should select a new output folder.
+
+Implements only the included with NSIS release headers FileFunc and TextFunc.
+There is no need for external plugins and headers, adds a very small overhead.
+
+
+
+
+Restrictions
+
+If uninstall log (uninstall.dat) is missing uninstaller won't execute at all.
+
+Due to file create - write procedure that is required in order to add/update
+the uninstall log (uninstall.dat), restricted users on NT based systems won't
+be able to execute the installer.
+
+
+
+
+Disadvantage
+
+Since the header does not implement anything else than the common NSIS release,
+a delay occurs while builds and reads the uninstall log because it needs to
+throw the list several times. Talking for common cases, most likely the delay
+won't be noticeable, however, in cases where the target directory isn't empty
+and contains a large amount of data which will be excluded from uninstall log,
+or added large amount of data after the installation which will be excluded also,
+the delay should be noticeable.
+
+
+
+
+Credits
+
+A very big thanks goes to kichik.
+When my idea of the Advanced Uninstall Log became an NSIS header, it was
+indeed an amateur's attempt to write a flexible and errors free NSIS header.
+Kichik dropped me a dozen of suggestions helping me to achieve my plan.
+However, his main suggestion to eliminate the mentioned above disadvantage,
+still remains untouched by me.
+
+
+
+
+License
+
+This header file is provided 'as-is', without any express or implied warranty.
+In no event will the author be held liable for any damages arising from the use
+of this header file.
+
+Permission is granted to anyone to use this header file for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+ 1. The origin of this header file must not be misrepresented;
+ you must not claim that you wrote the original header file.
+ If you use this header file in a product, an acknowledgment in
+ the product documentation would be appreciated but is not required.
+
+ 2. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original header file.
+
+ 3. This notice may not be removed or altered from any distribution.
+
+
+eof \ No newline at end of file
diff --git a/packaging/win32/macros/RequireLatestNSIS.nsh b/packaging/win32/macros/RequireLatestNSIS.nsh
new file mode 100644
index 0000000..7d6308e
--- /dev/null
+++ b/packaging/win32/macros/RequireLatestNSIS.nsh
@@ -0,0 +1,4 @@
+!searchparse ${NSIS_VERSION} "v" V
+!if ${V} < 3.0
+ !error "You only have NSIS ${V}, but NSIS 3.0 or later is required to support Unicode and Windows 10. Please upgrade to NSIS 3.0 or later and try again."
+!endif
diff --git a/packaging/win32/macros/SHMessageBoxCheck.nsh b/packaging/win32/macros/SHMessageBoxCheck.nsh
new file mode 100644
index 0000000..502923b
--- /dev/null
+++ b/packaging/win32/macros/SHMessageBoxCheck.nsh
@@ -0,0 +1,94 @@
+# SHMessageBoxCheck
+# Works like MessageBox but includes a checkbox that gives the user the option not to show the message box again.
+# In that case the return value (first value on the stack) is always set to the last user choice
+#
+# See
+# http://nsis.sourceforge.net/SHMessageBoxCheck (documentation)
+# https://msdn.microsoft.com/library/windows/desktop/bb773836.aspx (implementation details)
+#
+
+# types to indicate the buttons displayed in the message box
+!define MB_OK 0x00000000
+!define MB_OKCANCEL 0x00000001
+!define MB_ABORTRETRYIGNORE 0x00000002 # not officially supported, use at your own risk!
+!define MB_YESNOCANCEL 0x00000003 # not officially supported, use at your own risk!
+!define MB_YESNO 0x00000004
+!define MB_RETRYCANCEL 0x00000005 # not officially supported, use at your own risk!
+!define MB_CANCELTRYCONTINUE 0x00000006 # not officially supported, use at your own risk!
+!define MB_HELP 0x00004000 # not officially supported, use at your own risk!
+
+# types to display an icon in the message box
+!define MB_ICONHAND 0x00000010
+!define MB_ICONQUESTION 0x00000020 # MS bug: Same as MB_ICONEXCLAMATION
+!define MB_ICONEXCLAMATION 0x00000030
+!define MB_ICONINFORMATION 0x00000040
+
+
+# return values
+!define IDOK 1
+!define IDCANCEL 2
+!define IDABORT 3
+!define IDRETRY 4
+!define IDIGNORE 5
+!define IDYES 6
+!define IDNO 7
+!define IDCONTINUE 11
+!define IDTRYAGAIN 10
+
+
+
+# the user's previous choice (i.e. the button clicked in the message box)
+Var _lastReturnValue
+
+# The value that the call to SHMessageBoxCheck should return when the user chose not to display the message box again
+!define _DEFAULT 9999
+
+# Windows XP does not expose the function name, so we have to specify the function by ordinal value
+!ifdef NSIS_UNICODE
+ !define _SHMessageBoxCheck_Ordinal 191
+!else
+ !define _SHMessageBoxCheck_Ordinal 185
+!endif
+
+
+
+!macro SHMessageBoxCheckInit _UNIQUE_STRING
+ # SHMessageBoxCheck stores the user's choice not to display the message box again in the registry, see
+ # HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain
+ !ifdef _PSZ_REG_VAL
+ !error "Only call SHMessageBoxCheckInit once and make sure to call SHMessageBoxCheckCleanup before using it again"
+ !else
+ # the unique string used to identify this message (and name of the registry value used to store the checkbox status)
+ !define _PSZ_REG_VAL ${_UNIQUE_STRING}
+ !endif
+
+ # make sure the registry value is not yet set (for whatever reason)
+ ${SHMessageBoxCheckCleanup}
+!macroend
+!define SHMessageBoxCheckInit "!insertmacro SHMessageBoxCheckInit"
+
+
+!macro SHMessageBoxCheckCleanup
+ # delete the registry key that is used to store the checkbox status so we can start fresh next time
+ DeleteRegValue HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain" "${_PSZ_REG_VAL}"
+!macroend
+!define SHMessageBoxCheckCleanup "!insertmacro SHMessageBoxCheckCleanup"
+
+
+!macro SHMessageBoxCheck _CAPTION _TEXT _TYPE
+ # this would be the simple way (by name)
+ # System::Call "shlwapi::SHMessageBoxCheck(p $HWNDPARENT, t '${_TEXT}', t '${_CAPTION}', i ${_TYPE}, i ${_DEFAULT}, t '${_PSZ_REG_VAL}') i .r0"
+
+ # for backwards-compatibility we get the process address by specifying the function's ordinal value
+ System::Call "kernel32::GetModuleHandle(t 'shlwapi.dll') p .s"
+ System::Call "kernel32::GetProcAddress(p s, i ${_SHMessageBoxCheck_Ordinal}) p .r0"
+ System::Call "::$0(p $HWNDPARENT, t '${_TEXT}', t '${_CAPTION}', i ${_TYPE}, i ${_DEFAULT}, t '${_PSZ_REG_VAL}') i .r0"
+
+ # save the user's choice (unless the default value was returned - then don't update and return the saved choice)
+ StrCmp $0 ${_DEFAULT} +2 0
+ StrCpy $_lastReturnValue $0
+
+ # push the return value to the stack
+ Push $_lastReturnValue
+!macroend
+!define SHMessageBoxCheck "!insertmacro SHMessageBoxCheck" \ No newline at end of file
diff --git a/packaging/win32/macros/ifexist.nsh b/packaging/win32/macros/ifexist.nsh
new file mode 100644
index 0000000..5a0ea62
--- /dev/null
+++ b/packaging/win32/macros/ifexist.nsh
@@ -0,0 +1,36 @@
+; See http://nsis.sourceforge.net/Check_if_a_file_exists_at_compile_time for documentation
+!macro !ifexist _FILE_NAME
+ !tempfile _TEMPFILE
+ !system `if exist "${_FILE_NAME}" echo !define _FILE_EXISTS > "${_TEMPFILE}"`
+ !include `${_TEMPFILE}`
+ !delfile `${_TEMPFILE}`
+ !undef _TEMPFILE
+ !ifdef _FILE_EXISTS
+ !undef _FILE_EXISTS
+!macroend
+!define !ifexist "!insertmacro !ifexist"
+!macro !ifnexist _FILE_NAME
+ !tempfile _TEMPFILE
+ !system `if not exist "${_FILE_NAME}" echo !define _FILE_EXISTS > "${_TEMPFILE}"`
+ !include `${_TEMPFILE}`
+ !delfile `${_TEMPFILE}`
+ !undef _TEMPFILE
+ !ifdef _FILE_EXISTS
+ !undef _FILE_EXISTS
+!macroend
+!define !ifnexist "!insertmacro !ifnexist"
+
+!macro !defineifexist _FILE_NAME _VAR_NAME _VAR_VALUE
+ !tempfile _TEMPFILE
+ !ifdef NSIS_WIN32_MAKENSIS
+ ; Windows - cmd.exe
+ !system 'if exist "${_FILE_NAME}" echo !define ${_VAR_NAME} ${_VAR_VALUE} > "${_TEMPFILE}"'
+ !else
+ ; Posix - sh
+ !system 'if [ -e "${_FILE_NAME}" ]; then echo "!define ${_VAR_NAME} ${_VAR_VALUE}" > "${_TEMPFILE}"; fi'
+ !endif
+ !include '${_TEMPFILE}'
+ !delfile '${_TEMPFILE}'
+ !undef _TEMPFILE
+!macroend
+!define !defineifexist "!insertmacro !defineifexist"