diff options
author | Nir Bar <nir.bar@panel-sw.co.il> | 2021-10-06 14:11:17 +0300 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-11-02 17:44:50 -0500 |
commit | ce3aea757a01f0eea906fa610501a66735ef3a15 (patch) | |
tree | 2864f2edfbd3809e594caa910f410d7f136c00b5 | |
parent | 956c6bc4011618a05d4cff3992df687530a26e67 (diff) | |
download | wix-ce3aea757a01f0eea906fa610501a66735ef3a15.tar.gz wix-ce3aea757a01f0eea906fa610501a66735ef3a15.tar.bz2 wix-ce3aea757a01f0eea906fa610501a66735ef3a15.zip |
Support multiple attached containers
See https://github.com/wixtoolset/issues/issues/6144
16 files changed, 170 insertions, 100 deletions
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 @@ | |||
8 | // If these defaults ever change, be sure to update constants in burn\stub\StubSection.cpp as well. | 8 | // If these defaults ever change, be sure to update constants in burn\stub\StubSection.cpp as well. |
9 | #define BURN_SECTION_NAME ".wixburn" | 9 | #define BURN_SECTION_NAME ".wixburn" |
10 | #define BURN_SECTION_MAGIC 0x00f14300 | 10 | #define BURN_SECTION_MAGIC 0x00f14300 |
11 | #define BURN_SECTION_VERSION 0x00000002 | 11 | #define BURN_SECTION_VERSION 0x00000003 |
12 | #define MANIFEST_CABINET_TOKEN L"0" | 12 | #define MANIFEST_CABINET_TOKEN L"0" |
13 | 13 | ||
14 | // structs | 14 | // structs |
@@ -26,7 +26,7 @@ typedef struct _BURN_SECTION_HEADER | |||
26 | 26 | ||
27 | DWORD dwFormat; | 27 | DWORD dwFormat; |
28 | DWORD cContainers; | 28 | DWORD cContainers; |
29 | DWORD rgcbContainers[1]; | 29 | DWORD rgcbContainers[116]; |
30 | } BURN_SECTION_HEADER; | 30 | } BURN_SECTION_HEADER; |
31 | 31 | ||
32 | static HRESULT VerifySectionMatchesMemoryPEHeader( | 32 | 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 @@ | |||
7 | // If these defaults ever change, be sure to update constants in burn\engine\section.cpp as well. | 7 | // If these defaults ever change, be sure to update constants in burn\engine\section.cpp as well. |
8 | #pragma data_seg(push, ".wixburn") | 8 | #pragma data_seg(push, ".wixburn") |
9 | static DWORD dwMagic = 0x00f14300; | 9 | static DWORD dwMagic = 0x00f14300; |
10 | static DWORD dwVersion = 0x00000002; | 10 | static DWORD dwVersion = 0x00000003; |
11 | 11 | ||
12 | static GUID guidBundleId = { }; | 12 | static GUID guidBundleId = { }; |
13 | 13 | ||
@@ -18,6 +18,5 @@ static DWORD dwOriginalSignatureSize = 0; | |||
18 | 18 | ||
19 | static DWORD dwContainerFormat = 1; | 19 | static DWORD dwContainerFormat = 1; |
20 | static DWORD dwContainerCount = 0; | 20 | static DWORD dwContainerCount = 0; |
21 | static DWORD qwBootstrapperApplicationContainerSize = 0; | 21 | static DWORD qwAttachedContainerSizes[116]; // Including UX container |
22 | static DWORD qwAttachedContainerSize = 0; | ||
23 | #pragma data_seg(pop) | 22 | #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 | |||
296 | } | 296 | } |
297 | 297 | ||
298 | // Give the embedded payloads without an embedded id yet an embedded id. | 298 | // Give the embedded payloads without an embedded id yet an embedded id. |
299 | var payloadIndex = 0; | ||
300 | foreach (var payload in payloadSymbols.Values) | 299 | foreach (var payload in payloadSymbols.Values) |
301 | { | 300 | { |
302 | Debug.Assert(PackagingType.Unknown != payload.Packaging); | 301 | Debug.Assert(PackagingType.Unknown != payload.Packaging); |
303 | 302 | ||
304 | if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.EmbeddedId)) | 303 | if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.EmbeddedId)) |
305 | { | 304 | { |
306 | payload.EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnAuthoredContainerEmbeddedIdFormat, payloadIndex); | 305 | payload.EmbeddedId = Guid.NewGuid().ToString("N"); |
307 | ++payloadIndex; | ||
308 | } | 306 | } |
309 | } | 307 | } |
310 | } | 308 | } |
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 | |||
62 | public Intermediate Unbind(IUnbindContext context) | 62 | public Intermediate Unbind(IUnbindContext context) |
63 | { | 63 | { |
64 | var uxExtractPath = Path.Combine(context.ExportBasePath, "UX"); | 64 | var uxExtractPath = Path.Combine(context.ExportBasePath, "UX"); |
65 | var acExtractPath = Path.Combine(context.ExportBasePath, "AttachedContainer"); | ||
66 | var messaging = context.ServiceProvider.GetService<IMessaging>(); | 65 | var messaging = context.ServiceProvider.GetService<IMessaging>(); |
67 | 66 | ||
68 | using (var reader = BurnReader.Open(messaging, context.InputFilePath)) | 67 | using (var reader = BurnReader.Open(messaging, context.InputFilePath)) |
69 | { | 68 | { |
70 | reader.ExtractUXContainer(uxExtractPath, context.IntermediateFolder); | 69 | reader.ExtractUXContainer(uxExtractPath, context.IntermediateFolder); |
71 | reader.ExtractAttachedContainer(acExtractPath, context.IntermediateFolder); | 70 | reader.ExtractAttachedContainers(context.ExportBasePath); |
72 | } | 71 | } |
73 | 72 | ||
74 | return null; | 73 | 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 @@ | |||
3 | namespace WixToolset.Core.Burn.Bundles | 3 | namespace WixToolset.Core.Burn.Bundles |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | ||
6 | using System.Diagnostics; | 7 | using System.Diagnostics; |
7 | using System.IO; | 8 | using System.IO; |
8 | using WixToolset.Data; | 9 | using WixToolset.Data; |
@@ -19,7 +20,6 @@ namespace WixToolset.Core.Burn.Bundles | |||
19 | { | 20 | { |
20 | public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn"; | 21 | public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn"; |
21 | public const string BurnUXContainerEmbeddedIdFormat = "u{0}"; | 22 | public const string BurnUXContainerEmbeddedIdFormat = "u{0}"; |
22 | public const string BurnAuthoredContainerEmbeddedIdFormat = "a{0}"; | ||
23 | 23 | ||
24 | public const string BADataFileName = "BootstrapperApplicationData.xml"; | 24 | public const string BADataFileName = "BootstrapperApplicationData.xml"; |
25 | public const string BADataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData"; | 25 | public const string BADataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData"; |
@@ -67,7 +67,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
67 | // 40-43: container type (1 = CAB) | 67 | // 40-43: container type (1 = CAB) |
68 | // 44-47: container count | 68 | // 44-47: container count |
69 | // 48-51: byte count of manifest + UX container | 69 | // 48-51: byte count of manifest + UX container |
70 | // 52-55: byte count of attached container | 70 | // 52-512: byte count of attached containers (4 bytes for each container) |
71 | protected const UInt32 BURN_SECTION_OFFSET_MAGIC = 0; | 71 | protected const UInt32 BURN_SECTION_OFFSET_MAGIC = 0; |
72 | protected const UInt32 BURN_SECTION_OFFSET_VERSION = 4; | 72 | protected const UInt32 BURN_SECTION_OFFSET_VERSION = 4; |
73 | protected const UInt32 BURN_SECTION_OFFSET_BUNDLEGUID = 8; | 73 | protected const UInt32 BURN_SECTION_OFFSET_BUNDLEGUID = 8; |
@@ -78,11 +78,14 @@ namespace WixToolset.Core.Burn.Bundles | |||
78 | protected const UInt32 BURN_SECTION_OFFSET_FORMAT = 40; | 78 | protected const UInt32 BURN_SECTION_OFFSET_FORMAT = 40; |
79 | protected const UInt32 BURN_SECTION_OFFSET_COUNT = 44; | 79 | protected const UInt32 BURN_SECTION_OFFSET_COUNT = 44; |
80 | protected const UInt32 BURN_SECTION_OFFSET_UXSIZE = 48; | 80 | protected const UInt32 BURN_SECTION_OFFSET_UXSIZE = 48; |
81 | protected const UInt32 BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE = 52; | 81 | protected const UInt32 BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0 = 52; |
82 | protected const UInt32 BURN_SECTION_SIZE = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE + 4; // last field + sizeof(DWORD) | ||
83 | 82 | ||
84 | protected const UInt32 BURN_SECTION_MAGIC = 0x00f14300; | 83 | protected const UInt32 BURN_SECTION_MAGIC = 0x00f14300; |
85 | protected const UInt32 BURN_SECTION_VERSION = 0x00000002; | 84 | protected const UInt32 BURN_SECTION_VERSION = 0x00000003; |
85 | protected const UInt32 BURN_SECTION_COMPATIBLE_VERSION = 0x00000002; | ||
86 | protected const UInt32 BURN_SECTION_SIZE = 512; | ||
87 | protected const UInt32 BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT = (BURN_SECTION_SIZE - BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0) / sizeof(UInt32); | ||
88 | |||
86 | protected string fileExe; | 89 | protected string fileExe; |
87 | protected UInt32 peOffset = UInt32.MaxValue; | 90 | protected UInt32 peOffset = UInt32.MaxValue; |
88 | protected UInt16 sections = UInt16.MaxValue; | 91 | protected UInt16 sections = UInt16.MaxValue; |
@@ -112,6 +115,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
112 | { | 115 | { |
113 | this.Messaging = messaging; | 116 | this.Messaging = messaging; |
114 | this.fileExe = fileExe; | 117 | this.fileExe = fileExe; |
118 | this.AttachedContainers = new List<ContainerSlot>(); | ||
115 | } | 119 | } |
116 | 120 | ||
117 | public UInt32 Checksum { get; protected set; } | 121 | public UInt32 Checksum { get; protected set; } |
@@ -126,8 +130,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
126 | public UInt32 ContainerCount { get; protected set; } | 130 | public UInt32 ContainerCount { get; protected set; } |
127 | public UInt32 UXAddress { get; protected set; } | 131 | public UInt32 UXAddress { get; protected set; } |
128 | public UInt32 UXSize { get; protected set; } | 132 | public UInt32 UXSize { get; protected set; } |
129 | public UInt32 AttachedContainerAddress { get; protected set; } | 133 | public List<ContainerSlot> AttachedContainers { get; protected set; } |
130 | public UInt32 AttachedContainerSize { get; protected set; } | ||
131 | 134 | ||
132 | protected IMessaging Messaging { get; } | 135 | protected IMessaging Messaging { get; } |
133 | 136 | ||
@@ -177,7 +180,9 @@ namespace WixToolset.Core.Burn.Bundles | |||
177 | } | 180 | } |
178 | 181 | ||
179 | reader.BaseStream.Seek(this.wixburnDataOffset, SeekOrigin.Begin); | 182 | reader.BaseStream.Seek(this.wixburnDataOffset, SeekOrigin.Begin); |
180 | byte[] bytes = reader.ReadBytes((int)BURN_SECTION_SIZE); | 183 | List<byte> manifest = new List<byte>(); |
184 | manifest.AddRange(reader.ReadBytes((int)BURN_SECTION_SIZE)); | ||
185 | byte[] bytes = manifest.ToArray(); | ||
181 | UInt32 uint32 = 0; | 186 | UInt32 uint32 = 0; |
182 | 187 | ||
183 | uint32 = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_MAGIC); | 188 | uint32 = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_MAGIC); |
@@ -188,9 +193,9 @@ namespace WixToolset.Core.Burn.Bundles | |||
188 | } | 193 | } |
189 | 194 | ||
190 | this.Version = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_VERSION); | 195 | this.Version = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_VERSION); |
191 | if (BURN_SECTION_VERSION != this.Version) | 196 | if ((BURN_SECTION_VERSION != this.Version) && (BURN_SECTION_COMPATIBLE_VERSION != this.Version)) |
192 | { | 197 | { |
193 | this.Messaging.Write(ErrorMessages.BundleTooNew(this.fileExe, this.Version)); | 198 | this.Messaging.Write(BurnBackendErrors.IncompatibleWixBurnSection(this.fileExe, this.Version)); |
194 | return false; | 199 | return false; |
195 | } | 200 | } |
196 | 201 | ||
@@ -207,6 +212,11 @@ namespace WixToolset.Core.Burn.Bundles | |||
207 | this.OriginalSignatureSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALSIGNATURESIZE); | 212 | this.OriginalSignatureSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALSIGNATURESIZE); |
208 | 213 | ||
209 | this.ContainerCount = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_COUNT); | 214 | this.ContainerCount = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_COUNT); |
215 | if (BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT < this.ContainerCount) | ||
216 | { | ||
217 | this.Messaging.Write(ErrorMessages.InvalidBundle(this.fileExe)); | ||
218 | return false; | ||
219 | } | ||
210 | this.UXAddress = this.StubSize; | 220 | this.UXAddress = this.StubSize; |
211 | this.UXSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_UXSIZE); | 221 | this.UXSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_UXSIZE); |
212 | 222 | ||
@@ -224,8 +234,18 @@ namespace WixToolset.Core.Burn.Bundles | |||
224 | this.EngineSize = this.StubSize + this.UXSize; | 234 | this.EngineSize = this.StubSize + this.UXSize; |
225 | } | 235 | } |
226 | 236 | ||
227 | this.AttachedContainerAddress = this.ContainerCount > 1 ? this.EngineSize : 0; | 237 | this.AttachedContainers.Clear(); |
228 | this.AttachedContainerSize = this.ContainerCount > 1 ? BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE) : 0; | 238 | uint nextAddress = this.EngineSize; |
239 | if (this.ContainerCount > 1) | ||
240 | { | ||
241 | for (uint i = 0; i < (this.ContainerCount - 1 /* Excluding UX */); ++i) | ||
242 | { | ||
243 | uint sizeOffset = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0 + (i * 4); | ||
244 | uint size = BurnCommon.ReadUInt32(bytes, sizeOffset); | ||
245 | this.AttachedContainers.Add(new ContainerSlot(nextAddress, size)); | ||
246 | nextAddress += size; | ||
247 | } | ||
248 | } | ||
229 | 249 | ||
230 | return true; | 250 | return true; |
231 | } | 251 | } |
@@ -268,8 +288,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
268 | return false; | 288 | return false; |
269 | } | 289 | } |
270 | 290 | ||
271 | // we need 56 bytes for the manifest header, which is always going to fit in | 291 | // We need 512 bytes for the manifest header |
272 | // the smallest alignment (512 bytes), but just to be paranoid... | ||
273 | if (BURN_SECTION_SIZE > BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_SIZEOFRAWDATA)) | 292 | if (BURN_SECTION_SIZE > BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_SIZEOFRAWDATA)) |
274 | { | 293 | { |
275 | this.Messaging.Write(ErrorMessages.StubWixburnSectionTooSmall(this.fileExe)); | 294 | this.Messaging.Write(ErrorMessages.StubWixburnSectionTooSmall(this.fileExe)); |
@@ -382,4 +401,16 @@ namespace WixToolset.Core.Burn.Bundles | |||
382 | return BurnCommon.ReadUInt32(bytes, offset) + ((UInt64)BurnCommon.ReadUInt32(bytes, offset + 4) << 32); | 401 | return BurnCommon.ReadUInt32(bytes, offset) + ((UInt64)BurnCommon.ReadUInt32(bytes, offset + 4) << 32); |
383 | } | 402 | } |
384 | } | 403 | } |
404 | |||
405 | internal struct ContainerSlot | ||
406 | { | ||
407 | public ContainerSlot(uint address, uint size) : this() | ||
408 | { | ||
409 | this.Address = address; | ||
410 | this.Size = size; | ||
411 | } | ||
412 | |||
413 | public uint Address { get; set; } | ||
414 | public uint Size { get; set; } | ||
415 | } | ||
385 | } | 416 | } |
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 | |||
126 | 126 | ||
127 | foreach (XmlNode payload in payloads) | 127 | foreach (XmlNode payload in payloads) |
128 | { | 128 | { |
129 | XmlNode sourcePathNode = payload.Attributes.GetNamedItem("SourcePath"); | ||
130 | XmlNode filePathNode = payload.Attributes.GetNamedItem("FilePath"); | ||
131 | XmlNode packagingNode = payload.Attributes.GetNamedItem("Packaging"); | 129 | XmlNode packagingNode = payload.Attributes.GetNamedItem("Packaging"); |
132 | 130 | ||
133 | string sourcePath = sourcePathNode.Value; | ||
134 | string destinationPath = filePathNode.Value; | ||
135 | string packaging = packagingNode.Value; | 131 | string packaging = packagingNode.Value; |
136 | 132 | ||
137 | if (packaging.Equals("embedded", StringComparison.OrdinalIgnoreCase)) | 133 | if (packaging.Equals("embedded", StringComparison.OrdinalIgnoreCase)) |
138 | { | 134 | { |
135 | XmlNode sourcePathNode = payload.Attributes.GetNamedItem("SourcePath"); | ||
136 | XmlNode filePathNode = payload.Attributes.GetNamedItem("FilePath"); | ||
137 | XmlNode containerNode = payload.Attributes.GetNamedItem("Container"); | ||
138 | |||
139 | string sourcePath = sourcePathNode.Value; | ||
140 | string destinationPath = Path.Combine(containerNode.Value, filePathNode.Value); | ||
141 | |||
139 | this.attachedContainerPayloadNames.Add(new DictionaryEntry(sourcePath, destinationPath)); | 142 | this.attachedContainerPayloadNames.Add(new DictionaryEntry(sourcePath, destinationPath)); |
140 | } | 143 | } |
141 | } | 144 | } |
@@ -152,12 +155,11 @@ namespace WixToolset.Core.Burn.Bundles | |||
152 | /// Gets the attached container from the exe and extracts its contents to the output directory. | 155 | /// Gets the attached container from the exe and extracts its contents to the output directory. |
153 | /// </summary> | 156 | /// </summary> |
154 | /// <param name="outputDirectory">Directory to write extracted files to.</param> | 157 | /// <param name="outputDirectory">Directory to write extracted files to.</param> |
155 | /// <param name="tempDirectory">Scratch directory.</param> | ||
156 | /// <returns>True if successful, false otherwise</returns> | 158 | /// <returns>True if successful, false otherwise</returns> |
157 | public bool ExtractAttachedContainer(string outputDirectory, string tempDirectory) | 159 | public bool ExtractAttachedContainers(string outputDirectory) |
158 | { | 160 | { |
159 | // No attached container to extract | 161 | // No attached container to extract |
160 | if (this.AttachedContainerAddress == 0 || this.AttachedContainerSize == 0) | 162 | if (this.AttachedContainers.Count == 0) |
161 | { | 163 | { |
162 | return false; | 164 | return false; |
163 | } | 165 | } |
@@ -168,16 +170,19 @@ namespace WixToolset.Core.Burn.Bundles | |||
168 | } | 170 | } |
169 | 171 | ||
170 | Directory.CreateDirectory(outputDirectory); | 172 | Directory.CreateDirectory(outputDirectory); |
171 | string tempCabPath = Path.Combine(tempDirectory, "attached.cab"); | 173 | foreach (ContainerSlot cntnr in this.AttachedContainers) |
172 | |||
173 | this.binaryReader.BaseStream.Seek(this.AttachedContainerAddress, SeekOrigin.Begin); | ||
174 | using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write)) | ||
175 | { | 174 | { |
176 | BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)this.AttachedContainerSize); | 175 | string tempCabPath = Path.GetTempFileName(); |
177 | } | ||
178 | 176 | ||
179 | var cabinet = new Cabinet(tempCabPath); | 177 | this.binaryReader.BaseStream.Seek(cntnr.Address, SeekOrigin.Begin); |
180 | cabinet.Extract(outputDirectory); | 178 | using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write)) |
179 | { | ||
180 | BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)cntnr.Size); | ||
181 | } | ||
182 | |||
183 | var cabinet = new Cabinet(tempCabPath); | ||
184 | cabinet.Extract(outputDirectory); | ||
185 | } | ||
181 | 186 | ||
182 | foreach (DictionaryEntry entry in this.attachedContainerPayloadNames) | 187 | foreach (DictionaryEntry entry in this.attachedContainerPayloadNames) |
183 | { | 188 | { |
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 | |||
93 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_FORMAT, 1); // Hard-coded to CAB for now. | 93 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_FORMAT, 1); // Hard-coded to CAB for now. |
94 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_COUNT, 0); | 94 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_COUNT, 0); |
95 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_UXSIZE, 0); | 95 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_UXSIZE, 0); |
96 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE, 0); | 96 | for (uint i = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0; i < BURN_SECTION_SIZE; i += sizeof(UInt32)) |
97 | { | ||
98 | this.WriteToBurnSectionOffset(i, 0); | ||
99 | } | ||
97 | this.binaryWriter.BaseStream.Flush(); | 100 | this.binaryWriter.BaseStream.Flush(); |
98 | 101 | ||
99 | this.EngineSize = this.StubSize; | 102 | this.EngineSize = this.StubSize; |
@@ -127,6 +130,11 @@ namespace WixToolset.Core.Burn.Bundles | |||
127 | UInt32 burnSectionCount = 0; | 130 | UInt32 burnSectionCount = 0; |
128 | UInt32 burnSectionOffsetSize = 0; | 131 | UInt32 burnSectionOffsetSize = 0; |
129 | 132 | ||
133 | if (containerSize == 0) | ||
134 | { | ||
135 | return false; | ||
136 | } | ||
137 | |||
130 | switch (container) | 138 | switch (container) |
131 | { | 139 | { |
132 | case Container.UX: | 140 | case Container.UX: |
@@ -138,10 +146,19 @@ namespace WixToolset.Core.Burn.Bundles | |||
138 | break; | 146 | break; |
139 | 147 | ||
140 | case Container.Attached: | 148 | case Container.Attached: |
141 | burnSectionCount = 2; | ||
142 | burnSectionOffsetSize = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE; | ||
143 | // TODO: verify that the size in the section data is 0 or the same size. | 149 | // TODO: verify that the size in the section data is 0 or the same size. |
144 | this.AttachedContainerSize = (uint)containerSize; | 150 | uint nextAddress = this.EngineSize; |
151 | foreach (ContainerSlot cntnr in this.AttachedContainers) | ||
152 | { | ||
153 | if (cntnr.Address >= nextAddress) | ||
154 | { | ||
155 | nextAddress = cntnr.Address + cntnr.Size; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | this.AttachedContainers.Add(new ContainerSlot(nextAddress, (uint)containerSize)); | ||
160 | burnSectionCount = 1 + (uint)this.AttachedContainers.Count; | ||
161 | burnSectionOffsetSize = BURN_SECTION_OFFSET_UXSIZE + ((uint)this.AttachedContainers.Count * 4); | ||
145 | break; | 162 | break; |
146 | 163 | ||
147 | default: | 164 | default: |
@@ -208,6 +225,12 @@ namespace WixToolset.Core.Burn.Bundles | |||
208 | { | 225 | { |
209 | return false; | 226 | return false; |
210 | } | 227 | } |
228 | if (burnSectionOffsetSize > (BURN_SECTION_SIZE - sizeof(UInt32))) | ||
229 | { | ||
230 | this.invalidBundle = true; | ||
231 | this.Messaging.Write(BurnBackendErrors.TooManyAttachedContainers(BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT)); | ||
232 | return false; | ||
233 | } | ||
211 | 234 | ||
212 | // Update the ".wixburn" section data | 235 | // Update the ".wixburn" section data |
213 | this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_COUNT, burnSectionCount); | 236 | 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 | |||
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | foreach (var container in this.Containers.Where(c => !String.IsNullOrEmpty(c.WorkingPath) && c.Id.Id != BurnConstants.BurnUXContainerName)) | ||
121 | { | ||
122 | if (container.Type == ContainerType.Attached && attachedContainerIndex > 2 && container.Id.Id != BurnConstants.BurnDefaultAttachedContainerName) | ||
123 | { | ||
124 | this.Messaging.Write(BurnBackendErrors.MultipleAttachedContainersUnsupported(container.SourceLineNumbers, container.Id.Id)); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | if (!this.Messaging.EncounteredError) | 120 | if (!this.Messaging.EncounteredError) |
129 | { | 121 | { |
130 | foreach (var container in this.Containers.Where(c => !String.IsNullOrEmpty(c.WorkingPath) && c.Id.Id != BurnConstants.BurnUXContainerName)) | 122 | 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 | |||
36 | return Message(sourceLineNumbers, Ids.ExternalPayloadCollision2, "The location of the symbol related to the previous error."); | 36 | return Message(sourceLineNumbers, Ids.ExternalPayloadCollision2, "The location of the symbol related to the previous error."); |
37 | } | 37 | } |
38 | 38 | ||
39 | public static Message MultipleAttachedContainersUnsupported(SourceLineNumber sourceLineNumbers, string containerId) | ||
40 | { | ||
41 | 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); | ||
42 | } | ||
43 | |||
44 | public static Message PackageCachePayloadCollision(SourceLineNumber sourceLineNumbers, string payloadId, string payloadName, string packageId) | 39 | public static Message PackageCachePayloadCollision(SourceLineNumber sourceLineNumbers, string payloadId, string payloadName, string packageId) |
45 | { | 40 | { |
46 | 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); | 41 | 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 | |||
51 | return Message(sourceLineNumbers, Ids.PackageCachePayloadCollision2, "The location of the payload related to the previous error."); | 46 | return Message(sourceLineNumbers, Ids.PackageCachePayloadCollision2, "The location of the payload related to the previous error."); |
52 | } | 47 | } |
53 | 48 | ||
49 | public static Message TooManyAttachedContainers(uint maxAllowed) | ||
50 | { | ||
51 | return Message(null, Ids.TooManyAttachedContainers, "The bundle has too many attached containers. The maximal attached container count is {0}", maxAllowed); | ||
52 | } | ||
53 | |||
54 | public static Message IncompatibleWixBurnSection(string bundleExecutable, long bundleVersion) | ||
55 | { | ||
56 | 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); | ||
57 | } | ||
58 | |||
54 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) | 59 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) |
55 | { | 60 | { |
56 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); | 61 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); |
@@ -66,7 +71,8 @@ namespace WixToolset.Core.Burn | |||
66 | ExternalPayloadCollision2 = 8005, | 71 | ExternalPayloadCollision2 = 8005, |
67 | PackageCachePayloadCollision = 8006, | 72 | PackageCachePayloadCollision = 8006, |
68 | PackageCachePayloadCollision2 = 8007, | 73 | PackageCachePayloadCollision2 = 8007, |
69 | MultipleAttachedContainersUnsupported = 8008, | 74 | TooManyAttachedContainers = 8008, |
75 | IncompatibleWixBurnSection = 8009, | ||
70 | } // last available is 8499. 8500 is BurnBackendWarnings. | 76 | } // last available is 8499. 8500 is BurnBackendWarnings. |
71 | } | 77 | } |
72 | } | 78 | } |
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 | |||
29 | using (var reader = BurnReader.Open(this.Context.InputFilePath)) | 29 | using (var reader = BurnReader.Open(this.Context.InputFilePath)) |
30 | { | 30 | { |
31 | FileSystem.CopyFile(this.Context.SignedEngineFile, tempFile, allowHardlink: false); | 31 | FileSystem.CopyFile(this.Context.SignedEngineFile, tempFile, allowHardlink: false); |
32 | 32 | using (BurnWriter writer = BurnWriter.Open(this.Messaging, tempFile)) | |
33 | // If there was an attached container on the original (unsigned) bundle, put it back. | ||
34 | if (reader.AttachedContainerSize > 0) | ||
35 | { | 33 | { |
36 | reader.Stream.Seek(reader.AttachedContainerAddress, SeekOrigin.Begin); | 34 | if (reader.Version != writer.Version) |
35 | { | ||
36 | this.Messaging.Write(BurnBackendErrors.IncompatibleWixBurnSection(this.Context.InputFilePath, reader.Version)); | ||
37 | } | ||
37 | 38 | ||
38 | using (var writer = BurnWriter.Open(this.Messaging, tempFile)) | 39 | writer.AttachedContainers.Clear(); |
40 | writer.RememberThenResetSignature(); | ||
41 | foreach (ContainerSlot cntnr in reader.AttachedContainers) | ||
39 | { | 42 | { |
40 | writer.RememberThenResetSignature(); | 43 | if (cntnr.Size > 0) |
41 | writer.AppendContainer(reader.Stream, reader.AttachedContainerSize, BurnCommon.Container.Attached); | 44 | { |
42 | inscribed = true; | 45 | reader.Stream.Seek(cntnr.Address, SeekOrigin.Begin); |
46 | writer.AppendContainer(reader.Stream, cntnr.Size, BurnCommon.Container.Attached); | ||
47 | inscribed = true; | ||
48 | } | ||
43 | } | 49 | } |
44 | } | 50 | } |
45 | } | 51 | } |
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 | |||
50 | /// <param name="messaging"></param> | 50 | /// <param name="messaging"></param> |
51 | /// <param name="bundleFilePath">Path to the bundle.</param> | 51 | /// <param name="bundleFilePath">Path to the bundle.</param> |
52 | /// <param name="destinationFolderPath">Path to extract to.</param> | 52 | /// <param name="destinationFolderPath">Path to extract to.</param> |
53 | /// <param name="tempFolderPath">Temp path for extraction.</param> | ||
54 | /// <returns>True if there was an attached container.</returns> | 53 | /// <returns>True if there was an attached container.</returns> |
55 | public static bool ExtractAttachedContainer(IMessaging messaging, string bundleFilePath, string destinationFolderPath, string tempFolderPath) | 54 | public static bool ExtractAttachedContainers(IMessaging messaging, string bundleFilePath, string destinationFolderPath) |
56 | { | 55 | { |
57 | Directory.CreateDirectory(tempFolderPath); | ||
58 | using (var burnReader = BurnReader.Open(messaging, bundleFilePath)) | 56 | using (var burnReader = BurnReader.Open(messaging, bundleFilePath)) |
59 | { | 57 | { |
60 | return burnReader.ExtractAttachedContainer(destinationFolderPath, tempFolderPath); | 58 | return burnReader.ExtractAttachedContainers(destinationFolderPath); |
61 | } | 59 | } |
62 | } | 60 | } |
63 | 61 | ||
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 | |||
26 | var pdbPath = Path.Combine(baseFolder, @"bin\test.wixpdb"); | 26 | var pdbPath = Path.Combine(baseFolder, @"bin\test.wixpdb"); |
27 | var extractFolderPath = Path.Combine(baseFolder, "extract"); | 27 | var extractFolderPath = Path.Combine(baseFolder, "extract"); |
28 | var baFolderPath = Path.Combine(extractFolderPath, "UX"); | 28 | var baFolderPath = Path.Combine(extractFolderPath, "UX"); |
29 | var attachedContainerFolderPath = Path.Combine(extractFolderPath, "AttachedContainer"); | 29 | var attachedContainerFolderPath = Path.Combine(extractFolderPath, "WixAttachedContainer"); |
30 | 30 | ||
31 | // TODO: use WixRunner.Execute(string[]) to always go through the command line. | 31 | // TODO: use WixRunner.Execute(string[]) to always go through the command line. |
32 | var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider(); | 32 | 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 | |||
125 | 125 | ||
126 | var msiPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='test.msi']"); | 126 | var msiPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='test.msi']"); |
127 | var msiPayload = (XmlNode)Assert.Single(msiPayloads); | 127 | var msiPayload = (XmlNode)Assert.Single(msiPayloads); |
128 | Assert.Equal("<Payload Id='test.msi' FilePath='test.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />", | 128 | Assert.Equal("<Payload Id='test.msi' FilePath='test.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='WixAttachedContainer' />", |
129 | msiPayload.GetTestXml(new Dictionary<string, List<string>>() { { "Payload", new List<string> { "FileSize", "Hash" } } })); | 129 | msiPayload.GetTestXml(new Dictionary<string, List<string>>() { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } })); |
130 | } | 130 | } |
131 | 131 | ||
132 | var manifestResource = new Resource(ResourceType.Manifest, "#1", 1033); | 132 | 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 @@ | |||
2 | 2 | ||
3 | namespace WixToolsetTest.CoreIntegration | 3 | namespace WixToolsetTest.CoreIntegration |
4 | { | 4 | { |
5 | using System; | ||
6 | using System.Collections.Generic; | 5 | using System.Collections.Generic; |
7 | using System.IO; | 6 | using System.IO; |
8 | using System.Linq; | 7 | using System.Linq; |
9 | using System.Xml; | 8 | using System.Xml; |
10 | using WixBuildTools.TestSupport; | 9 | using WixBuildTools.TestSupport; |
11 | using WixToolset.Core; | 10 | using WixToolset.Core.Burn.Bundles; |
12 | using WixToolset.Core.Burn; | ||
13 | using WixToolset.Core.TestPackage; | 11 | using WixToolset.Core.TestPackage; |
14 | using Xunit; | 12 | using Xunit; |
15 | 13 | ||
@@ -51,11 +49,11 @@ namespace WixToolsetTest.CoreIntegration | |||
51 | 49 | ||
52 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload"); | 50 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload"); |
53 | Assert.Equal(4, payloads.Count); | 51 | Assert.Equal(4, payloads.Count); |
54 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } }; | 52 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } }; |
55 | Assert.Equal(@"<Payload Id='FirstX64' FilePath='FirstX64\FirstX64.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX64/FirstX64/FirstX64.msi' Packaging='embedded' SourcePath='a0' Container='BundlePackages' />", payloads[0].GetTestXml(ignoreAttributes)); | 53 | Assert.Equal(@"<Payload Id='FirstX64' FilePath='FirstX64\FirstX64.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX64/FirstX64/FirstX64.msi' Packaging='embedded' SourcePath='*' Container='BundlePackages' />", payloads[0].GetTestXml(ignoreAttributes)); |
56 | Assert.Equal(@"<Payload Id='FirstX86.msi' FilePath='FirstX86\FirstX86.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX86.msi/FirstX86/FirstX86.msi' Packaging='embedded' SourcePath='a1' Container='BundlePackages' />", payloads[1].GetTestXml(ignoreAttributes)); | 54 | Assert.Equal(@"<Payload Id='FirstX86.msi' FilePath='FirstX86\FirstX86.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX86.msi/FirstX86/FirstX86.msi' Packaging='embedded' SourcePath='*' Container='BundlePackages' />", payloads[1].GetTestXml(ignoreAttributes)); |
57 | Assert.Equal(@"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='FirstX86\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX86.msi/fk1m38Cf9RZ2Bx_ipinRY6BftelU/FirstX86/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='a2' Container='BundlePackages' />", payloads[2].GetTestXml(ignoreAttributes)); | 55 | Assert.Equal(@"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='FirstX86\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX86.msi/fk1m38Cf9RZ2Bx_ipinRY6BftelU/FirstX86/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='*' Container='BundlePackages' />", payloads[2].GetTestXml(ignoreAttributes)); |
58 | Assert.Equal(@"<Payload Id='ff2L_N_DLQ.nSUi.l8LxG14gd2V4' FilePath='FirstX64\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX64/ff2L_N_DLQ.nSUi.l8LxG14gd2V4/FirstX64/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='a3' Container='BundlePackages' />", payloads[3].GetTestXml(ignoreAttributes)); | 56 | Assert.Equal(@"<Payload Id='ff2L_N_DLQ.nSUi.l8LxG14gd2V4' FilePath='FirstX64\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX64/ff2L_N_DLQ.nSUi.l8LxG14gd2V4/FirstX64/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='*' Container='BundlePackages' />", payloads[3].GetTestXml(ignoreAttributes)); |
59 | } | 57 | } |
60 | } | 58 | } |
61 | 59 | ||
@@ -95,11 +93,11 @@ namespace WixToolsetTest.CoreIntegration | |||
95 | 93 | ||
96 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload"); | 94 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload"); |
97 | Assert.Equal(4, payloads.Count); | 95 | Assert.Equal(4, payloads.Count); |
98 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } }; | 96 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } }; |
99 | Assert.Equal(@"<Payload Id='FirstX86.msi' FilePath='FirstX86.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />", payloads[0].GetTestXml(ignoreAttributes)); | 97 | Assert.Equal(@"<Payload Id='FirstX86.msi' FilePath='FirstX86.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='WixAttachedContainer' />", payloads[0].GetTestXml(ignoreAttributes)); |
100 | Assert.Equal(@"<Payload Id='FirstX64.msi' FilePath='FirstX64.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a1' Container='FirstX64' />", payloads[1].GetTestXml(ignoreAttributes)); | 98 | Assert.Equal(@"<Payload Id='FirstX64.msi' FilePath='FirstX64.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='FirstX64' />", payloads[1].GetTestXml(ignoreAttributes)); |
101 | Assert.Equal(@"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='WixAttachedContainer' />", payloads[2].GetTestXml(ignoreAttributes)); | 99 | Assert.Equal(@"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='WixAttachedContainer' />", payloads[2].GetTestXml(ignoreAttributes)); |
102 | Assert.Equal(@"<Payload Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a3' Container='FirstX64' />", payloads[3].GetTestXml(ignoreAttributes)); | 100 | Assert.Equal(@"<Payload Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='FirstX64' />", payloads[3].GetTestXml(ignoreAttributes)); |
103 | } | 101 | } |
104 | } | 102 | } |
105 | 103 | ||
@@ -205,20 +203,20 @@ namespace WixToolsetTest.CoreIntegration | |||
205 | var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); | 203 | var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); |
206 | extractResult.AssertSuccess(); | 204 | extractResult.AssertSuccess(); |
207 | 205 | ||
208 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } }; | 206 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } }; |
209 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']") | 207 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']") |
210 | .Cast<XmlElement>() | 208 | .Cast<XmlElement>() |
211 | .Select(e => e.GetTestXml(ignoreAttributes)) | 209 | .Select(e => e.GetTestXml(ignoreAttributes)) |
212 | .ToArray(); | 210 | .ToArray(); |
213 | WixAssert.CompareLineByLine(new string[] | 211 | WixAssert.CompareLineByLine(new string[] |
214 | { | 212 | { |
215 | "<Payload Id='SharedPayload' FilePath='LayoutPayloadInContainer.wxs' FileSize='*' Hash='*' LayoutOnly='yes' Packaging='embedded' SourcePath='a1' Container='FirstX64' />", | 213 | "<Payload Id='SharedPayload' FilePath='LayoutPayloadInContainer.wxs' FileSize='*' Hash='*' LayoutOnly='yes' Packaging='embedded' SourcePath='*' Container='FirstX64' />", |
216 | }, payloads); | 214 | }, payloads); |
217 | } | 215 | } |
218 | } | 216 | } |
219 | 217 | ||
220 | [Fact] | 218 | [Fact] |
221 | public void MultipleAttachedContainersAreNotCurrentlySupported() | 219 | public void MultipleAttachedContainers() |
222 | { | 220 | { |
223 | var folder = TestData.Get(@"TestData"); | 221 | var folder = TestData.Get(@"TestData"); |
224 | 222 | ||
@@ -230,6 +228,7 @@ namespace WixToolsetTest.CoreIntegration | |||
230 | var bundlePath = Path.Combine(binFolder, "test.exe"); | 228 | var bundlePath = Path.Combine(binFolder, "test.exe"); |
231 | var baFolderPath = Path.Combine(baseFolder, "ba"); | 229 | var baFolderPath = Path.Combine(baseFolder, "ba"); |
232 | var extractFolderPath = Path.Combine(baseFolder, "extract"); | 230 | var extractFolderPath = Path.Combine(baseFolder, "extract"); |
231 | var tempFolderPath = Path.Combine(baseFolder, "temp"); | ||
233 | 232 | ||
234 | this.BuildMsis(folder, intermediateFolder, binFolder); | 233 | this.BuildMsis(folder, intermediateFolder, binFolder); |
235 | 234 | ||
@@ -244,7 +243,19 @@ namespace WixToolsetTest.CoreIntegration | |||
244 | "-o", bundlePath | 243 | "-o", bundlePath |
245 | }); | 244 | }); |
246 | 245 | ||
247 | Assert.Equal((int)BurnBackendErrors.Ids.MultipleAttachedContainersUnsupported, result.ExitCode); | 246 | Assert.Equal(0, result.ExitCode); |
247 | Assert.True(File.Exists(bundlePath)); | ||
248 | |||
249 | Directory.CreateDirectory(tempFolderPath); | ||
250 | using (var burnReader = BurnReader.Open(null, bundlePath)) | ||
251 | { | ||
252 | // Extract the BA because that loads the payload target paths from the manifest | ||
253 | Assert.True(burnReader.ExtractUXContainer(baFolderPath, tempFolderPath)); | ||
254 | Assert.True(burnReader.ExtractAttachedContainers(extractFolderPath)); | ||
255 | } | ||
256 | |||
257 | Assert.True(File.Exists(Path.Combine(extractFolderPath, "FirstX64", "FirstX64.msi")), "Expected extracted container to contain FirstX64.msi"); | ||
258 | Assert.True(File.Exists(Path.Combine(extractFolderPath, "WixAttachedContainer", "FirstX86.msi")), "Expected extracted container to contain FirstX86.msi"); | ||
248 | } | 259 | } |
249 | } | 260 | } |
250 | 261 | ||
@@ -286,14 +297,14 @@ namespace WixToolsetTest.CoreIntegration | |||
286 | var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); | 297 | var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); |
287 | extractResult.AssertSuccess(); | 298 | extractResult.AssertSuccess(); |
288 | 299 | ||
289 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } }; | 300 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } }; |
290 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']") | 301 | var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']") |
291 | .Cast<XmlElement>() | 302 | .Cast<XmlElement>() |
292 | .Select(e => e.GetTestXml(ignoreAttributes)) | 303 | .Select(e => e.GetTestXml(ignoreAttributes)) |
293 | .ToArray(); | 304 | .ToArray(); |
294 | WixAssert.CompareLineByLine(new string[] | 305 | WixAssert.CompareLineByLine(new string[] |
295 | { | 306 | { |
296 | "<Payload Id='SharedPayload' FilePath='PayloadInMultipleContainers.wxs' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='FirstX86' />", | 307 | "<Payload Id='SharedPayload' FilePath='PayloadInMultipleContainers.wxs' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='FirstX86' />", |
297 | }, payloads); | 308 | }, payloads); |
298 | } | 309 | } |
299 | } | 310 | } |
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 | |||
46 | var ignoreAttributesByElementName = new Dictionary<string, List<string>> | 46 | var ignoreAttributesByElementName = new Dictionary<string, List<string>> |
47 | { | 47 | { |
48 | { "ExePackage", new List<string> { "CacheId", "InstallSize", "Size" } }, | 48 | { "ExePackage", new List<string> { "CacheId", "InstallSize", "Size" } }, |
49 | { "Payload", new List<string> { "SourcePath" } }, | ||
49 | }; | 50 | }; |
50 | Assert.Equal(1, exePackageElements.Count); | 51 | Assert.Equal(1, exePackageElements.Count); |
51 | Assert.Equal("<ExePackage Id='PackagePayloadInPayloadGroup' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_PackagePayloadInPayloadGroup' RollbackLogPathVariable='WixBundleRollbackLog_PackagePayloadInPayloadGroup' DetectCondition='none' InstallArguments='' UninstallArguments='' RepairArguments='' Repairable='no'><PayloadRef Id='burn.exe' /></ExePackage>", exePackageElements[0].GetTestXml(ignoreAttributesByElementName)); | 52 | Assert.Equal("<ExePackage Id='PackagePayloadInPayloadGroup' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_PackagePayloadInPayloadGroup' RollbackLogPathVariable='WixBundleRollbackLog_PackagePayloadInPayloadGroup' DetectCondition='none' InstallArguments='' UninstallArguments='' RepairArguments='' Repairable='no'><PayloadRef Id='burn.exe' /></ExePackage>", exePackageElements[0].GetTestXml(ignoreAttributesByElementName)); |
52 | 53 | ||
53 | var payloadElements = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='burn.exe']"); | 54 | var payloadElements = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='burn.exe']"); |
54 | Assert.Equal(1, payloadElements.Count); | 55 | Assert.Equal(1, payloadElements.Count); |
55 | Assert.Equal("<Payload Id='burn.exe' FilePath='burn.exe' FileSize='463360' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />", payloadElements[0].GetTestXml()); | 56 | Assert.Equal("<Payload Id='burn.exe' FilePath='burn.exe' FileSize='463360' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Packaging='embedded' SourcePath='*' Container='WixAttachedContainer' />", payloadElements[0].GetTestXml(ignoreAttributesByElementName)); |
56 | } | 57 | } |
57 | } | 58 | } |
58 | 59 | ||
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 | |||
189 | .Cast<XmlElement>() | 189 | .Cast<XmlElement>() |
190 | .Select(e => e.GetTestXml(ignoreAttributesByElementName)) | 190 | .Select(e => e.GetTestXml(ignoreAttributesByElementName)) |
191 | .ToArray(); | 191 | .ToArray(); |
192 | WixAssert.CompareLineByLine(new string[] | 192 | |
193 | { | 193 | var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash"} } }; |
194 | "<Payload Id='burn.exe' FilePath='burn.exe' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='PackagesContainer' />", | 194 | var ignoreAttributesWithSrc = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } }; |
195 | "<Payload Id='test.msi' FilePath='test.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com/id/test.msi/test.msi' Packaging='external' SourcePath='test.msi' />", | 195 | Assert.Equal(5, payloads.Length); |
196 | "<Payload Id='LayoutOnlyPayload' FilePath='DownloadUrlPlaceholdersBundle.wxs' FileSize='*' Hash='*' LayoutOnly='yes' DownloadUrl='http://example.com/id/LayoutOnlyPayload/DownloadUrlPlaceholdersBundle.wxs' Packaging='external' SourcePath='DownloadUrlPlaceholdersBundle.wxs' />", | 196 | Assert.Equal(@"<Payload Id='burn.exe' FilePath='burn.exe' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='PackagesContainer' />", payloads[0].GetTestXml(ignoreAttributesWithSrc)); |
197 | @"<Payload Id='fhuZsOcBDTuIX8rF96kswqI6SnuI' FilePath='MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/test.msiid/fhuZsOcBDTuIX8rF96kswqI6SnuI/MsiPackage/test.txt' Packaging='external' SourcePath='MsiPackage\test.txt' />", | 197 | Assert.Equal(@"<Payload Id='test.msi' FilePath='test.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com/id/test.msi/test.msi' Packaging='external' SourcePath='test.msi' />", payloads[1].GetTestXml(ignoreAttributes)); |
198 | @"<Payload Id='faf_OZ741BG7SJ6ZkcIvivZ2Yzo8' FilePath='MsiPackage\Shared.dll' FileSize='*' Hash='*' DownloadUrl='http://example.com/test.msiid/faf_OZ741BG7SJ6ZkcIvivZ2Yzo8/MsiPackage/Shared.dll' Packaging='external' SourcePath='MsiPackage\Shared.dll' />", | 198 | Assert.Equal(@"<Payload Id='LayoutOnlyPayload' FilePath='DownloadUrlPlaceholdersBundle.wxs' FileSize='*' Hash='*' LayoutOnly='yes' DownloadUrl='http://example.com/id/LayoutOnlyPayload/DownloadUrlPlaceholdersBundle.wxs' Packaging='external' SourcePath='DownloadUrlPlaceholdersBundle.wxs' />", payloads[2].GetTestXml(ignoreAttributes)); |
199 | }, payloads); | 199 | Assert.Equal(@"<Payload Id='fhuZsOcBDTuIX8rF96kswqI6SnuI' FilePath='MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/test.msiid/fhuZsOcBDTuIX8rF96kswqI6SnuI/MsiPackage/test.txt' Packaging='external' SourcePath='MsiPackage\test.txt' />", payloads[3].GetTestXml(ignoreAttributes)); |
200 | Assert.Equal(@"<Payload Id='faf_OZ741BG7SJ6ZkcIvivZ2Yzo8' FilePath='MsiPackage\Shared.dll' FileSize='*' Hash='*' DownloadUrl='http://example.com/test.msiid/faf_OZ741BG7SJ6ZkcIvivZ2Yzo8/MsiPackage/Shared.dll' Packaging='external' SourcePath='MsiPackage\Shared.dll' />", payloads[4].GetTestXml(ignoreAttributes)); | ||
200 | 201 | ||
201 | var containers = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Container") | 202 | var containers = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Container") |
202 | .Cast<XmlElement>() | 203 | .Cast<XmlElement>() |