multiUserUi.nsh 8.71 KB
!include nsDialogs.nsh

Var HasTwoAvailableOptions
Var RadioButtonLabel1
Var isForceMachineInstall
Var isForceCurrentInstall

!macro PAGE_INSTALL_MODE
  !insertmacro MUI_PAGE_INIT

  !insertmacro MUI_SET MULTIUSER_${MUI_PAGE_UNINSTALLER_PREFIX}INSTALLMODEPAGE ""
  Var MultiUser.InstallModePage
  Var MultiUser.InstallModePage.Text
  Var MultiUser.InstallModePage.AllUsers
  Var MultiUser.InstallModePage.CurrentUser
  Var MultiUser.InstallModePage.ReturnValue

  !ifndef BUILD_UNINSTALLER
    !insertmacro FUNCTION_INSTALL_MODE_PAGE_FUNCTION MultiUser.InstallModePre_${MUI_UNIQUEID} MultiUser.InstallModeLeave_${MUI_UNIQUEID} ""
    PageEx custom
      PageCallbacks MultiUser.InstallModePre_${MUI_UNIQUEID} MultiUser.InstallModeLeave_${MUI_UNIQUEID}
      Caption " "
    PageExEnd
  !else
    !insertmacro FUNCTION_INSTALL_MODE_PAGE_FUNCTION MultiUser.InstallModePre_${MUI_UNIQUEID} MultiUser.InstallModeLeave_${MUI_UNIQUEID} un.
    UninstPage custom un.multiUser.InstallModePre_${MUI_UNIQUEID} un.MultiUser.InstallModeLeave_${MUI_UNIQUEID}
  !endif
!macroend

