Skip to content

Commit

Permalink
Always run the uninstaller as the correct user
Browse files Browse the repository at this point in the history
When a standard user uses an admin account for elevation to change an
existing single-user installation to all-users, the uninstaller is now
run for the correct (standard) user (instead of the admin).
  • Loading branch information
bitraid committed Oct 30, 2018
1 parent bf51ad8 commit c87e3b7
Showing 1 changed file with 52 additions and 46 deletions.
98 changes: 52 additions & 46 deletions misc/nsis/install.nsh
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,48 @@ var KeepReg
!macroend

; Functions
Function CheckInstallation
; if there's an installed version, uninstall it first (I chose not to start the uninstaller silently, so that user sees what failed)
; if both per-user and per-machine versions are installed, unistall the one that matches $MultiUser.InstallMode
StrCpy $0 ""
${if} $HasCurrentModeInstallation = 1
StrCpy $0 "$MultiUser.InstallMode"
${else}
!if ${MULTIUSER_INSTALLMODE_ALLOW_BOTH_INSTALLATIONS} = 0
${if} $HasPerMachineInstallation = 1
StrCpy $0 "AllUsers" ; if there's no per-user installation, but there's per-machine installation, uninstall it
${elseif} $HasPerUserInstallation = 1
StrCpy $0 "CurrentUser" ; if there's no per-machine installation, but there's per-user installation, uninstall it
${endif}
!endif
${endif}

${if} "$0" != ""
${if} $0 == "AllUsers"
StrCpy $1 "$PerMachineUninstallString"
StrCpy $3 "$PerMachineInstallationFolder"
${else}
StrCpy $1 "$PerUserUninstallString"
StrCpy $3 "$PerUserInstallationFolder"
${endif}
${if} ${silent}
StrCpy $2 "/S"
${else}
StrCpy $2 ""
${endif}
${if} $KeepReg = 1
StrCpy $4 "/upgrade"
${endif}
${endif}
FunctionEnd

Function RunUninstaller
StrCpy $0 0
; $1 is quoted in registry; the _? param stops the uninstaller from copying
; itself to the temporary directory, which is the only way for ExecWait to work
ExecWait '$1 /SS $2 _?=$3' $0 ; $1 is quoted in registry; the _? param stops the uninstaller from copying itself to the temporary directory, which is the only way for ExecWait to work
FunctionEnd

Function GetDefaultBrowser
ReadRegStr $0 HKCU "SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice" "ProgId"
ReadRegStr $1 HKCU "SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice" "ProgId"
Expand Down Expand Up @@ -180,54 +222,17 @@ InstType "Minimal"
Section "Core Files (required)" SectionCoreFiles
SectionIn 1 2 3 RO

; if there's an installed version, uninstall it first (I chose not to start
; the uninstaller silently, so that user sees what failed)
; if both per-user and per-machine versions are installed, unistall the one
; that matches $MultiUser.InstallMode
StrCpy $0 ""
${if} $HasCurrentModeInstallation = 1
StrCpy $0 "$MultiUser.InstallMode"
${else}
StrCpy $KeepReg 0
!if ${MULTIUSER_INSTALLMODE_ALLOW_BOTH_INSTALLATIONS} = 0
${if} $HasPerMachineInstallation = 1
; if there's no per-user installation, but there's per-machine installation, uninstall it
StrCpy $0 "AllUsers"
${elseif} $HasPerUserInstallation = 1
; if there's no per-machine installation, but there's per-user installation, uninstall it
StrCpy $0 "CurrentUser"
${endif}
!endif
${endif}

!insertmacro UAC_AsUser_Call Function CheckInstallation ${UAC_SYNCREGISTERS}
${if} "$0" != ""
${if} $0 == "AllUsers"
StrCpy $1 "$PerMachineUninstallString"
StrCpy $3 "$PerMachineInstallationFolder"
${else}
StrCpy $1 "$PerUserUninstallString"
StrCpy $3 "$PerUserInstallationFolder"
${endif}
${if} ${silent}
StrCpy $2 "/S"
${else}
StrCpy $2 ""
${endif}

${if} $KeepReg = 1
StrCpy $4 "/upgrade"
${endif}

; Make sure the uninstaller is there before attempting to run it
${if} ${FileExists} "$3\${UNINSTALL_FILENAME}"

HideWindow
ClearErrors
StrCpy $0 0
; $1 is quoted in registry; the _? param stops the uninstaller from copying
; itself to the temporary directory, which is the only way for ExecWait to work
ExecWait '$1 $4 /SS $2 _?=$3' $0

${if} $0 == "AllUsers"
Call RunUninstaller
${else}
!insertmacro UAC_AsUser_Call Function RunUninstaller ${UAC_SYNCREGISTERS}
${endif}
${if} ${errors} ; stay in installer
SetErrorLevel 2 ; Installation aborted by script
BringToFront
Expand All @@ -248,9 +253,10 @@ Section "Core Files (required)" SectionCoreFiles
${EndSwitch}
${endif}

; the uninstaller doesn't delete itself when not copied to the temp directory
!insertmacro DeleteRetryAbort "$3\${UNINSTALL_FILENAME}"
RMDir "$3"
${if} $IsAdmin = 1
!insertmacro DeleteRetryAbort "$3\${UNINSTALL_FILENAME}"
RMDir "$3"
${endif}
${endif}
${endif}

Expand Down

0 comments on commit c87e3b7

Please sign in to comment.