From 893c3d7485dde647499b2b36577b441d2dd4020b Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 22 Apr 2024 16:26:16 +0200 Subject: [PATCH] Windows package --- .../singleapplication/singleapplication.cpp | 2 + cmake/install/install.cmake | 89 ++ cmake/install/packaging.cmake.in | 122 ++- cmake/install/windows/NSIS.template.in | 995 ++++++++++++++++++ cmake/install/windows/ReadMe_banner.txt | 6 + cmake/install/windows/appDetailsWindows.rc.in | 40 + cmake/install/windows/install.nsi.in | 87 ++ cmake/install/windows/nsis_banner.bmp | Bin 0 -> 576566 bytes cmake/install/windows/uninstall.nsi.in | 24 + cmake/install/windows/winshortcut.vbs.in | 6 + 10 files changed, 1313 insertions(+), 58 deletions(-) create mode 100644 cmake/install/windows/NSIS.template.in create mode 100644 cmake/install/windows/ReadMe_banner.txt create mode 100644 cmake/install/windows/appDetailsWindows.rc.in create mode 100644 cmake/install/windows/install.nsi.in create mode 100644 cmake/install/windows/nsis_banner.bmp create mode 100644 cmake/install/windows/uninstall.nsi.in create mode 100644 cmake/install/windows/winshortcut.vbs.in diff --git a/Linphone/core/singleapplication/singleapplication.cpp b/Linphone/core/singleapplication/singleapplication.cpp index b8b21049b..2efbb3f73 100644 --- a/Linphone/core/singleapplication/singleapplication.cpp +++ b/Linphone/core/singleapplication/singleapplication.cpp @@ -28,6 +28,8 @@ #include "singleapplication.h" #include "singleapplication_p.h" +#include "tool/Utils.hpp" + /** * @brief Constructor. Checks and fires up LocalServer or closes the program * if another instance already exists diff --git a/cmake/install/install.cmake b/cmake/install/install.cmake index a2a8f83a8..4892dbbfd 100644 --- a/cmake/install/install.cmake +++ b/cmake/install/install.cmake @@ -100,6 +100,20 @@ if(APPLE) install(CODE "MESSAGE(\"MacDeploy install: execute_process(COMMAND ${DEPLOYQT_PROGRAM} ${APPLICATION_OUTPUT_DIR}/${APPLICATION_NAME}.app -qmldir=${LINPHONE_QML_DIR} -no-strip -verbose=2 -always-overwrite) \")") install(CODE "execute_process(COMMAND ${DEPLOYQT_PROGRAM} ${APPLICATION_OUTPUT_DIR}/${APPLICATION_NAME}.app -qmldir=${LINPHONE_QML_DIR} -no-strip -verbose=2 -always-overwrite)") endif() +elseif(WIN32) + set(BIN_ARCH "win32") + if( CMAKE_SIZEOF_VOID_P EQUAL 8) + set(MINGW_PACKAGE_PREFIX "mingw-w64-x86_64-") + set(MINGW_TYPE "mingw64") + set(BIN_ARCH "win64") + else() + set(MINGW_PACKAGE_PREFIX "mingw-w64-i686-") + set(MINGW_TYPE "mingw32") + endif() + find_program(MSYS2_PROGRAM + NAMES msys2_shell.cmd + HINTS "C:/msys64/" + ) endif() # ============================================================================== @@ -145,6 +159,81 @@ if(${ENABLE_APP_PACKAGING}) set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_BINARY_DIR}/cmake/install/macos/cleanCPack.cmake") message(STATUS "Set DragNDrop CPack generator in OUTPUT/Packages") + elseif(WIN32) +############################################## +# WINDOWS +############################################## + set(CPACK_GENERATOR "NSIS") + set(DO_GENERATOR YES) + set(PACKAGE_EXT "exe") + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${PACKAGE_VERSION}-${BIN_ARCH}") + find_program(NSIS_PROGRAM makensis) + if(NOT NSIS_PROGRAM) + + message(STATUS "Installing windows tools for nsis") + execute_process( + COMMAND "${MSYS2_PROGRAM}" "-${MINGW_TYPE}" "-here" "-full-path" "-defterm" "-shell" "sh" "-l" "-c" "pacman -Sy ${MINGW_PACKAGE_PREFIX}nsis --noconfirm --needed" + ) + endif() + set(PACKAGE_EXT "exe") + # Use magic `NSIS.template.in` template from the current source directory to force uninstallation + # and ensure that linphone is not running before installation. + set(CPACK_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/install/windows") + set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}\\\\cmake\\\\install\\\\windows\\\\nsis_banner.bmp") + set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/Linphone/data/icon.ico") + set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/Linphone/data/icon.ico") + set(CPACK_NSIS_DISPLAY_NAME "${APPLICATION_NAME}") # = The display name string that appears in the Windows Add/Remove Program control panel + + if (LINPHONE_MICRO_VERSION)# CPACK_NSIS_PACKAGE_NAME = Title at the top of the installer + set(CPACK_NSIS_PACKAGE_NAME "${APPLICATION_NAME} ${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}.${LINPHONE_MICRO_VERSION}") + else () + set(CPACK_NSIS_PACKAGE_NAME "${APPLICATION_NAME} ${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}") + endif () + set(CPACK_NSIS_URL_INFO_ABOUT ${APPLICATION_URL}) + + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" DOS_STYLE_BINARY_DIR) + string(REPLACE "\\" "\\\\" ESCAPED_DOS_STYLE_BINARY_DIR "${DOS_STYLE_BINARY_DIR}") + configure_file("${CMAKE_SOURCE_DIR}/cmake/install/windows/install.nsi.in" "${CMAKE_CURRENT_BINARY_DIR}/install.nsi" @ONLY) + set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "!include \\\"${ESCAPED_DOS_STYLE_BINARY_DIR}\\\\install.nsi\\\"") + configure_file("${CMAKE_SOURCE_DIR}/cmake/install/windows/uninstall.nsi.in" "${CMAKE_CURRENT_BINARY_DIR}/uninstall.nsi" @ONLY) + set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "!include \\\"${ESCAPED_DOS_STYLE_BINARY_DIR}\\\\uninstall.nsi\\\"") + set(CPACK_NSIS_EXECUTABLES_DIRECTORY "bin") + set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${EXECUTABLE_NAME}.exe") + set(CPACK_NSIS_INSTALLED_ICON_NAME "${CPACK_NSIS_EXECUTABLES_DIRECTORY}/${CPACK_NSIS_MUI_FINISHPAGE_RUN}") + message(STATUS "Set NSIS CPack generator in OUTPUT/Packages") + + + if(LINPHONE_WINDOWS_SIGN_TOOL AND LINPHONE_WINDOWS_SIGN_TIMESTAMP_URL) + find_program(SIGNTOOL ${LINPHONE_WINDOWS_SIGN_TOOL}) + set(TIMESTAMP_URL ${LINPHONE_WINDOWS_SIGN_TIMESTAMP_URL}) + set(SIGN_HASH ${LINPHONE_WINDOWS_SIGN_HASH}) + if (SIGNTOOL) + set(SIGNTOOL_COMMAND ${SIGNTOOL}) + message("Found requested signtool") + set(PERFORM_SIGNING 1) + else () + message(STATUS "Could not find requested signtool! Code signing disabled (${LINPHONE_WINDOWS_SIGN_TOOL})") + endif () + elseif(LINPHONE_WINDOWS_SIGNING_DIR) + # Sign the installer. + set(TIMESTAMP_URL "http://timestamp.digicert.com") + set(PFX_FILE "${LINPHONE_WINDOWS_SIGNING_DIR}/linphone.pfx") + set(PASSPHRASE_FILE "${LINPHONE_WINDOWS_SIGNING_DIR}/passphrase.txt") + get_filename_component(WINSDK_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" REALPATH CACHE) + find_program(SIGNTOOL signtool PATHS ${WINSDK_DIR}/${CMAKE_INSTALL_BINDIR}) + if (EXISTS ${PFX_FILE}) + if (SIGNTOOL) + set(SIGNTOOL_COMMAND ${SIGNTOOL}) + message("Found signtool and certificate ${PFX_FILE}") + set(PERFORM_SIGNING 1) + else () + message(STATUS "Could not find signtool! Code signing disabled (${SIGNTOOL})") + endif () + else () + message(STATUS "No signtool certificate found; assuming development machine (${PFX_FILE})") + endif () + endif () + else() ############################################## # LINUX diff --git a/cmake/install/packaging.cmake.in b/cmake/install/packaging.cmake.in index 12e4c56d4..047a53cc3 100644 --- a/cmake/install/packaging.cmake.in +++ b/cmake/install/packaging.cmake.in @@ -28,64 +28,70 @@ set(DO_APPIMAGE @DO_APPIMAGE@) if (NOT "${CMAKE_INSTALL_PREFIX}" MATCHES .*/_CPack_Packages/.*) - if(DO_TGZ) - execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G TGZ RESULT_VARIABLE CPACK_COMMAND_RESULT) - if(CPACK_COMMAND_RESULT) - message(FATAL_ERROR "Failed to create TGZ package!") - endif() - endif() - if(DO_TZ) - execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G TZ RESULT_VARIABLE CPACK_COMMAND_RESULT) - if(CPACK_COMMAND_RESULT) - message(FATAL_ERROR "Failed to create TZ package!") - endif() - endif() - if(DO_STGZ) - execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G STGZ RESULT_VARIABLE CPACK_COMMAND_RESULT) - if(CPACK_COMMAND_RESULT) - message(FATAL_ERROR "Failed to create STGZ package!") - endif() - endif() - if(DO_DRAGNDROP) - execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G DragNDrop RESULT_VARIABLE CPACK_COMMAND_RESULT) - if(CPACK_COMMAND_RESULT) - message(FATAL_ERROR "Failed to create DragAndDrop package!") - endif() - endif() - if(DO_GENERATOR) - execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G @CPACK_GENERATOR@ -C @CMAKE_BUILD_TYPE@ RESULT_VARIABLE CPACK_COMMAND_RESULT) - if(CPACK_COMMAND_RESULT) - message(FATAL_ERROR "Failed to create @CPACK_GENERATOR@ package!") - endif() - endif() - if(DO_APPIMAGE) - set(ENV{QML_SOURCES_PATHS} "@LINPHONE_QML_DIR@") - set(ENV{QML_MODULES_PATHS} "@LINPHONE_QML_DIR@") - execute_process( COMMAND mkdir -p "WORK/Packages/AppImageDir/" WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/..") - execute_process( COMMAND cp -rf "@LINPHONE_QML_DIR@" "WORK/Packages/AppImageDir/" WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/..") - execute_process( COMMAND "@CMAKE_SOURCE_DIR@/cmake/install/create_appimage.sh" @EXECUTABLE_NAME@ @CPACK_PACKAGE_FILE_NAME@ @QT_PATH@ @LINPHONE_BUILDER_SIGNING_IDENTITY@ RESULT_VARIABLE CPACK_COMMAND_RESULT WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/.." ) - if(CPACK_COMMAND_RESULT) - message(FATAL_ERROR "Failed to create AppImage package with this command : '@CMAKE_CURRENT_SOURCE_DIR@/../../tools/create_appimage.sh @EXECUTABLE_NAME@ @QT_PATH@ @LINPHONEAPP_VERSION@' at @CMAKE_INSTALL_PREFIX@/..\nMaybe the .appimage already exists and is running. Please remove the file before packaging if it is the case.") - endif() - endif() - if (@PERFORM_SIGNING@) - if(@PASSPHRASE_FILE@) - execute_process( - COMMAND "@CMAKE_SOURCE_DIR@/cmake/install/sign_package.bat" 1 "@PASSPHRASE_FILE@" "@SIGNTOOL_COMMAND@" "@PFX_FILE@" "@TIMESTAMP_URL@" @CPACK_PACKAGE_FILE_NAME@.@PACKAGE_EXT@ - RESULT_VARIABLE SIGNING_RESULT WORKING_DIRECTORY "@CPACK_PACKAGE_DIRECTORY@" - ) - else() - execute_process( - COMMAND "@CMAKE_SOURCE_DIR@/cmake/install/sign_package.bat" 2 "@SIGNTOOL_COMMAND@" "@TIMESTAMP_URL@" @SIGN_HASH@ @CPACK_PACKAGE_FILE_NAME@.@PACKAGE_EXT@ - RESULT_VARIABLE SIGNING_RESULT WORKING_DIRECTORY "@CPACK_PACKAGE_DIRECTORY@" - ) - endif() - if(SIGNING_RESULT) - message(FATAL_ERROR "Failed to sign the package! ${SIGNING_RESULT} ${RESULT_VARIABLE}") - endif() - endif () - execute_process( COMMAND mkdir -p "@CMAKE_INSTALL_PREFIX@/Packages/" WORKING_DIRECTORY "@CMAKE_BINARY_DIR@") - execute_process( COMMAND bash -c "cp -rf @CMAKE_BINARY_DIR@/*.@PACKAGE_EXT@ @CMAKE_INSTALL_PREFIX@/Packages" WORKING_DIRECTORY "@CMAKE_BINARY_DIR@") + if(DO_TGZ) + execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G TGZ RESULT_VARIABLE CPACK_COMMAND_RESULT) + if(CPACK_COMMAND_RESULT) + message(FATAL_ERROR "Failed to create TGZ package!") + endif() + endif() + if(DO_TZ) + execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G TZ RESULT_VARIABLE CPACK_COMMAND_RESULT) + if(CPACK_COMMAND_RESULT) + message(FATAL_ERROR "Failed to create TZ package!") + endif() + endif() + if(DO_STGZ) + execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G STGZ RESULT_VARIABLE CPACK_COMMAND_RESULT) + if(CPACK_COMMAND_RESULT) + message(FATAL_ERROR "Failed to create STGZ package!") + endif() + endif() + if(DO_DRAGNDROP) + execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G DragNDrop RESULT_VARIABLE CPACK_COMMAND_RESULT) + if(CPACK_COMMAND_RESULT) + message(FATAL_ERROR "Failed to create DragAndDrop package!") + endif() + endif() + if(DO_GENERATOR) + execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G @CPACK_GENERATOR@ -C @CMAKE_BUILD_TYPE@ RESULT_VARIABLE CPACK_COMMAND_RESULT) + if(CPACK_COMMAND_RESULT) + message(FATAL_ERROR "Failed to create @CPACK_GENERATOR@ package!") + endif() + endif() + if(DO_APPIMAGE) + set(ENV{QML_SOURCES_PATHS} "@LINPHONE_QML_DIR@") + set(ENV{QML_MODULES_PATHS} "@LINPHONE_QML_DIR@") + execute_process( COMMAND mkdir -p "WORK/Packages/AppImageDir/" WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/..") + execute_process( COMMAND cp -rf "@LINPHONE_QML_DIR@" "WORK/Packages/AppImageDir/" WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/..") + execute_process( COMMAND "@CMAKE_SOURCE_DIR@/cmake/install/create_appimage.sh" @EXECUTABLE_NAME@ @CPACK_PACKAGE_FILE_NAME@ @QT_PATH@ @LINPHONE_BUILDER_SIGNING_IDENTITY@ RESULT_VARIABLE CPACK_COMMAND_RESULT WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/.." ) + if(CPACK_COMMAND_RESULT) + message(FATAL_ERROR "Failed to create AppImage package with this command : '@CMAKE_CURRENT_SOURCE_DIR@/../../tools/create_appimage.sh @EXECUTABLE_NAME@ @QT_PATH@ @LINPHONEAPP_VERSION@' at @CMAKE_INSTALL_PREFIX@/..\nMaybe the .appimage already exists and is running. Please remove the file before packaging if it is the case.") + endif() + endif() + if (@PERFORM_SIGNING@) + if(@PASSPHRASE_FILE@) + execute_process( + COMMAND "@CMAKE_SOURCE_DIR@/cmake/install/sign_package.bat" 1 "@PASSPHRASE_FILE@" "@SIGNTOOL_COMMAND@" "@PFX_FILE@" "@TIMESTAMP_URL@" @CPACK_PACKAGE_FILE_NAME@.@PACKAGE_EXT@ + RESULT_VARIABLE SIGNING_RESULT WORKING_DIRECTORY "@CPACK_PACKAGE_DIRECTORY@" + ) + else() + execute_process( + COMMAND "@CMAKE_SOURCE_DIR@/cmake/install/sign_package.bat" 2 "@SIGNTOOL_COMMAND@" "@TIMESTAMP_URL@" @SIGN_HASH@ @CPACK_PACKAGE_FILE_NAME@.@PACKAGE_EXT@ + RESULT_VARIABLE SIGNING_RESULT WORKING_DIRECTORY "@CPACK_PACKAGE_DIRECTORY@" + ) + endif() + if(SIGNING_RESULT) + message(FATAL_ERROR "Failed to sign the package! ${SIGNING_RESULT} ${RESULT_VARIABLE}") + endif() + endif () + execute_process( COMMAND mkdir -p "@CMAKE_INSTALL_PREFIX@/Packages/" WORKING_DIRECTORY "@CMAKE_BINARY_DIR@") + message(STATUS "Copy @CPACK_PACKAGE_FILE_NAME@.@PACKAGE_EXT@ into @CMAKE_INSTALL_PREFIX@/Packages") + if(WIN32)# Windows special case because bash try to open Linux distribution + execute_process( COMMAND cp -rf @CPACK_PACKAGE_FILE_NAME@.@PACKAGE_EXT@ @CMAKE_INSTALL_PREFIX@/Packages WORKING_DIRECTORY "@CMAKE_BINARY_DIR@") + else() + execute_process( COMMAND bash -c "cp -rf @CPACK_PACKAGE_FILE_NAME@.@PACKAGE_EXT@ @CMAKE_INSTALL_PREFIX@/Packages" WORKING_DIRECTORY "@CMAKE_BINARY_DIR@") + endif() + message(STATUS "End of Packaging") endif () diff --git a/cmake/install/windows/NSIS.template.in b/cmake/install/windows/NSIS.template.in new file mode 100644 index 000000000..4bfdfe54f --- /dev/null +++ b/cmake/install/windows/NSIS.template.in @@ -0,0 +1,995 @@ +; CPack install script designed for a nmake build + +;-------------------------------- +; You must define these values + + !define VERSION "@CPACK_PACKAGE_VERSION@" + !define PATCH "@CPACK_PACKAGE_VERSION_PATCH@" + !define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@" + +;-------------------------------- +;Variables + + Var MUI_TEMP + Var STARTMENU_FOLDER + Var SV_ALLUSERS + Var START_MENU + Var DO_NOT_ADD_TO_PATH + Var ADD_TO_PATH_ALL_USERS + Var ADD_TO_PATH_CURRENT_USER + Var INSTALL_DESKTOP + Var IS_DEFAULT_INSTALLDIR +;-------------------------------- +;Include Modern UI + + !include "MUI.nsh" + + ;Default installation folder + InstallDir "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + +;-------------------------------- +;General + + ;Name and file + !include "FileFunc.nsh" + Name "@CPACK_NSIS_PACKAGE_NAME@" + OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@" + + ;Set compression + SetCompressor @CPACK_NSIS_COMPRESSOR@ + + ;Require administrator access + RequestExecutionLevel admin + +@CPACK_NSIS_DEFINES@ + + !include Sections.nsh + +;--- Component support macros: --- +; The code for the add/remove functionality is from: +; http://nsis.sourceforge.net/Add/Remove_Functionality +; It has been modified slightly and extended to provide +; inter-component dependencies. +Var AR_SecFlags +Var AR_RegFlags +@CPACK_NSIS_SECTION_SELECTED_VARS@ + +; Loads the "selected" flag for the section named SecName into the +; variable VarName. +!macro LoadSectionSelectedIntoVar SecName VarName + SectionGetFlags ${${SecName}} $${VarName} + IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits +!macroend + +; Loads the value of a variable... can we get around this? +!macro LoadVar VarName + IntOp $R0 0 + $${VarName} +!macroend + +; Sets the value of a variable +!macro StoreVar VarName IntValue + IntOp $${VarName} 0 + ${IntValue} +!macroend + +!macro InitSection SecName + ; This macro reads component installed flag from the registry and + ;changes checked state of the section on the components page. + ;Input: section index constant name specified in Section command. + + ClearErrors + ;Reading component status from registry + ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" "Installed" + IfErrors "default_${SecName}" + ;Status will stay default if registry value not found + ;(component was never installed) + IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags + IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off + IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit + + ; Note whether this component was installed before + !insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags + IntOp $R0 $AR_RegFlags & $AR_RegFlags + + ;Writing modified flags + SectionSetFlags ${${SecName}} $AR_SecFlags + + "default_${SecName}:" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected +!macroend + +!macro FinishSection SecName + ; This macro reads section flag set by user and removes the section + ;if it is not selected. + ;Then it writes component installed flag to registry + ;Input: section index constant name specified in Section command. + + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags + ;Checking lowest bit: + IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED} + IntCmp $AR_SecFlags 1 "leave_${SecName}" + ;Section is not selected: + ;Calling Section uninstall macro and writing zero installed flag + !insertmacro "Remove_${${SecName}}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 0 + Goto "exit_${SecName}" + + "leave_${SecName}:" + ;Section is selected: + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 1 + + "exit_${SecName}:" +!macroend + +!macro RemoveSection_CPack SecName + ; This macro is used to call section's Remove_... macro + ;from the uninstaller. + ;Input: section index constant name specified in Section command. + + !insertmacro "Remove_${${SecName}}" +!macroend + +; Determine whether the selection of SecName changed +!macro MaybeSelectionChanged SecName + !insertmacro LoadVar ${SecName}_selected + SectionGetFlags ${${SecName}} $R1 + IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits + + ; See if the status has changed: + IntCmp $R0 $R1 "${SecName}_unchanged" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected + + IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected" + !insertmacro "Deselect_required_by_${SecName}" + goto "${SecName}_unchanged" + + "${SecName}_was_selected:" + !insertmacro "Select_${SecName}_depends" + + "${SecName}_unchanged:" +!macroend +;--- End of Add/Remove macros --- + +;-------------------------------- +;Interface Settings + + !define MUI_HEADERIMAGE + !define MUI_ABORTWARNING + +;-------------------------------- +; path functions + +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 + +;---------------------------------------- +; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02" +;---------------------------------------- +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 +;==================================================== +; get_NT_environment +; Returns: the selected environment +; Output : head of the stack +;==================================================== +!macro select_NT_profile UN +Function ${UN}select_NT_profile + StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single + DetailPrint "Selected environment for all users" + Push "all" + Return + environment_single: + DetailPrint "Selected environment for current user only." + Push "current" + Return +FunctionEnd +!macroend +!insertmacro select_NT_profile "" +!insertmacro select_NT_profile "un." +;---------------------------------------------------- +!define NT_current_env 'HKCU "Environment"' +!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + +!ifndef WriteEnvStr_RegKey + !ifdef ALL_USERS + !define WriteEnvStr_RegKey \ + 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + !else + !define WriteEnvStr_RegKey 'HKCU "Environment"' + !endif +!endif + +; AddToPath - Adds the given dir to the search path. +; Input - head of the stack +; Note - Win9x systems requires reboot + +Function AddToPath + Exch $0 + Push $1 + Push $2 + Push $3 + + # don't add if the path doesn't exist + IfFileExists "$0\*.*" "" AddToPath_done + + ReadEnvStr $1 PATH + ; if the path is too long for a NSIS variable NSIS will return a 0 + ; length string. If we find that, then warn and skip any path + ; modification as it will trash the existing path. + StrLen $2 $1 + IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done + CheckPathLength_ShowPathWarning: + Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!" + Goto AddToPath_done + CheckPathLength_Done: + Push "$1;" + Push "$0;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$0\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + GetFullPathName /SHORT $3 $0 + Push "$1;" + Push "$3;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$3\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + + Call IsNT + Pop $1 + StrCmp $1 1 AddToPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" a + FileSeek $1 -1 END + FileReadByte $1 $2 + IntCmp $2 26 0 +2 +2 # DOS EOF + FileSeek $1 -1 END # write over EOF + FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" + FileClose $1 + SetRebootFlag true + Goto AddToPath_done + + AddToPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" ReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto DoTrim + ReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + DoTrim: + StrCmp $1 "" AddToPath_NTdoIt + Push $1 + Call Trim + Pop $1 + StrCpy $0 "$1;$0" + AddToPath_NTdoIt: + StrCmp $ADD_TO_PATH_ALL_USERS "1" WriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $0 + Goto DoSend + WriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $0 + DoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + AddToPath_done: + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + + +; RemoveFromPath - Remove a given dir from the path +; Input: head of the stack + +Function un.RemoveFromPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + IntFmt $6 "%c" 26 # DOS EOF + + Call un.IsNT + Pop $1 + StrCmp $1 1 unRemoveFromPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" r + GetTempFileName $4 + FileOpen $2 $4 w + GetFullPathName /SHORT $0 $0 + StrCpy $0 "SET PATH=%PATH%;$0" + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoop: + FileRead $1 $3 + StrCpy $5 $3 1 -1 # read last char + StrCmp $5 $6 0 +2 # if DOS EOF + StrCpy $3 $3 -1 # remove DOS EOF so we can compare + StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "" unRemoveFromPath_dosLoopEnd + FileWrite $2 $3 + Goto unRemoveFromPath_dosLoop + unRemoveFromPath_dosLoopRemoveLine: + SetRebootFlag true + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoopEnd: + FileClose $2 + FileClose $1 + StrCpy $1 $WINDIR 2 + Delete "$1\autoexec.bat" + CopyFiles /SILENT $4 "$1\autoexec.bat" + Delete $4 + Goto unRemoveFromPath_done + + unRemoveFromPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" unReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto unDoTrim + unReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + unDoTrim: + StrCpy $5 $1 1 -1 # copy last char + StrCmp $5 ";" +2 # if last char != ; + StrCpy $1 "$1;" # append ; + Push $1 + Push "$0;" + Call un.StrStr ; Find `$0;` in $1 + Pop $2 ; pos of our dir + StrCmp $2 "" unRemoveFromPath_done + ; else, it is in path + # $0 - path to add + # $1 - path var + StrLen $3 "$0;" + StrLen $4 $2 + StrCpy $5 $1 -$4 # $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove + StrCpy $3 $5$6 + + StrCpy $5 $3 1 -1 # copy last char + StrCmp $5 ";" 0 +2 # if last char == ; + StrCpy $3 $3 -1 # remove last char + + StrCmp $ADD_TO_PATH_ALL_USERS "1" unWriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $3 + Goto unDoSend + unWriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $3 + unDoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + unRemoveFromPath_done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Uninstall sutff +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +########################################### +# Utility Functions # +########################################### + +;==================================================== +; IsNT - Returns 1 if the current system is NT, 0 +; otherwise. +; Output: head of the stack +;==================================================== +; IsNT +; no input +; output, top of the stack = 1 if NT or 0 if not +; +; Usage: +; Call IsNT +; Pop $R0 +; ($R0 at this point is 1 or 0) + +!macro IsNT un +Function ${un}IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 IsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + + IsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd +!macroend +!insertmacro IsNT "" +!insertmacro IsNT "un." + +; StrStr +; input, top of stack = string to search for +; top of stack-1 = string to search in +; output, top of stack (replaces with the portion of the string remaining) +; modifies no other variables. +; +; Usage: +; Push "this is a long ass string" +; Push "ass" +; Call StrStr +; Pop $R0 +; ($R0 at this point is "ass string") + +!macro StrStr un +Function ${un}StrStr +Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + loop: + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 done + StrCmp $R5 "" done + IntOp $R4 $R4 + 1 + Goto loop +done: + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +FunctionEnd +!macroend +!insertmacro StrStr "" +!insertmacro StrStr "un." + +Function Trim ; Added by Pelaca + Exch $R1 + Push $R2 +Loop: + StrCpy $R2 "$R1" 1 -1 + StrCmp "$R2" " " RTrim + StrCmp "$R2" "$\n" RTrim + StrCmp "$R2" "$\r" RTrim + StrCmp "$R2" ";" RTrim + GoTo Done +RTrim: + StrCpy $R1 "$R1" -1 + Goto Loop +Done: + Pop $R2 + Exch $R1 +FunctionEnd + +Function ConditionalAddToRegisty + Pop $0 + Pop $1 + StrCmp "$0" "" ConditionalAddToRegisty_EmptyString + WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \ + "$1" "$0" + ;MessageBox MB_OK "Set Registry: '$1' to '$0'" + DetailPrint "Set install registry entry: '$1' to '$0'" + ConditionalAddToRegisty_EmptyString: +FunctionEnd + +;-------------------------------- + +!ifdef CPACK_USES_DOWNLOAD +Function DownloadFile + IfFileExists $INSTDIR\* +2 + CreateDirectory $INSTDIR + Pop $0 + + ; Skip if already downloaded + IfFileExists $INSTDIR\$0 0 +2 + Return + + StrCpy $1 "@CPACK_DOWNLOAD_SITE@" + + try_again: + NSISdl::download "$1/$0" "$INSTDIR\$0" + + Pop $1 + StrCmp $1 "success" success + StrCmp $1 "Cancelled" cancel + MessageBox MB_OK "Download failed: $1" + cancel: + Return + success: +FunctionEnd +!endif + +;-------------------------------- +; Installation types +@CPACK_NSIS_INSTALLATION_TYPES@ + +;-------------------------------- +; Component sections +@CPACK_NSIS_COMPONENT_SECTIONS@ + +;-------------------------------- +; Define some macro setting for the gui +@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@ +@CPACK_NSIS_INSTALLER_ICON_CODE@ +@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@ +@CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE@ + +;-------------------------------- +;Pages + !insertmacro MUI_PAGE_WELCOME + + !if @CPACK_RESOURCE_FILE_LICENSE_PROVIDED@ + !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" + !endif + + Page custom InstallOptionsPage + !insertmacro MUI_PAGE_DIRECTORY + + ;Start Menu Folder Page Configuration + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" + !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER + + @CPACK_NSIS_PAGE_COMPONENTS@ + + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" ;first language is the default language + !insertmacro MUI_LANGUAGE "Albanian" + !insertmacro MUI_LANGUAGE "Arabic" + !insertmacro MUI_LANGUAGE "Basque" + !insertmacro MUI_LANGUAGE "Belarusian" + !insertmacro MUI_LANGUAGE "Bosnian" + !insertmacro MUI_LANGUAGE "Breton" + !insertmacro MUI_LANGUAGE "Bulgarian" + !insertmacro MUI_LANGUAGE "Croatian" + !insertmacro MUI_LANGUAGE "Czech" + !insertmacro MUI_LANGUAGE "Danish" + !insertmacro MUI_LANGUAGE "Dutch" + !insertmacro MUI_LANGUAGE "Estonian" + !insertmacro MUI_LANGUAGE "Farsi" + !insertmacro MUI_LANGUAGE "Finnish" + !insertmacro MUI_LANGUAGE "French" + !insertmacro MUI_LANGUAGE "German" + !insertmacro MUI_LANGUAGE "Greek" + !insertmacro MUI_LANGUAGE "Hebrew" + !insertmacro MUI_LANGUAGE "Hungarian" + !insertmacro MUI_LANGUAGE "Icelandic" + !insertmacro MUI_LANGUAGE "Indonesian" + !insertmacro MUI_LANGUAGE "Irish" + !insertmacro MUI_LANGUAGE "Italian" + !insertmacro MUI_LANGUAGE "Japanese" + !insertmacro MUI_LANGUAGE "Korean" + !insertmacro MUI_LANGUAGE "Kurdish" + !insertmacro MUI_LANGUAGE "Latvian" + !insertmacro MUI_LANGUAGE "Lithuanian" + !insertmacro MUI_LANGUAGE "Luxembourgish" + !insertmacro MUI_LANGUAGE "Macedonian" + !insertmacro MUI_LANGUAGE "Malay" + !insertmacro MUI_LANGUAGE "Mongolian" + !insertmacro MUI_LANGUAGE "Norwegian" + !insertmacro MUI_LANGUAGE "Polish" + !insertmacro MUI_LANGUAGE "Portuguese" + !insertmacro MUI_LANGUAGE "PortugueseBR" + !insertmacro MUI_LANGUAGE "Romanian" + !insertmacro MUI_LANGUAGE "Russian" + !insertmacro MUI_LANGUAGE "Serbian" + !insertmacro MUI_LANGUAGE "SerbianLatin" + !insertmacro MUI_LANGUAGE "SimpChinese" + !insertmacro MUI_LANGUAGE "Slovak" + !insertmacro MUI_LANGUAGE "Slovenian" + !insertmacro MUI_LANGUAGE "Spanish" + !insertmacro MUI_LANGUAGE "Swedish" + !insertmacro MUI_LANGUAGE "Thai" + !insertmacro MUI_LANGUAGE "TradChinese" + !insertmacro MUI_LANGUAGE "Turkish" + !insertmacro MUI_LANGUAGE "Ukrainian" + !insertmacro MUI_LANGUAGE "Welsh" + + +;-------------------------------- +;Reserve Files + + ;These files should be inserted before other files in the data block + ;Keep these lines before any File command + ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA) + + ReserveFile "NSIS.InstallOptions.ini" + !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +;-------------------------------- +;Installer Sections + +Section "-Core installation" + ;Use the entire tree produced by the INSTALL target. Keep the + ;list of directories here in sync with the RMDir commands below. + SetOutPath "$INSTDIR" + @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@ + @CPACK_NSIS_FULL_INSTALL@ + + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 + IntFmt $0 "0x%08X" $0 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "EstimatedSize" "$0" + + ;Store installation folder + WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR + + ;Create uninstaller + WriteUninstaller "$INSTDIR\Uninstall.exe" + Push "DisplayName" + Push "@CPACK_NSIS_DISPLAY_NAME@" + Call ConditionalAddToRegisty + Push "DisplayVersion" + Push "@CPACK_PACKAGE_VERSION@" + Call ConditionalAddToRegisty + Push "Publisher" + Push "@CPACK_PACKAGE_VENDOR@" + Call ConditionalAddToRegisty + Push "UninstallString" + Push "$INSTDIR\Uninstall.exe" + Call ConditionalAddToRegisty + Push "NoRepair" + Push "1" + Call ConditionalAddToRegisty + + !ifdef CPACK_NSIS_ADD_REMOVE + ;Create add/remove functionality + Push "ModifyPath" + Push "$INSTDIR\AddRemove.exe" + Call ConditionalAddToRegisty + !else + Push "NoModify" + Push "1" + Call ConditionalAddToRegisty + !endif + + ; Optional registration + Push "DisplayIcon" + Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@" + Call ConditionalAddToRegisty + Push "HelpLink" + Push "@CPACK_NSIS_HELP_LINK@" + Call ConditionalAddToRegisty + Push "URLInfoAbout" + Push "@CPACK_NSIS_URL_INFO_ABOUT@" + Call ConditionalAddToRegisty + Push "Contact" + Push "@CPACK_NSIS_CONTACT@" + Call ConditionalAddToRegisty + !insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State" + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + + ;Create shortcuts + CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" +@CPACK_NSIS_CREATE_ICONS@ +@CPACK_NSIS_CREATE_ICONS_EXTRA@ + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" + + ;Read a value from an InstallOptions INI file + !insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS "NSIS.InstallOptions.ini" "Field 3" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER "NSIS.InstallOptions.ini" "Field 4" "State" + + ; Write special uninstall registry entries + Push "StartMenu" + Push "$STARTMENU_FOLDER" + Call ConditionalAddToRegisty + Push "DoNotAddToPath" + Push "$DO_NOT_ADD_TO_PATH" + Call ConditionalAddToRegisty + Push "AddToPathAllUsers" + Push "$ADD_TO_PATH_ALL_USERS" + Call ConditionalAddToRegisty + Push "AddToPathCurrentUser" + Push "$ADD_TO_PATH_CURRENT_USER" + Call ConditionalAddToRegisty + Push "InstallToDesktop" + Push "$INSTALL_DESKTOP" + Call ConditionalAddToRegisty + + !insertmacro MUI_STARTMENU_WRITE_END + +@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@ + +SectionEnd + +Section "-Add to path" + Push $INSTDIR\bin + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath + StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0 + Call AddToPath + doNotAddToPath: +SectionEnd + +;-------------------------------- +; Create custom pages +Function InstallOptionsPage + !insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@" + !insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini" + +FunctionEnd + +;-------------------------------- +; determine admin versus local install +Function un.onInit + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + Goto done + StrCmp $1 "Power" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + Goto done + + noLM: + ;Get installation folder from registry if available + + done: + +FunctionEnd + +;--- Add/Remove callback functions: --- +!macro SectionList MacroName + ;This macro used to perform operation on multiple sections. + ;List all of your components in following manner here. +@CPACK_NSIS_COMPONENT_SECTION_LIST@ +!macroend + +Section -FinishComponents + ;Removes unselected components and writes component status to registry + !insertmacro SectionList "FinishSection" + +!ifdef CPACK_NSIS_ADD_REMOVE + ; Get the name of the installer executable + System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1' + StrCpy $R3 $R0 + + ; Strip off the last 13 characters, to see if we have AddRemove.exe + StrLen $R1 $R0 + IntOp $R1 $R0 - 13 + StrCpy $R2 $R0 13 $R1 + StrCmp $R2 "AddRemove.exe" addremove_installed + + ; We're not running AddRemove.exe, so install it + CopyFiles $R3 $INSTDIR\AddRemove.exe + + addremove_installed: +!endif +SectionEnd +;--- End of Add/Remove callback functions --- + +;-------------------------------- +; Component dependencies +Function .onSelChange + !insertmacro SectionList MaybeSelectionChanged +FunctionEnd + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + ReadRegStr $START_MENU SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" + ;MessageBox MB_OK "Start menu is in: $START_MENU" + ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "DoNotAddToPath" + ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathAllUsers" + ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathCurrentUser" + ;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS" + ReadRegStr $INSTALL_DESKTOP SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "InstallToDesktop" + ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP " + +@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ + + ;Remove files we installed. + ;Keep the list of directories here in sync with the File commands above. +@CPACK_NSIS_DELETE_FILES@ +@CPACK_NSIS_DELETE_DIRECTORIES@ + +!ifdef CPACK_NSIS_ADD_REMOVE + ;Remove the add/remove program + Delete "$INSTDIR\AddRemove.exe" +!endif + + ;Remove the uninstaller itself. + Delete "$INSTDIR\Uninstall.exe" + DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ;Remove the installation directory if it is empty. + RMDir "$INSTDIR" + + ; Remove the registry entries. + DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ; Removes all optional components + !insertmacro SectionList "RemoveSection_CPack" + + !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP + + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS@ +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + startMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors startMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop + startMenuDeleteLoopDone: + + ; If the user changed the shortcut, then untinstall may not work. This should + ; try to fix it. + StrCpy $MUI_TEMP "$START_MENU" + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + secondStartMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors secondStartMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop + secondStartMenuDeleteLoopDone: + + DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + Push $INSTDIR\bin + StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0 + Call un.RemoveFromPath + doNotRemoveFromPath: +SectionEnd + +;-------------------------------- +; determine admin versus local install +; Is install for "AllUsers" or "JustMe"? +; Default to "JustMe" - set to "AllUsers" if admin or on Win9x +; This function is used for the very first "custom page" of the installer. +; This custom page does not show up visibly, but it executes prior to the +; first visible page and sets up $INSTDIR properly... +; Choose different default installation folder based on SV_ALLUSERS... +; "Program Files" for AllUsers, "My Documents" for JustMe... + + + + + +Function .onInit + ClearErrors + ExecWait '"cmd" /C ""%SystemRoot%\System32\tasklist" /NH /FI "IMAGENAME eq @CPACK_NSIS_MUI_FINISHPAGE_RUN@" | "%SystemRoot%\System32\find" /I /C "@CPACK_NSIS_MUI_FINISHPAGE_RUN@""' $0 + IntCmp $0 1 notRunning + MessageBox MB_OK|MB_ICONEXCLAMATION "@CPACK_NSIS_MUI_FINISHPAGE_RUN@ is running. Please close it first from the application menu and restart the installation." /SD IDOK + Abort + +notRunning: + + ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString" + StrCmp $0 "" inst + + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ + "@CPACK_PACKAGE_NAME@ is already installed. $\n$\nDo you want to continue and uninstall the old version before installing the new one?" \ + IDOK uninst + Abort + +;Run the uninstaller +uninst: + ClearErrors + StrLen $2 "\Uninstall.exe" + StrCpy $3 $0 -$2 # remove "\Uninstall.exe" from UninstallString to get path + ExecWait '$0 _?=$3' ;Do not copy the uninstaller to a temp file + + IfErrors uninst_failed inst +uninst_failed: + MessageBox MB_OK|MB_ICONSTOP "Uninstall failed." + Abort + + +inst: + ; Reads components status for registry + !insertmacro SectionList "InitSection" + + ; check to see if /D has been used to change + ; the install directory by comparing it to the + ; install directory that is expected to be the + ; default + StrCpy $IS_DEFAULT_INSTALLDIR 0 + StrCmp "$INSTDIR" "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2 + StrCpy $IS_DEFAULT_INSTALLDIR 1 + + StrCpy $SV_ALLUSERS "JustMe" + ; if default install dir then change the default + ; if it is installed for JustMe + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + StrCmp $1 "Power" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + + noLM: + StrCpy $SV_ALLUSERS "AllUsers" + ;Get installation folder from registry if available + + done: + StrCmp $SV_ALLUSERS "AllUsers" 0 +3 + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 noOptionsPage + !insertmacro MUI_INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini" + + noOptionsPage: +FunctionEnd diff --git a/cmake/install/windows/ReadMe_banner.txt b/cmake/install/windows/ReadMe_banner.txt new file mode 100644 index 000000000..20349f27a --- /dev/null +++ b/cmake/install/windows/ReadMe_banner.txt @@ -0,0 +1,6 @@ +nsis_banner should be in old format. +file nsis_banner.bmp => "PC bitmap, Windows 98/2000 and newer format" is not good. + + +convert nsis_banner.bmp BMP3:nsis_banner.bmp +file nsis_banner.bmp => "PC bitmap, Windows 3.x format" OK diff --git a/cmake/install/windows/appDetailsWindows.rc.in b/cmake/install/windows/appDetailsWindows.rc.in new file mode 100644 index 000000000..94fa1b416 --- /dev/null +++ b/cmake/install/windows/appDetailsWindows.rc.in @@ -0,0 +1,40 @@ +A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "assets/icon.ico" + +# if defined(UNDER_CE) +# include +# else +# include +# endif + +VS_VERSION_INFO VERSIONINFO + PRODUCTVERSION ${version_major},${version_minor},${version_patch},0 + FILEVERSION ${version_major},${version_minor},${version_patch},0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "${APPLICATION_VENDOR}\0" + VALUE "FileDescription", "${APPLICATION_NAME} - ${APPLICATION_DESCRIPTION}\0" + VALUE "FileVersion", "${FULL_VERSION}" + VALUE "ProductVersion", "${version_major}.${version_minor}.${version_patch}\0" + VALUE "LegalCopyright", "Copyright (C) ${COPYRIGHT_RANGE_DATE} ${APPLICATION_VENDOR} ${APPLICATION_URL}\0" + VALUE "OriginalFilename", "${EXECUTABLE_NAME}.exe\0" + VALUE "ProductName", "${APPLICATION_NAME}\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END + END +/* End of Version info */ \ No newline at end of file diff --git a/cmake/install/windows/install.nsi.in b/cmake/install/windows/install.nsi.in new file mode 100644 index 000000000..11fc8e0d9 --- /dev/null +++ b/cmake/install/windows/install.nsi.in @@ -0,0 +1,87 @@ + +# Application details + +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@" "" "" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@" "" "" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities" "ApplicationDescription" "@APPLICATION_DESCRIPTION@" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities" "ApplicationName" "@APPLICATION_NAME@" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities" "FriendlyAppName" "@APPLICATION_NAME@" +WriteRegStr HKLM "SOFTWARE\RegisteredApplications" "@APPLICATION_NAME@" "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities" +WriteRegStr HKLM "SOFTWARE\IM Providers\@APPLICATION_NAME@" "ProcessName" "@EXECUTABLE_NAME@.exe" +WriteRegStr HKLM "SOFTWARE\IM Providers\@APPLICATION_NAME@" "FriendlyName" "@APPLICATION_NAME@" + + +# PROTOCOL declaration + +WriteRegStr HKCR "sip" "" "URL:sip Protocol" +WriteRegStr HKCR "sip" "URL Protocol" "" + +WriteRegStr HKCR "sip-@EXECUTABLE_NAME@" "" "URL:sip-@EXECUTABLE_NAME@ Protocol" +WriteRegStr HKCR "sip-@EXECUTABLE_NAME@" "URL Protocol" "" + +WriteRegStr HKCR "@EXECUTABLE_NAME@-config" "" "URL:@EXECUTABLE_NAME@-config Protocol" +WriteRegStr HKCR "@EXECUTABLE_NAME@-config" "URL Protocol" "" + +WriteRegStr HKCR "sips" "" "URL:sips Protocol" +WriteRegStr HKCR "sips" "URL Protocol" "" + +WriteRegStr HKCR "sips-@EXECUTABLE_NAME@" "" "URL:sips-@EXECUTABLE_NAME@ Protocol" +WriteRegStr HKCR "sips-@EXECUTABLE_NAME@" "URL Protocol" "" + +WriteRegStr HKCR "tel" "" "URL:tel Protocol" +WriteRegStr HKCR "tel" "URL Protocol" "" + +WriteRegStr HKCR "callto" "" "URL:callto Protocol" +WriteRegStr HKCR "callto" "URL Protocol" "" + + +# Application protocol handlers + +## SIP +WriteRegStr HKCR "@APPLICATION_NAME@.sip" "" "@APPLICATION_NAME@ sip Protocol" +WriteRegStr HKCR "@APPLICATION_NAME@.sip\Shell" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sip\Shell\Open" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sip\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\"" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "sip" "@APPLICATION_NAME@.sip" + +## SIP-@EXECUTABLE_NAME@ +WriteRegStr HKCR "@APPLICATION_NAME@.sip-@EXECUTABLE_NAME@" "" "@APPLICATION_NAME@ sip-@EXECUTABLE_NAME@ Protocol" +WriteRegStr HKCR "@APPLICATION_NAME@.sip-@EXECUTABLE_NAME@\Shell" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sip-@EXECUTABLE_NAME@\Shell\Open" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sip-@EXECUTABLE_NAME@\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\"" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "sip-@EXECUTABLE_NAME@" "@APPLICATION_NAME@.sip-@EXECUTABLE_NAME@" + +## SIPS +WriteRegStr HKCR "@APPLICATION_NAME@.sips" "" "@APPLICATION_NAME@ sips Protocol" +WriteRegStr HKCR "@APPLICATION_NAME@.sips\Shell" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sips\Shell\Open" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sips\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\"" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "sips" "@APPLICATION_NAME@.sips" + +## SIPS-@EXECUTABLE_NAME@ +WriteRegStr HKCR "@APPLICATION_NAME@.sips-@EXECUTABLE_NAME@" "" "@APPLICATION_NAME@ sips-@EXECUTABLE_NAME@ Protocol" +WriteRegStr HKCR "@APPLICATION_NAME@.sips-@EXECUTABLE_NAME@\Shell" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sips-@EXECUTABLE_NAME@\Shell\Open" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.sips-@EXECUTABLE_NAME@\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\"" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "sips-@EXECUTABLE_NAME@" "@APPLICATION_NAME@.sips-@EXECUTABLE_NAME@" + +## @EXECUTABLE_NAME@-CONFIG +WriteRegStr HKCR "@APPLICATION_NAME@.@EXECUTABLE_NAME@-config" "" "@APPLICATION_NAME@ @EXECUTABLE_NAME@-config Protocol" +WriteRegStr HKCR "@APPLICATION_NAME@.@EXECUTABLE_NAME@-config\Shell" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.@EXECUTABLE_NAME@-config\Shell\Open" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.@EXECUTABLE_NAME@-config\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\"" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "@EXECUTABLE_NAME@-config" "@APPLICATION_NAME@.@EXECUTABLE_NAME@-config" + +## TEL +WriteRegStr HKCR "@APPLICATION_NAME@.tel" "" "@APPLICATION_NAME@ tel Protocol" +WriteRegStr HKCR "@APPLICATION_NAME@.tel\Shell" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.tel\Shell\Open" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.tel\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\"" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "tel" "@APPLICATION_NAME@.tel" + +## CALLTO +WriteRegStr HKCR "@APPLICATION_NAME@.callto" "" "@APPLICATION_NAME@ callto Protocol" +WriteRegStr HKCR "@APPLICATION_NAME@.callto\Shell" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.callto\Shell\Open" "" "" +WriteRegStr HKCR "@APPLICATION_NAME@.callto\Shell\Open\Command" "" "$INSTDIR\bin\@EXECUTABLE_NAME@.exe $\"%1$\"" +WriteRegStr HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@\Capabilities\URLAssociations" "callto" "@APPLICATION_NAME@.callto" diff --git a/cmake/install/windows/nsis_banner.bmp b/cmake/install/windows/nsis_banner.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c344345d1ae527adc0cc475e8dd3b88d3cc4096c GIT binary patch literal 576566 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 LKvyBqtJnVzz82}F literal 0 HcmV?d00001 diff --git a/cmake/install/windows/uninstall.nsi.in b/cmake/install/windows/uninstall.nsi.in new file mode 100644 index 000000000..545948bf5 --- /dev/null +++ b/cmake/install/windows/uninstall.nsi.in @@ -0,0 +1,24 @@ +ClearErrors +ExecWait '"cmd" /C ""%SystemRoot%\System32\tasklist" /NH /FI "IMAGENAME eq @CPACK_NSIS_MUI_FINISHPAGE_RUN@" | "%SystemRoot%\System32\find" /I /C "@CPACK_NSIS_MUI_FINISHPAGE_RUN@""' $0 +IntCmp $0 1 notRunningInUninstall +MessageBox MB_OK|MB_ICONEXCLAMATION "@CPACK_NSIS_MUI_FINISHPAGE_RUN@ is running. Please close it first from the application menu and restart the installation." /SD IDOK +Abort + +notRunningInUninstall: + +## Application + +DeleteRegKey HKLM "SOFTWARE\IM Providers\@APPLICATION_NAME@" +DeleteRegKey HKLM "SOFTWARE\@APPLICATION_VENDOR@\@APPLICATION_NAME@" +DeleteRegValue HKLM "SOFTWARE\RegisteredApplications" "@APPLICATION_NAME@" + +## Handlers + +DeleteRegKey HKCR "@APPLICATION_NAME@.sip" +DeleteRegKey HKCR "@APPLICATION_NAME@.sip-@EXECUTABLE_NAME@" +DeleteRegKey HKCR "@APPLICATION_NAME@.sips" +DeleteRegKey HKCR "@APPLICATION_NAME@.sips-@EXECUTABLE_NAME@" +DeleteRegKey HKCR "@APPLICATION_NAME@.@EXECUTABLE_NAME@-config" +DeleteRegKey HKCR "@APPLICATION_NAME@.tel" +DeleteRegKey HKCR "@APPLICATION_NAME@.callto" + diff --git a/cmake/install/windows/winshortcut.vbs.in b/cmake/install/windows/winshortcut.vbs.in new file mode 100644 index 000000000..58750a7b1 --- /dev/null +++ b/cmake/install/windows/winshortcut.vbs.in @@ -0,0 +1,6 @@ +Set oWS = WScript.CreateObject("WScript.Shell") +sLinkFile = "@SHORTCUT_PATH@" +Set oLink = oWS.CreateShortcut(sLinkFile) +oLink.TargetPath = "@SHORTCUT_TARGET_PATH@" +oLink.WorkingDirectory = "@SHORTCUT_WORKING_DIRECTORY@" +oLink.Save