Fix building and perf for bundles with 1000s of package and BA payloads
Fixes other half of #5300
Sean Hall committed
Jun 9, 2021 at 11:30 UTC
56105916271ff9a7c0bfa237b45b9b3fab9c570b
23 files changed
+317
-186
.gitignore
+2
@@ -399,3 +399,5 @@ build/.tools/
399
400
# Ignore generated test data
401
src/test/burn/TestData/CacheTests/BundleC/fivegb.file
402
+src/test/burn/TestData/Manual/BundleB/BAPayloads
403
+src/test/burn/TestData/Manual/BundleB/PackagePayloads
src/burn/engine/apply.cpp
+1
-1
@@ -1175,7 +1175,7 @@ static HRESULT ExtractContainer(
1175
{
1176
BOOL fExtracted = FALSE;
1177
1178
- hr = PayloadFindEmbeddedBySourcePath(pContext->pPayloads, sczStreamName, &pExtract);
1178
+ hr = PayloadFindEmbeddedBySourcePath(pContainer->sdhPayloads, sczStreamName, &pExtract);
1179
if (E_NOTFOUND != hr)
1180
{
1181
ExitOnFailure(hr, "Failed to find embedded payload by source path: %ls container: %ls", sczStreamName, pContainer->sczId);
src/burn/engine/burnextension.cpp
+6
-5
@@ -26,6 +26,7 @@ EXTERN_C HRESULT BurnExtensionParseFromXml(
26
IXMLDOMNodeList* pixnNodes = NULL;
27
IXMLDOMNode* pixnNode = NULL;
28
DWORD cNodes = 0;
29
+ LPWSTR scz = NULL;
30
31
// Select BundleExtension nodes.
32
hr = XmlSelectNodes(pixnBundle, L"BundleExtension", &pixnNodes);
@@ -59,11 +60,11 @@ EXTERN_C HRESULT BurnExtensionParseFromXml(
60
ExitOnFailure(hr, "Failed to get @Id.");
61
62
// @EntryPayloadId
62
- hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadId", &pExtension->sczEntryPayloadId);
63
- ExitOnFailure(hr, "Failed to get @EntryPayloadId.");
63
+ hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadSourcePath", &scz);
64
+ ExitOnFailure(hr, "Failed to get @EntryPayloadSourcePath.");
65
65
- hr = PayloadFindById(pBaPayloads, pExtension->sczEntryPayloadId, &pExtension->pEntryPayload);
66
- ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczEntryPayloadId);
66
+ hr = PayloadFindEmbeddedBySourcePath(pBaPayloads->sdhPayloads, scz, &pExtension->pEntryPayload);
67
+ ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczId);
68
69
// prepare next iteration
70
ReleaseNullObject(pixnNode);
@@ -72,6 +73,7 @@ EXTERN_C HRESULT BurnExtensionParseFromXml(
73
hr = S_OK;
74
75
LExit:
76
+ ReleaseStr(scz);
77
ReleaseObject(pixnNode);
78
ReleaseObject(pixnNodes);
79
@@ -92,7 +94,6 @@ EXTERN_C void BurnExtensionUninitialize(
94
{
95
BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i];
96
95
- ReleaseStr(pExtension->sczEntryPayloadId);
97
ReleaseStr(pExtension->sczId);
98
}
99
MemFree(pBurnExtensions->rgExtensions);
src/burn/engine/burnextension.h
-1
@@ -13,7 +13,6 @@ typedef struct _BURN_EXTENSION_ENGINE_CONTEXT BURN_EXTENSION_ENGINE_CONTEXT;
13
14
typedef struct _BURN_EXTENSION
15
{
16
- LPWSTR sczEntryPayloadId;
16
LPWSTR sczId;
17
18
BURN_PAYLOAD* pEntryPayload;
src/burn/engine/container.cpp
+2
-1
@@ -35,7 +35,7 @@ extern "C" HRESULT ContainersParseFromXml(
35
36
pContainers->cContainers = cNodes;
37
38
- // parse search elements
38
+ // parse container elements
39
for (DWORD i = 0; i < cNodes; ++i)
40
{
41
BURN_CONTAINER* pContainer = &pContainers->rgContainers[i];
@@ -181,6 +181,7 @@ extern "C" void ContainersUninitialize(
181
ReleaseStr(pContainer->downloadSource.sczUser);
182
ReleaseStr(pContainer->downloadSource.sczPassword);
183
ReleaseStr(pContainer->sczUnverifiedPath);
184
+ ReleaseDict(pContainer->sdhPayloads);
185
}
186
MemFree(pContainers->rgContainers);
187
}
src/burn/engine/container.h
+3
@@ -72,6 +72,9 @@ typedef struct _BURN_CONTAINER
72
LPWSTR sczFilePath; // relative path to container.
73
DOWNLOAD_SOURCE downloadSource;
74
75
+ DWORD cParsedPayloads;
76
+ STRINGDICT_HANDLE sdhPayloads; // value is BURN_PAYLOAD*
77
+
78
BYTE* pbHash;
79
DWORD cbHash;
80
BURN_CONTAINER_VERIFICATION verification;
src/burn/engine/manifest.h
-2
@@ -2,8 +2,6 @@
2
// 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.
3
4
5
-interface IBurnPayload; // forward declare.
6
-
5
#if defined(__cplusplus)
6
extern "C" {
7
#endif
src/burn/engine/payload.cpp
+39
-41
@@ -5,13 +5,6 @@
5
6
// internal function declarations
7
8
-static HRESULT FindEmbeddedBySourcePath(
9
- __in BURN_PAYLOADS* pPayloads,
10
- __in_opt BURN_CONTAINER* pContainer,
11
- __in_z LPCWSTR wzStreamName,
12
- __out BURN_PAYLOAD** ppPayload
13
- );
14
-
8
9
// function definitions
10
@@ -29,6 +22,7 @@ extern "C" HRESULT PayloadsParseFromXml(
22
LPWSTR scz = NULL;
23
BOOL fChainPayload = pContainers && pLayoutPayloads; // These are required when parsing chain payloads.
24
BOOL fValidFileSize = FALSE;
25
+ size_t cByteOffset = fChainPayload ? offsetof(BURN_PAYLOAD, sczKey) : offsetof(BURN_PAYLOAD, sczSourcePath);
26
27
// select payload nodes
28
hr = XmlSelectNodes(pixnBundle, L"Payload", &pixnNodes);
@@ -49,7 +43,11 @@ extern "C" HRESULT PayloadsParseFromXml(
43
44
pPayloads->cPayloads = cNodes;
45
52
- // parse search elements
46
+ // create dictionary for payloads
47
+ hr = DictCreateWithEmbeddedKey(&pPayloads->sdhPayloads, pPayloads->cPayloads, reinterpret_cast<void**>(&pPayloads->rgPayloads), cByteOffset, DICT_FLAG_NONE);
48
+ ExitOnFailure(hr, "Failed to create dictionary for payloads.");
49
+
50
+ // parse payload elements
51
for (DWORD i = 0; i < cNodes; ++i)
52
{
53
BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i];
@@ -104,6 +102,8 @@ extern "C" HRESULT PayloadsParseFromXml(
102
// find container
103
hr = ContainerFindById(pContainers, scz, &pPayload->pContainer);
104
ExitOnFailure(hr, "Failed to to find container: %ls", scz);
105
+
106
+ pPayload->pContainer->cParsedPayloads += 1;
107
}
108
109
// @LayoutOnly
@@ -190,12 +190,37 @@ extern "C" HRESULT PayloadsParseFromXml(
190
}
191
}
192
193
+ hr = DictAddValue(pPayloads->sdhPayloads, pPayload);
194
+ ExitOnFailure(hr, "Failed to add payload to payloads dictionary.");
195
+
196
// prepare next iteration
197
ReleaseNullObject(pixnNode);
198
}
199
200
hr = S_OK;
201
202
+ if (pContainers && pContainers->cContainers)
203
+ {
204
+ for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
205
+ {
206
+ BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i];
207
+ BURN_CONTAINER* pContainer = pPayload->pContainer;
208
+
209
+ if (!pContainer)
210
+ {
211
+ continue;
212
+ }
213
+ else if (!pContainer->sdhPayloads)
214
+ {
215
+ hr = DictCreateWithEmbeddedKey(&pContainer->sdhPayloads, pContainer->cParsedPayloads, NULL, offsetof(BURN_PAYLOAD, sczSourcePath), DICT_FLAG_NONE);
216
+ ExitOnFailure(hr, "Failed to create dictionary for container payloads.");
217
+ }
218
+
219
+ hr = DictAddValue(pContainer->sdhPayloads, pPayload);
220
+ ExitOnFailure(hr, "Failed to add payload to container dictionary.");
221
+ }
222
+ }
223
+
224
LExit:
225
ReleaseObject(pixnNodes);
226
ReleaseObject(pixnNode);
@@ -237,6 +262,8 @@ extern "C" void PayloadsUninitialize(
262
MemFree(pPayloads->rgPayloads);
263
}
264
265
+ ReleaseDict(pPayloads->sdhPayloads);
266
+
267
// clear struct
268
memset(pPayloads, 0, sizeof(BURN_PAYLOADS));
269
}
@@ -265,7 +292,7 @@ extern "C" HRESULT PayloadExtractUXContainer(
292
ExitOnFailure(hr, "Failed to get next stream.");
293
294
// find payload by stream name
268
- hr = PayloadFindEmbeddedBySourcePath(pPayloads, sczStreamName, &pPayload);
295
+ hr = PayloadFindEmbeddedBySourcePath(pPayloads->sdhPayloads, sczStreamName, &pPayload);
296
ExitOnFailure(hr, "Failed to find embedded payload: %ls", sczStreamName);
297
298
// make file path
@@ -313,51 +340,22 @@ extern "C" HRESULT PayloadFindById(
340
)
341
{
342
HRESULT hr = S_OK;
316
- BURN_PAYLOAD* pPayload = NULL;
343
318
- for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
319
- {
320
- pPayload = &pPayloads->rgPayloads[i];
321
-
322
- if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczKey, -1, wzId, -1))
323
- {
324
- *ppPayload = pPayload;
325
- ExitFunction1(hr = S_OK);
326
- }
327
- }
344
+ hr = DictGetValue(pPayloads->sdhPayloads, wzId, reinterpret_cast<void**>(ppPayload));
345
329
- hr = E_NOTFOUND;
330
-
331
-LExit:
346
return hr;
347
}
348
349
extern "C" HRESULT PayloadFindEmbeddedBySourcePath(
336
- __in BURN_PAYLOADS* pPayloads,
350
+ __in STRINGDICT_HANDLE sdhPayloads,
351
__in_z LPCWSTR wzStreamName,
352
__out BURN_PAYLOAD** ppPayload
353
)
354
{
355
HRESULT hr = S_OK;
342
- BURN_PAYLOAD* pPayload = NULL;
356
344
- for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
345
- {
346
- pPayload = &pPayloads->rgPayloads[i];
347
-
348
- if (BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging)
349
- {
350
- if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczSourcePath, -1, wzStreamName, -1))
351
- {
352
- *ppPayload = pPayload;
353
- ExitFunction1(hr = S_OK);
354
- }
355
- }
356
- }
357
+ hr = DictGetValue(sdhPayloads, wzStreamName, reinterpret_cast<void**>(ppPayload));
358
358
- hr = E_NOTFOUND;
359
-
360
-LExit:
359
return hr;
360
}
361
src/burn/engine/payload.h
+2
-1
@@ -66,6 +66,7 @@ typedef struct _BURN_PAYLOADS
66
{
67
BURN_PAYLOAD* rgPayloads;
68
DWORD cPayloads;
69
+ STRINGDICT_HANDLE sdhPayloads; // value is BURN_PAYLOAD*
70
} BURN_PAYLOADS;
71
72
typedef struct _BURN_PAYLOAD_GROUP_ITEM
@@ -109,7 +110,7 @@ HRESULT PayloadFindById(
110
__out BURN_PAYLOAD** ppPayload
111
);
112
HRESULT PayloadFindEmbeddedBySourcePath(
112
- __in BURN_PAYLOADS* pPayloads,
113
+ __in STRINGDICT_HANDLE sdhPayloads,
114
__in_z LPCWSTR wzStreamName,
115
__out BURN_PAYLOAD** ppPayload
116
);
src/burn/engine/userexperience.h
+1
-1
@@ -15,7 +15,7 @@ const DWORD MB_RETRYTRYAGAIN = 0xF;
15
16
// structs
17
18
-typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT;
18
+typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT; // forward declare
19
20
typedef struct _BURN_USER_EXPERIENCE
21
{
src/libs/dutil/WixToolset.DUtil/dictutil.cpp
+58
-70
@@ -72,6 +72,14 @@ struct STRINGDICT_STRUCT
72
73
const int STRINGDICT_HANDLE_BYTES = sizeof(STRINGDICT_STRUCT);
74
75
+static HRESULT CreateDict(
76
+ __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle,
77
+ __in DICT_TYPE dtType,
78
+ __in DWORD dwNumExpectedItems,
79
+ __in_opt void** ppvArray,
80
+ __in size_t cByteOffset,
81
+ __in DICT_FLAG dfFlags
82
+ );
83
static HRESULT StringHash(
84
__in const STRINGDICT_STRUCT *psd,
85
__in DWORD dwNumBuckets,
@@ -135,41 +143,7 @@ extern "C" HRESULT DAPI DictCreateWithEmbeddedKey(
143
__in DICT_FLAG dfFlags
144
)
145
{
138
- HRESULT hr = S_OK;
139
-
140
- DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict");
141
-
142
- // Allocate the handle
143
- *psdHandle = static_cast<STRINGDICT_HANDLE>(MemAlloc(sizeof(STRINGDICT_STRUCT), FALSE));
144
- DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object");
145
-
146
- STRINGDICT_STRUCT *psd = static_cast<STRINGDICT_STRUCT *>(*psdHandle);
147
-
148
- // Fill out the new handle's values
149
- psd->dtType = DICT_EMBEDDED_KEY;
150
- psd->dfFlags = dfFlags;
151
- psd->cByteOffset = cByteOffset;
152
- psd->dwBucketSizeIndex = 0;
153
- psd->dwNumItems = 0;
154
- psd->ppvItemList = NULL;
155
- psd->ppvValueArray = ppvArray;
156
-
157
- // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime
158
- // array based on expected number of items and items to buckets ratio
159
- // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end
160
- // this loop past the end of the array!
161
- while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES)-1) &&
162
- MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO)
163
- {
164
- ++psd->dwBucketSizeIndex;
165
- }
166
-
167
- // Finally, allocate our initial buckets
168
- psd->ppvBuckets = static_cast<void**>(MemAlloc(sizeof(void *) * MAX_BUCKET_SIZES[psd->dwBucketSizeIndex], TRUE));
169
- DictExitOnNull(psd->ppvBuckets, hr, E_OUTOFMEMORY, "Failed to allocate buckets for dictionary");
170
-
171
-LExit:
172
- return hr;
146
+ return CreateDict(psdHandle, DICT_EMBEDDED_KEY, dwNumExpectedItems, ppvArray, cByteOffset, dfFlags);
147
}
148
149
// The dict will store a set of keys, with no values associated with them. Use DictAddKey() and DictKeyExists() with this dictionary type.
@@ -179,41 +153,7 @@ extern "C" HRESULT DAPI DictCreateStringList(
153
__in DICT_FLAG dfFlags
154
)
155
{
182
- HRESULT hr = S_OK;
183
-
184
- DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict");
185
-
186
- // Allocate the handle
187
- *psdHandle = static_cast<STRINGDICT_HANDLE>(MemAlloc(sizeof(STRINGDICT_STRUCT), FALSE));
188
- DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object");
189
-
190
- STRINGDICT_STRUCT *psd = static_cast<STRINGDICT_STRUCT *>(*psdHandle);
191
-
192
- // Fill out the new handle's values
193
- psd->dtType = DICT_STRING_LIST;
194
- psd->dfFlags = dfFlags;
195
- psd->cByteOffset = 0;
196
- psd->dwBucketSizeIndex = 0;
197
- psd->dwNumItems = 0;
198
- psd->ppvItemList = NULL;
199
- psd->ppvValueArray = NULL;
200
-
201
- // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime
202
- // array based on expected number of items and items to buckets ratio
203
- // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end
204
- // this loop past the end of the array!
205
- while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES)-1) &&
206
- MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO)
207
- {
208
- ++psd->dwBucketSizeIndex;
209
- }
210
-
211
- // Finally, allocate our initial buckets
212
- psd->ppvBuckets = static_cast<void**>(MemAlloc(sizeof(void *) * MAX_BUCKET_SIZES[psd->dwBucketSizeIndex], TRUE));
213
- DictExitOnNull(psd->ppvBuckets, hr, E_OUTOFMEMORY, "Failed to allocate buckets for dictionary");
214
-
215
-LExit:
216
- return hr;
156
+ return CreateDict(psdHandle, DICT_STRING_LIST, dwNumExpectedItems, NULL, 0, dfFlags);
157
}
158
159
extern "C" HRESULT DAPI DictCreateStringListFromArray(
@@ -467,6 +407,54 @@ extern "C" void DAPI DictDestroy(
407
ReleaseMem(psd);
408
}
409
410
+static HRESULT CreateDict(
411
+ __out_bcount(STRINGDICT_HANDLE_BYTES) STRINGDICT_HANDLE* psdHandle,
412
+ __in DICT_TYPE dtType,
413
+ __in DWORD dwNumExpectedItems,
414
+ __in_opt void** ppvArray,
415
+ __in size_t cByteOffset,
416
+ __in DICT_FLAG dfFlags
417
+ )
418
+{
419
+ HRESULT hr = S_OK;
420
+
421
+ DictExitOnNull(psdHandle, hr, E_INVALIDARG, "Handle not specified while creating dict.");
422
+
423
+ // Allocate the handle
424
+ *psdHandle = static_cast<STRINGDICT_HANDLE>(MemAlloc(sizeof(STRINGDICT_STRUCT), TRUE));
425
+ DictExitOnNull(*psdHandle, hr, E_OUTOFMEMORY, "Failed to allocate dictionary object.");
426
+
427
+ STRINGDICT_STRUCT* psd = static_cast<STRINGDICT_STRUCT*>(*psdHandle);
428
+
429
+ // Fill out the new handle's values
430
+ psd->dtType = dtType;
431
+ psd->dfFlags = dfFlags;
432
+ psd->cByteOffset = cByteOffset;
433
+ psd->ppvValueArray = ppvArray;
434
+
435
+ // Make psd->dwBucketSizeIndex point to the appropriate spot in the prime
436
+ // array based on expected number of items and items to buckets ratio
437
+ // Careful: the "-1" in "countof(MAX_BUCKET_SIZES)-1" ensures we don't end
438
+ // this loop past the end of the array!
439
+ while (psd->dwBucketSizeIndex < (countof(MAX_BUCKET_SIZES) - 1) &&
440
+ MAX_BUCKET_SIZES[psd->dwBucketSizeIndex] < dwNumExpectedItems * MAX_BUCKETS_TO_ITEMS_RATIO)
441
+ {
442
+ ++psd->dwBucketSizeIndex;
443
+ }
444
+
445
+ hr = MemAllocArray(reinterpret_cast<LPVOID*>(&psd->ppvBuckets), sizeof(void*), MAX_BUCKET_SIZES[psd->dwBucketSizeIndex]);
446
+ DictExitOnFailure(hr, "Failed to allocate buckets for dictionary.");
447
+
448
+ if (dwNumExpectedItems)
449
+ {
450
+ hr = MemAllocArray(reinterpret_cast<LPVOID*>(&psd->ppvItemList), sizeof(void*), dwNumExpectedItems);
451
+ DictExitOnFailure(hr, "Failed to pre-allocate item list for dictionary.");
452
+ }
453
+
454
+LExit:
455
+ return hr;
456
+}
457
+
458
static HRESULT StringHash(
459
__in const STRINGDICT_STRUCT *psd,
460
__in DWORD dwNumBuckets,
src/test/burn/TestData/Manual/BundleB/Bundle.wxs
new
+56
@@ -0,0 +1,56 @@
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
+<?ifndef Version?>
4
+<?define Version = 1.0.0.0?>
5
+<?endif?>
6
+
7
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
8
+ <!-- The only difference from the template should be the SplashScreen -->
9
+ <Bundle Name="~$(var.TestGroupName) - $(var.BundleName)" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)" Compressed="yes" SplashScreenSourceFile="..\BafThmutilTesting\theme\star_transparent.bmp">
10
+ <Log Prefix="~$(var.TestGroupName)_$(var.BundleName)" />
11
+
12
+ <Variable Name="TestGroupName" Value="$(var.TestGroupName)" />
13
+
14
+ <?ifdef SoftwareTag?>
15
+ <SoftwareTag Regid="regid.1995-08.com.example" InstallPath="[CommonAppDataFolder]regid.1995-08.com.example" />
16
+ <?endif?>
17
+
18
+ <?ifndef BA?>
19
+ <!-- pulled in through the PackageGroupRef below -->
20
+ <?elseif $(var.BA) = "TestBAdnc"?>
21
+ <!-- pulled in through the PackageGroupRef below -->
22
+ <?elseif $(var.BA) = "TestBA_x64"?>
23
+ <!-- pulled in through the PackageGroupRef below -->
24
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
25
+ <!-- pulled in through the PackageGroupRef below -->
26
+ <?elseif $(var.BA) = "WixBA"?>
27
+ <!-- pulled in through the PackageGroupRef below -->
28
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
29
+ <!-- pulled in through the PackageGroupRef below -->
30
+ <?elseif $(var.BA) = "hyperlinkLicense"?>
31
+ <BootstrapperApplication>
32
+ <bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" />
33
+ </BootstrapperApplication>
34
+ <?else?>
35
+ <BootstrapperApplicationRef Id="$(var.BA)" />
36
+ <?endif?>
37
+
38
+ <Chain>
39
+ <?ifndef BA?>
40
+ <PackageGroupRef Id="TestBA" />
41
+ <?elseif $(var.BA) = "TestBAdnc"?>
42
+ <PackageGroupRef Id="TestBAdnc" />
43
+ <?elseif $(var.BA) = "TestBA_x64"?>
44
+ <PackageGroupRef Id="TestBA_x64" />
45
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
46
+ <PackageGroupRef Id="TestBAdnc_x64" />
47
+ <?elseif $(var.BA) = "WixBA"?>
48
+ <PackageGroupRef Id="WixBA" />
49
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
50
+ <PackageGroupRef Id="WixBAdnc_x64" />
51
+ <?endif?>
52
+
53
+ <PackageGroupRef Id="BundlePackages" />
54
+ </Chain>
55
+ </Bundle>
56
+</Wix>
src/test/burn/TestData/Manual/BundleB/BundleB.wixproj
new
+32
@@ -0,0 +1,32 @@
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
+ <BA>hyperlinkLicense</BA>
6
+ <UpgradeCode>{5DE2F206-3C37-4265-81F7-095284E16B08}</UpgradeCode>
7
+ <HarvestDirectoryAdditionalOptions>-generate payloadgroup</HarvestDirectoryAdditionalOptions>
8
+ </PropertyGroup>
9
+ <ItemGroup>
10
+ <HarvestDirectory Include="BAPayloads">
11
+ <ComponentGroupName>BAPayloads</ComponentGroupName>
12
+ <DirectoryRefId>BAPayloads</DirectoryRefId>
13
+ <Transforms>ba.xslt</Transforms>
14
+ </HarvestDirectory>
15
+ <HarvestDirectory Include="PackagePayloads">
16
+ <ComponentGroupName>PackagePayloads</ComponentGroupName>
17
+ <DirectoryRefId>PackagePayloads</DirectoryRefId>
18
+ <Transforms>package.xslt</Transforms>
19
+ </HarvestDirectory>
20
+ </ItemGroup>
21
+ <ItemGroup>
22
+ <ProjectReference Include="..\PackageA\PackageA.wixproj" />
23
+ </ItemGroup>
24
+ <ItemGroup>
25
+ <PackageReference Include="WixToolset.Bal.wixext" />
26
+ </ItemGroup>
27
+ <!-- We do this dynamically to avoid committing so many files to source control. -->
28
+ <Target Name="CreateThousandsOfFiles" AfterTargets="BeforeBuild">
29
+ <Exec Command='"$(BaseOutputPath)$(Configuration)\netcoreapp3.1\win-x86\testexe.exe" /gf "BAPayloads|10000' WorkingDirectory="$(MSBuildProjectDirectory)" />
30
+ <Exec Command='"$(BaseOutputPath)$(Configuration)\netcoreapp3.1\win-x86\testexe.exe" /gf "PackagePayloads|10000' WorkingDirectory="$(MSBuildProjectDirectory)" />
31
+ </Target>
32
+</Project>
\ No newline at end of file
src/test/burn/TestData/Manual/BundleB/BundleB.wxs
new
+15
@@ -0,0 +1,15 @@
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" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
5
+ <Fragment>
6
+ <BootstrapperApplication>
7
+ <PayloadGroupRef Id="BAPayloads" />
8
+ </BootstrapperApplication>
9
+ <PackageGroup Id="BundlePackages">
10
+ <MsiPackage Id="PackageA" SourceFile="$(var.PackageA.TargetPath)">
11
+ <PayloadGroupRef Id="PackagePayloads" />
12
+ </MsiPackage>
13
+ </PackageGroup>
14
+ </Fragment>
15
+</Wix>
src/test/burn/TestData/Manual/BundleB/ba.xslt
new
+21
@@ -0,0 +1,21 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3
+ xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
4
+ xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"
5
+>
6
+ <xsl:output method="xml" indent="yes"/>
7
+
8
+ <xsl:template match="@* | node()">
9
+ <xsl:copy>
10
+ <xsl:apply-templates select="@* | node()"/>
11
+ </xsl:copy>
12
+ </xsl:template>
13
+
14
+ <xsl:template match="wix:Payload" >
15
+ <xsl:copy>
16
+ <xsl:apply-templates select="@* | node()"/>
17
+ <xsl:attribute name="Id">ba_<xsl:value-of select="substring(@SourceFile, 11)" /></xsl:attribute>
18
+ <xsl:attribute name="SourceFile">BAPayloads<xsl:value-of select="substring(@SourceFile, 10)" /></xsl:attribute>
19
+ </xsl:copy>
20
+ </xsl:template>
21
+</xsl:stylesheet>
src/test/burn/TestData/Manual/BundleB/package.xslt
new
+21
@@ -0,0 +1,21 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3
+ xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
4
+ xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"
5
+>
6
+ <xsl:output method="xml" indent="yes"/>
7
+
8
+ <xsl:template match="@* | node()">
9
+ <xsl:copy>
10
+ <xsl:apply-templates select="@* | node()"/>
11
+ </xsl:copy>
12
+ </xsl:template>
13
+
14
+ <xsl:template match="wix:Payload" >
15
+ <xsl:copy>
16
+ <xsl:apply-templates select="@* | node()"/>
17
+ <xsl:attribute name="Id">package_<xsl:value-of select="substring(@SourceFile, 11)" /></xsl:attribute>
18
+ <xsl:attribute name="SourceFile">PackagePayloads<xsl:value-of select="substring(@SourceFile, 10)" /></xsl:attribute>
19
+ </xsl:copy>
20
+ </xsl:template>
21
+</xsl:stylesheet>
src/test/burn/TestExe/Task.cs
+22
@@ -59,6 +59,24 @@ namespace TestExe
59
}
60
}
61
62
+ public class GenerateFilesTask : Task
63
+ {
64
+ public GenerateFilesTask(string Data) : base(Data) { }
65
+
66
+ public override void RunTask()
67
+ {
68
+ string[] tokens = this.data.Split(new char[] { '|' }, 2);
69
+ string folderPath = System.Environment.ExpandEnvironmentVariables(tokens[0]);
70
+ long size = long.Parse(tokens[1]);
71
+ Directory.CreateDirectory(folderPath);
72
+ var bytes = new byte[0];
73
+ for (long i = 1; i <= size; i++)
74
+ {
75
+ File.WriteAllBytes(Path.Combine(folderPath, $"{i}.txt"), bytes);
76
+ }
77
+ }
78
+ }
79
+
80
public class LargeFileTask : Task
81
{
82
public LargeFileTask(string Data) : base(Data) { }
@@ -163,6 +181,10 @@ namespace TestExe
181
t = new SleepRandomTask(args[i + 1]);
182
tasks.Add(t);
183
break;
184
+ case "/gf":
185
+ t = new GenerateFilesTask(args[i + 1]);
186
+ tasks.Add(t);
187
+ break;
188
case "/lf":
189
t = new LargeFileTask(args[i + 1]);
190
tasks.Add(t);
src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+5
-2
@@ -239,15 +239,18 @@ namespace WixToolset.Core.Burn
239
{
240
foreach (var facade in facades.Values)
241
{
242
- facade.PackageSymbol.Size = 0;
242
+ // Use temporary variable to avoid excessive number of PreviousValues.
243
+ long packageSize = 0;
244
245
var packagePayloads = packagesPayloads[facade.PackageId];
246
247
foreach (var payload in packagePayloads.Values)
248
{
248
- facade.PackageSymbol.Size += payload.FileSize.Value;
249
+ packageSize += payload.FileSize.Value;
250
}
251
252
+ facade.PackageSymbol.Size = packageSize;
253
+
254
if (!facade.PackageSymbol.InstallSize.HasValue)
255
{
256
facade.PackageSymbol.InstallSize = facade.PackageSymbol.Size;
src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+4
-1
@@ -604,12 +604,15 @@ namespace WixToolset.Core.Burn.Bundles
604
605
// Write the BundleExtension elements.
606
var bundleExtensions = this.Section.Symbols.OfType<WixBundleExtensionSymbol>();
607
+ var uxPayloadsById = this.UXContainerPayloads.ToDictionary(p => p.Id.Id);
608
609
foreach (var bundleExtension in bundleExtensions)
610
{
611
+ var entryPayload = uxPayloadsById[bundleExtension.PayloadRef];
612
+
613
writer.WriteStartElement("BundleExtension");
614
writer.WriteAttributeString("Id", bundleExtension.Id.Id);
612
- writer.WriteAttributeString("EntryPayloadId", bundleExtension.PayloadRef);
615
+ writer.WriteAttributeString("EntryPayloadSourcePath", entryPayload.EmbeddedId);
616
617
writer.WriteEndElement();
618
}
src/wix/WixToolset.Core/Compile/CompilerPayload.cs
+2
-2
@@ -143,7 +143,7 @@ namespace WixToolset.Core
143
}
144
}
145
146
- public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType = ComplexReferenceChildType.Unknown, string previousId = null)
146
+ public WixBundlePayloadSymbol CreatePayloadSymbol(ComplexReferenceParentType parentType, string parentId)
147
{
148
WixBundlePayloadSymbol symbol = null;
149
@@ -179,7 +179,7 @@ namespace WixToolset.Core
179
Version = this.Version,
180
});
181
182
- this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, previousType, previousId);
182
+ this.Core.CreateGroupAndOrderingRows(this.SourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, symbol.Id.Id, ComplexReferenceChildType.Unknown, null);
183
}
184
185
return symbol;
src/wix/WixToolset.Core/Compiler_Bundle.cs
+20
-50
@@ -351,7 +351,7 @@ namespace WixToolset.Core
351
this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads);
352
break;
353
case "PayloadGroupRef":
354
- this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads, ComplexReferenceChildType.Unknown, null);
354
+ this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads);
355
break;
356
case "RelatedBundle":
357
this.ParseRelatedBundleElement(child);
@@ -649,8 +649,6 @@ namespace WixToolset.Core
649
{
650
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
651
Identifier id = null;
652
- Identifier previousId = null;
653
- var previousType = ComplexReferenceChildType.Unknown;
652
653
foreach (var attrib in node.Attributes())
654
{
@@ -675,16 +673,13 @@ namespace WixToolset.Core
673
switch (child.Name.LocalName)
674
{
675
case "BootstrapperApplicationDll":
678
- previousId = this.ParseBootstrapperApplicationDllElement(child, id, previousType, previousId);
679
- previousType = ComplexReferenceChildType.Payload;
676
+ this.ParseBootstrapperApplicationDllElement(child, id);
677
break;
678
case "Payload":
682
- previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
683
- previousType = ComplexReferenceChildType.Payload;
679
+ this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
680
break;
681
case "PayloadGroupRef":
686
- previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
687
- previousType = ComplexReferenceChildType.PayloadGroup;
682
+ this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
683
break;
684
default:
685
this.Core.UnexpectedElement(node, child);
@@ -708,9 +703,7 @@ namespace WixToolset.Core
703
/// </summary>
704
/// <param name="node">Element to parse</param>
705
/// <param name="defaultId"></param>
711
- /// <param name="previousType"></param>
712
- /// <param name="previousId"></param>
713
- private Identifier ParseBootstrapperApplicationDllElement(XElement node, Identifier defaultId, ComplexReferenceChildType previousType, Identifier previousId)
706
+ private Identifier ParseBootstrapperApplicationDllElement(XElement node, Identifier defaultId)
707
{
708
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
709
var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node)
@@ -805,7 +798,7 @@ namespace WixToolset.Core
798
799
if (!this.Core.EncounteredError)
800
{
808
- compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id);
801
+ compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id);
802
this.Core.AddSymbol(new WixBundleContainerSymbol(sourceLineNumbers, Compiler.BurnUXContainerId)
803
{
804
Name = "bundle-ux.cab",
@@ -829,8 +822,6 @@ namespace WixToolset.Core
822
{
823
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
824
string id = null;
832
- Identifier previousId = null;
833
- var previousType = ComplexReferenceChildType.Unknown;
825
826
foreach (var attrib in node.Attributes())
827
{
@@ -859,12 +850,10 @@ namespace WixToolset.Core
850
switch (child.Name.LocalName)
851
{
852
case "Payload":
862
- previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
863
- previousType = ComplexReferenceChildType.Payload;
853
+ this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
854
break;
855
case "PayloadGroupRef":
866
- previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
867
- previousType = ComplexReferenceChildType.PayloadGroup;
856
+ this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
857
break;
858
default:
859
this.Core.UnexpectedElement(node, child);
@@ -1195,8 +1184,6 @@ namespace WixToolset.Core
1184
{
1185
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1186
var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node);
1198
- Identifier previousId = null;
1199
- var previousType = ComplexReferenceChildType.Unknown;
1187
1188
// This list lets us evaluate extension attributes *after* all core attributes
1189
// have been parsed and dealt with, regardless of authoring order.
@@ -1241,9 +1228,7 @@ namespace WixToolset.Core
1228
this.Core.ParseExtensionAttribute(node, extensionAttribute, context);
1229
}
1230
1244
- compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id, previousType, previousId?.Id);
1245
- previousId = compilerPayload.Id;
1246
- previousType = ComplexReferenceChildType.Payload;
1231
+ compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.Container, Compiler.BurnUXContainerId.Id);
1232
1233
foreach (var child in node.Elements())
1234
{
@@ -1252,12 +1237,10 @@ namespace WixToolset.Core
1237
switch (child.Name.LocalName)
1238
{
1239
case "Payload":
1255
- previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
1256
- previousType = ComplexReferenceChildType.Payload;
1240
+ this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
1241
break;
1242
case "PayloadGroupRef":
1259
- previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId);
1260
- previousType = ComplexReferenceChildType.PayloadGroup;
1243
+ this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId);
1244
break;
1245
default:
1246
this.Core.UnexpectedElement(node, child);
@@ -1388,12 +1371,9 @@ namespace WixToolset.Core
1371
/// <param name="node">Element to parse</param>
1372
/// <param name="parentType">ComplexReferenceParentType of parent element. (BA or PayloadGroup)</param>
1373
/// <param name="parentId">Identifier of parent element.</param>
1391
- /// <param name="previousType"></param>
1392
- /// <param name="previousId"></param>
1393
- private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId)
1374
+ private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId)
1375
{
1376
Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
1396
- Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType);
1377
1378
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1379
var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node);
@@ -1470,7 +1450,7 @@ namespace WixToolset.Core
1450
}
1451
}
1452
1473
- compilerPayload.CreatePayloadSymbol(parentType, parentId?.Id, previousType, previousId?.Id);
1453
+ compilerPayload.CreatePayloadSymbol(parentType, parentId?.Id);
1454
1455
return compilerPayload.Id;
1456
}
@@ -1514,8 +1494,6 @@ namespace WixToolset.Core
1494
id = Identifier.Invalid;
1495
}
1496
1517
- var previousType = ComplexReferenceChildType.Unknown;
1518
- Identifier previousId = null;
1497
foreach (var child in node.Elements())
1498
{
1499
if (CompilerCore.WixNamespace == child.Name.Namespace)
@@ -1536,12 +1514,10 @@ namespace WixToolset.Core
1514
packageType = WixBundlePackageType.Msu;
1515
break;
1516
case "Payload":
1539
- previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId);
1540
- previousType = ComplexReferenceChildType.Payload;
1517
+ this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id);
1518
break;
1519
case "PayloadGroupRef":
1543
- previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId);
1544
- previousType = ComplexReferenceChildType.PayloadGroup;
1520
+ this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id);
1521
break;
1522
default:
1523
this.Core.UnexpectedElement(node, child);
@@ -1551,12 +1527,9 @@ namespace WixToolset.Core
1527
if (packageType.HasValue)
1528
{
1529
var compilerPayload = this.ParsePackagePayloadElement(null, child, packageType.Value, null);
1554
- var payloadSymbol = compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.PayloadGroup, id?.Id, previousType, previousId?.Id);
1530
+ var payloadSymbol = compilerPayload.CreatePayloadSymbol(ComplexReferenceParentType.PayloadGroup, id?.Id);
1531
if (payloadSymbol != null)
1532
{
1557
- previousId = payloadSymbol.Id;
1558
- previousType = ComplexReferenceChildType.Payload;
1559
-
1533
this.CreatePackagePayloadSymbol(payloadSymbol.SourceLineNumbers, packageType.Value, payloadSymbol.Id, ComplexReferenceParentType.PayloadGroup, id);
1534
}
1535
}
@@ -1582,12 +1555,9 @@ namespace WixToolset.Core
1555
/// <param name="node">Element to parse.</param>
1556
/// <param name="parentType">ComplexReferenceParentType of parent element (BA or PayloadGroup).</param>
1557
/// <param name="parentId">Identifier of parent element.</param>
1585
- /// <param name="previousType"></param>
1586
- /// <param name="previousId"></param>
1587
- private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId)
1558
+ private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId)
1559
{
1560
Debug.Assert(ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
1590
- Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType);
1561
1562
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1563
Identifier id = null;
@@ -1620,7 +1590,7 @@ namespace WixToolset.Core
1590
1591
this.Core.ParseForExtensionElements(node);
1592
1623
- this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, previousType, previousId?.Id);
1593
+ this.Core.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id?.Id, ComplexReferenceChildType.Unknown, null);
1594
1595
return id;
1596
}
@@ -2259,10 +2229,10 @@ namespace WixToolset.Core
2229
}
2230
break;
2231
case "Payload":
2262
- this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null);
2232
+ this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id);
2233
break;
2234
case "PayloadGroupRef":
2265
- this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null);
2235
+ this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id);
2236
break;
2237
case "Provides":
2238
this.ParseProvidesElement(child, packageType, id.Id, out _);
src/wix/WixToolset.Core/Link/WixGroupingOrdering.cs
+2
-1
@@ -645,13 +645,14 @@ namespace WixToolset.Core.Link
645
this.AddAfter(nestedAfterItems, messageHandler);
646
}
647
648
- // We *don't* propagate ordering information from Packages or
648
+ // We *don't* propagate ordering information from Packages, PayloadGroups, or
649
// Containers to their children, because ordering doesn't matter
650
// for them, and a Payload in two Packages (or Containers) can
651
// cause a circular reference to occur.
652
private bool ShouldItemPropagateChildOrdering()
653
{
654
if (String.Equals(nameof(ComplexReferenceParentType.Package), this.Type, StringComparison.Ordinal) ||
655
+ String.Equals(nameof(ComplexReferenceParentType.PayloadGroup), this.Type, StringComparison.Ordinal) ||
656
String.Equals(nameof(ComplexReferenceParentType.Container), this.Type, StringComparison.Ordinal))
657
{
658
return false;
src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
+3
-7
@@ -211,15 +211,11 @@ namespace WixToolsetTest.CoreIntegration
211
212
var bundleExtensions = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:BundleExtension");
213
Assert.Equal(1, bundleExtensions.Count);
214
- Assert.Equal("<BundleExtension Id='ExampleBext' EntryPayloadId='ExampleBext' />", bundleExtensions[0].GetTestXml());
214
+ Assert.Equal("<BundleExtension Id='ExampleBext' EntryPayloadSourcePath='u1' />", bundleExtensions[0].GetTestXml());
215
216
var bundleExtensionPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:UX/burn:Payload[@Id='ExampleBext']");
217
Assert.Equal(1, bundleExtensionPayloads.Count);
218
- var ignored = new Dictionary<string, List<string>>
219
- {
220
- { "Payload", new List<string> { "FileSize", "Hash", "SourcePath" } },
221
- };
222
- Assert.Equal("<Payload Id='ExampleBext' FilePath='fakebext.dll' SourcePath='*' />", bundleExtensionPayloads[0].GetTestXml(ignored));
218
+ Assert.Equal("<Payload Id='ExampleBext' FilePath='fakebext.dll' SourcePath='u1' />", bundleExtensionPayloads[0].GetTestXml());
219
}
220
}
221
@@ -259,7 +255,7 @@ namespace WixToolsetTest.CoreIntegration
255
256
var bundleExtensions = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:BundleExtension");
257
Assert.Equal(1, bundleExtensions.Count);
262
- Assert.Equal("<BundleExtension Id='ExampleBundleExtension' EntryPayloadId='ExampleBundleExtension' />", bundleExtensions[0].GetTestXml());
258
+ Assert.Equal("<BundleExtension Id='ExampleBundleExtension' EntryPayloadSourcePath='u1' />", bundleExtensions[0].GetTestXml());
259
260
var extensionSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:ExtensionSearch");
261
Assert.Equal(2, extensionSearches.Count);