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 ++++---- src/WixToolset.Core/Compiler.cs | 3 +- .../ExtensibilityServices/PathResolver.cs | 51 +++++++++--- .../Link/ResolveReferencesCommand.cs | 25 +++--- src/WixToolset.Core/Link/SymbolWithSection.cs | 91 +++++++++++++++++++++ src/WixToolset.Core/Linker.cs | 22 +++-- .../DirectoryFixture.cs | 89 ++++++++++++++++++++ .../MsiQueryFixture.cs | 7 +- .../TestData/CustomAction/SimpleCustomAction.wxs | 15 ++++ .../TestData/CustomTable/CustomTable-Expected.wxs | 12 +-- .../TestData/Directory/Empty.wxs | 6 ++ .../ProductWithComponentGroupRef/Product.wxs | 6 +- .../WixToolsetTest.CoreIntegration.csproj | 2 + 17 files changed, 437 insertions(+), 72 deletions(-) create mode 100644 src/WixToolset.Core.WindowsInstaller/Bind/AddRequiredStandardDirectories.cs create mode 100644 src/WixToolset.Core/Link/SymbolWithSection.cs create mode 100644 src/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/CustomAction/SimpleCustomAction.wxs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Directory/Empty.wxs (limited to 'src') 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. /// diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index c504e96f..c641bceb 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs @@ -4279,8 +4279,7 @@ namespace WixToolset.Core this.Core.AddInlineDirectoryId(inlineSyntax, id.Id); } } - - if ("TARGETDIR".Equals(id.Id, StringComparison.Ordinal) && !("SourceDir".Equals(name, StringComparison.Ordinal) && shortName == null && shortSourceName == null && sourceName == null)) + else if ("TARGETDIR".Equals(id.Id, StringComparison.Ordinal) && !("SourceDir".Equals(name, StringComparison.Ordinal) && shortName == null && shortSourceName == null && sourceName == null)) { this.Core.Write(ErrorMessages.IllegalTargetDirDefaultDir(sourceLineNumbers, name)); } diff --git a/src/WixToolset.Core/ExtensibilityServices/PathResolver.cs b/src/WixToolset.Core/ExtensibilityServices/PathResolver.cs index 15cd4fc9..72be2bcb 100644 --- a/src/WixToolset.Core/ExtensibilityServices/PathResolver.cs +++ b/src/WixToolset.Core/ExtensibilityServices/PathResolver.cs @@ -12,7 +12,7 @@ namespace WixToolset.Core.ExtensibilityServices internal class PathResolver : IPathResolver { - public string GetDirectoryPath(Dictionary directories, Dictionary componentIdGenSeeds, string directory, bool canonicalize) + public string GetCanonicalDirectoryPath(Dictionary directories, Dictionary componentIdGenSeeds, string directory, Platform platform) { if (!directories.TryGetValue(directory, out var resolvedDirectory)) { @@ -25,19 +25,13 @@ namespace WixToolset.Core.ExtensibilityServices { resolvedDirectory.Path = componentIdGenSeeds[directory]; } - else if (canonicalize && WindowsInstallerStandard.IsStandardDirectory(directory)) + else if (WindowsInstallerStandard.IsStandardDirectory(directory)) { - // when canonicalization is on, standard directories are treated equally - resolvedDirectory.Path = directory; + resolvedDirectory.Path = WindowsInstallerStandard.GetPlatformSpecificDirectoryId(directory, platform); } else { - string name = resolvedDirectory.Name; - - if (canonicalize) - { - name = name?.ToLowerInvariant(); - } + var name = resolvedDirectory.Name?.ToLowerInvariant(); if (String.IsNullOrEmpty(resolvedDirectory.DirectoryParent)) { @@ -45,7 +39,7 @@ namespace WixToolset.Core.ExtensibilityServices } else { - var parentPath = this.GetDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, canonicalize); + var parentPath = this.GetCanonicalDirectoryPath(directories, componentIdGenSeeds, resolvedDirectory.DirectoryParent, platform); if (null != resolvedDirectory.Name) { @@ -62,6 +56,39 @@ namespace WixToolset.Core.ExtensibilityServices return resolvedDirectory.Path; } + public string GetDirectoryPath(Dictionary directories, string directory) + { + if (!directories.TryGetValue(directory, out var resolvedDirectory)) + { + throw new WixException(ErrorMessages.ExpectedDirectory(directory)); + } + + if (null == resolvedDirectory.Path) + { + var name = resolvedDirectory.Name; + + if (String.IsNullOrEmpty(resolvedDirectory.DirectoryParent)) + { + resolvedDirectory.Path = name; + } + else + { + var parentPath = this.GetDirectoryPath(directories, resolvedDirectory.DirectoryParent); + + if (null != resolvedDirectory.Name) + { + resolvedDirectory.Path = Path.Combine(parentPath, name); + } + else + { + resolvedDirectory.Path = parentPath; + } + } + } + + return resolvedDirectory.Path; + } + public string GetFileSourcePath(Dictionary directories, string directoryId, string fileName, bool compressed, bool useLongName) { var fileSourcePath = Common.GetName(fileName, true, useLongName); @@ -75,7 +102,7 @@ namespace WixToolset.Core.ExtensibilityServices { // Get the relative path of where we want the file to be layed out as specified // in the Directory table. - var directoryPath = this.GetDirectoryPath(directories, null, directoryId, false); + var directoryPath = this.GetDirectoryPath(directories, directoryId); fileSourcePath = Path.Combine(directoryPath, fileSourcePath); } diff --git a/src/WixToolset.Core/Link/ResolveReferencesCommand.cs b/src/WixToolset.Core/Link/ResolveReferencesCommand.cs index d2be0699..90b61e8b 100644 --- a/src/WixToolset.Core/Link/ResolveReferencesCommand.cs +++ b/src/WixToolset.Core/Link/ResolveReferencesCommand.cs @@ -72,27 +72,22 @@ namespace WixToolset.Core.Link continue; } - if (!this.symbolsWithSections.TryGetValue(wixSimpleReferenceRow.SymbolicName, out var symbolWithSection)) - { - this.Messaging.Write(ErrorMessages.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); - } - else // see if the symbol (and any of its duplicates) are appropriately accessible. + // See if the symbol (and any of its duplicates) are appropriately accessible. + if (this.symbolsWithSections.TryGetValue(wixSimpleReferenceRow.SymbolicName, out var symbolWithSection)) { var accessible = this.DetermineAccessibleSymbols(section, symbolWithSection); - if (!accessible.Any()) - { - this.Messaging.Write(ErrorMessages.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbolWithSection.Access)); - } - else if (1 == accessible.Count) + if (accessible.Count == 1) { var accessibleSymbol = accessible[0]; - this.referencedSymbols.Add(accessibleSymbol); - - if (null != accessibleSymbol.Section) + if (this.referencedSymbols.Add(accessibleSymbol) && null != accessibleSymbol.Section) { this.RecursivelyResolveReferences(accessibleSymbol.Section); } } + else if (accessible.Count == 0) + { + this.Messaging.Write(ErrorMessages.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbolWithSection.Access)); + } else // display errors for the duplicate symbols. { var accessibleSymbol = accessible[0]; @@ -113,6 +108,10 @@ namespace WixToolset.Core.Link } } } + else + { + this.Messaging.Write(ErrorMessages.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); + } } } diff --git a/src/WixToolset.Core/Link/SymbolWithSection.cs b/src/WixToolset.Core/Link/SymbolWithSection.cs new file mode 100644 index 00000000..c8934d0f --- /dev/null +++ b/src/WixToolset.Core/Link/SymbolWithSection.cs @@ -0,0 +1,91 @@ +// 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.Link +{ + using System; + using System.Collections.Generic; + using System.Linq; + using WixToolset.Data; + + /// + /// Symbol with section representing a single unique symbol. + /// + internal class SymbolWithSection + { + private HashSet possibleConflicts; + private HashSet redundants; + + /// + /// Creates a symbol for a symbol. + /// + /// Symbol for the symbol + public SymbolWithSection(IntermediateSection section, IntermediateSymbol symbol) + { + this.Symbol = symbol; + this.Section = section; + this.Name = String.Concat(this.Symbol.Definition.Name, ":", this.Symbol.Id.Id); + } + + /// + /// Gets the accessibility of the symbol which is a direct reflection of the accessibility of the row's accessibility. + /// + /// Accessbility of the symbol. + public AccessModifier Access => this.Symbol.Id.Access; + + /// + /// Gets the name of the symbol. + /// + /// Name of the symbol. + public string Name { get; } + + /// + /// Gets the symbol for this symbol. + /// + /// Symbol for this symbol. + public IntermediateSymbol Symbol { get; } + + /// + /// Gets the section for the symbol. + /// + /// Section for the symbol. + public IntermediateSection Section { get; } + + /// + /// Gets any duplicates of this symbol with sections that are possible conflicts. + /// + public IEnumerable PossiblyConflicts => this.possibleConflicts ?? Enumerable.Empty(); + + /// + /// Gets any duplicates of this symbol with sections that are redundant. + /// + public IEnumerable Redundants => this.redundants ?? Enumerable.Empty(); + + /// + /// Adds a duplicate symbol with sections that is a possible conflict. + /// + /// Symbol with section that is a possible conflict of this symbol. + public void AddPossibleConflict(SymbolWithSection symbolWithSection) + { + if (null == this.possibleConflicts) + { + this.possibleConflicts = new HashSet(); + } + + this.possibleConflicts.Add(symbolWithSection); + } + + /// + /// Adds a duplicate symbol that is redundant. + /// + /// Symbol with section that is redundant of this symbol. + public void AddRedundant(SymbolWithSection symbolWithSection) + { + if (null == this.redundants) + { + this.redundants = new HashSet(); + } + + this.redundants.Add(symbolWithSection); + } + } +} diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index cdefa5c7..1cfd085d 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs @@ -149,13 +149,12 @@ namespace WixToolset.Core throw new WixException(ErrorMessages.MissingEntrySection(this.Context.ExpectedOutputType.ToString())); } - // Add the missing standard action symbols. - this.LoadStandardActions(find.EntrySection, find.SymbolsByName); + // Add the missing standard action and directory symbols. + this.LoadStandardSymbols(find.SymbolsByName); // Resolve the symbol references to find the set of sections we care about for linking. // Of course, we start with the entry section (that's how it got its name after all). var resolve = new ResolveReferencesCommand(this.Messaging, find.EntrySection, find.SymbolsByName); - resolve.Execute(); if (this.Messaging.EncounteredError) @@ -732,14 +731,14 @@ namespace WixToolset.Core #endif /// - /// Load the standard action symbols. + /// Load the standard action and directory symbols. /// /// Collection of symbols. - private void LoadStandardActions(IntermediateSection section, IDictionary symbolsByName) + private void LoadStandardSymbols(IDictionary symbolsByName) { foreach (var actionSymbol in WindowsInstallerStandard.StandardActions()) { - var symbolWithSection = new SymbolWithSection(section, actionSymbol); + var symbolWithSection = new SymbolWithSection(null, actionSymbol); // If the action's symbol has not already been defined (i.e. overriden by the user), add it now. if (!symbolsByName.ContainsKey(symbolWithSection.Name)) @@ -747,6 +746,17 @@ namespace WixToolset.Core symbolsByName.Add(symbolWithSection.Name, symbolWithSection); } } + + foreach (var directorySymbol in WindowsInstallerStandard.StandardDirectories()) + { + var symbolWithSection = new SymbolWithSection(null, directorySymbol); + + // If the directory's symbol has not already been defined (i.e. overriden by the user), add it now. + if (!symbolsByName.ContainsKey(symbolWithSection.Name)) + { + symbolsByName.Add(symbolWithSection.Name, symbolWithSection); + } + } } /// diff --git a/src/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs b/src/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs new file mode 100644 index 00000000..83f2f2bb --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/DirectoryFixture.cs @@ -0,0 +1,89 @@ +// 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 WixToolsetTest.CoreIntegration +{ + using System.IO; + using System.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Core.TestPackage; + using WixToolset.Data; + using Xunit; + + public class DirectoryFixture + { + [Fact] + public void CanGet32bitProgramFiles6432Folder() + { + var folder = TestData.Get(@"TestData"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var msiPath = Path.Combine(baseFolder, @"bin\test.msi"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "Directory", "Empty.wxs"), + Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), + "-bindpath", Path.Combine(folder, "SingleFile", "data"), + "-intermediateFolder", intermediateFolder, + "-o", msiPath + }); + + result.AssertSuccess(); + + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); + var section = intermediate.Sections.Single(); + + var dirSymbols = section.Symbols.OfType().ToList(); + Assert.Equal(new[] + { + "INSTALLFOLDER", + "ProgramFiles6432Folder", + "ProgramFilesFolder", + "TARGETDIR" + }, dirSymbols.Select(d => d.Id.Id).ToArray()); + } + } + + [Fact] + public void CanGet64bitProgramFiles6432Folder() + { + var folder = TestData.Get(@"TestData"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var msiPath = Path.Combine(baseFolder, @"bin\test.msi"); + + var result = WixRunner.Execute(new[] + { + "build", + "-arch", "x64", + Path.Combine(folder, "Directory", "Empty.wxs"), + Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), + "-bindpath", Path.Combine(folder, "SingleFile", "data"), + "-intermediateFolder", intermediateFolder, + "-o", msiPath + }); + + result.AssertSuccess(); + + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); + var section = intermediate.Sections.Single(); + + var dirSymbols = section.Symbols.OfType().ToList(); + Assert.Equal(new[] + { + "INSTALLFOLDER", + "ProgramFiles6432Folder", + "ProgramFiles64Folder", + "TARGETDIR" + }, dirSymbols.Select(d => d.Id.Id).ToArray()); + } + } + } +} diff --git a/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs b/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs index 3ab218d1..4ff7f5f6 100644 --- a/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs @@ -365,14 +365,15 @@ namespace WixToolsetTest.CoreIntegration Assert.True(File.Exists(msiPath)); var results = Query.QueryDatabase(msiPath, new[] { "Directory" }); - Assert.Equal(new[] + WixAssert.CompareLineByLine(new[] { "Directory:DUPLICATENAMEANDSHORTNAME\tINSTALLFOLDER\tduplicat", - "Directory:INSTALLFOLDER\tProgramFilesFolder\toekcr5lq|MsiPackage", + "Directory:INSTALLFOLDER\tProgramFiles6432Folder\t1egc1laj|MsiPackage", "Directory:NAMEANDSHORTNAME\tINSTALLFOLDER\tSHORTNAM|NameAndShortName", "Directory:NAMEANDSHORTSOURCENAME\tINSTALLFOLDER\tNAMEASSN|NameAndShortSourceName", "Directory:NAMEWITHSHORTVALUE\tINSTALLFOLDER\tSHORTVAL", - "Directory:ProgramFilesFolder\tTARGETDIR\t.", + "Directory:ProgramFiles6432Folder\tProgramFilesFolder\t.", + "Directory:ProgramFilesFolder\tTARGETDIR\tPFiles", "Directory:SHORTNAMEANDLONGSOURCENAME\tINSTALLFOLDER\tSHNALSNM:6ukthv5q|ShortNameAndLongSourceName", "Directory:SHORTNAMEONLY\tINSTALLFOLDER\tSHORTONL", "Directory:SOURCENAME\tINSTALLFOLDER\ts2s5bq-i|NameAndSourceName:dhnqygng|SourceNameWithName", diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/CustomAction/SimpleCustomAction.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomAction/SimpleCustomAction.wxs new file mode 100644 index 00000000..72d5e4a5 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomAction/SimpleCustomAction.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable-Expected.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable-Expected.wxs index 68386612..c55f4ed0 100644 --- a/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable-Expected.wxs +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable-Expected.wxs @@ -15,11 +15,13 @@ - - - - - + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Directory/Empty.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/Directory/Empty.wxs new file mode 100644 index 00000000..50cf6850 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Directory/Empty.wxs @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/ProductWithComponentGroupRef/Product.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductWithComponentGroupRef/Product.wxs index b2f22b7d..5b26091a 100644 --- a/src/test/WixToolsetTest.CoreIntegration/TestData/ProductWithComponentGroupRef/Product.wxs +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductWithComponentGroupRef/Product.wxs @@ -11,10 +11,6 @@ - - - - - + diff --git a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj index 15078b8a..601a66e7 100644 --- a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj +++ b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj @@ -36,6 +36,7 @@ + @@ -48,6 +49,7 @@ + -- cgit v1.2.3-55-g6feb