From 0fccd88bd9ebc4fd8655fe2e9072520912699183 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Sat, 9 Dec 2017 11:40:23 -0600 Subject: BUILD: Make Windows installer run unprivileged for non-admin users --- dists/win32/ScummVM.iss | 143 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 6 deletions(-) (limited to 'dists/win32') diff --git a/dists/win32/ScummVM.iss b/dists/win32/ScummVM.iss index e85975f108..38745c885a 100644 --- a/dists/win32/ScummVM.iss +++ b/dists/win32/ScummVM.iss @@ -1,18 +1,20 @@ +#define AppName "ScummVM" + [Setup] AppCopyright=2018 -AppName=ScummVM -AppVerName=ScummVM Git +AppName={#AppName} +AppVerName={#AppName} Git AppPublisher=The ScummVM Team AppPublisherURL=http://www.scummvm.org/ AppSupportURL=http://www.scummvm.org/ AppUpdatesURL=http://www.scummvm.org/ -DefaultDirName={pf}\ScummVM -DefaultGroupName=ScummVM +DefaultDirName={pf}\{#AppName} +DefaultGroupName={#AppName} AllowNoIcons=true AlwaysUsePersonalGroup=false EnableDirDoesntExistWarning=false Compression=lzma -OutputDir=C:\ScummVM +OutputDir=C:\{#AppName} OutputBaseFilename=scummvm-win32 DisableStartupPrompt=true AppendDefaultDirName=false @@ -22,7 +24,136 @@ SetupIconFile=graphics\scummvm-install.ico WizardImageFile=graphics\left.bmp ShowLanguageDialog=yes LanguageDetectionMethod=uilanguage -PrivilegesRequired=lowest +PrivilegesRequired=none + +; This privilege escalation code comes from +; https://stackoverflow.com/a/35435534/252087 + +#define InnoSetupReg \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\" + AppName + "_is1" +#define InnoSetupAppPathReg "Inno Setup: App Path" + +[Code] +function IsWinVista: Boolean; +begin + Result := (GetWindowsVersion >= $06000000); +end; + +function IsElevated: Boolean; +begin + Result := IsAdminLoggedOn or IsPowerUserLoggedOn; +end; + +function HaveWriteAccessToApp: Boolean; +var + FileName: string; +begin + FileName := AddBackslash(WizardDirValue) + 'writetest.tmp'; + Result := SaveStringToFile(FileName, 'test', False); + if Result then + begin + Log(Format( + 'Have write access to the last installation path [%s]', [WizardDirValue])); + DeleteFile(FileName); + end + else + begin + Log(Format('Does not have write access to the last installation path [%s]', [ + WizardDirValue])); + end; +end; + +procedure ExitProcess(uExitCode: UINT); + external 'ExitProcess@kernel32.dll stdcall'; +function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string; + lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle; + external 'ShellExecuteW@shell32.dll stdcall'; + +function Elevate: Boolean; +var + I: Integer; + RetVal: Integer; + Params: string; + S: string; +begin + { Collect current instance parameters } + for I := 1 to ParamCount do + begin + S := ParamStr(I); + { Unique log file name for the elevated instance } + if CompareText(Copy(S, 1, 5), '/LOG=') = 0 then + begin + S := S + '-elevated'; + end; + { Do not pass our /SL5 switch } + if CompareText(Copy(S, 1, 5), '/SL5=') <> 0 then + begin + Params := Params + AddQuotes(S) + ' '; + end; + end; + + { ... and add selected language } + Params := Params + '/LANG=' + ActiveLanguage; + + Log(Format('Elevating setup with parameters [%s]', [Params])); + RetVal := ShellExecute(0, 'runas', ExpandConstant('{srcexe}'), Params, '', SW_SHOW); + Log(Format('Running elevated setup returned [%d]', [RetVal])); + Result := (RetVal > 32); + { if elevated executing of this setup succeeded, then... } + if Result then + begin + Log('Elevation succeeded'); + { exit this non-elevated setup instance } + ExitProcess(0); + end + else + begin + Log(Format('Elevation failed [%s]', [SysErrorMessage(RetVal)])); + end; +end; + +procedure InitializeWizard; +var + S: string; + Upgrade: Boolean; +begin + Upgrade := + RegQueryStringValue(HKLM, '{#InnoSetupReg}', '{#InnoSetupAppPathReg}', S) or + RegQueryStringValue(HKCU, '{#InnoSetupReg}', '{#InnoSetupAppPathReg}', S); + + { elevate } + + if not IsWinVista then + begin + Log(Format('This version of Windows [%x] does not support elevation', [ + GetWindowsVersion])); + end + else + if IsElevated then + begin + Log('Running elevated'); + end + else + begin + Log('Running non-elevated'); + if Upgrade then + begin + if not HaveWriteAccessToApp then + begin + Elevate; + end; + end + else + begin + if not Elevate then + begin + WizardForm.DirEdit.Text := ExpandConstant('{localappdata}\{#AppName}'); + Log(Format('Falling back to local application user folder [%s]', [ + WizardForm.DirEdit.Text])); + end; + end; + end; +end; [Languages] Name: en; MessagesFile: compiler:Default.isl -- cgit v1.2.3