Merge pull request #8166 from nextcloud/backport/8160/stable-3.16

[stable-3.16] fix(msi): allow custom installation directory
This commit is contained in:
Jyrki Gadinger 2025-04-15 16:49:51 +02:00 committed by GitHub
commit 2bcb322cc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 9 deletions

View File

@ -25,6 +25,7 @@ install(FILES
${CMAKE_CURRENT_BINARY_DIR}/OEM.wxi
${CMAKE_CURRENT_BINARY_DIR}/collect-transform.xsl
${CMAKE_CURRENT_BINARY_DIR}/make-msi.bat
EnsureACL.js
Platform.wxi
Nextcloud.wxs
${CMAKE_CURRENT_BINARY_DIR}/RegistryCleanup.vbs

View File

@ -0,0 +1,44 @@
// writes a message to the MSI logs
function logInfo(message) {
var record = Session.Installer.CreateRecord(0);
record.stringData(0) = message
// 0x40000000 = msiMessageTypeUser -- see https://learn.microsoft.com/en-gb/windows/win32/msi/session-message#parameters
Session.Message(0x04000000, record)
}
function EnsureACL() {
var shell = new ActiveXObject("WScript.Shell");
var fs = new ActiveXObject("Scripting.FileSystemObject");
var programFilesPath = fs.GetAbsolutePathName(shell.ExpandEnvironmentStrings("%PROGRAMFILES%"));
var installPath = fs.GetAbsolutePathName(Session.Property("CustomActionData"));
logInfo("programFilesPath: " + programFilesPath + "\r\n" + "installPath: " + installPath);
if (installPath.toLowerCase().indexOf(programFilesPath.toLowerCase()) == 0) {
// no need to adapt ACLs when installing to C:/Program Files
return 0;
}
// using SIDs here (prefixed by *) to avoid potential issues with non-English installs
// see also: https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids
var grants = [
"*S-1-5-32-544:(OI)(CI)F", // DOMAIN_ALIAS_RID_ADMINS => full access
"*S-1-5-18:(OI)(CI)F", // SECURITY_LOCAL_SYSTEM_RID => full access
"*S-1-5-32-545:(OI)(CI)RX" // DOMAIN_ALIAS_RID_USERS => read, execute
];
var grantsOptions = "";
for (var i = 0; i < grants.length; i++) {
grantsOptions += ' /grant "' + grants[i] + '" ';
}
var icaclsCommand = 'icacls.exe "' + installPath + '" /inheritance:r ' + grantsOptions;
logInfo("Command: " + icaclsCommand);
var retval = shell.Run(icaclsCommand, 0, true);
if (retval != 0) {
logInfo("Return code: " + retval);
return 1603; // fatal error
}
return 0;
}

View File

@ -57,8 +57,8 @@
<!-- Detect legacy NSIS installation -->
<Property Id="NSIS_UNINSTALLEXE">
<RegistrySearch Id="RegistryLegacyUninstallString" Type="file" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\$(var.AppName)" Name="UninstallString" Win64="no">
<FileSearch Id="LegacyUninstallFileName" Name="Uninstall.exe"/>
</RegistrySearch>
<FileSearch Id="LegacyUninstallFileName" Name="Uninstall.exe"/>
</RegistrySearch>
</Property>
<!-- Property to disable update checks -->
@ -71,22 +71,30 @@
<SetProperty Id="ExecNsisUninstaller" Value="&quot;$(var.AppShortName)&quot; &quot;[NSIS_UNINSTALLEXE]&quot;" Before="ExecNsisUninstaller" Sequence="execute" />
<SetProperty Id="RemoveNavigationPaneEntries" Value="&quot;$(var.AppName)&quot;" Before="RemoveNavigationPaneEntries" Sequence="execute" />
<!-- Ensure ACLs -->
<Binary Id="EnsureACL" SourceFile="EnsureACL.js" />
<SetProperty Id="EnsureACL" Before="EnsureACL" Value="[INSTALLDIR]" Sequence="execute" />
<CustomAction Id="EnsureACL" BinaryKey="EnsureACL" JScriptCall="EnsureACL" Return="check" Execute="deferred" Impersonate="no" />
<InstallExecuteSequence>
<!-- Install: Remove previous NSIS installation, if detected -->
<Custom Action="ExecNsisUninstaller" Before="ProcessComponents">NSIS_UNINSTALLEXE AND NOT Installed</Custom>
<!-- Install: Ensure ACLs are set -->
<Custom Action="EnsureACL" After="InstallFiles">NOT Installed</Custom>
<!-- Uninstall: Remove sync folders from Explorer's Navigation Pane, only effective for the current user (home users) -->
<Custom Action="RemoveNavigationPaneEntries" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<!-- Uninstall: Cleanup the Registry -->
<Custom Action="RegistryCleanupCustomAction" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<!-- Uninstall: Cleanup the Registry -->
<Custom Action="RegistryCleanupCustomAction" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<!-- Schedule Reboot for the Shell Extensions (in silent installation mode only, or if SCHEDULE_REBOOT argument is set-->
<ScheduleReboot After="InstallFinalize">(SCHEDULE_REBOOT=1) OR NOT (UILevel=2)</ScheduleReboot>
</InstallExecuteSequence>
<!-- "Add or Remove" Programs Entries -->
<Property Id="APPNAME">$(var.AppName)</Property>
<Property Id="APPNAME">$(var.AppName)</Property>
<Property Id="ARPPRODUCTICON">$(var.AppIcon)</Property>
<Property Id="ARPHELPLINK">$(var.AppHelpLink)</Property>
<Property Id="ARPURLINFOABOUT">$(var.AppInfoLink)</Property>
@ -192,11 +200,11 @@
<RegistryValue Type="integer" Name="skipUpdateCheck" Value="[SKIPAUTOUPDATE]" />
</RegistryKey>
</Component>
<!-- Register URI handler -->
<!-- Register URI handler -->
<Component Id="RegistryUriHandler" Guid="*" Win64="$(var.PlatformWin64)">
<RegistryKey Root="HKLM" Key="Software\Classes\$(var.AppCommandOpenUrlScheme)" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Type="string" Value="URL:$(var.AppName) Protocol" />
<RegistryValue Type="string" Name="URL Protocol" Value="" />
<RegistryValue Type="string" Name="URL Protocol" Value="" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="Software\Classes\$(var.AppCommandOpenUrlScheme)\DefaultIcon" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Type="string" Value="[INSTALLDIR]$(var.AppExe)" />
@ -214,7 +222,7 @@
<ComponentRef Id="RegistryVersionInfo" />
<ComponentRef Id="RegistryDefaultSettings" />
<ComponentRef Id="RegistryUriHandler" />
<ComponentRef Id="RegistryUriHandler" />
<Feature Id="ShellExtensions" Title="Integration for Windows Explorer"
Description="This feature requires a reboot." >