From 6bccdc81b4de0b126de85be1a6fe22f9bfb6a1aa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 13 Jan 2016 14:16:50 -0800 Subject: [PATCH] use the UAC plugin to elevate uninstaller --- cmake/templates/NSIS.template.in | 34 ++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index a0d7ac09c4..fcdf5bfa3a 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -30,8 +30,10 @@ ;-------------------------------- ;General - !ifdef INNER + ; leverage the UAC NSIS plugin to promote uninstaller to elevated privileges + !include UAC.nsh + !echo "Inner invocation" ; just to see what's going on ; Require user only for temp installer @@ -62,7 +64,7 @@ ; The Inner invocation has written an uninstaller binary for us. ; We need to sign it if it's a production or PR build. !if @PRODUCTION_BUILD@ == 1 - !system '"@SIGNTOOL_EXECUTABLE@" sign /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://tsa.starfieldtech.com /td SHA256 $%TEMP%\uninstaller.exe' = 0 + !system '"@SIGNTOOL_EXECUTABLE@" sign /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://tsa.starfieldtech.com /td SHA256 $%TEMP%\Uninstall.exe' = 0 !endif ; Good. Now we can carry on writing the real installer. @@ -685,7 +687,7 @@ Section "-Core installation" ;Package the signed uninstaller produced by the inner loop !ifndef INNER ; this packages the signed uninstaller - File $%TEMP%\uninstaller.exe + File $%TEMP%\Uninstaller.exe !endif Push "DisplayName" @@ -928,6 +930,29 @@ FunctionEnd ; determine admin versus local install Function un.onInit + ; attempt to elevate the uninstaller to admin status + uac_tryagain: + !insertmacro UAC_RunElevated + ${Switch} $0 + ${Case} 0 + ${IfThen} $1 = 1 ${|} Quit ${|} ;we are the outer process, the inner process has done its work, we are done + ${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on + ${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user + MessageBox mb_YesNo|mb_IconExclamation|mb_TopMost|mb_SetForeground "The uninstaller requires admin privileges, try again" /SD IDNO IDYES uac_tryagain IDNO 0 + ${EndIf} + ;fall-through and die + + ${Case} 1223 + MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "The uninstaller requires admin privileges, aborting!" + Quit + ${Case} 1062 + MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!" + Quit + ${Default} + MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate, error $0" + Quit + ${EndSwitch} + ClearErrors UserInfo::GetName IfErrors noLM @@ -994,6 +1019,7 @@ FunctionEnd !ifdef INNER 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" @@ -1107,7 +1133,7 @@ Function .onInit ; the installer. This is better than processing a command line option as it means ; this entire code path is not present in the final (real) installer. - WriteUninstaller "$%TEMP%\uninstaller.exe" + WriteUninstaller "$%TEMP%\Uninstall.exe" ; just bail out quickly when running the "inner" installer Quit