scriptable-client-installers/tools/Include/MultiUser.nsh
2023-12-15 16:09:19 -05:00

506 lines
14 KiB
Plaintext

/*
MultiUser.nsh
Installer configuration for multi-user Windows environments
Copyright 2008-2023 Joost Verburg
*/
!ifndef MULTIUSER_INCLUDED
!define MULTIUSER_INCLUDED 20210216
!verbose push 3
;Standard NSIS header files
!ifdef MULTIUSER_MUI
!include MUI2.nsh
!endif
!include LogicLib.nsh
!include WinVer.nsh
!include FileFunc.nsh
!if ${NSIS_PTR_SIZE} > 4
!define /IfNDef MULTIUSER_MINWIN 0x501
!else
!define /IfNDef MULTIUSER_MINWIN 0x400
!endif
;Variables
Var MultiUser.Privileges
Var MultiUser.InstallMode
;Command line installation mode setting
!ifdef MULTIUSER_INSTALLMODE_COMMANDLINE
!include StrFunc.nsh
${Using:StrFunc} StrStr
!ifndef MULTIUSER_NOUNINSTALL
${Using:StrFunc} UnStrStr
!endif
Var MultiUser.Parameters
Var MultiUser.Result
!endif
;Installation folder stored in registry
!ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
Var MultiUser.InstDir
!endif
!ifdef MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY & MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
Var MultiUser.DefaultKeyValue
!endif
;Windows Vista UAC setting
!if "${MULTIUSER_EXECUTIONLEVEL}" == Admin
RequestExecutionLevel admin
!define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
!else if "${MULTIUSER_EXECUTIONLEVEL}" == Power
RequestExecutionLevel admin
!define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
!else if "${MULTIUSER_EXECUTIONLEVEL}" == Highest
RequestExecutionLevel highest
!define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
!else
RequestExecutionLevel user
!ifndef MULTIUSER_EXECUTIONLEVEL
!warning "MULTIUSER_EXECUTIONLEVEL not set!"
!endif
!endif
/*
Install modes
*/
!macro MULTIUSER_INSTALLMODE_ALLUSERS UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
;Install mode initialization - per-machine
${ifnot} ${IsNT}
${orif} $MultiUser.Privileges == "Admin"
${orif} $MultiUser.Privileges == "Power"
StrCpy $MultiUser.InstallMode AllUsers
SetShellVarContext all
!if "${UNINSTALLER_PREFIX}" != UN
;Set default installation location for installer
!ifdef MULTIUSER_INSTALLMODE_INSTDIR
!ifdef MULTIUSER_USE_PROGRAMFILES64
StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}"
!else
StrCpy $INSTDIR "$PROGRAMFILES\${MULTIUSER_INSTALLMODE_INSTDIR}"
!endif
!endif
!endif
!ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
ReadRegStr $MultiUser.InstDir HKLM "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME}"
${if} $MultiUser.InstDir != ""
StrCpy $INSTDIR $MultiUser.InstDir
${endif}
!endif
!ifdef MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION
Call "${MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION}"
!endif
${endif}
!macroend
!macro MULTIUSER_INSTALLMODE_CURRENTUSER UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
;Install mode initialization - per-user
!if ${MULTIUSER_MINWIN} < 0x500
${if} ${IsNT}
!endif
StrCpy $MultiUser.InstallMode CurrentUser
SetShellVarContext current
!if "${UNINSTALLER_PREFIX}" != UN
;Set default installation location for installer
!ifdef MULTIUSER_INSTALLMODE_INSTDIR
!if ${MULTIUSER_MINWIN} < 0x490
${if} ${AtLeastWin2000}
!endif
GetKnownFolderPath $INSTDIR {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB} ; FOLDERID_UserProgramFiles
StrCmp $INSTDIR "" 0 +2
StrCpy $INSTDIR "$LocalAppData\Programs" ; Fallback directory
StrCpy $INSTDIR "$INSTDIR\${MULTIUSER_INSTALLMODE_INSTDIR}"
!if ${MULTIUSER_MINWIN} < 0x490
${else}
StrCpy $INSTDIR "$PROGRAMFILES\${MULTIUSER_INSTALLMODE_INSTDIR}"
${endif}
!endif
!endif
!endif
!ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
ReadRegStr $MultiUser.InstDir HKCU "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME}"
${if} $MultiUser.InstDir != ""
StrCpy $INSTDIR $MultiUser.InstDir
${endif}
!endif
!ifdef MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION
Call "${MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION}"
!endif
!if ${MULTIUSER_MINWIN} < 0x500
${endif}
!endif
!macroend
Function MultiUser.InstallMode.AllUsers
!insertmacro MULTIUSER_INSTALLMODE_ALLUSERS "" ""
FunctionEnd
Function MultiUser.InstallMode.CurrentUser
!insertmacro MULTIUSER_INSTALLMODE_CURRENTUSER "" ""
FunctionEnd
!ifndef MULTIUSER_NOUNINSTALL
Function un.MultiUser.InstallMode.AllUsers
!insertmacro MULTIUSER_INSTALLMODE_ALLUSERS UN .un
FunctionEnd
Function un.MultiUser.InstallMode.CurrentUser
!insertmacro MULTIUSER_INSTALLMODE_CURRENTUSER UN .un
FunctionEnd
!endif
/*
Installer/uninstaller initialization
*/
!macro MULTIUSER_INIT_QUIT UNINSTALLER_FUNCPREFIX
!ifdef MULTIUSER_INIT_${UNINSTALLER_FUNCPREFIX}FUNCTIONQUIT
Call "${MULTIUSER_INIT_${UNINSTALLER_FUNCPREFIX}FUNCTIONQUIT}"
!else
Quit
!endif
!macroend
!macro MULTIUSER_INIT_TEXTS UNINSTALLER_PREFIX
!if "${UNINSTALLER_PREFIX}" == ""
!define /ReDef MULTIUSER_TMPSTR_CAPTION "$(^SetupCaption)"
!else
!define /ReDef MULTIUSER_TMPSTR_CAPTION "$(^Name)"
!endif
!define /IfNDef MULTIUSER_INIT_TEXT_ADMINREQUIRED "${MULTIUSER_TMPSTR_CAPTION} requires administrator privileges."
!define /IfNDef MULTIUSER_INIT_TEXT_POWERREQUIRED "${MULTIUSER_TMPSTR_CAPTION} requires at least Power User privileges."
!define /IfNDef MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE "Your user account does not have sufficient privileges to install $(^Name) for all users of this computer."
!undef MULTIUSER_TMPSTR_CAPTION
!macroend
!macro MULTIUSER_INIT_CHECKS UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
;Installer initialization - check privileges and set install mode
!insertmacro MULTIUSER_INIT_TEXTS "${UNINSTALLER_PREFIX}"
UserInfo::GetAccountType
Pop $MultiUser.Privileges
!if ${MULTIUSER_MINWIN} < 0x500
${if} ${IsNT}
!endif
;Check privileges
!if "${MULTIUSER_EXECUTIONLEVEL}" == Admin
${if} $MultiUser.Privileges != "Admin"
MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ADMINREQUIRED}"
!insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
${endif}
!else if "${MULTIUSER_EXECUTIONLEVEL}" == Power
${if} $MultiUser.Privileges != "Power"
${andif} $MultiUser.Privileges != "Admin"
${if} ${AtMostWinXP}
MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_POWERREQUIRED}"
${else}
MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ADMINREQUIRED}"
${endif}
!insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
${endif}
!endif
!ifdef MULTIUSER_EXECUTIONLEVEL_ALLUSERS
;Default to per-machine installation if possible
${if} $MultiUser.Privileges == "Admin"
${orif} $MultiUser.Privileges == "Power"
!ifndef MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
!else
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
!endif
!ifdef MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY & MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
;Set installation mode to setting from a previous installation
!ifndef MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
ReadRegStr $MultiUser.DefaultKeyValue HKLM "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
${if} $MultiUser.DefaultKeyValue == ""
ReadRegStr $MultiUser.DefaultKeyValue HKCU "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
${if} $MultiUser.DefaultKeyValue != ""
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
${endif}
${endif}
!else
ReadRegStr $MultiUser.DefaultKeyValue HKCU "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
${if} $MultiUser.DefaultKeyValue == ""
ReadRegStr $MultiUser.DefaultKeyValue HKLM "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
${if} $MultiUser.DefaultKeyValue != ""
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
${endif}
${endif}
!endif
!endif
${else}
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
${endif}
!else
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
!endif
!ifdef MULTIUSER_INSTALLMODE_COMMANDLINE
;Check for install mode setting on command line
${${UNINSTALLER_FUNCPREFIX}GetParameters} $MultiUser.Parameters
${${UNINSTALLER_PREFIX}StrStr} $MultiUser.Result $MultiUser.Parameters "/CurrentUser"
${if} $MultiUser.Result != ""
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
${endif}
${${UNINSTALLER_PREFIX}StrStr} $MultiUser.Result $MultiUser.Parameters "/AllUsers"
${if} $MultiUser.Result != ""
${if} $MultiUser.Privileges == "Admin"
${orif} $MultiUser.Privileges == "Power"
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
${else}
MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE}"
!insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
${endif}
${endif}
!endif
!if ${MULTIUSER_MINWIN} < 0x500
${else}
;Not running Windows NT, per-user installation not supported
Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
${endif}
!endif
!macroend
!macro MULTIUSER_INIT
!verbose push 3
!ifdef __UNINSTALL__
!insertmacro MULTIUSER_UNINIT
!else
!insertmacro MULTIUSER_INIT_CHECKS "" ""
!endif
!verbose pop
!macroend
!ifndef MULTIUSER_NOUNINSTALL
!macro MULTIUSER_UNINIT
!verbose push 3
!insertmacro MULTIUSER_INIT_CHECKS Un un.
!verbose pop
!macroend
!endif
/*
Mode selection page
*/
!macro MULTIUSER_PAGE_FUNCTION_CUSTOM TYPE
!ifmacrodef MUI_PAGE_FUNCTION_CUSTOM
!insertmacro MUI_PAGE_FUNCTION_CUSTOM "${TYPE}"
!endif
!ifdef MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}
Call "${MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}}"
!undef MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}
!endif
!macroend
!macro MULTIUSER_INSTALLMODEPAGE_INTERFACE
!ifndef MULTIUSER_INSTALLMODEPAGE_INTERFACE
!define MULTIUSER_INSTALLMODEPAGE_INTERFACE
Var MultiUser.InstallModePage
Var MultiUser.InstallModePage.Text
Var MultiUser.InstallModePage.AllUsers
Var MultiUser.InstallModePage.CurrentUser
!endif
!macroend
!macro MULTIUSER_PAGEDECLARATION_INSTALLMODE UNPREFIX UNIQUEID
!define /ReDef MULTIUSER_${UNPREFIX}INSTALLMODEPAGE "" ; Unlock strings in the language file(s)
!insertmacro MULTIUSER_INSTALLMODEPAGE_INTERFACE
!define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_TOP "$(MULTIUSER_INNERTEXT_INSTALLMODE_TOP)"
!define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS "$(MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS)"
!define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER "$(MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER)"
PageEx custom
PageCallbacks MultiUser.InstallModePre_${UNIQUEID} MultiUser.InstallModeLeave_${UNIQUEID}
!define /IfNDef MULTIUSER_INSTALLMODEPAGE_CAPTION " "
Caption "${MULTIUSER_INSTALLMODEPAGE_CAPTION}"
PageExEnd
!insertmacro MULTIUSER_FUNCTION_INSTALLMODEPAGE MultiUser.InstallModePre_${UNIQUEID} MultiUser.InstallModeLeave_${UNIQUEID}
!undef MULTIUSER_INSTALLMODEPAGE_TEXT_TOP
!undef MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS
!undef MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER
!macroend
!macro MULTIUSER_PAGE_INSTALLMODE
!verbose push 3
!ifndef MULTIUSER_EXECUTIONLEVEL_ALLUSERS
!error "A mixed-mode installation requires MULTIUSER_EXECUTIONLEVEL to be set to Admin, Power or Highest."
!endif
!ifmacrodef MUI_PAGE_INIT
!insertmacro MUI_PAGE_INIT
!endif
!insertmacro MULTIUSER_PAGEDECLARATION_INSTALLMODE "" ${__COUNTER__}
!verbose pop
!macroend
!macro MULTIUSER_FUNCTION_INSTALLMODEPAGE PRE LEAVE
!include nsDialogs.nsh
Function "${PRE}"
!if ${MULTIUSER_MINWIN} < 0x500
${ifnot} ${IsNT}
Abort
${endif}
!endif
${if} $MultiUser.Privileges != "Power"
${andif} $MultiUser.Privileges != "Admin"
Abort
${endif}
!insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM PRE
!ifmacrodef MUI_HEADER_TEXT_PAGE
!insertmacro MUI_HEADER_TEXT_PAGE $(MULTIUSER_TEXT_INSTALLMODE_TITLE) $(MULTIUSER_TEXT_INSTALLMODE_SUBTITLE)
!endif
nsDialogs::Create 1018
Pop $MultiUser.InstallModePage
${NSD_CreateLabel} 0 2u 100% 42u "${MULTIUSER_INSTALLMODEPAGE_TEXT_TOP}"
Pop $MultiUser.InstallModePage.Text
${NSD_CreateRadioButton} 15u 50u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS}"
Pop $MultiUser.InstallModePage.AllUsers
!ifdef MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME
!ifdef NOSYSTEMCALLS
ReadEnvStr $0 USERNAME
!else
System::Call 'ADVAPI32::GetUserName(t""r0,*i${NSIS_MAX_STRLEN})'
!endif
StrCmp $0 "" +2
StrCpy $0 " ($0)"
${NSD_CreateRadioButton} 15u 70u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER}$0"
!else
${NSD_CreateRadioButton} 15u 70u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER}"
!endif
Pop $MultiUser.InstallModePage.CurrentUser
${if} $MultiUser.InstallMode == "AllUsers"
SendMessage $MultiUser.InstallModePage.AllUsers ${BM_SETCHECK} ${BST_CHECKED} 0
${else}
SendMessage $MultiUser.InstallModePage.CurrentUser ${BM_SETCHECK} ${BST_CHECKED} 0
${endif}
!insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM SHOW
nsDialogs::Show
!insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM DESTROYED
FunctionEnd
Function "${LEAVE}"
SendMessage $MultiUser.InstallModePage.AllUsers ${BM_GETCHECK} 0 0 $0
${if} $0 = ${BST_CHECKED}
Call MultiUser.InstallMode.AllUsers
${else}
Call MultiUser.InstallMode.CurrentUser
${endif}
!insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM LEAVE
FunctionEnd
!macroend
!verbose pop
!endif