Follow up for multiple attached container support
* validate cContainers * use previous embeddedid format and use intermediate folder when extracting attached containers * remove special cases for 0 byte containers in BurnCommon classes and Insignia * don't hardcode max containers * reduce properties in BurnCommon * add e2e test #6144
Sean Hall committed
Nov 2, 2021 at 17:47 UTC
323f62d3d0f4b73db5fde8977e2540194c6de006
19 files changed
+276
-158
src/burn/engine/section.cpp
+13
-11
@@ -26,7 +26,7 @@ typedef struct _BURN_SECTION_HEADER
26
27
DWORD dwFormat;
28
DWORD cContainers;
29
- DWORD rgcbContainers[116];
29
+ DWORD rgcbContainers[1];
30
} BURN_SECTION_HEADER;
31
32
static HRESULT VerifySectionMatchesMemoryPEHeader(
@@ -53,6 +53,7 @@ extern "C" HRESULT SectionInitialize(
53
IMAGE_SECTION_HEADER sectionHeader = { };
54
DWORD_PTR dwOriginalChecksumAndSignatureOffset = 0;
55
BURN_SECTION_HEADER* pBurnSectionHeader = NULL;
56
+ DWORD cMaxContainers = 0;
57
58
pSection->hEngineFile = hEngineFile;
59
ExitOnInvalidHandleWithLastError(pSection->hEngineFile, hr, "Failed to open handle to engine process path.");
@@ -142,8 +143,7 @@ extern "C" HRESULT SectionInitialize(
143
}
144
if (sizeof(IMAGE_SECTION_HEADER) > cbRead)
145
{
145
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
146
- ExitOnRootFailure(hr, "Failed to read complete image section header, index: %u", i);
146
+ ExitWithRootFailure(hr, E_INVALIDDATA, "Failed to read complete image section header, index: %u", i);
147
}
148
149
// compare header name
@@ -156,8 +156,7 @@ extern "C" HRESULT SectionInitialize(
156
// fail if we hit the end
157
if (i + 1 >= ntHeader.FileHeader.NumberOfSections)
158
{
159
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
160
- ExitOnRootFailure(hr, "Failed to find Burn section.");
159
+ ExitWithRootFailure(hr, E_INVALIDDATA, "Failed to find Burn section.");
160
}
161
}
162
@@ -168,8 +167,7 @@ extern "C" HRESULT SectionInitialize(
167
// check size of section
168
if (sizeof(BURN_SECTION_HEADER) > sectionHeader.SizeOfRawData)
169
{
171
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
172
- ExitOnRootFailure(hr, "Failed to read section info, data to short: %u", sectionHeader.SizeOfRawData);
170
+ ExitWithRootFailure(hr, E_INVALIDDATA, "Failed to read section info, data too short: %u", sectionHeader.SizeOfRawData);
171
}
172
173
// allocate buffer for section info
@@ -193,15 +191,19 @@ extern "C" HRESULT SectionInitialize(
191
}
192
else if (sectionHeader.SizeOfRawData > cbRead)
193
{
196
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
197
- ExitOnRootFailure(hr, "Failed to read complete section info.");
194
+ ExitWithRootFailure(hr, E_INVALIDDATA, "Failed to read complete section info.");
195
}
196
197
// validate version of section info
198
if (BURN_SECTION_VERSION != pBurnSectionHeader->dwVersion)
199
{
203
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
204
- ExitOnRootFailure(hr, "Failed to read section info, unsupported version: %08x", pBurnSectionHeader->dwVersion);
200
+ ExitWithRootFailure(hr, E_INVALIDDATA, "Failed to read section info, unsupported version: %08x", pBurnSectionHeader->dwVersion);
201
+ }
202
+
203
+ cMaxContainers = (sectionHeader.SizeOfRawData - offsetof(BURN_SECTION_HEADER, rgcbContainers)) / sizeof(DWORD);
204
+ if (cMaxContainers < pBurnSectionHeader->cContainers)
205
+ {
206
+ ExitWithRootFailure(hr, E_INVALIDDATA, "Invalid section info, cContainers too large: %u", pBurnSectionHeader->cContainers);
207
}
208
209
hr = FileSizeByHandle(pSection->hSourceEngineFile, &llSize);
src/burn/stub/StubSection.cpp
+2
-1
@@ -18,5 +18,6 @@ static DWORD dwOriginalSignatureSize = 0;
18
19
static DWORD dwContainerFormat = 1;
20
static DWORD dwContainerCount = 0;
21
-static DWORD qwAttachedContainerSizes[116]; // Including UX container
21
+// (512 (minimum section size) - 48 (size of above data)) / 4 (size of DWORD)
22
+static DWORD qwAttachedContainerSizes[116];
23
#pragma data_seg(pop)
src/test/burn/TestData/ContainerTests/BundleA/BundleA.wixproj
new
+19
@@ -0,0 +1,19 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <OutputType>Bundle</OutputType>
5
+ <UpgradeCode>{16798DF3-C365-410D-B376-E63A961E4822}</UpgradeCode>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" />
9
+ </ItemGroup>
10
+ <ItemGroup>
11
+ <ProjectReference Include="..\PackageA\PackageA.wixproj" />
12
+ <ProjectReference Include="..\PackageB\PackageB.wixproj" />
13
+ <ProjectReference Include="..\..\TestBA\TestBAWixlib\testbawixlib.wixproj" />
14
+ </ItemGroup>
15
+ <ItemGroup>
16
+ <PackageReference Include="WixToolset.Bal.wixext" />
17
+ <PackageReference Include="WixToolset.NetFx.wixext" />
18
+ </ItemGroup>
19
+</Project>
\ No newline at end of file
src/test/burn/TestData/ContainerTests/BundleA/BundleA.wxs
new
+17
@@ -0,0 +1,17 @@
1
+<!-- 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. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
5
+ <Fragment>
6
+ <PackageGroup Id="BundlePackages">
7
+ <MsiPackage Id="PackageA" SourceFile="$(var.PackageA.TargetPath)" />
8
+ <PackageGroupRef Id="PackageB" />
9
+ </PackageGroup>
10
+ <PackageGroup Id="PackageB">
11
+ <MsiPackage Id="PackageB" SourceFile="$(var.PackageB.TargetPath)" />
12
+ </PackageGroup>
13
+ <Container Id="CustomAttachedContainer" Name="CustomAttachedContainer" Type="attached">
14
+ <PackageGroupRef Id="PackageB" />
15
+ </Container>
16
+ </Fragment>
17
+</Wix>
src/test/burn/TestData/ContainerTests/PackageA/PackageA.wixproj
new
+10
@@ -0,0 +1,10 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <CabPrefix>a</CabPrefix>
5
+ <UpgradeCode>{D452A40D-27B2-41A1-A103-4FD5744B548E}</UpgradeCode>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
9
+ </ItemGroup>
10
+</Project>
\ No newline at end of file
src/test/burn/TestData/ContainerTests/PackageB/PackageB.wixproj
new
+10
@@ -0,0 +1,10 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <CabPrefix>b</CabPrefix>
5
+ <UpgradeCode>{EB8E7A16-9855-4019-90D6-F5A242A75250}</UpgradeCode>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
9
+ </ItemGroup>
10
+</Project>
\ No newline at end of file
src/test/burn/WixToolsetTest.BurnE2E/ContainerTests.cs
new
+29
@@ -0,0 +1,29 @@
1
+// 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.
2
+
3
+namespace WixToolsetTest.BurnE2E
4
+{
5
+ using Xunit;
6
+ using Xunit.Abstractions;
7
+
8
+ public class ContainerTests : BurnE2ETests
9
+ {
10
+ public ContainerTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
11
+
12
+ [Fact]
13
+ public void CanSupportMultipleAttachedContainers()
14
+ {
15
+ var packageA = this.CreatePackageInstaller("PackageA");
16
+ var packageB = this.CreatePackageInstaller("PackageB");
17
+ var bundleA = this.CreateBundleInstaller("BundleA");
18
+
19
+ packageA.VerifyInstalled(false);
20
+ packageB.VerifyInstalled(false);
21
+
22
+ bundleA.Install();
23
+ bundleA.VerifyRegisteredAndInPackageCache();
24
+
25
+ packageA.VerifyInstalled(true);
26
+ packageB.VerifyInstalled(true);
27
+ }
28
+ }
29
+}
src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+3
-1
@@ -296,13 +296,15 @@ namespace WixToolset.Core.Burn
296
}
297
298
// Give the embedded payloads without an embedded id yet an embedded id.
299
+ var payloadIndex = 0;
300
foreach (var payload in payloadSymbols.Values)
301
{
302
Debug.Assert(PackagingType.Unknown != payload.Packaging);
303
304
if (PackagingType.Embedded == payload.Packaging && String.IsNullOrEmpty(payload.EmbeddedId))
305
{
305
- payload.EmbeddedId = Guid.NewGuid().ToString("N");
306
+ payload.EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnAuthoredContainerEmbeddedIdFormat, payloadIndex);
307
+ ++payloadIndex;
308
}
309
}
310
}
src/wix/WixToolset.Core.Burn/BundleBackend.cs
+1
-1
@@ -67,7 +67,7 @@ namespace WixToolset.Core.Burn
67
using (var reader = BurnReader.Open(messaging, context.InputFilePath))
68
{
69
reader.ExtractUXContainer(uxExtractPath, context.IntermediateFolder);
70
- reader.ExtractAttachedContainers(context.ExportBasePath);
70
+ reader.ExtractAttachedContainers(context.ExportBasePath, context.IntermediateFolder);
71
}
72
73
return null;
src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs
+29
-32
@@ -20,6 +20,7 @@ namespace WixToolset.Core.Burn.Bundles
20
{
21
public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn";
22
public const string BurnUXContainerEmbeddedIdFormat = "u{0}";
23
+ public const string BurnAuthoredContainerEmbeddedIdFormat = "a{0}";
24
25
public const string BADataFileName = "BootstrapperApplicationData.xml";
26
public const string BADataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData";
@@ -79,12 +80,11 @@ namespace WixToolset.Core.Burn.Bundles
80
protected const UInt32 BURN_SECTION_OFFSET_COUNT = 44;
81
protected const UInt32 BURN_SECTION_OFFSET_UXSIZE = 48;
82
protected const UInt32 BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0 = 52;
83
+ protected const UInt32 BURN_SECTION_MIN_SIZE = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0;
84
85
protected const UInt32 BURN_SECTION_MAGIC = 0x00f14300;
86
protected const UInt32 BURN_SECTION_VERSION = 0x00000003;
87
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
89
protected string fileExe;
90
protected UInt32 peOffset = UInt32.MaxValue;
@@ -94,6 +94,8 @@ namespace WixToolset.Core.Burn.Bundles
94
protected UInt32 certificateTableSignatureOffset;
95
protected UInt32 certificateTableSignatureSize;
96
protected UInt32 wixburnDataOffset = UInt32.MaxValue;
97
+ protected UInt32 wixburnRawDataSize;
98
+ protected UInt32 wixburnMaxContainers;
99
100
// TODO: does this enum exist in another form somewhere?
101
/// <summary>
@@ -127,9 +129,7 @@ namespace WixToolset.Core.Burn.Bundles
129
public UInt32 OriginalSignatureOffset { get; protected set; }
130
public UInt32 OriginalSignatureSize { get; protected set; }
131
public UInt32 EngineSize { get; protected set; }
130
- public UInt32 ContainerCount { get; protected set; }
131
- public UInt32 UXAddress { get; protected set; }
132
- public UInt32 UXSize { get; protected set; }
132
+ public UInt32 UXAddress { get { return this.StubSize; } }
133
public List<ContainerSlot> AttachedContainers { get; protected set; }
134
135
protected IMessaging Messaging { get; }
@@ -180,9 +180,7 @@ namespace WixToolset.Core.Burn.Bundles
180
}
181
182
reader.BaseStream.Seek(this.wixburnDataOffset, SeekOrigin.Begin);
183
- List<byte> manifest = new List<byte>();
184
- manifest.AddRange(reader.ReadBytes((int)BURN_SECTION_SIZE));
185
- byte[] bytes = manifest.ToArray();
183
+ byte[] bytes = reader.ReadBytes((int)this.wixburnRawDataSize);
184
UInt32 uint32 = 0;
185
186
uint32 = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_MAGIC);
@@ -211,40 +209,37 @@ namespace WixToolset.Core.Burn.Bundles
209
this.OriginalSignatureOffset = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALSIGNATUREOFFSET);
210
this.OriginalSignatureSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALSIGNATURESIZE);
211
214
- this.ContainerCount = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_COUNT);
215
- if (BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT < this.ContainerCount)
212
+ uint containerCount = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_COUNT);
213
+ uint uxSize = 0;
214
+ if (this.wixburnMaxContainers < containerCount)
215
{
216
this.Messaging.Write(ErrorMessages.InvalidBundle(this.fileExe));
217
return false;
218
}
220
- this.UXAddress = this.StubSize;
221
- this.UXSize = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_UXSIZE);
219
+ else if (containerCount > 0)
220
+ {
221
+ this.AttachedContainers.Clear();
222
+ for (uint i = 0; i < containerCount; ++i)
223
+ {
224
+ uint sizeOffset = BURN_SECTION_OFFSET_UXSIZE + (i * 4);
225
+ uint size = BurnCommon.ReadUInt32(bytes, sizeOffset);
226
+ this.AttachedContainers.Add(new ContainerSlot(size));
227
+ }
228
+ uxSize = this.AttachedContainers[0].Size;
229
+ }
230
231
// If there is an original signature use that to determine the engine size.
232
if (0 < this.OriginalSignatureOffset)
233
{
234
this.EngineSize = this.OriginalSignatureOffset + this.OriginalSignatureSize;
235
}
228
- else if (0 < this.SignatureOffset && 2 > this.ContainerCount) // if there is a signature and no attached containers, use the current signature.
236
+ else if (0 < this.SignatureOffset && 2 > containerCount) // if there is a signature and no attached containers, use the current signature.
237
{
238
this.EngineSize = this.SignatureOffset + this.SignatureSize;
239
}
240
else // just use the stub and UX container as the size of the engine.
241
{
234
- this.EngineSize = this.StubSize + this.UXSize;
235
- }
236
-
237
- this.AttachedContainers.Clear();
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
- }
242
+ this.EngineSize = this.UXAddress + uxSize;
243
}
244
245
return true;
@@ -288,13 +283,17 @@ namespace WixToolset.Core.Burn.Bundles
283
return false;
284
}
285
291
- // We need 512 bytes for the manifest header
292
- if (BURN_SECTION_SIZE > BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_SIZEOFRAWDATA))
286
+ this.wixburnRawDataSize = BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_SIZEOFRAWDATA);
287
+
288
+ // we need 52 bytes for the manifest header, which is always going to fit in
289
+ // the smallest alignment (512 bytes), but just to be paranoid...
290
+ if (BURN_SECTION_MIN_SIZE > this.wixburnRawDataSize)
291
{
292
this.Messaging.Write(ErrorMessages.StubWixburnSectionTooSmall(this.fileExe));
293
return false;
294
}
295
296
+ this.wixburnMaxContainers = (this.wixburnRawDataSize - BURN_SECTION_OFFSET_UXSIZE) / sizeof(UInt32);
297
this.wixburnDataOffset = BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_POINTERTORAWDATA);
298
}
299
@@ -404,13 +403,11 @@ namespace WixToolset.Core.Burn.Bundles
403
404
internal struct ContainerSlot
405
{
407
- public ContainerSlot(uint address, uint size) : this()
406
+ public ContainerSlot(uint size) : this()
407
{
409
- this.Address = address;
408
this.Size = size;
409
}
410
413
- public uint Address { get; set; }
411
public uint Size { get; set; }
412
}
413
}
src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs
+15
-9
@@ -78,7 +78,7 @@ namespace WixToolset.Core.Burn.Bundles
78
public bool ExtractUXContainer(string outputDirectory, string tempDirectory)
79
{
80
// No UX container to extract
81
- if (this.UXAddress == 0 || this.UXSize == 0)
81
+ if (this.AttachedContainers.Count == 0)
82
{
83
return false;
84
}
@@ -92,11 +92,12 @@ namespace WixToolset.Core.Burn.Bundles
92
string tempCabPath = Path.Combine(tempDirectory, "ux.cab");
93
string manifestOriginalPath = Path.Combine(outputDirectory, "0");
94
string manifestPath = Path.Combine(outputDirectory, "manifest.xml");
95
+ var uxContainerSlot = this.AttachedContainers[0];
96
97
this.binaryReader.BaseStream.Seek(this.UXAddress, SeekOrigin.Begin);
98
using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write))
99
{
99
- BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)this.UXSize);
100
+ BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)uxContainerSlot.Size);
101
}
102
103
var cabinet = new Cabinet(tempCabPath);
@@ -152,14 +153,15 @@ namespace WixToolset.Core.Burn.Bundles
153
}
154
155
/// <summary>
155
- /// Gets the attached container from the exe and extracts its contents to the output directory.
156
+ /// Gets each non-UX attached container from the exe and extracts its contents to the output directory.
157
/// </summary>
158
/// <param name="outputDirectory">Directory to write extracted files to.</param>
159
+ /// <param name="tempDirectory">Scratch directory.</param>
160
/// <returns>True if successful, false otherwise</returns>
159
- public bool ExtractAttachedContainers(string outputDirectory)
161
+ public bool ExtractAttachedContainers(string outputDirectory, string tempDirectory)
162
{
161
- // No attached container to extract
162
- if (this.AttachedContainers.Count == 0)
163
+ // No attached containers to extract
164
+ if (this.AttachedContainers.Count < 2)
165
{
166
return false;
167
}
@@ -170,11 +172,13 @@ namespace WixToolset.Core.Burn.Bundles
172
}
173
174
Directory.CreateDirectory(outputDirectory);
173
- foreach (ContainerSlot cntnr in this.AttachedContainers)
175
+ uint nextAddress = this.EngineSize;
176
+ for (int i = 1; i < this.AttachedContainers.Count; i++)
177
{
175
- string tempCabPath = Path.GetTempFileName();
178
+ ContainerSlot cntnr = this.AttachedContainers[i];
179
+ string tempCabPath = Path.Combine(tempDirectory, $"a{i}.cab");
180
177
- this.binaryReader.BaseStream.Seek(cntnr.Address, SeekOrigin.Begin);
181
+ this.binaryReader.BaseStream.Seek(nextAddress, SeekOrigin.Begin);
182
using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write))
183
{
184
BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)cntnr.Size);
@@ -182,6 +186,8 @@ namespace WixToolset.Core.Burn.Bundles
186
187
var cabinet = new Cabinet(tempCabPath);
188
cabinet.Extract(outputDirectory);
189
+
190
+ nextAddress += cntnr.Size;
191
}
192
193
foreach (DictionaryEntry entry in this.attachedContainerPayloadNames)
src/wix/WixToolset.Core.Burn/Bundles/BurnWriter.cs
+50
-30
@@ -91,9 +91,9 @@ namespace WixToolset.Core.Burn.Bundles
91
this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_ORIGINALSIGNATUREOFFSET, 0);
92
this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_ORIGINALSIGNATURESIZE, 0);
93
this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_FORMAT, 1); // Hard-coded to CAB for now.
94
+ this.AttachedContainers.Clear();
95
this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_COUNT, 0);
95
- this.WriteToBurnSectionOffset(BURN_SECTION_OFFSET_UXSIZE, 0);
96
- for (uint i = BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE0; i < BURN_SECTION_SIZE; i += sizeof(UInt32))
96
+ for (uint i = BURN_SECTION_OFFSET_UXSIZE; i < this.wixburnMaxContainers; i += sizeof(UInt32))
97
{
98
this.WriteToBurnSectionOffset(i, 0);
99
}
@@ -118,6 +118,39 @@ namespace WixToolset.Core.Burn.Bundles
118
}
119
}
120
121
+ /// <summary>
122
+ /// Appends the non-UX attached containers from the reader to this bundle.
123
+ /// </summary>
124
+ /// <param name="reader">The source bundle.</param>
125
+ /// <returns>true if the container data is successfully appended; false otherwise.</returns>
126
+ public bool ReattachContainers(BurnReader reader)
127
+ {
128
+ if (this.AttachedContainers.Count == 0 || reader.AttachedContainers.Count < 2)
129
+ {
130
+ return false;
131
+ }
132
+
133
+ this.RememberThenResetSignature();
134
+
135
+ var uxContainerSlot = this.AttachedContainers[0];
136
+ this.AttachedContainers.Clear();
137
+ this.AttachedContainers.Add(uxContainerSlot);
138
+
139
+ uint nextAddress = this.EngineSize;
140
+ for (int i = 1; i < reader.AttachedContainers.Count; i++)
141
+ {
142
+ ContainerSlot cntnr = reader.AttachedContainers[i];
143
+
144
+ reader.Stream.Seek(nextAddress, SeekOrigin.Begin);
145
+ // TODO: verify that the size in the section data is 0 or the same size.
146
+ this.AppendContainer(reader.Stream, cntnr.Size, BurnCommon.Container.Attached);
147
+
148
+ nextAddress += cntnr.Size;
149
+ }
150
+
151
+ return true;
152
+ }
153
+
154
/// <summary>
155
/// Appends a UX or Attached container to the exe and updates the ".wixburn" section data to point to it.
156
/// </summary>
@@ -127,38 +160,23 @@ namespace WixToolset.Core.Burn.Bundles
160
/// <returns>true if the container data is successfully appended; false otherwise</returns>
161
public bool AppendContainer(Stream containerStream, long containerSize, BurnCommon.Container container)
162
{
130
- UInt32 burnSectionCount = 0;
131
- UInt32 burnSectionOffsetSize = 0;
132
-
133
- if (containerSize == 0)
134
- {
135
- return false;
136
- }
163
+ uint containerCount = (uint)this.AttachedContainers.Count;
164
+ uint burnSectionOffsetSize = BURN_SECTION_OFFSET_UXSIZE + (containerCount * sizeof(UInt32));
165
+ var containerSlot = new ContainerSlot((uint)containerSize);
166
167
switch (container)
168
{
169
case Container.UX:
141
- burnSectionCount = 1;
142
- burnSectionOffsetSize = BURN_SECTION_OFFSET_UXSIZE;
143
- // TODO: verify that the size in the section data is 0 or the same size.
144
- this.EngineSize += (uint)containerSize;
145
- this.UXSize = (uint)containerSize;
146
- break;
147
-
148
- case Container.Attached:
149
- // TODO: verify that the size in the section data is 0 or the same size.
150
- uint nextAddress = this.EngineSize;
151
- foreach (ContainerSlot cntnr in this.AttachedContainers)
170
+ if (containerCount != 0)
171
{
153
- if (cntnr.Address >= nextAddress)
154
- {
155
- nextAddress = cntnr.Address + cntnr.Size;
156
- }
172
+ Debug.Assert(false);
173
+ return false;
174
}
175
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);
176
+ this.EngineSize += containerSlot.Size;
177
+ break;
178
+
179
+ case Container.Attached:
180
break;
181
182
default:
@@ -166,7 +184,9 @@ namespace WixToolset.Core.Burn.Bundles
184
return false;
185
}
186
169
- return this.AppendContainer(containerStream, (UInt32)containerSize, burnSectionOffsetSize, burnSectionCount);
187
+ this.AttachedContainers.Add(containerSlot);
188
+ ++containerCount;
189
+ return this.AppendContainer(containerStream, containerSlot.Size, burnSectionOffsetSize, containerCount);
190
}
191
192
public void RememberThenResetSignature()
@@ -225,10 +245,10 @@ namespace WixToolset.Core.Burn.Bundles
245
{
246
return false;
247
}
228
- if (burnSectionOffsetSize > (BURN_SECTION_SIZE - sizeof(UInt32)))
248
+ if (burnSectionOffsetSize > (this.wixburnRawDataSize - sizeof(UInt32)))
249
{
250
this.invalidBundle = true;
231
- this.Messaging.Write(BurnBackendErrors.TooManyAttachedContainers(BURN_SECTION_MAX_ATTACHEDCONTAINER_COUNT));
251
+ this.Messaging.Write(BurnBackendErrors.TooManyAttachedContainers(this.wixburnMaxContainers));
252
return false;
253
}
254
src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs
+1
-16
@@ -31,22 +31,7 @@ namespace WixToolset.Core.Burn.Inscribe
31
FileSystem.CopyFile(this.Context.SignedEngineFile, tempFile, allowHardlink: false);
32
using (BurnWriter writer = BurnWriter.Open(this.Messaging, tempFile))
33
{
34
- if (reader.Version != writer.Version)
35
- {
36
- this.Messaging.Write(BurnBackendErrors.IncompatibleWixBurnSection(this.Context.InputFilePath, reader.Version));
37
- }
38
-
39
- writer.AttachedContainers.Clear();
40
- writer.RememberThenResetSignature();
41
- foreach (ContainerSlot cntnr in reader.AttachedContainers)
42
- {
43
- if (cntnr.Size > 0)
44
- {
45
- reader.Stream.Seek(cntnr.Address, SeekOrigin.Begin);
46
- writer.AppendContainer(reader.Stream, cntnr.Size, BurnCommon.Container.Attached);
47
- inscribed = true;
48
- }
49
- }
34
+ inscribed = writer.ReattachContainers(reader);
35
}
36
}
37
src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs
+23
-19
@@ -21,44 +21,48 @@ namespace WixToolset.Core.TestPackage
21
/// <param name="tempFolderPath">Temp path for extraction.</param>
22
/// <returns></returns>
23
public static ExtractBAContainerResult ExtractBAContainer(IMessaging messaging, string bundleFilePath, string destinationFolderPath, string tempFolderPath)
24
+ {
25
+ return ExtractAllContainers(messaging, bundleFilePath, destinationFolderPath, null, tempFolderPath);
26
+ }
27
+
28
+ /// <summary>
29
+ /// Extracts the BA container.
30
+ /// </summary>
31
+ /// <param name="messaging"></param>
32
+ /// <param name="bundleFilePath">Path to the bundle.</param>
33
+ /// <param name="baFolderPath">Path to extract BA to.</param>
34
+ /// <param name="otherContainersFolderPath">Path to extract other attached containers to.</param>
35
+ /// <param name="tempFolderPath">Temp path for extraction.</param>
36
+ /// <returns></returns>
37
+ public static ExtractBAContainerResult ExtractAllContainers(IMessaging messaging, string bundleFilePath, string baFolderPath, string otherContainersFolderPath, string tempFolderPath)
38
{
39
var result = new ExtractBAContainerResult();
40
Directory.CreateDirectory(tempFolderPath);
41
using (var burnReader = BurnReader.Open(messaging, bundleFilePath))
42
{
29
- result.Success = burnReader.ExtractUXContainer(destinationFolderPath, tempFolderPath);
43
+ result.Success = burnReader.ExtractUXContainer(baFolderPath, tempFolderPath);
44
+
45
+ if (otherContainersFolderPath != null)
46
+ {
47
+ result.AttachedContainersSuccess = burnReader.ExtractAttachedContainers(otherContainersFolderPath, tempFolderPath);
48
+ }
49
}
50
51
if (result.Success)
52
{
34
- result.ManifestDocument = LoadBurnManifest(destinationFolderPath);
53
+ result.ManifestDocument = LoadBurnManifest(baFolderPath);
54
result.ManifestNamespaceManager = GetBurnNamespaceManager(result.ManifestDocument, "burn");
55
37
- result.BADataDocument = LoadBAData(destinationFolderPath);
56
+ result.BADataDocument = LoadBAData(baFolderPath);
57
result.BADataNamespaceManager = GetBADataNamespaceManager(result.BADataDocument, "ba");
58
40
- result.BundleExtensionDataDocument = LoadBundleExtensionData(destinationFolderPath);
59
+ result.BundleExtensionDataDocument = LoadBundleExtensionData(baFolderPath);
60
result.BundleExtensionDataNamespaceManager = GetBundleExtensionDataNamespaceManager(result.BundleExtensionDataDocument, "be");
61
}
62
63
return result;
64
}
65
47
- /// <summary>
48
- /// Extracts the attached container.
49
- /// </summary>
50
- /// <param name="messaging"></param>
51
- /// <param name="bundleFilePath">Path to the bundle.</param>
52
- /// <param name="destinationFolderPath">Path to extract to.</param>
53
- /// <returns>True if there was an attached container.</returns>
54
- public static bool ExtractAttachedContainers(IMessaging messaging, string bundleFilePath, string destinationFolderPath)
55
- {
56
- using (var burnReader = BurnReader.Open(messaging, bundleFilePath))
57
- {
58
- return burnReader.ExtractAttachedContainers(destinationFolderPath);
59
- }
60
- }
61
-
66
/// <summary>
67
/// Gets an <see cref="XmlNamespaceManager"/> for BootstrapperApplicationData.xml with the given prefix assigned to the root namespace.
68
/// </summary>
src/wix/WixToolset.Core.TestPackage/ExtractBAContainerResult.cs
+6
@@ -46,6 +46,11 @@ namespace WixToolset.Core.TestPackage
46
/// </summary>
47
public bool Success { get; set; }
48
49
+ /// <summary>
50
+ /// Whether attached containers extraction succeeded.
51
+ /// </summary>
52
+ public bool? AttachedContainersSuccess { get; set; }
53
+
54
/// <summary>
55
///
56
/// </summary>
@@ -53,6 +58,7 @@ namespace WixToolset.Core.TestPackage
58
public ExtractBAContainerResult AssertSuccess()
59
{
60
Assert.True(this.Success);
61
+ Assert.True(!this.AttachedContainersSuccess.HasValue || this.AttachedContainersSuccess.Value);
62
return this;
63
}
64
src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
+6
-2
@@ -125,8 +125,8 @@ namespace WixToolsetTest.CoreIntegration
125
126
var msiPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='test.msi']");
127
var msiPayload = (XmlNode)Assert.Single(msiPayloads);
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", "SourcePath" } } }));
128
+ Assert.Equal("<Payload Id='test.msi' FilePath='test.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />",
129
+ msiPayload.GetTestXml(new Dictionary<string, List<string>>() { { "Payload", new List<string> { "FileSize", "Hash" } } }));
130
}
131
132
var manifestResource = new Resource(ResourceType.Manifest, "#1", 1033);
@@ -156,6 +156,7 @@ namespace WixToolsetTest.CoreIntegration
156
var exePath = Path.Combine(baseFolder, @"bin\test.exe");
157
var pdbPath = Path.Combine(baseFolder, @"bin\test.wixpdb");
158
var baFolderPath = Path.Combine(baseFolder, "ba");
159
+ var attachedFolderPath = Path.Combine(baseFolder, "attached");
160
var extractFolderPath = Path.Combine(baseFolder, "extract");
161
162
var result = WixRunner.Execute(false, new[] // TODO: go back to elevating warnings as errors.
@@ -186,6 +187,9 @@ namespace WixToolsetTest.CoreIntegration
187
"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\"><security><requestedPrivileges><requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\" /></requestedPrivileges></security></trustInfo>" +
188
"<application xmlns=\"urn:schemas-microsoft-com:asm.v3\"><windowsSettings><dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">true/pm</dpiAware><dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2, PerMonitor</dpiAwareness></windowsSettings></application>" +
189
"</assembly>", actualManifestData);
190
+
191
+ var extractResult = BundleExtractor.ExtractAllContainers(null, exePath, baFolderPath, attachedFolderPath, extractFolderPath);
192
+ extractResult.AssertSuccess();
193
}
194
}
195
src/wix/test/WixToolsetTest.CoreIntegration/ContainerFixture.cs
+33
-25
@@ -49,11 +49,11 @@ namespace WixToolsetTest.CoreIntegration
49
50
var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload");
51
Assert.Equal(4, payloads.Count);
52
- var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } };
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));
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));
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));
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));
52
+ var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
53
+ 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));
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='a1' Container='BundlePackages' />", payloads[1].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='a2' Container='BundlePackages' />", payloads[2].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='a3' Container='BundlePackages' />", payloads[3].GetTestXml(ignoreAttributes));
57
}
58
}
59
@@ -93,11 +93,11 @@ namespace WixToolsetTest.CoreIntegration
93
94
var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload");
95
Assert.Equal(4, payloads.Count);
96
- var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } };
97
- Assert.Equal(@"<Payload Id='FirstX86.msi' FilePath='FirstX86.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='WixAttachedContainer' />", payloads[0].GetTestXml(ignoreAttributes));
98
- Assert.Equal(@"<Payload Id='FirstX64.msi' FilePath='FirstX64.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='FirstX64' />", payloads[1].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));
100
- Assert.Equal(@"<Payload Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='FirstX64' />", payloads[3].GetTestXml(ignoreAttributes));
96
+ var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
97
+ Assert.Equal(@"<Payload Id='FirstX86.msi' FilePath='FirstX86.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />", payloads[0].GetTestXml(ignoreAttributes));
98
+ Assert.Equal(@"<Payload Id='FirstX64.msi' FilePath='FirstX64.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a1' Container='FirstX64' />", payloads[1].GetTestXml(ignoreAttributes));
99
+ Assert.Equal(@"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='WixAttachedContainer' />", payloads[2].GetTestXml(ignoreAttributes));
100
+ Assert.Equal(@"<Payload Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a3' Container='FirstX64' />", payloads[3].GetTestXml(ignoreAttributes));
101
}
102
}
103
@@ -203,14 +203,14 @@ namespace WixToolsetTest.CoreIntegration
203
var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
204
extractResult.AssertSuccess();
205
206
- var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } };
206
+ var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
207
var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']")
208
.Cast<XmlElement>()
209
.Select(e => e.GetTestXml(ignoreAttributes))
210
.ToArray();
211
WixAssert.CompareLineByLine(new string[]
212
{
213
- "<Payload Id='SharedPayload' FilePath='LayoutPayloadInContainer.wxs' FileSize='*' Hash='*' LayoutOnly='yes' Packaging='embedded' SourcePath='*' Container='FirstX64' />",
213
+ "<Payload Id='SharedPayload' FilePath='LayoutPayloadInContainer.wxs' FileSize='*' Hash='*' LayoutOnly='yes' Packaging='embedded' SourcePath='a1' Container='FirstX64' />",
214
}, payloads);
215
}
216
}
@@ -227,8 +227,8 @@ namespace WixToolsetTest.CoreIntegration
227
var binFolder = Path.Combine(baseFolder, "bin");
228
var bundlePath = Path.Combine(binFolder, "test.exe");
229
var baFolderPath = Path.Combine(baseFolder, "ba");
230
+ var attachedFolderPath = Path.Combine(baseFolder, "attached");
231
var extractFolderPath = Path.Combine(baseFolder, "extract");
231
- var tempFolderPath = Path.Combine(baseFolder, "temp");
232
233
this.BuildMsis(folder, intermediateFolder, binFolder);
234
@@ -243,19 +243,27 @@ namespace WixToolsetTest.CoreIntegration
243
"-o", bundlePath
244
});
245
246
- Assert.Equal(0, result.ExitCode);
246
+ result.AssertSuccess();
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
- }
249
+ var extractResult = BundleExtractor.ExtractAllContainers(null, bundlePath, baFolderPath, attachedFolderPath, extractFolderPath);
250
+ extractResult.AssertSuccess();
251
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");
252
+ Assert.True(File.Exists(Path.Combine(attachedFolderPath, "FirstX64", "FirstX64.msi")), "Expected extracted container to contain FirstX64.msi");
253
+ Assert.True(File.Exists(Path.Combine(attachedFolderPath, "WixAttachedContainer", "FirstX86.msi")), "Expected extracted container to contain FirstX86.msi");
254
+
255
+ var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
256
+ var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload")
257
+ .Cast<XmlElement>()
258
+ .Select(e => e.GetTestXml(ignoreAttributes))
259
+ .ToArray();
260
+ WixAssert.CompareLineByLine(new string[]
261
+ {
262
+ "<Payload Id='FirstX86.msi' FilePath='FirstX86.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />",
263
+ "<Payload Id='FirstX64.msi' FilePath='FirstX64.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a1' Container='FirstX64' />",
264
+ "<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='PFiles\\MsiPackage\\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='WixAttachedContainer' />",
265
+ "<Payload Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' FilePath='PFiles\\MsiPackage\\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a3' Container='FirstX64' />",
266
+ }, payloads);
267
}
268
}
269
@@ -297,14 +305,14 @@ namespace WixToolsetTest.CoreIntegration
305
var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
306
extractResult.AssertSuccess();
307
300
- var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } };
308
+ var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
309
var payloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']")
310
.Cast<XmlElement>()
311
.Select(e => e.GetTestXml(ignoreAttributes))
312
.ToArray();
313
WixAssert.CompareLineByLine(new string[]
314
{
307
- "<Payload Id='SharedPayload' FilePath='PayloadInMultipleContainers.wxs' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='FirstX86' />",
315
+ "<Payload Id='SharedPayload' FilePath='PayloadInMultipleContainers.wxs' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='FirstX86' />",
316
}, payloads);
317
}
318
}
src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs
+1
-2
@@ -46,14 +46,13 @@ namespace WixToolsetTest.CoreIntegration
46
var ignoreAttributesByElementName = new Dictionary<string, List<string>>
47
{
48
{ "ExePackage", new List<string> { "CacheId", "InstallSize", "Size" } },
49
- { "Payload", new List<string> { "SourcePath" } },
49
};
50
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
53
var payloadElements = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='burn.exe']");
54
Assert.Equal(1, payloadElements.Count);
56
- Assert.Equal("<Payload Id='burn.exe' FilePath='burn.exe' FileSize='463360' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Packaging='embedded' SourcePath='*' Container='WixAttachedContainer' />", payloadElements[0].GetTestXml(ignoreAttributesByElementName));
55
+ Assert.Equal("<Payload Id='burn.exe' FilePath='burn.exe' FileSize='463360' Hash='F6E722518AC3AB7E31C70099368D5770788C179AA23226110DCF07319B1E1964E246A1E8AE72E2CF23E0138AFC281BAFDE45969204405E114EB20C8195DA7E5E' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />", payloadElements[0].GetTestXml());
56
}
57
}
58
src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs
+8
-9
@@ -189,15 +189,14 @@ namespace WixToolsetTest.CoreIntegration
189
.Cast<XmlElement>()
190
.Select(e => e.GetTestXml(ignoreAttributesByElementName))
191
.ToArray();
192
-
193
- var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash"} } };
194
- var ignoreAttributesWithSrc = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } } };
195
- Assert.Equal(5, payloads.Length);
196
- Assert.Equal(@"<Payload Id='burn.exe' FilePath='burn.exe' FileSize='*' Hash='*' Packaging='embedded' SourcePath='*' Container='PackagesContainer' />", payloads[0].GetTestXml(ignoreAttributesWithSrc));
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
- 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
- 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));
192
+ WixAssert.CompareLineByLine(new string[]
193
+ {
194
+ "<Payload Id='burn.exe' FilePath='burn.exe' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='PackagesContainer' />",
195
+ "<Payload Id='test.msi' FilePath='test.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com/id/test.msi/test.msi' Packaging='external' SourcePath='test.msi' />",
196
+ "<Payload Id='LayoutOnlyPayload' FilePath='DownloadUrlPlaceholdersBundle.wxs' FileSize='*' Hash='*' LayoutOnly='yes' DownloadUrl='http://example.com/id/LayoutOnlyPayload/DownloadUrlPlaceholdersBundle.wxs' Packaging='external' SourcePath='DownloadUrlPlaceholdersBundle.wxs' />",
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' />",
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' />",
199
+ }, payloads);
200
201
var containers = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Container")
202
.Cast<XmlElement>()