From b62a7a0beb7ceb7987de28ec768c7814cadb83b9 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 21 Jul 2020 14:31:53 -0700 Subject: Support implicit standard directory reference and "3264" platform folders Completes wixtoolset/issues#5798 and wixtoolset/issues#5835 --- .../Bind/AddRequiredStandardDirectories.cs | 95 ++++++++++++++++++++++ .../Bind/BindDatabaseCommand.cs | 9 +- .../Bind/BindSummaryInfoCommand.cs | 31 +++++++ .../Bind/CalculateComponentGuids.cs | 9 +- .../Bind/SequenceActionsCommand.cs | 36 ++++---- 5 files changed, 154 insertions(+), 26 deletions(-) create mode 100644 src/WixToolset.Core.WindowsInstaller/Bind/AddRequiredStandardDirectories.cs (limited to 'src/WixToolset.Core.WindowsInstaller') diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AddRequiredStandardDirectories.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AddRequiredStandardDirectories.cs new file mode 100644 index 00000000..4597639b --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/AddRequiredStandardDirectories.cs @@ -0,0 +1,95 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core.WindowsInstaller.Bind +{ + using System; + using System.Collections.Generic; + using System.Linq; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using WixToolset.Data.WindowsInstaller; + + /// + /// Add referenced standard directory symbols, if not already present. + /// + internal class AddRequiredStandardDirectories + { + internal AddRequiredStandardDirectories(IntermediateSection section, Platform platform) + { + this.Section = section; + this.Platform = platform; + } + + private IntermediateSection Section { get; } + + private Platform Platform { get; } + + public void Execute() + { + var directories = this.Section.Symbols.OfType().ToList(); + var directoriesById = directories.ToDictionary(d => d.Id.Id); + + foreach (var directory in directories) + { + var parentDirectoryId = directory.ParentDirectoryRef; + + if (String.IsNullOrEmpty(parentDirectoryId)) + { + if (directory.Id.Id != "TARGETDIR") + { + directory.ParentDirectoryRef = "TARGETDIR"; + } + } + else + { + this.EnsureStandardDirectoryAdded(directoriesById, parentDirectoryId, directory.SourceLineNumbers); + } + } + + if (!directoriesById.ContainsKey("TARGETDIR") && WindowsInstallerStandard.TryGetStandardDirectory("TARGETDIR", out var targetDir)) + { + directoriesById.Add(targetDir.Id.Id, targetDir); + this.Section.AddSymbol(targetDir); + } + } + + private void EnsureStandardDirectoryAdded(Dictionary directoriesById, string directoryId, SourceLineNumber sourceLineNumbers) + { + if (!directoriesById.ContainsKey(directoryId) && WindowsInstallerStandard.TryGetStandardDirectory(directoryId, out var standardDirectory)) + { + var parentDirectoryId = this.GetStandardDirectoryParent(directoryId); + + var directory = new DirectorySymbol(sourceLineNumbers, standardDirectory.Id) + { + Name = standardDirectory.Name, + ParentDirectoryRef = parentDirectoryId, + }; + + directoriesById.Add(directory.Id.Id, directory); + this.Section.AddSymbol(directory); + + if (!String.IsNullOrEmpty(parentDirectoryId)) + { + this.EnsureStandardDirectoryAdded(directoriesById, parentDirectoryId, sourceLineNumbers); + } + } + } + + private string GetStandardDirectoryParent(string directoryId) + { + switch (directoryId) + { + case "TARGETDIR": + return null; + + case "CommonFiles6432Folder": + case "ProgramFiles6432Folder": + case "System6432Folder": + return WindowsInstallerStandard.GetPlatformSpecificDirectoryId(directoryId, this.Platform); + + default: + return "TARGETDIR"; + } + } + } +} diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index 950fe1c1..93c617d9 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs @@ -133,6 +133,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind bool compressed; bool longNames; int installerVersion; + Platform platform; string modularizationSuffix; { var command = new BindSummaryInfoCommand(section); @@ -141,6 +142,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind compressed = command.Compressed; longNames = command.LongNames; installerVersion = command.InstallerVersion; + platform = command.Platform; modularizationSuffix = command.ModularizationSuffix; } @@ -193,6 +195,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind command.Execute(); } + { + var command = new AddRequiredStandardDirectories(section, platform); + command.Execute(); + } + { var command = new CreateSpecialPropertiesCommand(section); command.Execute(); @@ -332,7 +339,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind // Set generated component guids. { - var command = new CalculateComponentGuids(this.Messaging, this.BackendHelper, this.PathResolver, section); + var command = new CalculateComponentGuids(this.Messaging, this.BackendHelper, this.PathResolver, section, platform); command.Execute(); } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs index 82688edf..63691016 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs @@ -32,6 +32,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind public int InstallerVersion { get; private set; } + public Platform Platform { get; private set; } + /// /// Modularization guid, or null if the output is not a module. /// @@ -66,6 +68,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind summaryInformationSymbol.Value = Common.GetValidCodePage(codepage, false, false, summaryInformationSymbol.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); } break; + case SummaryInformationType.PlatformAndLanguage: + this.Platform = GetPlatformFromSummaryInformation(summaryInformationSymbol.Value); + break; + case SummaryInformationType.PackageCode: // PID_REVNUMBER var packageCode = summaryInformationSymbol.Value; @@ -137,5 +143,30 @@ namespace WixToolset.Core.WindowsInstaller.Bind }); } } + + private static Platform GetPlatformFromSummaryInformation(string value) + { + var separatorIndex = value.IndexOf(';'); + var platformValue = separatorIndex > 0 ? value.Substring(0, separatorIndex) : value; + + switch (platformValue) + { + case "x64": + return Platform.X64; + + case "Arm": + return Platform.ARM; + + case "Arm64": + return Platform.ARM64; + + case "Intel64": + return Platform.IA64; + + case "Intel": + default: + return Platform.X86; + } + } } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs index a1e3ac83..02336cae 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs @@ -16,12 +16,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind /// internal class CalculateComponentGuids { - internal CalculateComponentGuids(IMessaging messaging, IBackendHelper helper, IPathResolver pathResolver, IntermediateSection section) + internal CalculateComponentGuids(IMessaging messaging, IBackendHelper helper, IPathResolver pathResolver, IntermediateSection section, Platform platform) { this.Messaging = messaging; this.BackendHelper = helper; this.PathResolver = pathResolver; this.Section = section; + this.Platform = platform; } private IMessaging Messaging { get; } @@ -32,6 +33,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind private IntermediateSection Section { get; } + private Platform Platform { get; } + public void Execute() { Dictionary registryKeyRows = null; @@ -42,7 +45,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind // Find components with generatable guids. foreach (var componentSymbol in this.Section.Symbols.OfType()) { - // Skip components that do not specify generate guid. + // Skip components that do not specify generate guid. if (componentSymbol.ComponentId != "*") { continue; @@ -135,7 +138,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind if (fileRow.Id.Id == componentSymbol.KeyPath) { // calculate the key file's canonical target path - string directoryPath = this.PathResolver.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentSymbol.DirectoryRef, true); + string directoryPath = this.PathResolver.GetCanonicalDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentSymbol.DirectoryRef, this.Platform); string fileName = Common.GetName(fileRow.Name, false, true).ToLowerInvariant(); path = Path.Combine(directoryPath, fileName); diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs index 7f43da9a..93e25878 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs @@ -34,25 +34,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind { var requiredActionSymbols = new Dictionary(); - // Get the standard actions required based on symbols in the section. - var overridableActionSymbols = this.GetRequiredStandardActions(); - // Index all the action symbols and look for collisions. foreach (var actionSymbol in this.Section.Symbols.OfType()) { if (actionSymbol.Overridable) // overridable action { - if (overridableActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol)) + if (requiredActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol)) { - this.Messaging.Write(ErrorMessages.OverridableActionCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action)); - if (null != collidingActionSymbol.SourceLineNumbers) + if (collidingActionSymbol.Overridable) { - this.Messaging.Write(ErrorMessages.OverridableActionCollision2(collidingActionSymbol.SourceLineNumbers)); + this.Messaging.Write(ErrorMessages.OverridableActionCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action)); + if (null != collidingActionSymbol.SourceLineNumbers) + { + this.Messaging.Write(ErrorMessages.OverridableActionCollision2(collidingActionSymbol.SourceLineNumbers)); + } } } else { - overridableActionSymbols.Add(actionSymbol.Id.Id, actionSymbol); + requiredActionSymbols.Add(actionSymbol.Id.Id, actionSymbol); } } else // unsequenced or sequenced action. @@ -71,7 +71,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind } } - if (requiredActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol)) + if (requiredActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol) && !collidingActionSymbol.Overridable) { this.Messaging.Write(ErrorMessages.ActionCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action)); if (null != collidingActionSymbol.SourceLineNumbers) @@ -81,13 +81,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind } else { - requiredActionSymbols.Add(actionSymbol.Id.Id, actionSymbol); + requiredActionSymbols[actionSymbol.Id.Id] = actionSymbol; } } } + // Get the standard actions required based on symbols in the section. + var requiredStandardActions = this.GetRequiredStandardActions(); + // Add the overridable action symbols that are not overridden to the required action symbols. - foreach (var actionSymbol in overridableActionSymbols.Values) + foreach (var actionSymbol in requiredStandardActions.Values) { if (!requiredActionSymbols.ContainsKey(actionSymbol.Id.Id)) { @@ -557,17 +560,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind return set; } - private IEnumerable GetActions(SequenceTable sequence, string[] actionNames) - { - foreach (var action in WindowsInstallerStandard.StandardActions()) - { - if (action.SequenceTable == sequence && actionNames.Contains(action.Action)) - { - yield return action; - } - } - } - /// /// Sequence an action before or after a standard action. /// -- cgit v1.2.3-55-g6feb