From ce3aea757a01f0eea906fa610501a66735ef3a15 Mon Sep 17 00:00:00 2001 From: Nir Bar Date: Wed, 6 Oct 2021 14:11:17 +0300 Subject: Support multiple attached containers See https://github.com/wixtoolset/issues/issues/6144 --- src/burn/engine/section.cpp | 4 +- src/burn/stub/StubSection.cpp | 5 +- .../WixToolset.Core.Burn/Bind/BindBundleCommand.cs | 4 +- src/wix/WixToolset.Core.Burn/BundleBackend.cs | 3 +- src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs | 59 +++++++++++++++++----- src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs | 35 +++++++------ src/wix/WixToolset.Core.Burn/Bundles/BurnWriter.cs | 31 ++++++++++-- .../Bundles/CreateNonUXContainers.cs | 8 --- src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs | 18 ++++--- .../Inscribe/InscribeBundleCommand.cs | 22 +++++--- .../WixToolset.Core.TestPackage/BundleExtractor.cs | 6 +-- .../BundleExtractionFixture.cs | 2 +- .../BundleFixture.cs | 4 +- .../ContainerFixture.cs | 49 +++++++++++------- .../PackagePayloadFixture.cs | 3 +- .../PayloadFixture.cs | 17 ++++--- 16 files changed, 170 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/burn/engine/section.cpp b/src/burn/engine/section.cpp index 3720155c..1fd6cce4 100644 --- a/src/burn/engine/section.cpp +++ b/src/burn/engine/section.cpp @@ -8,7 +8,7 @@ // If these defaults ever change, be sure to update constants in burn\stub\StubSection.cpp as well. #define BURN_SECTION_NAME ".wixburn" #define BURN_SECTION_MAGIC 0x00f14300 -#define BURN_SECTION_VERSION 0x00000002 +#define BURN_SECTION_VERSION 0x00000003 #define MANIFEST_CABINET_TOKEN L"0" // structs @@ -26,7 +26,7 @@ typedef struct _BURN_SECTION_HEADER DWORD dwFormat; DWORD cContainers; - DWORD rgcbContainers[1]; + DWORD rgcbContainers[116]; } BURN_SECTION_HEADER; static HRESULT VerifySectionMatchesMemoryPEHeader( diff --git a/src/burn/stub/StubSection.cpp b/src/burn/stub/StubSection.cpp index 962bb3cf..01b4b576 100644 --- a/src/burn/stub/StubSection.cpp +++ b/src/burn/stub/StubSection.cpp @@ -7,7 +7,7 @@ // If these defaults ever change, be sure to update constants in burn\engine\section.cpp as well. #pragma data_seg(push, ".wixburn") static DWORD dwMagic = 0x00f14300; -static DWORD dwVersion = 0x00000002; +static DWORD dwVersion = 0x00000003; static GUID guidBundleId = { }; @@ -18,6 +18,5 @@ static DWORD dwOriginalSignatureSize = 0; static DWORD dwContainerFormat = 1; static DWORD dwContainerCount = 0; -static DWORD qwBootstrapperApplicationContainerSize = 0; -static DWORD qwAttachedContainerSize = 0; +static DWORD qwAttachedContainerSizes[116]; // Including UX container #pragma data_seg(pop) diff --git a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs index cd00232a..a60d3ddf 100644 --- a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs @@ -296,15 +296,13 @@ namespace WixToolset.Core.Burn } // Give the embedded payloads without an embedded id yet an embedded id. - var payloadIndex = 0; foreach (var payload in payloadSymbols.Values) { Debug.Assert(PackagingType.Unknown != payload.Packaging); if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.EmbeddedId)) { - payload.EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnAuthoredContainerEmbeddedIdFormat, payloadIndex); - ++payloadIndex; + payload.EmbeddedId = Guid.NewGuid().ToString("N"); } } } diff --git a/src/wix/WixToolset.Core.Burn/BundleBackend.cs b/src/wix/WixToolset.Core.Burn/BundleBackend.cs index 60e9ea60..83572cda 100644 --- a/src/wix/WixToolset.Core.Burn/BundleBackend.cs +++ b/src/wix/WixToolset.Core.Burn/BundleBackend.cs @@ -62,13 +62,12 @@ namespace WixToolset.Core.Burn public Intermediate Unbind(IUnbindContext context) { var uxExtractPath = Path.Combine(context.ExportBasePath, "UX"); - var acExtractPath = Path.Combine(context.ExportBasePath, "AttachedContainer"); var messaging = context.ServiceProvider.GetService(); using (var reader = BurnReader.Open(messaging, context.InputFilePath)) { reader.ExtractUXContainer(uxExtractPath, context.IntermediateFolder); - reader.ExtractAttachedContainer(acExtractPath, context.IntermediateFolder); + reader.ExtractAttachedContainers(context.ExportBasePath); } return null; diff --git a/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs b/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs index 1eb3563a..6a9d7950 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs @@ -3,6 +3,7 @@ namespace WixToolset.Core.Burn.Bundles { using System; + using System.Collections.Generic; using System.Diagnostics; using System.IO; using WixToolset.Data; @@ -19,7 +20,6 @@ namespace WixToolset.Core.Burn.Bundles { public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn"; public const string BurnUXContainerEmbeddedIdFormat = "u{0}"; - public const string BurnAuthoredContainerEmbeddedIdFormat = "a{0}"; public const string BADataFileName = "BootstrapperApplicationData.xml"; public const string BADataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData"; @@ -67,7 +67,7 @@ namespace WixToolset.Core.Burn.Bundles // 40-43: container type (1 = CAB) // 44-47: container count // 48-51: byte count of manifest + UX container - // 52-55: byte count of attached container + // 52-512: byte count of attached containers (4 bytes for each container) protected const UInt32 BURN_SECTION_OFFSET_MAGIC = 0; protected const UInt32 BURN_SECTION_OFFSET_VERSION = 4; protected const UInt32 BURN_SECTION_OFFSET_BUNDLEGUID = 8; @@ -78,11 +78,14 @@ namespace WixToolset.Core.Burn.Bundles protected const UInt32 BURN_SECTION_OFFSET_FORMAT = 40; protected const UInt32 BURN_SECTION_OFFSET_COUNT = 44; protected const UInt32 BURN_SECTION_OFFSET_UXSIZE = 48; - protected const UInt32 BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE = 52; - protected const UInt32 BURN_SECTION_SIZE = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE + 4; // last field + sizeof(DWORD) + protected const UInt32 BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0 = 52; protected const UInt32 BURN_SECTION_MAGIC = 0x00f14300; - protected const UInt32 BURN_SECTION_VERSION = 0x00000002; + protected const UInt32 BURN_SECTION_VERSION = 0x00000003; + protected const UInt32 BURN_SECTION_COMPATIBLE_VERSION = 0x00000002; + protected const UInt32 BURN_SECTION_SIZE = 512; + protected const UInt32 BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT = (BURN_SECTION_SIZE - BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0) / sizeof(UInt32); + protected string fileExe; protected UInt32 peOffset = UInt32.MaxValue; protected UInt16 sections = UInt16.MaxValue; @@ -112,6 +115,7 @@ namespace WixToolset.Core.Burn.Bundles { this.Messaging = messaging; this.fileExe = fileExe; + this.AttachedContainers = new List(); } public UInt32 Checksum { get; protected set; } @@ -126,8 +130,7 @@ namespace WixToolset.Core.Burn.Bundles public UInt32 ContainerCount { get; protected set; } public UInt32 UXAddress { get; protected set; } public UInt32 UXSize { get; protected set; } - public UInt32 AttachedContainerAddress { get; protected set; } - public UInt32 AttachedContainerSize { get; protected set; } + public List AttachedContainers { get; protected set; } protected IMessaging Messaging { get; } @@ -177,7 +180,9 @@ namespace WixToolset.Core.Burn.Bundles } reader.BaseStream.Seek(this.wixburnDataOffset, SeekOrigin.Begin); - byte[] bytes = reader.ReadBytes((int)BURN_SECTION_SIZE); + List manifest = new List(); + manifest.AddRange(reader.ReadBytes((int)BURN_SECTION_SIZE)); + byte[] bytes = manifest.ToArray(); UInt32 uint32 = 0; uint32 = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_MAGIC); @@ -188,9 +193,9 @@ namespace WixToolset.Core.Burn.Bundles } this.Version = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_VERSION); - if (BURN_SECTION_VERSION != this.Version) + if ((BURN_SECTION_VERSION != this.Version) && (BURN_SECTION_COMPATIBLE_VERSION != this.Version)) { - this.Messaging.Write(ErrorMessages.BundleTooNew(this.fileExe, this.Version)); + this.Messaging.Write(BurnBackendErrors.IncompatibleWixBurnSection(this.fileExe, this.Version)); return false; } @@ -207,6 +212,11 @@ namespace WixToolset.Core.Burn.Bundles this.OriginalSignatureSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALSIGNATURESIZE); this.ContainerCount = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_COUNT); + if (BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT < this.ContainerCount) + { + this.Messaging.Write(ErrorMessages.InvalidBundle(this.fileExe)); + return false; + } this.UXAddress = this.StubSize; this.UXSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_UXSIZE); @@ -224,8 +234,18 @@ namespace WixToolset.Core.Burn.Bundles this.EngineSize = this.StubSize + this.UXSize; } - this.AttachedContainerAddress = this.ContainerCount > 1 ? this.EngineSize : 0; - this.AttachedContainerSize = this.ContainerCount > 1 ? BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE) : 0; + this.AttachedContainers.Clear(); + uint nextAddress = this.EngineSize; + if (this.ContainerCount > 1) + { + for (uint i = 0; i < (this.ContainerCount - 1 /* Excluding UX */); ++i) + { + uint sizeOffset = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0 + (i * 4); + uint size = BurnCommon.ReadUInt32(bytes, sizeOffset); + this.AttachedContainers.Add(new ContainerSlot(nextAddress, size)); + nextAddress += size; + } + } return true; } @@ -268,8 +288,7 @@ namespace WixToolset.Core.Burn.Bundles return false; } - // we need 56 bytes for the manifest header, which is always going to fit in - // the smallest alignment (512 bytes), but just to be paranoid... + // We need 512 bytes for the manifest header if (BURN_SECTION_SIZE > BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_SIZEOFRAWDATA)) { this.Messaging.Write(ErrorMessages.StubWixburnSectionTooSmall(this.fileExe)); @@ -382,4 +401,16 @@ namespace WixToolset.Core.Burn.Bundles return BurnCommon.ReadUInt32(bytes, offset) + ((UInt64)BurnCommon.ReadUInt32(bytes, offset + 4) << 32); } } + + internal struct ContainerSlot + { + public ContainerSlot(uint address, uint size) : this() + { + this.Address = address; + this.Size = size; + } + + public uint Address { get; set; } + public uint Size { get; set; } + } } diff --git a/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs b/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs index 5b06b31e..e3fd9f51 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs @@ -126,16 +126,19 @@ namespace WixToolset.Core.Burn.Bundles foreach (XmlNode payload in payloads) { - XmlNode sourcePathNode = payload.Attributes.GetNamedItem("SourcePath"); - XmlNode filePathNode = payload.Attributes.GetNamedItem("FilePath"); XmlNode packagingNode = payload.Attributes.GetNamedItem("Packaging"); - string sourcePath = sourcePathNode.Value; - string destinationPath = filePathNode.Value; string packaging = packagingNode.Value; if (packaging.Equals("embedded", StringComparison.OrdinalIgnoreCase)) { + XmlNode sourcePathNode = payload.Attributes.GetNamedItem("SourcePath"); + XmlNode filePathNode = payload.Attributes.GetNamedItem("FilePath"); + XmlNode containerNode = payload.Attributes.GetNamedItem("Container"); + + string sourcePath = sourcePathNode.Value; + string destinationPath = Path.Combine(containerNode.Value, filePathNode.Value); + this.attachedContainerPayloadNames.Add(new DictionaryEntry(sourcePath, destinationPath)); } } @@ -152,12 +155,11 @@ namespace WixToolset.Core.Burn.Bundles /// Gets the attached container from the exe and extracts its contents to the output directory. /// /// Directory to write extracted files to. - /// Scratch directory. /// True if successful, false otherwise - public bool ExtractAttachedContainer(string outputDirectory, string tempDirectory) + public bool ExtractAttachedContainers(string outputDirectory) { // No attached container to extract - if (this.AttachedContainerAddress == 0 || this.AttachedContainerSize == 0) + if (this.AttachedContainers.Count == 0) { return false; } @@ -168,16 +170,19 @@ namespace WixToolset.Core.Burn.Bundles } Directory.CreateDirectory(outputDirectory); - string tempCabPath = Path.Combine(tempDirectory, "attached.cab"); - - this.binaryReader.BaseStream.Seek(this.AttachedContainerAddress, SeekOrigin.Begin); - using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write)) + foreach (ContainerSlot cntnr in this.AttachedContainers) { - BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)this.AttachedContainerSize); - } + string tempCabPath = Path.GetTempFileName(); - var cabinet = new Cabinet(tempCabPath); - cabinet.Extract(outputDirectory); + this.binaryReader.BaseStream.Seek(cntnr.Address, SeekOrigin.Begin); + using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write)) + { + BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)cntnr.Size); + } + + var cabinet = new Cabinet(tempCabPath); + cabinet.Extract(outputDirectory); + } foreach (DictionaryEntry entry in this.attachedContainerPayloadNames) { diff --git a/src/wix/WixToolset.Core.Burn/Bundles/BurnWriter.cs b/src/wix/WixToolset.Core.Burn/Bundles/BurnWriter.cs index 2d16d11c..c6419ba9 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/BurnWriter.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/BurnWriter.cs @@ -93,7 +93,10 @@ namespace WixToolset.Core.Burn.Bundles this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_FORMAT, 1); // Hard-coded to CAB for now. this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_COUNT, 0); this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_UXSIZE, 0); - this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE, 0); + for (uint i = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0; i < BURN_SECTION_SIZE; i += sizeof(UInt32)) + { + this.WriteToBurnSectionOffset(i, 0); + } this.binaryWriter.BaseStream.Flush(); this.EngineSize = this.StubSize; @@ -127,6 +130,11 @@ namespace WixToolset.Core.Burn.Bundles UInt32 burnSectionCount = 0; UInt32 burnSectionOffsetSize = 0; + if (containerSize == 0) + { + return false; + } + switch (container) { case Container.UX: @@ -138,10 +146,19 @@ namespace WixToolset.Core.Burn.Bundles break; case Container.Attached: - burnSectionCount = 2; - burnSectionOffsetSize = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE; // TODO: verify that the size in the section data is 0 or the same size. - this.AttachedContainerSize = (uint)containerSize; + uint nextAddress = this.EngineSize; + foreach (ContainerSlot cntnr in this.AttachedContainers) + { + if (cntnr.Address >= nextAddress) + { + nextAddress = cntnr.Address + cntnr.Size; + } + } + + this.AttachedContainers.Add(new ContainerSlot(nextAddress, (uint)containerSize)); + burnSectionCount = 1 + (uint)this.AttachedContainers.Count; + burnSectionOffsetSize = BURN_SECTION_OFFSET_UXSIZE + ((uint)this.AttachedContainers.Count * 4); break; default: @@ -208,6 +225,12 @@ namespace WixToolset.Core.Burn.Bundles { return false; } + if (burnSectionOffsetSize > (BURN_SECTION_SIZE - sizeof(UInt32))) + { + this.invalidBundle = true; + this.Messaging.Write(BurnBackendErrors.TooManyAttachedContainers(BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT)); + return false; + } // Update the ".wixburn" section data this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_COUNT, burnSectionCount); diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs index f020ed84..9cddfc35 100644 --- a/src/wix/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs +++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs @@ -117,14 +117,6 @@ namespace WixToolset.Core.Burn.Bundles } } - foreach (var container in this.Containers.Where(c => !String.IsNullOrEmpty(c.WorkingPath) && c.Id.Id != BurnConstants.BurnUXContainerName)) - { - if (container.Type == ContainerType.Attached && attachedContainerIndex > 2 && container.Id.Id != BurnConstants.BurnDefaultAttachedContainerName) - { - this.Messaging.Write(BurnBackendErrors.MultipleAttachedContainersUnsupported(container.SourceLineNumbers, container.Id.Id)); - } - } - if (!this.Messaging.EncounteredError) { foreach (var container in this.Containers.Where(c => !String.IsNullOrEmpty(c.WorkingPath) && c.Id.Id != BurnConstants.BurnUXContainerName)) diff --git a/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs b/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs index 854c84e0..fd6eb093 100644 --- a/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs +++ b/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs @@ -36,11 +36,6 @@ namespace WixToolset.Core.Burn return Message(sourceLineNumbers, Ids.ExternalPayloadCollision2, "The location of the symbol related to the previous error."); } - public static Message MultipleAttachedContainersUnsupported(SourceLineNumber sourceLineNumbers, string containerId) - { - return Message(sourceLineNumbers, Ids.MultipleAttachedContainersUnsupported, "Bundles don't currently support having more than one attached container. Either remove all authored attached containers to use the default attached container, or make sure all compressed payloads are included in this Container '{0}'.", containerId); - } - public static Message PackageCachePayloadCollision(SourceLineNumber sourceLineNumbers, string payloadId, string payloadName, string packageId) { return Message(sourceLineNumbers, Ids.PackageCachePayloadCollision, "The Payload '{0}' has a duplicate Name '{1}' in package '{2}'. When caching the package, the file will get overwritten.", payloadId, payloadName, packageId); @@ -51,6 +46,16 @@ namespace WixToolset.Core.Burn return Message(sourceLineNumbers, Ids.PackageCachePayloadCollision2, "The location of the payload related to the previous error."); } + public static Message TooManyAttachedContainers(uint maxAllowed) + { + return Message(null, Ids.TooManyAttachedContainers, "The bundle has too many attached containers. The maximal attached container count is {0}", maxAllowed); + } + + public static Message IncompatibleWixBurnSection(string bundleExecutable, long bundleVersion) + { + return Message(null, Ids.IncompatibleWixBurnSection, "Unable to read bundle executable '{0}', because this bundle was created with a different version of WiX burn (.wixburn section version '{1}'). You must use the same version of Windows Installer XML in order to read this bundle.", bundleExecutable, bundleVersion); + } + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) { return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); @@ -66,7 +71,8 @@ namespace WixToolset.Core.Burn ExternalPayloadCollision2 = 8005, PackageCachePayloadCollision = 8006, PackageCachePayloadCollision2 = 8007, - MultipleAttachedContainersUnsupported = 8008, + TooManyAttachedContainers = 8008, + IncompatibleWixBurnSection = 8009, } // last available is 8499. 8500 is BurnBackendWarnings. } } diff --git a/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs b/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs index b466d0de..17030dd3 100644 --- a/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs @@ -29,17 +29,23 @@ namespace WixToolset.Core.Burn.Inscribe using (var reader = BurnReader.Open(this.Context.InputFilePath)) { FileSystem.CopyFile(this.Context.SignedEngineFile, tempFile, allowHardlink: false); - - // If there was an attached container on the original (unsigned) bundle, put it back. - if (reader.AttachedContainerSize > 0) + using (BurnWriter writer = BurnWriter.Open(this.Messaging, tempFile)) { - reader.Stream.Seek(reader.AttachedContainerAddress, SeekOrigin.Begin); + if (reader.Version != writer.Version) + { + this.Messaging.Write(BurnBackendErrors.IncompatibleWixBurnSection(this.Context.InputFilePath, reader.Version)); + } - using (var writer = BurnWriter.Open(this.Messaging, tempFile)) + writer.AttachedContainers.Clear(); + writer.RememberThenResetSignature(); + foreach (ContainerSlot cntnr in reader.AttachedContainers) { - writer.RememberThenResetSignature(); - writer.AppendContainer(reader.Stream, reader.AttachedContainerSize, BurnCommon.Container.Attached); - inscribed = true; + if (cntnr.Size > 0) + { + reader.Stream.Seek(cntnr.Address, SeekOrigin.Begin); + writer.AppendContainer(reader.Stream, cntnr.Size, BurnCommon.Container.Attached); + inscribed = true; + } } } } diff --git a/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs b/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs index 8c9f31e6..affe8c17 100644 --- a/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs +++ b/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs @@ -50,14 +50,12 @@ namespace WixToolset.Core.TestPackage /// /// Path to the bundle. /// Path to extract to. - /// Temp path for extraction. /// True if there was an attached container. - public static bool ExtractAttachedContainer(IMessaging messaging, string bundleFilePath, string destinationFolderPath, string tempFolderPath) + public static bool ExtractAttachedContainers(IMessaging messaging, string bundleFilePath, string destinationFolderPath) { - Directory.CreateDirectory(tempFolderPath); using (var burnReader = BurnReader.Open(messaging, bundleFilePath)) { - return burnReader.ExtractAttachedContainer(destinationFolderPath, tempFolderPath); + return burnReader.ExtractAttachedContainers(destinationFolderPath); } } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundleExtractionFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundleExtractionFixture.cs index b33b8891..0e056c29 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BundleExtractionFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundleExtractionFixture.cs @@ -26,7 +26,7 @@ namespace WixToolsetTest.CoreIntegration var pdbPath = Path.Combine(baseFolder, @"bin\test.wixpdb"); var extractFolderPath = Path.Combine(baseFolder, "extract"); var baFolderPath = Path.Combine(extractFolderPath, "UX"); - var attachedContainerFolderPath = Path.Combine(extractFolderPath, "AttachedContainer"); + var attachedContainerFolderPath = Path.Combine(extractFolderPath, "WixAttachedContainer"); // TODO: use WixRunner.Execute(string[]) to always go through the command line. var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider(); diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs index eee4c498..3491def9 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs @@ -125,8 +125,8 @@ namespace WixToolsetTest.CoreIntegration var msiPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='test.msi']"); var msiPayload = (XmlNode)Assert.Single(msiPayloads); - Assert.Equal("", - msiPayload.GetTestXml(new Dictionary>() { { "Payload", new List { "FileSize", "Hash" } } })); + Assert.Equal("", + msiPayload.GetTestXml(new Dictionary>() { { "Payload", new List { "FileSize", "Hash", "SourcePath" } } })); } var manifestResource = new Resource(ResourceType.Manifest, "#1", 1033); diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/ContainerFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/ContainerFixture.cs index 1de38f33..6e6f44be 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/ContainerFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/ContainerFixture.cs @@ -2,14 +2,12 @@ namespace WixToolsetTest.CoreIntegration { - using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; using WixBuildTools.TestSupport; - using WixToolset.Core; - using WixToolset.Core.Burn; + using WixToolset.Core.Burn.Bundles; using WixToolset.Core.TestPackage; using Xunit; @@ -51,11 +49,11 @@ namespace WixToolsetTest.CoreIntegration var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload"); Assert.Equal(4, payloads.Count); - var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash" } } }; - Assert.Equal(@"", payloads[0].GetTestXml(ignoreAttributes)); - Assert.Equal(@"", payloads[1].GetTestXml(ignoreAttributes)); - Assert.Equal(@"", payloads[2].GetTestXml(ignoreAttributes)); - Assert.Equal(@"", payloads[3].GetTestXml(ignoreAttributes)); + var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash", "SourcePath" } } }; + Assert.Equal(@"", payloads[0].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[1].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[2].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[3].GetTestXml(ignoreAttributes)); } } @@ -95,11 +93,11 @@ namespace WixToolsetTest.CoreIntegration var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload"); Assert.Equal(4, payloads.Count); - var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash" } } }; - Assert.Equal(@"", payloads[0].GetTestXml(ignoreAttributes)); - Assert.Equal(@"", payloads[1].GetTestXml(ignoreAttributes)); - Assert.Equal(@"", payloads[2].GetTestXml(ignoreAttributes)); - Assert.Equal(@"", payloads[3].GetTestXml(ignoreAttributes)); + var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash", "SourcePath" } } }; + Assert.Equal(@"", payloads[0].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[1].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[2].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[3].GetTestXml(ignoreAttributes)); } } @@ -205,20 +203,20 @@ namespace WixToolsetTest.CoreIntegration var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); extractResult.AssertSuccess(); - var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash" } } }; + var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash", "SourcePath" } } }; var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']") .Cast() .Select(e => e.GetTestXml(ignoreAttributes)) .ToArray(); WixAssert.CompareLineByLine(new string[] { - "", + "", }, payloads); } } [Fact] - public void MultipleAttachedContainersAreNotCurrentlySupported() + public void MultipleAttachedContainers() { var folder = TestData.Get(@"TestData"); @@ -230,6 +228,7 @@ namespace WixToolsetTest.CoreIntegration var bundlePath = Path.Combine(binFolder, "test.exe"); var baFolderPath = Path.Combine(baseFolder, "ba"); var extractFolderPath = Path.Combine(baseFolder, "extract"); + var tempFolderPath = Path.Combine(baseFolder, "temp"); this.BuildMsis(folder, intermediateFolder, binFolder); @@ -244,7 +243,19 @@ namespace WixToolsetTest.CoreIntegration "-o", bundlePath }); - Assert.Equal((int)BurnBackendErrors.Ids.MultipleAttachedContainersUnsupported, result.ExitCode); + Assert.Equal(0, result.ExitCode); + Assert.True(File.Exists(bundlePath)); + + Directory.CreateDirectory(tempFolderPath); + using (var burnReader = BurnReader.Open(null, bundlePath)) + { + // Extract the BA because that loads the payload target paths from the manifest + Assert.True(burnReader.ExtractUXContainer(baFolderPath, tempFolderPath)); + Assert.True(burnReader.ExtractAttachedContainers(extractFolderPath)); + } + + Assert.True(File.Exists(Path.Combine(extractFolderPath, "FirstX64", "FirstX64.msi")), "Expected extracted container to contain FirstX64.msi"); + Assert.True(File.Exists(Path.Combine(extractFolderPath, "WixAttachedContainer", "FirstX86.msi")), "Expected extracted container to contain FirstX86.msi"); } } @@ -286,14 +297,14 @@ namespace WixToolsetTest.CoreIntegration var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); extractResult.AssertSuccess(); - var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash" } } }; + var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash", "SourcePath" } } }; var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']") .Cast() .Select(e => e.GetTestXml(ignoreAttributes)) .ToArray(); WixAssert.CompareLineByLine(new string[] { - "", + "", }, payloads); } } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs index 6b2d8bfa..cbd1f32f 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs @@ -46,13 +46,14 @@ namespace WixToolsetTest.CoreIntegration var ignoreAttributesByElementName = new Dictionary> { { "ExePackage", new List { "CacheId", "InstallSize", "Size" } }, + { "Payload", new List { "SourcePath" } }, }; Assert.Equal(1, exePackageElements.Count); Assert.Equal("", exePackageElements[0].GetTestXml(ignoreAttributesByElementName)); var payloadElements = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='burn.exe']"); Assert.Equal(1, payloadElements.Count); - Assert.Equal("", payloadElements[0].GetTestXml()); + Assert.Equal("", payloadElements[0].GetTestXml(ignoreAttributesByElementName)); } } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs index cb35976a..1e6fd0e3 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs @@ -189,14 +189,15 @@ namespace WixToolsetTest.CoreIntegration .Cast() .Select(e => e.GetTestXml(ignoreAttributesByElementName)) .ToArray(); - WixAssert.CompareLineByLine(new string[] - { - "", - "", - "", - @"", - @"", - }, payloads); + + var ignoreAttributes = new Dictionary> { { "Payload", new List { "FileSize", "Hash"} } }; + var ignoreAttributesWithSrc = new Dictionary> { { "Payload", new List { "FileSize", "Hash", "SourcePath" } } }; + Assert.Equal(5, payloads.Length); + Assert.Equal(@"", payloads[0].GetTestXml(ignoreAttributesWithSrc)); + Assert.Equal(@"", payloads[1].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[2].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[3].GetTestXml(ignoreAttributes)); + Assert.Equal(@"", payloads[4].GetTestXml(ignoreAttributes)); var containers = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Container") .Cast() -- cgit v1.2.3-55-g6feb