#define MyAppName "Sandboxie-Plus" #include "Languages.iss" ; Use commandline to populate: ; ISCC.exe /ORelease Sandboxie-Plus.iss /DMyAppVersion=%SbiePlusVer% /DMyAppArch=x64 /DMyAppSrc=SbiePlus64 ; ;#define MyAppVersion "0.7.5" ;#define MyDrvVersion "5.49.8" ;#define MyAppArch "x64" ;#define MyAppSrc "SbiePlus64" [Setup] AppName={#MyAppName} AppVerName={#MyAppName} v{#MyAppVersion} AppId=Sandboxie-Plus AppVersion={#MyAppVersion} AppPublisher=http://xanasoft.com/ AppPublisherURL=http://sandboxie-plus.com/ AppMutex=SBIEPLUS_MUTEX DefaultDirName={code:InstallPath} DefaultGroupName={#MyAppName} Uninstallable=not IsPortable UninstallDisplayIcon={app}\SandMan.exe OutputBaseFilename={#MyAppName}-{#MyAppArch}-v{#MyAppVersion} Compression=lzma ArchitecturesAllowed={#MyAppArch} ArchitecturesInstallIn64BitMode=x64 AllowNoIcons=yes AlwaysRestart=no LicenseFile=.\license.txt UsedUserAreasWarning=no VersionInfoCopyright=Copyright (C) 2020-2021 by David Xanatos (xanasoft.com) VersionInfoVersion={#MyAppVersion} ; Handled in code section as always want DirPage for portable mode. DisableDirPage=no ; Allow /CURRENTUSER to be used with /PORTABLE=1 to avoid admin requirement. PrivilegesRequiredOverridesAllowed=commandline [Tasks] Name: "DesktopIcon"; Description: "{cm:CreateDesktopIcon}"; MinVersion: 0.0,5.0; Check: not IsPortable Name: "AutoStartEntry"; Description: "{cm:AutoStartProgram,{#MyAppName}}"; MinVersion: 0.0,5.0; Check: not IsPortable Name: "AddRunSandboxed"; Description: "{cm:AddSandboxedMenu}"; MinVersion: 0.0,5.0; Check: not IsPortable [Files] ; Both portable and install. Source: ".\Release\{#MyAppSrc}\*"; DestDir: "{app}"; MinVersion: 0.0,5.0; Flags: recursesubdirs ignoreversion; Excludes: "*.pdb" ; Only if portable. Source: ".\Sandboxie.ini"; DestDir: "{app}"; Flags: ignoreversion onlyifdoesntexist; Check: IsPortable Source: ".\Sandboxie-Plus.ini"; DestDir: "{app}"; Flags: ignoreversion onlyifdoesntexist; Check: IsPortable [Icons] Name: "{group}\Sandboxie-Plus"; Filename: "{app}\SandMan.exe"; MinVersion: 0.0,5.0 Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "http://sandboxie-plus.com/"; MinVersion: 0.0,5.0 Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"; MinVersion: 0.0,5.0 Name: "{userdesktop}\Sandboxie-Plus"; Filename: "{app}\SandMan.exe"; Tasks: DesktopIcon; MinVersion: 0.0,5.0 [INI] ; Set Sandman language. Filename: "{localappdata}\{#MyAppName}\{#MyAppName}.ini"; Section: "Options"; Key: "UiLanguage"; String: "{code:SandmanLanguage|{language}}"; Check: not IsPortable Filename: "{app}\{#MyAppName}.ini"; Section: "Options"; Key: "UiLanguage"; String: "{code:SandmanLanguage|{language}}"; Check: IsPortable [Registry] ; Autostart Sandman. Root: HKCU; Subkey: "Software\Software\Microsoft\Windows\CurrentVersion\Run"; ValueName: "SandboxiePlus_AutoRun"; ValueType: string; ValueData: """{app}\SandMan.exe"" -autorun"; Flags: uninsdeletevalue; Tasks: AutoStartEntry ; AddRunSandboxed all files. Root: HKCU; Subkey: "Software\Classes\*\shell\sandbox"; ValueName: ""; ValueType: string; ValueData: "{cm:RunSandboxedMenu}"; Flags: uninsdeletekey; Tasks: AddRunSandboxed Root: HKCU; Subkey: "Software\Classes\*\shell\sandbox"; ValueName: "Icon"; ValueType: string; ValueData: """{app}\start.exe"""; Tasks: AddRunSandboxed Root: HKCU; Subkey: "Software\Classes\*\shell\sandbox\command"; ValueName: ""; ValueType: string; ValueData: """{app}\SandMan.exe"" /box:__ask__ ""%1"" %*"; Tasks: AddRunSandboxed ; AddRunSandboxed folder. Root: HKCU; Subkey: "Software\Classes\Folder\shell\sandbox"; ValueName: ""; ValueType: string; ValueData: "{cm:RunSandboxedMenu}"; Flags: uninsdeletekey; Tasks: AddRunSandboxed Root: HKCU; Subkey: "Software\Classes\Folder\shell\sandbox"; ValueName: "Icon"; ValueType: string; ValueData: """{app}\start.exe"""; Tasks: AddRunSandboxed Root: HKCU; Subkey: "Software\Classes\Folder\shell\sandbox\command"; ValueName: ""; ValueType: string; ValueData: """{app}\SandMan.exe"" /box:__ask__ ""%1"" %*"; Tasks: AddRunSandboxed ; External manifest for Sbie service. Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Services\SbieSvc"; ValueName: "PreferExternalManifest"; ValueType: dword; ValueData: "1"; Check: not IsPortable ; Set language for Sbie service. Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Services\SbieSvc"; ValueType: dword; ValueName: "Language"; ValueData: "{code:SystemLanguage}"; Check: not IsPortable [Run] ; Install the Sbie driver. Filename: "{app}\KmdUtil.exe"; Parameters: "install SbieDrv ""{app}\SbieDrv.sys"" type=kernel start=demand msgfile=""{app}\SbieMsg.dll"" altitude=86900"; StatusMsg: "KmdUtil install SbieDrv..."; Check: not IsPortable ; Install the Sbie service. Filename: "{app}\KmdUtil.exe"; Parameters: "install SbieSvc ""{app}\SbieSvc.exe"" type=own start=auto msgfile=""{app}\SbieMsg.dll"" display=""Sandboxie Service"" group=UIGroup"; StatusMsg: "KmdUtil install SbieSvc..."; Check: not IsPortable ; Start the Sbie service. Filename: "{app}\KmdUtil.exe"; Parameters: "start SbieSvc"; StatusMsg: "KmdUtil start SbieSvc"; Check: not IsPortable ; Start the Sandman UI. ;Filename: "{app}\SandMan.exe"; Parameters: "-autorun"; StatusMsg: "Launch SandMan UI..."; Flags: postinstall nowait; Check: not IsPortable Filename: "{app}\SandMan.exe"; Parameters: "-autorun"; StatusMsg: "Launch SandMan UI..."; Flags: nowait; Check: not IsPortable [UninstallDelete] Type: files; Name: "{app}\SbieDrv.sys.w10" Type: files; Name: "{app}\SbieDrv.sys.rc4" Type: dirifempty; Name: "{app}" Type: dirifempty; Name: "{localappdata}\{#MyAppName}" [Messages] ; Include with commandline /? message. HelpTextNote=/PORTABLE=1%nEnable portable mode.%n [Code] var CustomPage: TInputOptionWizardPage; IsInstalled: Boolean; Portable: Boolean; function IsPortable(): Boolean; begin // Return True or False for the value of Check. if (ExpandConstant('{param:portable|0}') = '1') or Portable then begin Result := True; end; end; function IsUpgrade(): Boolean; var S: String; InnoSetupReg: String; AppPathName: String; begin // Detect if already installed. // Source: https://stackoverflow.com/a/30568071 InnoSetupReg := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppName")}_is1'); AppPathName := 'Inno Setup: App Path'; Result := RegQueryStringValue(HKLM, InnoSetupReg, AppPathName, S) or RegQueryStringValue(HKCU, InnoSetupReg, AppPathName, S); end; function InstallPath(Dummy: String): String; var DrvPath: String; SbiePath: String; begin // Return the path to use for the value of DefaultDirName. IsInstalled := False; SbiePath := ExpandConstant('{param:dir}'); if SbiePath = '' then begin if (ExpandConstant('{param:portable|0}') = '1') or Portable then begin SbiePath := ExpandConstant('{src}') + '\{#MyAppName}'; end else begin if RegQueryStringValue(HKLM, 'SYSTEM\CurrentControlSet\Services\SbieDrv', 'ImagePath', DrvPath) then begin IsInstalled := True; DrvPath := ExtractFilePath(DrvPath); if Copy(DrvPath, 1, 4) = '\??\' then begin DrvPath := Copy(DrvPath, 5, Length(DrvPath) - 5); end; SbiePath := DrvPath; end else begin SbiePath := ExpandConstant('{autopf}') + '\{#MyAppName}'; end; end; end; Result := SbiePath; end; function SandmanLanguage(Language: String): String; begin // Language values for Sandboxie-Plus.ini. case Lowercase(Language) of 'english': Result := 'en'; 'chinesesimplified': Result := 'zh-CN'; 'chinesetraditional': Result := 'zh-TW'; 'dutch': Result := 'nl'; 'french': Result := 'fr'; 'german': Result := 'de'; 'italian': Result := 'it'; 'polish': Result := 'pl'; 'portuguese': Result := 'pt'; 'russian': Result := 'ru'; 'spanish': Result := 'es'; 'turkish': Result := 'tr'; end; end; function SystemLanguage(Dummy: String): String; begin // Language identifier for the System Eventlog messages. Result := IntToStr(GetUILanguage()); end; procedure UpdateStatus(OutputProgressPage: TOutputProgressWizardPage; Text: String; Percentage: Integer); begin // Called by ShutdownSbie() to update status or progress. if IsUninstaller() then UninstallProgressForm.StatusLabel.Caption := Text else begin OutputProgressPage.SetProgress(Percentage, 100); OutputProgressPage.SetText(Text, ''); end; // Output status information to log. Log('Debug: ' + Text); end; function ShutdownSbie(): Boolean; var ExecRet: Integer; StatusText: String; OutputProgressPage: TOutputProgressWizardPage; begin // Require KmdUtil.exe to continue. if (FileExists(ExpandConstant('{app}\KmdUtil.exe')) = False) then begin Result := True; exit; end; try // Backup status text (uninstall). Prepare progress page (install). if IsUninstaller() then StatusText := UninstallProgressForm.StatusLabel.Caption else begin OutputProgressPage := CreateOutputProgressPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc)); OutputProgressPage.Show(); end; // Run KmdUtil scandll. UpdateStatus(OutputProgressPage, 'KmdUtil scandll', 5); Exec(ExpandConstant('{app}\KmdUtil.exe'), 'scandll', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ExecRet); if (ExecRet <> 0) then begin Result := False; exit; end; // Stop processes. UpdateStatus(OutputProgressPage, 'Taskkill /IM Sandman.exe /IM SbieCtrl.exe /IM Start.exe /F', 30); Exec(ExpandConstant('{sys}\taskkill.exe'), '/IM Sandman.exe /IM SbieCtrl.exe /IM Start.exe /F', '', SW_HIDE, ewWaitUntilTerminated, ExecRet); // Stop service and driver. UpdateStatus(OutputProgressPage, 'KmdUtil stop SbieSvc', 55); Exec(ExpandConstant('{app}\KmdUtil.exe'), 'stop SbieSvc', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ExecRet); UpdateStatus(OutputProgressPage, 'KmdUtil stop SbieDrv', 85); Exec(ExpandConstant('{app}\KmdUtil.exe'), 'stop SbieDrv', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ExecRet); // Uninstall service and driver. UpdateStatus(OutputProgressPage, 'KmdUtil delete SbieSvc', 95); Exec(ExpandConstant('{app}\KmdUtil.exe'), 'delete SbieSvc', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ExecRet); UpdateStatus(OutputProgressPage, 'KmdUtil delete SbieDrv', 100); Exec(ExpandConstant('{app}\KmdUtil.exe'), 'delete SbieDrv', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ExecRet); // Query driver which can remove SbieDrv key if exist. if RegKeyExists(HKLM, 'SYSTEM\CurrentControlSet\services\SbieDrv') then begin UpdateStatus(OutputProgressPage, 'SC query SbieDrv', 100); Exec(ExpandConstant('{sys}\sc.exe'), 'query SbieDrv', '', SW_HIDE, ewWaitUntilTerminated, ExecRet); end; finally // Restore status text (uninstall). Hide Prepare progress page (install). if IsUninstaller() then UninstallProgressForm.StatusLabel.Caption := StatusText else begin OutputProgressPage.SetProgress(0, 100); OutputProgressPage.Hide(); end; end; Result := True; end; ////////////////////////////////////////////////////// // Installation Events // function NextButtonClick(CurPageID: Integer): Boolean; begin // Get mode setting from Custom page and set path for the Dir page. if CurPageID = CustomPage.ID then begin Portable := not (CustomPage.SelectedValueIndex = 0); WizardForm.DirEdit.Text := InstallPath(''); // No Start Menu folder setting on Ready page if portable. if Portable then begin WizardForm.NoIconsCheck.Checked := True; end else begin WizardForm.NoIconsCheck.Checked := False; end; end; // Shutdown service, driver and processes as ready to install. if ((CurPageID = wpReady) and (not IsPortable())) then begin Result := ShutdownSbie(); exit; end; Result := True; end; function ShouldSkipPage(PageID: Integer): Boolean; begin // Skip Custom page and Group page if portable. if PageID = CustomPage.ID then begin if ExpandConstant('{param:portable|0}') = '1' then Result := True; end else if PageID = wpSelectDir then begin if not IsPortable and IsUpgrade then Result := True; end else if PageID = wpSelectProgramGroup then begin if IsPortable then Result := True; end; end; procedure InitializeWizard(); begin // Create the custom page. // Source: https://timesheetsandstuff.wordpress.com/2008/06/27/the-joy-of-part-2/ CustomPage := CreateInputOptionPage(wpLicense, CustomMessage('CustomPageLabel1'), CustomMessage('CustomPageLabel2'), CustomMessage('CustomPageLabel3'), True, False); if IsInstalled = True then begin CustomPage.Add(CustomMessage('CustomPageUpgradeMode')); end else begin CustomPage.Add(CustomMessage('CustomPageInstallMode')); end; CustomPage.Add(CustomMessage('CustomPagePortableMode')); // Default to Normal Installation if not argument /PORTABLE=1. if ExpandConstant('{param:portable|0}') = '1' then begin WizardForm.NoIconsCheck.Checked := True; CustomPage.SelectedValueIndex := 1; end else begin CustomPage.SelectedValueIndex := 0; end; end; function InitializeSetup(): Boolean; var Version: TWindowsVersion; ExecRet: Integer; UninstallString: String; begin // Require Windows 7 or later. GetWindowsVersionEx(Version); if (Version.NTPlatform = False) or (Version.Major < 6) then begin SuppressibleMsgBox(CustomMessage('RequiresWin7OrLater'), mbError, MB_OK, MB_OK); Result := False; exit; end; // Ask to uninstall Sandboxie Classic if found. ExecRet := IDYES; while (ExecRet = IDYES) do begin if RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Sandboxie', 'UninstallString', UninstallString) then begin ExecRet := MsgBox(CustomMessage('ClassicFound'), mbConfirmation, MB_YESNOCANCEL); if ExecRet = IDCANCEL then begin Result := False; exit; end; if ExecRet = IDYES then begin Exec('cmd.exe', '/c ' + UninstallString, '', SW_HIDE, ewWaitUntilTerminated, ExecRet); ExecRet := IDYES; end; end else begin break; end; end; Result := True; end; ////////////////////////////////////////////////////// // Uninstallation Exclusive // procedure UninstallCleanup(ButtonCount: Integer); var Buttons: Cardinal; ButtonLabels: TArrayOfString; ExecRet: Integer; I: Integer; Paths: TStringList; ShowMsgbox: Boolean; TaskRet: Integer; begin // Require 2 or 3 for button count. if (ButtonCount < 2) or (ButtonCount > 3) then exit; // Require Sandman.exe to continue. if not FileExists(ExpandConstant('{app}\Sandman.exe')) then exit; // Make a list. Paths := TStringList.Create; // Append file paths to the list for removal. Paths.Append('{localappdata}\{#MyAppName}\{#MyAppName}.ini'); Paths.Append('{win}\Sandboxie.ini'); Paths.Append('{app}\{#MyAppName}.ini'); Paths.Append('{app}\Sandboxie.ini'); // Expand paths and detect if any file exist. for I := 0 to Paths.Count - 1 do begin Paths[I] := ExpandConstant(Paths[I]); if FileExists(Paths[I]) then ShowMsgbox := True; end; // Delete the config files and the sandboxes. if ShowMsgbox then begin case ButtonCount of 2: begin Buttons := MB_YESNO; ButtonLabels := [CustomMessage('UninstallTaskLabel3'), CustomMessage('UninstallTaskLabel4')]; end; 3: begin Buttons := MB_ABORTRETRYIGNORE; ButtonLabels := [CustomMessage('UninstallTaskLabel3'), CustomMessage('UninstallTaskLabel4'), CustomMessage('UninstallTaskLabel5')]; end; end; case TaskDialogMsgBox(CustomMessage('UninstallTaskLabel1'), CustomMessage('UninstallTaskLabel2'), mbConfirmation, Buttons, ButtonLabels, 0) of IDRETRY: TaskRet := 1; IDIGNORE: TaskRet := 2; IDABORT: TaskRet := 3; IDYES: TaskRet := 1; IDNO: TaskRet := 2; end; if TaskRet > 2 then begin Log('Debug: Sandman /RemoveSandboxes'); Exec(ExpandConstant('{app}\Sandman.exe'), '/RemoveSandboxes', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ExecRet); end; if TaskRet > 1 then begin for I := 0 to Paths.Count - 1 do if FileExists(Paths[I]) then begin Log('Debug: DeleteFile(' + Paths[I] + ')'); DeleteFile(Paths[I]); end; end; end; // Release the list. Paths.Free; end; ////////////////////////////////////////////////////// // Uninstallation Events // procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); begin // Before the uninstallation. if (CurUninstallStep <> usUninstall) then exit; // User to confirm extra files to remove. if not UninstallSilent then UninstallCleanup(2); // Shutdown service, driver and processes. if (ShutdownSbie() = False) then begin Abort(); exit; end; end;