From 863c1b8180d802f98e37be876b0c27efce2e8ace Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 13 Apr 2022 10:13:36 -0500 Subject: Create Harvested*PackageSymbols. --- .../WixToolset.Data/Symbols/SymbolDefinitions.cs | 12 + .../WixBundleHarvestedBundlePackageSymbol.cs | 134 ++++++++ .../Symbols/WixBundleHarvestedMsiPackageSymbol.cs | 174 ++++++++++ .../Symbols/WixBundleHarvestedMspPackageSymbol.cs | 92 +++++ .../Bind/GenerateManifestDataFromIRCommand.cs | 3 + .../Bundles/ProcessBundlePackageCommand.cs | 158 ++++++--- .../Bundles/ProcessMsiPackageCommand.cs | 369 ++++++++++++--------- .../Bundles/ProcessMspPackageCommand.cs | 108 ++++-- .../WixToolset.Core.Burn/BurnBackendWarnings.cs | 4 +- .../BundlePackageFixture.cs | 2 +- 10 files changed, 820 insertions(+), 236 deletions(-) create mode 100644 src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs create mode 100644 src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs create mode 100644 src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs (limited to 'src') diff --git a/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs b/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs index 1fd8ded1..3e0ec512 100644 --- a/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs +++ b/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs @@ -130,6 +130,9 @@ namespace WixToolset.Data WixBundleExePackage, WixBundleExePackagePayload, WixBundleExtension, + WixBundleHarvestedBundlePackage, + WixBundleHarvestedMsiPackage, + WixBundleHarvestedMspPackage, WixBundleMsiFeature, WixBundleMsiPackage, WixBundleMsiPackagePayload, @@ -583,6 +586,15 @@ namespace WixToolset.Data case SymbolDefinitionType.WixBundleExePackagePayload: return SymbolDefinitions.WixBundleExePackagePayload; + case SymbolDefinitionType.WixBundleHarvestedBundlePackage: + return SymbolDefinitions.WixBundleHarvestedBundlePackage; + + case SymbolDefinitionType.WixBundleHarvestedMsiPackage: + return SymbolDefinitions.WixBundleHarvestedMsiPackage; + + case SymbolDefinitionType.WixBundleHarvestedMspPackage: + return SymbolDefinitions.WixBundleHarvestedMspPackage; + case SymbolDefinitionType.WixBundleMsiFeature: return SymbolDefinitions.WixBundleMsiFeature; diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs new file mode 100644 index 00000000..01e18728 --- /dev/null +++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs @@ -0,0 +1,134 @@ +// 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.Data +{ + using WixToolset.Data.Symbols; + + public static partial class SymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixBundleHarvestedBundlePackage = new IntermediateSymbolDefinition( + SymbolDefinitionType.WixBundleHarvestedBundlePackage, + new[] + { + new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.Attributes), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.BundleId), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.ManifestNamespace), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.ProtocolVersion), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.Version), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.DisplayName), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.InstallSize), IntermediateFieldType.LargeNumber), + }, + typeof(WixBundleHarvestedBundlePackageSymbol)); + } +} + +namespace WixToolset.Data.Symbols +{ + using System; + + public enum WixBundleHarvestedBundlePackageSymbolFields + { + Attributes, + BundleId, + ManifestNamespace, + ProtocolVersion, + Version, + DisplayName, + InstallSize, + } + + [Flags] + public enum WixBundleHarvestedBundlePackageAttributes + { + None = 0x0, + PerMachine = 0x1, + Win64 = 0x2, + } + + public class WixBundleHarvestedBundlePackageSymbol : IntermediateSymbol + { + public WixBundleHarvestedBundlePackageSymbol() : base(SymbolDefinitions.WixBundleHarvestedBundlePackage, null, null) + { + } + + public WixBundleHarvestedBundlePackageSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.WixBundleHarvestedBundlePackage, sourceLineNumber, id) + { + } + + public IntermediateField this[WixBundleHarvestedBundlePackageSymbolFields index] => this.Fields[(int)index]; + + public WixBundleHarvestedBundlePackageAttributes Attributes + { + get => (WixBundleHarvestedBundlePackageAttributes)this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.Attributes].AsNumber(); + set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.Attributes, (int)value); + } + + public string BundleId + { + get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.BundleId].AsString(); + set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.BundleId, value); + } + + public string ManifestNamespace + { + get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.ManifestNamespace].AsString(); + set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.ManifestNamespace, value); + } + + public int ProtocolVersion + { + get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.ProtocolVersion].AsNumber(); + set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.ProtocolVersion, value); + } + + public string Version + { + get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.Version].AsString(); + set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.Version, value); + } + + public string DisplayName + { + get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.DisplayName].AsString(); + set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.DisplayName, value); + } + + public long InstallSize + { + get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.InstallSize].AsLargeNumber(); + set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.InstallSize, value); + } + + public bool PerMachine + { + get { return this.Attributes.HasFlag(WixBundleHarvestedBundlePackageAttributes.PerMachine); } + set + { + if (value) + { + this.Attributes |= WixBundleHarvestedBundlePackageAttributes.PerMachine; + } + else + { + this.Attributes &= ~WixBundleHarvestedBundlePackageAttributes.PerMachine; + } + } + } + + public bool Win64 + { + get { return this.Attributes.HasFlag(WixBundleHarvestedBundlePackageAttributes.Win64); } + set + { + if (value) + { + this.Attributes |= WixBundleHarvestedBundlePackageAttributes.Win64; + } + else + { + this.Attributes &= ~WixBundleHarvestedBundlePackageAttributes.Win64; + } + } + } + } +} diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs new file mode 100644 index 00000000..8a274720 --- /dev/null +++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs @@ -0,0 +1,174 @@ +// 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.Data +{ + using WixToolset.Data.Symbols; + + public static partial class SymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixBundleHarvestedMsiPackage = new IntermediateSymbolDefinition( + SymbolDefinitionType.WixBundleHarvestedMsiPackage, + new[] + { + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.Attributes), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductName), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ArpComments), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.AllUsers), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.MsiFastInstall), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ArpSystemComponent), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductCode), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.UpgradeCode), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.Manufacturer), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductLanguage), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductVersion), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.InstallSize), IntermediateFieldType.LargeNumber), + }, + typeof(WixBundleHarvestedMsiPackageSymbol)); + } +} + +namespace WixToolset.Data.Symbols +{ + using System; + + public enum WixBundleHarvestedMsiPackageSymbolFields + { + Attributes, + ProductName, + ArpComments, + AllUsers, + MsiFastInstall, + ArpSystemComponent, + ProductCode, + UpgradeCode, + Manufacturer, + ProductLanguage, + ProductVersion, + InstallSize, + } + + [Flags] + public enum WixBundleHarvestedMsiPackageAttributes + { + None = 0x0, + PerMachine = 0x01, + Win64 = 0x2, + } + + public class WixBundleHarvestedMsiPackageSymbol : IntermediateSymbol + { + public WixBundleHarvestedMsiPackageSymbol() : base(SymbolDefinitions.WixBundleHarvestedMsiPackage, null, null) + { + } + + public WixBundleHarvestedMsiPackageSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.WixBundleHarvestedMsiPackage, sourceLineNumber, id) + { + } + + public IntermediateField this[WixBundleHarvestedMsiPackageSymbolFields index] => this.Fields[(int)index]; + + public WixBundleHarvestedMsiPackageAttributes Attributes + { + get => (WixBundleHarvestedMsiPackageAttributes)this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.Attributes].AsNumber(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.Attributes, (int)value); + } + + public string ProductName + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductName].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductName, value); + } + + public string ArpComments + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ArpComments].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ArpComments, value); + } + + public string AllUsers + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.AllUsers].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.AllUsers, value); + } + + public string MsiFastInstall + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.MsiFastInstall].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.MsiFastInstall, value); + } + + public string ArpSystemComponent + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ArpSystemComponent].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ArpSystemComponent, value); + } + + public string ProductCode + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductCode].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductCode, value); + } + + public string UpgradeCode + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.UpgradeCode].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.UpgradeCode, value); + } + + public string Manufacturer + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.Manufacturer].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.Manufacturer, value); + } + + public string ProductLanguage + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductLanguage].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductLanguage, value); + } + + public string ProductVersion + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductVersion].AsString(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductVersion, value); + } + + public long InstallSize + { + get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.InstallSize].AsLargeNumber(); + set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.InstallSize, value); + } + + public bool PerMachine + { + get { return this.Attributes.HasFlag(WixBundleHarvestedMsiPackageAttributes.PerMachine); } + set + { + if (value) + { + this.Attributes |= WixBundleHarvestedMsiPackageAttributes.PerMachine; + } + else + { + this.Attributes &= ~WixBundleHarvestedMsiPackageAttributes.PerMachine; + } + } + } + + public bool Win64 + { + get { return this.Attributes.HasFlag(WixBundleHarvestedMsiPackageAttributes.Win64); } + set + { + if (value) + { + this.Attributes |= WixBundleHarvestedMsiPackageAttributes.Win64; + } + else + { + this.Attributes &= ~WixBundleHarvestedMsiPackageAttributes.Win64; + } + } + } + } +} diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs new file mode 100644 index 00000000..43bcc763 --- /dev/null +++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs @@ -0,0 +1,92 @@ +// 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.Data +{ + using WixToolset.Data.Symbols; + + public static partial class SymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixBundleHarvestedMspPackage = new IntermediateSymbolDefinition( + SymbolDefinitionType.WixBundleHarvestedMspPackage, + new[] + { + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.Attributes), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.PatchCode), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.DisplayName), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.Description), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.ManufacturerName), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.PatchXml), IntermediateFieldType.String), + }, + typeof(WixBundleHarvestedMspPackageSymbol)); + } +} + +namespace WixToolset.Data.Symbols +{ + using System; + + public enum WixBundleHarvestedMspPackageSymbolFields + { + Attributes, + PatchCode, + DisplayName, + Description, + ManufacturerName, + PatchXml, + } + + [Flags] + public enum WixBundleHarvestedMspPackageAttributes + { + None = 0x0, + } + + public class WixBundleHarvestedMspPackageSymbol : IntermediateSymbol + { + public WixBundleHarvestedMspPackageSymbol() : base(SymbolDefinitions.WixBundleHarvestedMspPackage, null, null) + { + } + + public WixBundleHarvestedMspPackageSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.WixBundleHarvestedMspPackage, sourceLineNumber, id) + { + } + + public IntermediateField this[WixBundleHarvestedMspPackageSymbolFields index] => this.Fields[(int)index]; + + public WixBundleHarvestedMspPackageAttributes Attributes + { + get => (WixBundleHarvestedMspPackageAttributes)this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.Attributes].AsNumber(); + set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.Attributes, (int)value); + } + + public string PatchCode + { + get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.PatchCode].AsString(); + set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.PatchCode, value); + } + + public string DisplayName + { + get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.DisplayName].AsString(); + set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.DisplayName, value); + } + + public string Description + { + get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.Description].AsString(); + set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.Description, value); + } + + public string ManufacturerName + { + get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.ManufacturerName].AsString(); + set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.ManufacturerName, value); + } + + public string PatchXml + { + get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.PatchXml].AsString(); + set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.PatchXml, value); + } + } +} diff --git a/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs index 396e0eff..610bdd75 100644 --- a/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs @@ -70,6 +70,9 @@ namespace WixToolset.Core.Burn.Bind case SymbolDefinitionType.WixBundleExePackage: case SymbolDefinitionType.WixBundleExePackagePayload: case SymbolDefinitionType.WixBundleExtension: + case SymbolDefinitionType.WixBundleHarvestedBundlePackage: + case SymbolDefinitionType.WixBundleHarvestedMsiPackage: + case SymbolDefinitionType.WixBundleHarvestedMspPackage: case SymbolDefinitionType.WixBundleMsiFeature: case SymbolDefinitionType.WixBundleMsiPackage: case SymbolDefinitionType.WixBundleMsiPackagePayload: diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs index aed005ba..2abdec06 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs @@ -6,6 +6,7 @@ namespace WixToolset.Core.Burn.Bundles using System.Collections.Generic; using System.Diagnostics; using System.IO; + using System.Linq; using System.Xml; using WixToolset.Data; using WixToolset.Data.Symbols; @@ -23,8 +24,11 @@ namespace WixToolset.Core.Burn.Bundles this.BackendHelper = serviceProvider.GetService(); this.PackagePayloads = packagePayloads; this.Section = section; - this.Facade = facade; this.IntermediateFolder = intermediateFolder; + + this.ChainPackage = facade.PackageSymbol; + this.BundlePackage = (WixBundleBundlePackageSymbol)facade.SpecificPackageSymbol; + this.PackagePayload = packagePayloads[this.ChainPackage.PayloadRef]; } private IMessaging Messaging { get; } @@ -33,7 +37,13 @@ namespace WixToolset.Core.Burn.Bundles private Dictionary PackagePayloads { get; } - private PackageFacade Facade { get; } + private WixBundlePackageSymbol ChainPackage { get; } + + private WixBundleBundlePackageSymbol BundlePackage { get; } + + private string PackageId => this.ChainPackage.Id.Id; + + private WixBundlePayloadSymbol PackagePayload { get; } private IntermediateSection Section { get; } @@ -46,27 +56,81 @@ namespace WixToolset.Core.Burn.Bundles /// public void Execute() { - var bundlePackage = (WixBundleBundlePackageSymbol)this.Facade.SpecificPackageSymbol; - var packagePayload = this.PackagePayloads[this.Facade.PackageSymbol.PayloadRef]; - var sourcePath = packagePayload.SourceFile.Path; + var harvestedBundlePackage = this.Section.Symbols.OfType() + .Where(h => h.Id == this.ChainPackage.Id) + .SingleOrDefault(); + + if (harvestedBundlePackage == null) + { + harvestedBundlePackage = this.HarvestPackage(); + + if (harvestedBundlePackage == null) + { + return; + } + } + + this.ChainPackage.Win64 = harvestedBundlePackage.Win64; + this.BundlePackage.BundleId = Guid.Parse(harvestedBundlePackage.BundleId).ToString("B").ToUpperInvariant(); + this.BundlePackage.SupportsBurnProtocol = harvestedBundlePackage.ProtocolVersion == 1; // Keep in sync with burn\engine\inc\engine.h + + var supportsArpSystemComponent = BurnCommon.BurnV3Namespace != harvestedBundlePackage.ManifestNamespace; + if (!supportsArpSystemComponent && !this.ChainPackage.Visible) + { + this.Messaging.Write(BurnBackendWarnings.HiddenBundleNotSupported(this.PackagePayload.SourceLineNumbers, this.PackageId)); + + this.ChainPackage.Visible = true; + } + + this.ChainPackage.PerMachine = harvestedBundlePackage.PerMachine; + this.PackagePayload.Version = harvestedBundlePackage.Version; + this.BundlePackage.Version = harvestedBundlePackage.Version; + this.ChainPackage.Version = harvestedBundlePackage.Version; + + if (String.IsNullOrEmpty(this.ChainPackage.CacheId)) + { + this.ChainPackage.CacheId = String.Format("{0}v{1}", this.BundlePackage.BundleId, this.BundlePackage.Version); + } + + if (String.IsNullOrEmpty(this.ChainPackage.DisplayName)) + { + this.ChainPackage.DisplayName = harvestedBundlePackage.DisplayName; + } + + this.ChainPackage.InstallSize = harvestedBundlePackage.InstallSize; + } + + public WixBundleHarvestedBundlePackageSymbol HarvestPackage() + { + bool win64; + string bundleId; + int protocolVersion; + string manifestNamespace; + bool perMachine; + string version; + string displayName; + long installSize; + + var sourcePath = this.PackagePayload.SourceFile.Path; + var sourceLineNumbers = this.PackagePayload.SourceLineNumbers; using (var burnReader = BurnReader.Open(this.Messaging, sourcePath)) { if (burnReader.Invalid) { - return; + return null; } var baFolderPath = Path.Combine(this.IntermediateFolder, burnReader.BundleId.ToString()); if (!burnReader.ExtractUXContainer(baFolderPath, baFolderPath)) { - return; + return null; } foreach (var filePath in Directory.EnumerateFiles(baFolderPath, "*.*", SearchOption.AllDirectories)) { - this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, packagePayload.SourceLineNumbers)); + this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, sourceLineNumbers)); } switch (burnReader.MachineType) @@ -77,12 +141,13 @@ namespace WixToolset.Core.Burn.Bundles case BurnCommon.IMAGE_FILE_MACHINE_I386: case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH32: case BurnCommon.IMAGE_FILE_MACHINE_M32R: + win64 = false; break; case BurnCommon.IMAGE_FILE_MACHINE_AMD64: case BurnCommon.IMAGE_FILE_MACHINE_ARM64: case BurnCommon.IMAGE_FILE_MACHINE_IA64: case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH64: - this.Facade.PackageSymbol.Win64 = true; + win64 = true; break; case BurnCommon.IMAGE_FILE_MACHINE_EBC: case BurnCommon.IMAGE_FILE_MACHINE_MIPS16: @@ -101,15 +166,16 @@ namespace WixToolset.Core.Burn.Bundles case BurnCommon.IMAGE_FILE_MACHINE_THUMB: case BurnCommon.IMAGE_FILE_MACHINE_WCEMIPSV2: default: - this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(packagePayload.SourceLineNumbers, sourcePath, burnReader.MachineType)); + win64 = false; + this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(sourceLineNumbers, sourcePath, burnReader.MachineType)); break; } - bundlePackage.BundleId = burnReader.BundleId.ToString("B").ToUpperInvariant(); + bundleId = burnReader.BundleId.ToString("B").ToUpperInvariant(); // Assume that the .wixburn section version will change when the Burn protocol changes. // This should be a safe assumption since we will need to add the protocol version to the section to support this harvesting. - bundlePackage.SupportsBurnProtocol = burnReader.Version == 2; + protocolVersion = burnReader.Version == 2 ? 1 : 0; try { @@ -119,63 +185,59 @@ namespace WixToolset.Core.Burn.Bundles if (document.DocumentElement.LocalName != "BurnManifest") { - this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(packagePayload.SourceLineNumbers, sourcePath, $"Expected root element to be 'Manifest' but was '{document.DocumentElement.LocalName}'.")); - return; + this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, $"Expected root element to be 'BurnManifest' but was '{document.DocumentElement.LocalName}'.")); + return null; } - if (BurnCommon.BurnV3Namespace == document.DocumentElement.NamespaceURI && !this.Facade.PackageSymbol.Visible) - { - this.Messaging.Write(BurnBackendWarnings.HiddenBundleNotSupported(packagePayload.SourceLineNumbers, sourcePath)); - - this.Facade.PackageSymbol.Visible = true; - } + manifestNamespace = document.DocumentElement.NamespaceURI; namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI); var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement; var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement; - var perMachine = registrationElement.GetAttribute("PerMachine") == "yes"; - this.Facade.PackageSymbol.PerMachine = perMachine; - - var version = registrationElement.GetAttribute("Version"); - packagePayload.Version = version; - bundlePackage.Version = version; - this.Facade.PackageSymbol.Version = version; + perMachine = registrationElement.GetAttribute("PerMachine") == "yes"; - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.CacheId)) - { - this.Facade.PackageSymbol.CacheId = String.Format("{0}v{1}", bundlePackage.BundleId, version); - } + version = registrationElement.GetAttribute("Version"); var providerKey = registrationElement.GetAttribute("ProviderKey"); - var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", bundlePackage.Id.Id, providerKey)); - this.Section.AddSymbol(new WixDependencyProviderSymbol(packagePayload.SourceLineNumbers, depId) + var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackageId, providerKey)); + this.Section.AddSymbol(new WixDependencyProviderSymbol(sourceLineNumbers, depId) { - ParentRef = bundlePackage.Id.Id, + ParentRef = this.PackageId, ProviderKey = providerKey, Version = version, Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported, }); - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) - { - this.Facade.PackageSymbol.DisplayName = arpElement.GetAttribute("DisplayName"); - } + displayName = arpElement.GetAttribute("DisplayName"); - this.ProcessPackages(document, namespaceManager); + installSize = this.ProcessPackages(document, namespaceManager); - this.ProcessRelatedBundles(document, namespaceManager, packagePayload, sourcePath); + this.ProcessRelatedBundles(document, namespaceManager, sourcePath); // TODO: Add payloads? } catch (Exception e) { - this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(packagePayload.SourceLineNumbers, sourcePath, e.ToString())); + this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, e.ToString())); + return null; } } + + return this.Section.AddSymbol(new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id) + { + Win64 = win64, + BundleId = bundleId, + ManifestNamespace = manifestNamespace, + ProtocolVersion = protocolVersion, + PerMachine = perMachine, + Version = version, + DisplayName = displayName, + InstallSize = installSize, + }); } - private void ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager) + private long ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager) { long packageInstallSize = 0; @@ -192,11 +254,13 @@ namespace WixToolset.Core.Burn.Bundles } } - this.Facade.PackageSymbol.InstallSize = packageInstallSize; + return packageInstallSize; } - private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, WixBundlePayloadSymbol packagePayload, string sourcePath) + private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, string sourcePath) { + var sourceLineNumbers = this.PackagePayload.SourceLineNumbers; + foreach (XmlElement relatedBundleElement in document.SelectNodes("/burn:BurnManifest/burn:RelatedBundle", namespaceManager)) { var id = relatedBundleElement.GetAttribute("Id"); @@ -204,13 +268,13 @@ namespace WixToolset.Core.Burn.Bundles if (!Enum.TryParse(actionValue, out RelatedBundleActionType action)) { - this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(packagePayload.SourceLineNumbers, sourcePath, actionValue)); + this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(sourceLineNumbers, sourcePath, actionValue)); continue; } - this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol + this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers) { - PackageRef = this.Facade.PackageId, + PackageRef = this.PackageId, BundleId = id, Action = action, }); diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs index 4ca3a730..5acec2a4 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs @@ -33,7 +33,10 @@ namespace WixToolset.Core.Burn.Bundles this.PackagePayloads = packagePayloads; this.Section = section; - this.Facade = facade; + + this.ChainPackage = facade.PackageSymbol; + this.MsiPackage = (WixBundleMsiPackageSymbol)facade.SpecificPackageSymbol; + this.PackagePayload = packagePayloads[this.ChainPackage.PayloadRef]; } private IMessaging Messaging { get; } @@ -46,7 +49,13 @@ namespace WixToolset.Core.Burn.Bundles private Dictionary PackagePayloads { get; } - private PackageFacade Facade { get; } + private WixBundlePackageSymbol ChainPackage { get; } + + private WixBundleMsiPackageSymbol MsiPackage { get; } + + private string PackageId => this.ChainPackage.Id.Id; + + private WixBundlePayloadSymbol PackagePayload { get; } private IntermediateSection Section { get; } @@ -55,16 +64,115 @@ namespace WixToolset.Core.Burn.Bundles /// public void Execute() { - var packagePayload = this.PackagePayloads[this.Facade.PackageSymbol.PayloadRef]; + var harvestedMsiPackage = this.Section.Symbols.OfType() + .Where(h => h.Id == this.ChainPackage.Id) + .SingleOrDefault(); + + if (harvestedMsiPackage == null) + { + harvestedMsiPackage = this.HarvestPackage(); + + if (harvestedMsiPackage == null) + { + return; + } + } + + this.ChainPackage.PerMachine = harvestedMsiPackage.PerMachine; + this.ChainPackage.Win64 = harvestedMsiPackage.Win64; + + this.MsiPackage.ProductCode = harvestedMsiPackage.ProductCode; + this.MsiPackage.UpgradeCode = harvestedMsiPackage.UpgradeCode; + this.MsiPackage.Manufacturer = harvestedMsiPackage.Manufacturer; + this.MsiPackage.ProductLanguage = Convert.ToInt32(harvestedMsiPackage.ProductLanguage, CultureInfo.InvariantCulture); + this.MsiPackage.ProductVersion = harvestedMsiPackage.ProductVersion; + + if (String.IsNullOrEmpty(this.ChainPackage.CacheId)) + { + this.ChainPackage.CacheId = String.Format("{0}v{1}", this.MsiPackage.ProductCode, this.MsiPackage.ProductVersion); + } + + if (String.IsNullOrEmpty(this.ChainPackage.DisplayName)) + { + this.ChainPackage.DisplayName = harvestedMsiPackage.ProductName; + } + + if (String.IsNullOrEmpty(this.ChainPackage.Description)) + { + this.ChainPackage.Description = harvestedMsiPackage.ArpComments; + } + + if (String.IsNullOrEmpty(this.ChainPackage.Version)) + { + this.ChainPackage.Version = this.MsiPackage.ProductVersion; + } + + if (!this.BackendHelper.IsValidFourPartVersion(this.MsiPackage.ProductVersion)) + { + // not a proper .NET version (e.g., five fields); can we get a valid four-part version number? + string version = null; + var versionParts = this.MsiPackage.ProductVersion.Split('.'); + var count = versionParts.Length; + if (0 < count) + { + version = versionParts[0]; + for (var i = 1; i < 4 && i < count; ++i) + { + version = String.Concat(version, ".", versionParts[i]); + } + } + + if (!String.IsNullOrEmpty(version) && this.BackendHelper.IsValidFourPartVersion(version)) + { + this.Messaging.Write(WarningMessages.VersionTruncated(this.PackagePayload.SourceLineNumbers, this.MsiPackage.ProductVersion, this.PackageId, version)); + this.MsiPackage.ProductVersion = version; + } + else + { + this.Messaging.Write(ErrorMessages.InvalidProductVersion(this.PackagePayload.SourceLineNumbers, this.MsiPackage.ProductVersion, this.PackageId)); + } + } + + this.SetPerMachineAppropriately(harvestedMsiPackage.AllUsers); + + var msiPropertyNames = this.GetMsiPropertyNames(); + + // Ensure the MSI package is appropriately marked visible or not. + this.SetPackageVisibility(harvestedMsiPackage.ArpSystemComponent, msiPropertyNames); + + // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance. + if (String.IsNullOrEmpty(harvestedMsiPackage.MsiFastInstall) && !msiPropertyNames.Contains("MSIFASTINSTALL")) + { + this.AddMsiProperty("MSIFASTINSTALL", "7"); + } + + this.ChainPackage.InstallSize = harvestedMsiPackage.InstallSize; + } - var msiPackage = (WixBundleMsiPackageSymbol)this.Facade.SpecificPackageSymbol; + public WixBundleHarvestedMsiPackageSymbol HarvestPackage() + { + bool perMachine; + bool win64; + string productName; + string arpComments; + string allUsers; + string msiFastInstall; + string arpSystemComponent; + string productCode; + string upgradeCode; + string manufacturer; + string productLanguage; + string productVersion; + long installSize; + + var sourcePath = this.PackagePayload.SourceFile.Path; - var sourcePath = packagePayload.SourceFile.Path; - var longNamesInImage = false; - var compressed = false; try { - this.CheckIfWindowsInstallerFileTooLarge(packagePayload.SourceLineNumbers, sourcePath, "MSI"); + var longNamesInImage = false; + var compressed = false; + + this.CheckIfWindowsInstallerFileTooLarge(this.PackagePayload.SourceLineNumbers, sourcePath, "MSI"); using (var db = new Database(sourcePath, OpenDatabase.ReadOnly)) { @@ -87,117 +195,68 @@ namespace WixToolset.Core.Burn.Bundles // 8 is the Word Count summary information stream bit that means // "Elevated privileges are not required to install this package." // in MSI 4.5 and below, if this bit is 0, elevation is required. - var perMachine = (0 == (fileAndElevateFlags & 8)); - - this.Facade.PackageSymbol.PerMachine = perMachine; - this.Facade.PackageSymbol.Win64 = this.IsWin64(packagePayload.SourceLineNumbers, sourcePath, platformsAndLanguages); + perMachine = (0 == (fileAndElevateFlags & 8)); + win64 = this.IsWin64(sourcePath, platformsAndLanguages); } - string packageName = null; - string packageDescription = null; - string allusers = null; - string fastInstall = null; - string systemComponent = null; - using (var view = db.OpenView(PropertySqlQuery)) { - packageName = ProcessMsiPackageCommand.GetProperty(view, "ProductName"); - packageDescription = ProcessMsiPackageCommand.GetProperty(view, "ARPCOMMENTS"); - allusers = ProcessMsiPackageCommand.GetProperty(view, "ALLUSERS"); - fastInstall = ProcessMsiPackageCommand.GetProperty(view, "MSIFASTINSTALL"); - systemComponent = ProcessMsiPackageCommand.GetProperty(view, "ARPSYSTEMCOMPONENT"); - - msiPackage.ProductCode = ProcessMsiPackageCommand.GetProperty(view, "ProductCode"); - msiPackage.UpgradeCode = ProcessMsiPackageCommand.GetProperty(view, "UpgradeCode"); - msiPackage.Manufacturer = ProcessMsiPackageCommand.GetProperty(view, "Manufacturer"); - msiPackage.ProductLanguage = Convert.ToInt32(ProcessMsiPackageCommand.GetProperty(view, "ProductLanguage"), CultureInfo.InvariantCulture); - msiPackage.ProductVersion = ProcessMsiPackageCommand.GetProperty(view, "ProductVersion"); - } - - if (!this.BackendHelper.IsValidFourPartVersion(msiPackage.ProductVersion)) - { - // not a proper .NET version (e.g., five fields); can we get a valid four-part version number? - string version = null; - var versionParts = msiPackage.ProductVersion.Split('.'); - var count = versionParts.Length; - if (0 < count) - { - version = versionParts[0]; - for (var i = 1; i < 4 && i < count; ++i) - { - version = String.Concat(version, ".", versionParts[i]); - } - } - - if (!String.IsNullOrEmpty(version) && this.BackendHelper.IsValidFourPartVersion(version)) - { - this.Messaging.Write(WarningMessages.VersionTruncated(this.Facade.PackageSymbol.SourceLineNumbers, msiPackage.ProductVersion, sourcePath, version)); - msiPackage.ProductVersion = version; - } - else - { - this.Messaging.Write(ErrorMessages.InvalidProductVersion(this.Facade.PackageSymbol.SourceLineNumbers, msiPackage.ProductVersion, sourcePath)); - } - } - - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.CacheId)) - { - this.Facade.PackageSymbol.CacheId = String.Format("{0}v{1}", msiPackage.ProductCode, msiPackage.ProductVersion); - } - - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) - { - this.Facade.PackageSymbol.DisplayName = packageName; - } - - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description)) - { - this.Facade.PackageSymbol.Description = packageDescription; - } - - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Version)) - { - this.Facade.PackageSymbol.Version = msiPackage.ProductVersion; + productName = ProcessMsiPackageCommand.GetProperty(view, "ProductName"); + arpComments = ProcessMsiPackageCommand.GetProperty(view, "ARPCOMMENTS"); + allUsers = ProcessMsiPackageCommand.GetProperty(view, "ALLUSERS"); + msiFastInstall = ProcessMsiPackageCommand.GetProperty(view, "MSIFASTINSTALL"); + arpSystemComponent = ProcessMsiPackageCommand.GetProperty(view, "ARPSYSTEMCOMPONENT"); + + productCode = ProcessMsiPackageCommand.GetProperty(view, "ProductCode"); + upgradeCode = ProcessMsiPackageCommand.GetProperty(view, "UpgradeCode"); + manufacturer = ProcessMsiPackageCommand.GetProperty(view, "Manufacturer"); + productLanguage = ProcessMsiPackageCommand.GetProperty(view, "ProductLanguage"); + productVersion = ProcessMsiPackageCommand.GetProperty(view, "ProductVersion"); } var payloadNames = this.GetPayloadTargetNames(); - var msiPropertyNames = this.GetMsiPropertyNames(packagePayload.Id.Id); - - this.SetPerMachineAppropriately(allusers, msiPackage, sourcePath); - - // Ensure the MSI package is appropriately marked visible or not. - this.SetPackageVisibility(systemComponent, msiPackage, msiPropertyNames); - - // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance. - if (String.IsNullOrEmpty(fastInstall) && !msiPropertyNames.Contains("MSIFASTINSTALL")) - { - this.AddMsiProperty(msiPackage, "MSIFASTINSTALL", "7"); - } - this.CreateRelatedPackages(db); // If feature selection is enabled, represent the Feature table in the manifest. - if (msiPackage.EnableFeatureSelection) + if (this.MsiPackage.EnableFeatureSelection) { this.CreateMsiFeatures(db); } // Add all external cabinets as package payloads. - this.ImportExternalCabinetAsPayloads(db, packagePayload, payloadNames); + this.ImportExternalCabinetAsPayloads(db, payloadNames); // Add all external files as package payloads and calculate the total install size as the rollup of // File table's sizes. - this.Facade.PackageSymbol.InstallSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, packagePayload, longNamesInImage, compressed, payloadNames); + installSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, longNamesInImage, compressed, payloadNames); // Add all dependency providers from the MSI. - this.ImportDependencyProviders(db, msiPackage); + this.ImportDependencyProviders(db); } } catch (MsiException e) { - this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, e.Message)); + this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.PackagePayload.SourceLineNumbers, sourcePath, e.Message)); + return null; } + + return this.Section.AddSymbol(new WixBundleHarvestedMsiPackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id) + { + PerMachine = perMachine, + Win64 = win64, + ProductName = productName, + ArpComments = arpComments, + AllUsers = allUsers, + MsiFastInstall = msiFastInstall, + ArpSystemComponent = arpSystemComponent, + ProductCode = productCode, + UpgradeCode = upgradeCode, + Manufacturer = manufacturer, + ProductLanguage = productLanguage, + ProductVersion = productVersion, + InstallSize = installSize, + }); } private ISet GetPayloadTargetNames() @@ -207,17 +266,17 @@ namespace WixToolset.Core.Burn.Bundles return new HashSet(payloadNames, StringComparer.OrdinalIgnoreCase); } - private ISet GetMsiPropertyNames(string packageId) + private ISet GetMsiPropertyNames() { var properties = this.Section.Symbols.OfType() - .Where(p => p.PackageRef == packageId) + .Where(p => p.PackageRef == this.PackageId) .Select(p => p.Name); return new HashSet(properties, StringComparer.Ordinal); } // https://docs.microsoft.com/en-us/windows/win32/msi/template-summary - private bool IsWin64(SourceLineNumber sourceLineNumbers, string sourcePath, string platformsAndLanguages) + private bool IsWin64(string sourcePath, string platformsAndLanguages) { var separatorIndex = platformsAndLanguages.IndexOf(';'); var platformValue = separatorIndex > 0 ? platformsAndLanguages.Substring(0, separatorIndex) : platformsAndLanguages; @@ -234,27 +293,27 @@ namespace WixToolset.Core.Burn.Bundles return false; default: - this.Messaging.Write(BurnBackendWarnings.UnknownMsiPackagePlatform(sourceLineNumbers, sourcePath, platformValue)); + this.Messaging.Write(BurnBackendWarnings.UnknownMsiPackagePlatform(this.PackagePayload.SourceLineNumbers, sourcePath, platformValue)); return true; } } - private void SetPerMachineAppropriately(string allusers, WixBundleMsiPackageSymbol msiPackage, string sourcePath) + private void SetPerMachineAppropriately(string allusers) { - Debug.Assert(this.Facade.PackageSymbol.PerMachine.HasValue); - var perMachine = this.Facade.PackageSymbol.PerMachine.Value; + Debug.Assert(this.ChainPackage.PerMachine.HasValue); + var perMachine = this.ChainPackage.PerMachine.Value; // Can ignore ALLUSERS from MsiProperties because it is not allowed there. - if (msiPackage.ForcePerMachine) + if (this.MsiPackage.ForcePerMachine) { if (!perMachine) { - this.Messaging.Write(WarningMessages.PerUserButForcingPerMachine(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath)); - this.Facade.PackageSymbol.PerMachine = true; // ensure that we think the package is per-machine. + this.Messaging.Write(WarningMessages.PerUserButForcingPerMachine(this.PackagePayload.SourceLineNumbers, this.PackageId)); + this.ChainPackage.PerMachine = true; // ensure that we think the package is per-machine. } // Force ALLUSERS=1 via the MSI command-line. - this.AddMsiProperty(msiPackage, "ALLUSERS", "1"); + this.AddMsiProperty("ALLUSERS", "1"); } else { @@ -263,40 +322,40 @@ namespace WixToolset.Core.Burn.Bundles // Not forced per-machine and no ALLUSERS property, flip back to per-user. if (perMachine) { - this.Messaging.Write(WarningMessages.ImplicitlyPerUser(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath)); - this.Facade.PackageSymbol.PerMachine = false; + this.Messaging.Write(WarningMessages.ImplicitlyPerUser(this.ChainPackage.SourceLineNumbers, this.PackageId)); + this.ChainPackage.PerMachine = false; } } else if (allusers.Equals("1", StringComparison.Ordinal)) { if (!perMachine) { - this.Messaging.Write(ErrorMessages.PerUserButAllUsersEquals1(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath)); + this.Messaging.Write(ErrorMessages.PerUserButAllUsersEquals1(this.ChainPackage.SourceLineNumbers, this.PackageId)); } } else if (allusers.Equals("2", StringComparison.Ordinal)) { - this.Messaging.Write(WarningMessages.DiscouragedAllUsersValue(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, perMachine ? "machine" : "user")); + this.Messaging.Write(WarningMessages.DiscouragedAllUsersValue(this.ChainPackage.SourceLineNumbers, this.PackageId, perMachine ? "machine" : "user")); } else { - this.Messaging.Write(ErrorMessages.UnsupportedAllUsersValue(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, allusers)); + this.Messaging.Write(ErrorMessages.UnsupportedAllUsersValue(this.ChainPackage.SourceLineNumbers, this.PackageId, allusers)); } } } - private void SetPackageVisibility(string systemComponent, WixBundleMsiPackageSymbol msiPackage, ISet msiPropertyNames) + private void SetPackageVisibility(string systemComponent, ISet msiPropertyNames) { // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again. if (!msiPropertyNames.Contains("ARPSYSTEMCOMPONENT")) { var alreadyVisible = String.IsNullOrEmpty(systemComponent); - var visible = this.Facade.PackageSymbol.Visible; + var visible = this.ChainPackage.Visible; // If not already set to the correct visibility. if (alreadyVisible != visible) { - this.AddMsiProperty(msiPackage, "ARPSYSTEMCOMPONENT", visible ? String.Empty : "1"); + this.AddMsiProperty("ARPSYSTEMCOMPONENT", visible ? String.Empty : "1"); } } } @@ -318,9 +377,9 @@ namespace WixToolset.Core.Burn.Bundles attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive ? WixBundleRelatedPackageAttributes.MaxInclusive : 0; attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive ? 0 : WixBundleRelatedPackageAttributes.LangInclusive; - this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.Facade.PackageSymbol.SourceLineNumbers) + this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.PackagePayload.SourceLineNumbers) { - PackageRef = this.Facade.PackageId, + PackageRef = this.PackageId, RelatedId = record.GetString(1), MinVersion = record.GetString(2), MaxVersion = record.GetString(3), @@ -366,9 +425,9 @@ namespace WixToolset.Core.Burn.Bundles } } - this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, this.Facade.PackageId, featureName)) + this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.PackagePayload.SourceLineNumbers, new Identifier(AccessModifier.Section, this.PackageId, featureName)) { - PackageRef = this.Facade.PackageId, + PackageRef = this.PackageId, Name = featureName, Parent = allFeaturesResultRecord.GetString(2), Title = allFeaturesResultRecord.GetString(3), @@ -385,12 +444,14 @@ namespace WixToolset.Core.Burn.Bundles } } - private void ImportExternalCabinetAsPayloads(Database db, WixBundlePayloadSymbol packagePayload, ISet payloadNames) + private void ImportExternalCabinetAsPayloads(Database db, ISet payloadNames) { if (db.TableExists("Media")) { using (var view = db.OpenExecuteView("SELECT `Cabinet` FROM `Media`")) { + var sourceLineNumbers = this.PackagePayload.SourceLineNumbers; + foreach (var cabinetRecord in view.Records) { var cabinet = cabinetRecord.GetString(1); @@ -400,34 +461,34 @@ namespace WixToolset.Core.Burn.Bundles // If we didn't find the Payload as an existing child of the package, we need to // add it. We expect the file to exist on-disk in the same relative location as // the MSI expects to find it... - var cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet); + var cabinetName = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), cabinet); if (!payloadNames.Contains(cabinetName)) { - var generatedId = this.BackendHelper.GenerateIdentifier("cab", packagePayload.Id.Id, cabinet); - var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.Facade.PackageSymbol.SourceLineNumbers); + var generatedId = this.BackendHelper.GenerateIdentifier("cab", this.PackagePayload.Id.Id, cabinet); + var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, cabinet, "Cabinet", sourceLineNumbers); - this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) + this.Section.AddSymbol(new WixGroupSymbol(sourceLineNumbers) { ParentType = ComplexReferenceParentType.Package, - ParentId = this.Facade.PackageId, + ParentId = this.PackageId, ChildType = ComplexReferenceChildType.Payload, ChildId = generatedId }); - this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) + this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) { Name = cabinetName, SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, - Compressed = packagePayload.Compressed, + Compressed = this.PackagePayload.Compressed, UnresolvedSourceFile = cabinetName, - ContainerRef = packagePayload.ContainerRef, - DownloadUrl = packagePayload.DownloadUrl, - Packaging = packagePayload.Packaging, - ParentPackagePayloadRef = packagePayload.Id.Id, + ContainerRef = this.PackagePayload.ContainerRef, + DownloadUrl = this.PackagePayload.DownloadUrl, + Packaging = this.PackagePayload.Packaging, + ParentPackagePayloadRef = this.PackagePayload.Id.Id, }); - this.CheckIfWindowsInstallerFileTooLarge(this.Facade.PackageSymbol.SourceLineNumbers, payloadSourceFile, "cabinet"); + this.CheckIfWindowsInstallerFileTooLarge(sourceLineNumbers, payloadSourceFile, "cabinet"); } } } @@ -435,7 +496,7 @@ namespace WixToolset.Core.Burn.Bundles } } - private long ImportExternalFileAsPayloadsAndReturnInstallSize(Database db, WixBundlePayloadSymbol packagePayload, bool longNamesInImage, bool compressed, ISet payloadNames) + private long ImportExternalFileAsPayloadsAndReturnInstallSize(Database db, bool longNamesInImage, bool compressed, ISet payloadNames) { long size = 0; @@ -461,6 +522,8 @@ namespace WixToolset.Core.Burn.Bundles // install size of the package. using (var view = db.OpenExecuteView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`")) { + var sourceLineNumbers = this.PackagePayload.SourceLineNumbers; + foreach (var record in view.Records) { // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not @@ -470,31 +533,31 @@ namespace WixToolset.Core.Burn.Bundles (!compressed && 0 == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesCompressed))) { var fileSourcePath = this.PathResolver.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage); - var name = Path.Combine(Path.GetDirectoryName(packagePayload.Name), fileSourcePath); + var name = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), fileSourcePath); if (!payloadNames.Contains(name)) { - var generatedId = this.BackendHelper.GenerateIdentifier("f", packagePayload.Id.Id, record.GetString(2)); - var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.Facade.PackageSymbol.SourceLineNumbers); + var generatedId = this.BackendHelper.GenerateIdentifier("f", this.PackagePayload.Id.Id, record.GetString(2)); + var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, fileSourcePath, "File", sourceLineNumbers); - this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) + this.Section.AddSymbol(new WixGroupSymbol(sourceLineNumbers) { ParentType = ComplexReferenceParentType.Package, - ParentId = this.Facade.PackageId, + ParentId = this.PackageId, ChildType = ComplexReferenceChildType.Payload, ChildId = generatedId }); - this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) + this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) { Name = name, SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, - Compressed = packagePayload.Compressed, + Compressed = this.PackagePayload.Compressed, UnresolvedSourceFile = name, - ContainerRef = packagePayload.ContainerRef, - DownloadUrl = packagePayload.DownloadUrl, - Packaging = packagePayload.Packaging, - ParentPackagePayloadRef = packagePayload.Id.Id, + ContainerRef = this.PackagePayload.ContainerRef, + DownloadUrl = this.PackagePayload.DownloadUrl, + Packaging = this.PackagePayload.Packaging, + ParentPackagePayloadRef = this.PackagePayload.Id.Id, }); } } @@ -507,23 +570,23 @@ namespace WixToolset.Core.Burn.Bundles return size; } - private void AddMsiProperty(WixBundleMsiPackageSymbol msiPackage, string name, string value) + private void AddMsiProperty(string name, string value) { - this.Section.AddSymbol(new WixBundleMsiPropertySymbol(msiPackage.SourceLineNumbers, new Identifier(AccessModifier.Section, msiPackage.Id.Id, name)) + this.Section.AddSymbol(new WixBundleMsiPropertySymbol(this.PackagePayload.SourceLineNumbers, new Identifier(AccessModifier.Section, this.PackageId, name)) { - PackageRef = msiPackage.Id.Id, + PackageRef = this.PackageId, Name = name, Value = value, }); } - private void ImportDependencyProviders(Database db, WixBundleMsiPackageSymbol msiPackage) + private void ImportDependencyProviders(Database db) { - this.ImportDependencyProvidersFromTable(db, msiPackage, "WixDependencyProvider"); - this.ImportDependencyProvidersFromTable(db, msiPackage, "Wix4DependencyProvider"); + this.ImportDependencyProvidersFromTable(db, "WixDependencyProvider"); + this.ImportDependencyProvidersFromTable(db, "Wix4DependencyProvider"); } - private void ImportDependencyProvidersFromTable(Database db, WixBundleMsiPackageSymbol msiPackage, string tableName) + private void ImportDependencyProvidersFromTable(Database db, string tableName) { if (db.TableExists(tableName)) { @@ -531,15 +594,15 @@ namespace WixToolset.Core.Burn.Bundles { foreach (var record in view.Records) { - var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", msiPackage.Id.Id, record.GetString(1))); + var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackageId, record.GetString(1))); // Import the provider key and attributes. - this.Section.AddSymbol(new WixDependencyProviderSymbol(msiPackage.SourceLineNumbers, id) + this.Section.AddSymbol(new WixDependencyProviderSymbol(this.PackagePayload.SourceLineNumbers, id) { - ParentRef = msiPackage.Id.Id, + ParentRef = this.PackageId, ProviderKey = record.GetString(2), - Version = record.GetString(3) ?? msiPackage.ProductVersion, - DisplayName = record.GetString(4) ?? this.Facade.PackageSymbol.DisplayName, + Version = record.GetString(3) ?? this.MsiPackage.ProductVersion, + DisplayName = record.GetString(4) ?? this.ChainPackage.DisplayName, Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported | (WixDependencyProviderAttributes)record.GetInteger(5), }); } diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs index d306957e..cef68c8a 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs @@ -5,6 +5,7 @@ namespace WixToolset.Core.Burn.Bundles using System; using System.Collections.Generic; using System.IO; + using System.Linq; using System.Text; using System.Xml; using WixToolset.Core.Native.Msi; @@ -29,30 +30,71 @@ namespace WixToolset.Core.Burn.Bundles public ProcessMspPackageCommand(IMessaging messaging, IntermediateSection section, PackageFacade facade, Dictionary payloadSymbols) { this.Messaging = messaging; - - this.AuthoredPayloads = payloadSymbols; this.Section = section; - this.Facade = facade; + + this.ChainPackage = facade.PackageSymbol; + this.MspPackage = (WixBundleMspPackageSymbol)facade.SpecificPackageSymbol; + this.PackagePayload = payloadSymbols[this.ChainPackage.PayloadRef]; } - public IMessaging Messaging { get; } + private IMessaging Messaging { get; } - public Dictionary AuthoredPayloads { private get; set; } + private WixBundlePackageSymbol ChainPackage { get; } - public PackageFacade Facade { private get; set; } + private WixBundleMspPackageSymbol MspPackage { get; } - public IntermediateSection Section { get; } + private WixBundlePayloadSymbol PackagePayload { get; } + + private IntermediateSection Section { get; } /// /// Processes the Msp packages to add properties and payloads from the Msp packages. /// public void Execute() { - var packagePayload = this.AuthoredPayloads[this.Facade.PackageSymbol.PayloadRef]; + var harvestedMspPackage = this.Section.Symbols.OfType() + .Where(h => h.Id == this.ChainPackage.Id) + .SingleOrDefault(); + + if (harvestedMspPackage == null) + { + harvestedMspPackage = this.HarvestPackage(); + + if (harvestedMspPackage == null) + { + return; + } + } + + this.MspPackage.PatchCode = harvestedMspPackage.PatchCode; + this.MspPackage.Manufacturer = harvestedMspPackage.ManufacturerName; + this.MspPackage.PatchXml = harvestedMspPackage.PatchXml; + + if (String.IsNullOrEmpty(this.ChainPackage.DisplayName)) + { + this.ChainPackage.DisplayName = harvestedMspPackage.DisplayName; + } - var mspPackage = (WixBundleMspPackageSymbol)this.Facade.SpecificPackageSymbol; + if (String.IsNullOrEmpty(this.ChainPackage.Description)) + { + this.ChainPackage.Description = harvestedMspPackage.Description; + } - var sourcePath = packagePayload.SourceFile.Path; + if (String.IsNullOrEmpty(this.ChainPackage.CacheId)) + { + this.ChainPackage.CacheId = this.MspPackage.PatchCode; + } + } + + private WixBundleHarvestedMspPackageSymbol HarvestPackage() + { + string patchCode; + string displayName; + string description; + string manufacturerName; + string patchXml; + + var sourcePath = this.PackagePayload.SourceFile.Path; try { @@ -61,41 +103,37 @@ namespace WixToolset.Core.Burn.Bundles // Read data out of the msp database... using (var sumInfo = new SummaryInformation(db)) { - var patchCode = sumInfo.GetProperty(SummaryInformation.Patch.PatchCode); - mspPackage.PatchCode = patchCode.Substring(0, 38); + var patchCodeValue = sumInfo.GetProperty(SummaryInformation.Patch.PatchCode); + patchCode = patchCodeValue.Substring(0, 38); } using (var view = db.OpenView(PatchMetadataQuery)) { - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) - { - this.Facade.PackageSymbol.DisplayName = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "DisplayName"); - } - - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description)) - { - this.Facade.PackageSymbol.Description = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "Description"); - } - - mspPackage.Manufacturer = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "ManufacturerName"); + displayName = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "DisplayName"); + description = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "Description"); + manufacturerName = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "ManufacturerName"); } } - this.ProcessPatchXml(packagePayload, mspPackage, sourcePath); + patchXml = ProcessMspPackageCommand.ProcessPatchXml(sourcePath, this.Section, this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id); } catch (MsiException e) { - this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(packagePayload.SourceLineNumbers, sourcePath, e.Message)); - return; + this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.PackagePayload.SourceLineNumbers, sourcePath, e.Message)); + return null; } - if (String.IsNullOrEmpty(this.Facade.PackageSymbol.CacheId)) + return this.Section.AddSymbol(new WixBundleHarvestedMspPackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id) { - this.Facade.PackageSymbol.CacheId = mspPackage.PatchCode; - } + PatchCode = patchCode, + DisplayName = displayName, + Description = description, + ManufacturerName = manufacturerName, + PatchXml = patchXml, + }); } - private void ProcessPatchXml(WixBundlePayloadSymbol packagePayload, WixBundleMspPackageSymbol mspPackage, string sourcePath) + private static string ProcessPatchXml(string sourcePath, IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id) { var uniqueTargetCodes = new Dictionary(); @@ -135,9 +173,9 @@ namespace WixToolset.Core.Burn.Bundles if (!uniqueTargetCodes.TryGetValue(targetCode, out var existing)) { - var symbol = this.Section.AddSymbol(new WixBundlePatchTargetCodeSymbol(packagePayload.SourceLineNumbers) + var symbol = section.AddSymbol(new WixBundlePatchTargetCodeSymbol(sourceLineNumbers) { - PackageRef = packagePayload.Id.Id, + PackageRef = id.Id, TargetCode = targetCode, Attributes = 0, Type = type, @@ -158,6 +196,8 @@ namespace WixToolset.Core.Burn.Bundles root.RemoveChild(node); } + string compactPatchXml; + // Save the XML as compact as possible. using (var writer = new StringWriter()) { @@ -166,8 +206,10 @@ namespace WixToolset.Core.Burn.Bundles doc.WriteTo(xmlWriter); } - mspPackage.PatchXml = writer.ToString(); + compactPatchXml = writer.ToString(); } + + return compactPatchXml; } private static string GetPatchMetadataProperty(View view, string property) diff --git a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs index 7235c792..0c305331 100644 --- a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs +++ b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs @@ -26,9 +26,9 @@ namespace WixToolset.Core.Burn return Message(sourceLineNumbers, Ids.FailedToExtractAttachedContainers, "Failed to extract attached container. This most often happens when extracting a stripped bundle from the package cache, which is not supported."); } - public static Message HiddenBundleNotSupported(SourceLineNumber sourceLineNumbers, string bundleExecutable) + public static Message HiddenBundleNotSupported(SourceLineNumber sourceLineNumbers, string packageId) { - return Message(sourceLineNumbers, Ids.HiddenBundleNotSupported, "The bundle '{0}' does not support hiding its ARP registration.", bundleExecutable); + return Message(sourceLineNumbers, Ids.HiddenBundleNotSupported, "The BundlePackage '{0}' does not support hiding its ARP registration.", packageId); } public static Message UnknownBundleRelationAction(SourceLineNumber sourceLineNumbers, string bundleExecutable, string action) diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs index 7cd13ebf..2925abb1 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs @@ -238,7 +238,7 @@ namespace WixToolsetTest.CoreIntegration .ToArray(); WixAssert.CompareLineByLine(new[] { - "The bundle '\\v3bundle.exe' does not support hiding its ARP registration.", + "The BundlePackage 'v3bundle.exe' does not support hiding its ARP registration.", }, warningMessages); Assert.True(File.Exists(parentBundlePath)); -- cgit v1.2.3-55-g6feb