!macro FUNCTION_INSTALL_MODE_PAGE_FUNCTION PRE LEAVE UNINSTALLER_FUNCPREFIX
	Function "${UNINSTALLER_FUNCPREFIX}${PRE}"
		${if} ${UAC_IsInnerInstance}
		${andIf} ${UAC_IsAdmin}
		  # inner Process (and Admin) - skip selection, inner process is always used for elevation (machine-wide)
			!insertmacro setInstallModePerAllUsers
			Abort
		${endIf}

		StrCpy $isForceMachineInstall "0"
		StrCpy $isForceCurrentInstall "0"
		!ifmacrodef customInstallmode
		  !insertmacro customInstallMode
		!endif

    ${if} $isForceMachineInstall == "1"
    ${OrIf} ${isForAllUsers}
      StrCpy $hasPerMachineInstallation "1"
      StrCpy $hasPerUserInstallation "0"
      ${ifNot} ${UAC_IsAdmin}
        ShowWindow $HWNDPARENT ${SW_HIDE}
        !insertmacro UAC_RunElevated
        Quit
      ${endIf}

      !insertmacro setInstallModePerAllUsers
      Abort
    ${endIf}

    ${if} $isForceCurrentInstall == "1"
    ${OrIf} ${isForCurrentUser}
      StrCpy $hasPerMachineInstallation "0"
      StrCpy $hasPerUserInstallation "1"
      !insertmacro setInstallModePerUser
      Abort
    ${endIf}

		# If uninstalling, will check if there is both a per-user and per-machine installation. If there is only one, will skip the form.
	  # If uninstallation was invoked from the "add/remove programs" Windows will automatically requests elevation (depending if uninstall keys are in HKLM or HKCU)
		# so (for uninstallation) just checking UAC_IsAdmin would probably be enought to determine if it's a per-user or per-machine. However, user can run the uninstall.exe from the folder itself
		!ifdef BUILD_UNINSTALLER
			${if} $hasPerUserInstallation == "1"
      ${andif} $hasPerMachineInstallation == "0"
				!insertmacro setInstallModePerUser
				Abort
			${elseIf} $hasPerUserInstallation == "0"
      ${andIf} $hasPerMachineInstallation == "1"
				${IfNot} ${UAC_IsAdmin}
          ShowWindow $HWNDPARENT ${SW_HIDE}
          !insertmacro UAC_RunElevated
          Quit
        ${endIf}

				!insertmacro setInstallModePerAllUsers
				Abort
			${endIf}

      !insertmacro MUI_HEADER_TEXT "$(chooseUninstallationOptions)" "$(whichInstallationShouldBeRemoved)"
		!else
      !insertmacro MUI_HEADER_TEXT "$(chooseInstallationOptions)" "$(whoShouldThisApplicationBeInstalledFor)"
		!endif

    !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
		nsDialogs::Create 1018
		Pop $MultiUser.InstallModePage

		!ifndef BUILD_UNINSTALLER
			${NSD_CreateLabel} 0u 0u 300u 20u "$(selectUserMode)"
			StrCpy $8 "$(forAll)"
			StrCpy $9 "$(onlyForMe)"
		!else
			${NSD_CreateLabel} 0u 0u 300u 20u "$(whichInstallationRemove)"
			StrCpy $8 "$(forAll)"
			StrCpy $9 "$(onlyForMe)"
		!endif
		Pop $MultiUser.InstallModePage.Text

		${NSD_CreateRadioButton} 10u 30u 280u 20u "$8"
		Pop $MultiUser.InstallModePage.AllUsers
		${IfNot} ${UAC_IsAdmin}
			!ifdef MULTIUSER_INSTALLMODE_ALLOW_ELEVATION
				StrCpy $HasTwoAvailableOptions 1
			!else
			  # since radio button is disabled, we add that comment to the disabled control itself
				SendMessage $MultiUser.InstallModePage.AllUsers ${WM_SETTEXT} 0 "STR:$8 (must run as admin)"
				EnableWindow $MultiUser.InstallModePage.AllUsers 0 # start out disabled
				StrCpy $HasTwoAvailableOptions 0
			!endif
		${else}
			StrCpy $HasTwoAvailableOptions 1
		${endif}

		System::Call "advapi32::GetUserName(t.r0,*i${NSIS_MAX_STRLEN})i"
		${NSD_CreateRadioButton} 10u 50u 280u 20u "$9 ($0)"
		Pop $MultiUser.InstallModePage.CurrentUser

		nsDialogs::SetUserData $MultiUser.InstallModePage.AllUsers 1 ; Install for All Users (1, pra exibir o icone SHIELD de elevation)
		nsDialogs::SetUserData $MultiUser.InstallModePage.CurrentUser 0	; Install for Single User (0 pra não exibir)

		${if} $HasTwoAvailableOptions == "1" ; if there are 2 available options, bind to radiobutton change
			${NSD_OnClick} $MultiUser.InstallModePage.CurrentUser ${UNINSTALLER_FUNCPREFIX}InstModeChange
			${NSD_OnClick} $MultiUser.InstallModePage.AllUsers ${UNINSTALLER_FUNCPREFIX}InstModeChange
		${endif}

		${NSD_CreateLabel} 0u 110u 280u 50u ""
		Pop $RadioButtonLabel1

		${if} $installMode == "all"
			SendMessage $MultiUser.InstallModePage.AllUsers ${BM_SETCHECK} ${BST_CHECKED} 0 ; set as default
			SendMessage $MultiUser.InstallModePage.AllUsers ${BM_CLICK} 0 0 ; trigger click event
		${else}
			SendMessage $MultiUser.InstallModePage.CurrentUser ${BM_SETCHECK} ${BST_CHECKED} 0 ; set as default
			SendMessage $MultiUser.InstallModePage.CurrentUser ${BM_CLICK} 0 0 ; trigger click event
		${endif}

		!insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
		nsDialogs::Show
	FunctionEnd

	Function "${UNINSTALLER_FUNCPREFIX}${LEAVE}"
		SendMessage $MultiUser.InstallModePage.AllUsers ${BM_GETCHECK} 0 0 $MultiUser.InstallModePage.ReturnValue

		${if} $MultiUser.InstallModePage.ReturnValue = ${BST_CHECKED}
			${IfNot} ${UAC_IsAdmin}
        ShowWindow $HWNDPARENT ${SW_HIDE}
        !insertmacro UAC_RunElevated
        ${Switch} $0
          ${Case} 0
            ${If} $1 = 1
              Quit ;we are the outer process, the inner process has done its work (ExitCode is $2), we are done
            ${EndIf}
            ${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user
            ${OrIf} $2 = 0x666666 ;our special return, the new process was not admin after all
              MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "$(loginWithAdminAccount)"
            ${EndIf}
            ${Break}
          ${Case} 1223 ;user aborted
            ;MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "This option requires admin privileges, aborting!"
            ;Quit ; instead of quit just abort going to the next page, and stay in the radiobuttons
            ${Break}
          ${Case} 1062
            MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!" ; "Unable to elevate, Secondary Logon service not running!"
            ;Quit ; instead of quit just abort going to the next page, and stay in the radiobuttons
            ${Break}
          ${Default}
            MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate, error $0"
            ;Quit ; instead of quit just abort going to the next page, and stay in the radiobuttons
            ${Break}
        ${EndSwitch}

        ShowWindow $HWNDPARENT ${SW_SHOW}
        BringToFront
        Abort
      ${else}
        !insertmacro setInstallModePerAllUsers
			${endif}
		${else}
			!insertmacro setInstallModePerUser
		${endif}

		!insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
	FunctionEnd

	Function "${UNINSTALLER_FUNCPREFIX}InstModeChange"
		pop $1
		nsDialogs::GetUserData $1
		pop $1
		GetDlgItem $0 $hwndParent 1 ; get item 1 (next button) at parent window, store in $0 - (0 is back, 1 is next .. what about CANCEL? http://nsis.sourceforge.net/Buttons_Header )

		StrCpy $7 ""
		${if} "$1" == "0" ; current user
			${if} $hasPerUserInstallation == "1"
				!ifndef BUILD_UNINSTALLER
					StrCpy $7 "$(perUserInstallExists)($perUserInstallationFolder)$\r$\n$(reinstallUpgrade)"
				!else
					StrCpy $7 "$(perUserInstall)($perUserInstallationFolder)$\r$\n$(uninstall)"
				!endif
			${else}
				StrCpy $7 "$(freshInstallForCurrent)"
			${endif}
			SendMessage $0 ${BCM_SETSHIELD} 0 0 ; hide SHIELD
		${else} ; all users
			${if} $hasPerMachineInstallation == "1"
				!ifndef BUILD_UNINSTALLER
					StrCpy $7 "$(perMachineInstallExists)($perMachineInstallationFolder)$\r$\n$(reinstallUpgrade)"
				!else
					StrCpy $7 "$(perMachineInstall)($perMachineInstallationFolder)$\r$\n$(uninstall)"
				!endif
			${else}
				StrCpy $7 "$(freshInstallForAll)"
			${endif}
			${ifNot} ${UAC_IsAdmin}
				StrCpy $7 "$7"
				SendMessage $0 ${BCM_SETSHIELD} 0 1 ; display SHIELD
			${else}
				SendMessage $0 ${BCM_SETSHIELD} 0 0 ; hide SHIELD
			${endif}
		${endif}
		SendMessage $RadioButtonLabel1 ${WM_SETTEXT} 0 "STR:$7"
	FunctionEnd
!macroend