multiUserUi.nsh 8.71 KB
Newer Older
huahua committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
!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