aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-03-21 23:22:23 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-03-22 12:26:48 -0500
commitfc3e4722307c86b5d06918f0721b98323735bb40 (patch)
tree1a8c6fa25274cce22f0e274a6b3b1c5c06614745
parent9bb420a19538321789b8300051cd595d6c00c710 (diff)
downloadwix-fc3e4722307c86b5d06918f0721b98323735bb40.tar.gz
wix-fc3e4722307c86b5d06918f0721b98323735bb40.tar.bz2
wix-fc3e4722307c86b5d06918f0721b98323735bb40.zip
Add `ExePackage/@Bundle` to opt-in to v3 behavior.
Automatically add '-norestart' for bundle ExePackages. Fixes 6252
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleExePackageSymbol.cs3
-rw-r--r--src/burn/engine/core.cpp5
-rw-r--r--src/burn/engine/elevation.cpp44
-rw-r--r--src/burn/engine/exeengine.cpp91
-rw-r--r--src/burn/engine/package.h4
-rw-r--r--src/burn/engine/plan.cpp33
-rw-r--r--src/burn/engine/plan.h3
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp10
-rw-r--r--src/ext/NetFx/wixlib/NetCore3.1.12_x64.wxs4
-rw-r--r--src/ext/NetFx/wixlib/NetCore3_Platform.wxi12
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs6
-rw-r--r--src/wix/WixToolset.Core/Compiler_Bundle.cs19
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs23
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs4
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/BadInput/BundleExePackageWithNetfxProtocol.wxs8
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/SharedPayloadsBetweenPackages/SharedPayloadsBetweenPackages.wxs4
16 files changed, 233 insertions, 40 deletions
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleExePackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleExePackageSymbol.cs
index 64a21321..fc891f13 100644
--- a/src/api/wix/WixToolset.Data/Symbols/WixBundleExePackageSymbol.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleExePackageSymbol.cs
@@ -39,6 +39,7 @@ namespace WixToolset.Data.Symbols
39 public enum WixBundleExePackageAttributes 39 public enum WixBundleExePackageAttributes
40 { 40 {
41 None = 0, 41 None = 0,
42 Bundle = 1,
42 } 43 }
43 44
44 public class WixBundleExePackageSymbol : IntermediateSymbol 45 public class WixBundleExePackageSymbol : IntermediateSymbol
@@ -89,6 +90,8 @@ namespace WixToolset.Data.Symbols
89 set => this.Set((int)WixBundleExePackageSymbolFields.ExeProtocol, value); 90 set => this.Set((int)WixBundleExePackageSymbolFields.ExeProtocol, value);
90 } 91 }
91 92
93 public bool IsBundle => this.Attributes.HasFlag(WixBundleExePackageAttributes.Bundle);
94
92 public bool Repairable => this.RepairCommand != null; 95 public bool Repairable => this.RepairCommand != null;
93 96
94 public bool Uninstallable => this.UninstallCommand != null; 97 public bool Uninstallable => this.UninstallCommand != null;
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index e077d224..551843f2 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -234,6 +234,11 @@ extern "C" HRESULT CoreInitializeConstants(
234 pPackage->Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors; 234 pPackage->Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
235 pPackage->Bundle.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory; 235 pPackage->Bundle.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
236 } 236 }
237 else if (BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fBundle)
238 {
239 pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors;
240 pPackage->Exe.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
241 }
237 } 242 }
238 243
239LExit: 244LExit:
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index ea56e242..8488b649 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -940,6 +940,15 @@ extern "C" HRESULT ElevationExecuteExePackage(
940 hr = BuffWriteNumber(&pbData, &cbData, fRollback); 940 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
941 ExitOnFailure(hr, "Failed to write rollback."); 941 ExitOnFailure(hr, "Failed to write rollback.");
942 942
943 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies);
944 ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer.");
945
946 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors);
947 ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer.");
948
949 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory);
950 ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer.");
951
943 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); 952 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
944 ExitOnFailure(hr, "Failed to write variables."); 953 ExitOnFailure(hr, "Failed to write variables.");
945 954
@@ -2844,6 +2853,9 @@ static HRESULT OnExecuteExePackage(
2844 LPWSTR sczPackage = NULL; 2853 LPWSTR sczPackage = NULL;
2845 DWORD dwRollback = 0; 2854 DWORD dwRollback = 0;
2846 BURN_EXECUTE_ACTION executeAction = { }; 2855 BURN_EXECUTE_ACTION executeAction = { };
2856 LPWSTR sczIgnoreDependencies = NULL;
2857 LPWSTR sczAncestors = NULL;
2858 LPWSTR sczEngineWorkingDirectory = NULL;
2847 BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2859 BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2848 2860
2849 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; 2861 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
@@ -2858,6 +2870,15 @@ static HRESULT OnExecuteExePackage(
2858 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); 2870 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
2859 ExitOnFailure(hr, "Failed to read rollback."); 2871 ExitOnFailure(hr, "Failed to read rollback.");
2860 2872
2873 hr = BuffReadString(pbData, cbData, &iData, &sczIgnoreDependencies);
2874 ExitOnFailure(hr, "Failed to read the list of dependencies to ignore.");
2875
2876 hr = BuffReadString(pbData, cbData, &iData, &sczAncestors);
2877 ExitOnFailure(hr, "Failed to read the list of ancestors.");
2878
2879 hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingDirectory);
2880 ExitOnFailure(hr, "Failed to read the custom working directory.");
2881
2861 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); 2882 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2862 ExitOnFailure(hr, "Failed to read variables."); 2883 ExitOnFailure(hr, "Failed to read variables.");
2863 2884
@@ -2869,11 +2890,34 @@ static HRESULT OnExecuteExePackage(
2869 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage); 2890 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage);
2870 } 2891 }
2871 2892
2893 // Pass the list of dependencies to ignore, if any, to the related bundle.
2894 if (sczIgnoreDependencies && *sczIgnoreDependencies)
2895 {
2896 hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2897 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
2898 }
2899
2900 // Pass the list of ancestors, if any, to the related bundle.
2901 if (sczAncestors && *sczAncestors)
2902 {
2903 hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0);
2904 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
2905 }
2906
2907 if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory)
2908 {
2909 hr = StrAllocString(&executeAction.exePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2910 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
2911 }
2912
2872 // Execute EXE package. 2913 // Execute EXE package.
2873 hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); 2914 hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
2874 ExitOnFailure(hr, "Failed to execute EXE package."); 2915 ExitOnFailure(hr, "Failed to execute EXE package.");
2875 2916
2876LExit: 2917LExit:
2918 ReleaseStr(sczEngineWorkingDirectory);
2919 ReleaseStr(sczAncestors);
2920 ReleaseStr(sczIgnoreDependencies);
2877 ReleaseStr(sczPackage); 2921 ReleaseStr(sczPackage);
2878 PlanUninitializeExecuteAction(&executeAction); 2922 PlanUninitializeExecuteAction(&executeAction);
2879 2923
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index a1049006..9754002f 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -40,6 +40,10 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
40 hr = XmlGetYesNoAttribute(pixnExePackage, L"Uninstallable", &pPackage->Exe.fUninstallable); 40 hr = XmlGetYesNoAttribute(pixnExePackage, L"Uninstallable", &pPackage->Exe.fUninstallable);
41 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Uninstallable."); 41 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Uninstallable.");
42 42
43 // @Bundle
44 hr = XmlGetYesNoAttribute(pixnExePackage, L"Bundle", &pPackage->Exe.fBundle);
45 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Bundle.");
46
43 // @Protocol 47 // @Protocol
44 hr = XmlGetAttributeEx(pixnExePackage, L"Protocol", &scz); 48 hr = XmlGetAttributeEx(pixnExePackage, L"Protocol", &scz);
45 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Protocol."); 49 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Protocol.");
@@ -87,6 +91,7 @@ extern "C" void ExeEnginePackageUninitialize(
87 ReleaseStr(pPackage->Exe.sczInstallArguments); 91 ReleaseStr(pPackage->Exe.sczInstallArguments);
88 ReleaseStr(pPackage->Exe.sczRepairArguments); 92 ReleaseStr(pPackage->Exe.sczRepairArguments);
89 ReleaseStr(pPackage->Exe.sczUninstallArguments); 93 ReleaseStr(pPackage->Exe.sczUninstallArguments);
94 ReleaseStr(pPackage->Exe.sczIgnoreDependencies);
90 ReleaseMem(pPackage->Exe.rgExitCodes); 95 ReleaseMem(pPackage->Exe.rgExitCodes);
91 96
92 // free command-line arguments 97 // free command-line arguments
@@ -286,6 +291,24 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
286 pAction->exePackage.pPackage = pPackage; 291 pAction->exePackage.pPackage = pPackage;
287 pAction->exePackage.action = pPackage->rollback; 292 pAction->exePackage.action = pPackage->rollback;
288 293
294 if (pPackage->Exe.sczIgnoreDependencies)
295 {
296 hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
297 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
298 }
299
300 if (pPackage->Exe.wzAncestors)
301 {
302 hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
303 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
304 }
305
306 if (pPackage->Exe.wzEngineWorkingDirectory)
307 {
308 hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0);
309 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
310 }
311
289 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors. 312 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
290 313
291 hr = PlanExecuteCheckpoint(pPlan); 314 hr = PlanExecuteCheckpoint(pPlan);
@@ -302,6 +325,24 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
302 pAction->exePackage.pPackage = pPackage; 325 pAction->exePackage.pPackage = pPackage;
303 pAction->exePackage.action = pPackage->execute; 326 pAction->exePackage.action = pPackage->execute;
304 327
328 if (pPackage->Exe.sczIgnoreDependencies)
329 {
330 hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
331 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
332 }
333
334 if (pPackage->Exe.wzAncestors)
335 {
336 hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
337 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
338 }
339
340 if (pPackage->Exe.wzEngineWorkingDirectory)
341 {
342 hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0);
343 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
344 }
345
305 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors. 346 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
306 } 347 }
307 348
@@ -406,27 +447,53 @@ extern "C" HRESULT ExeEngineExecutePackage(
406 } 447 }
407 448
408 // build command 449 // build command
409 if (*sczArguments) 450 AppAppendCommandLineArgument(&sczCommand, sczExecutablePath);
451 ExitOnFailure(hr, "Failed to create executable command.");
452
453 if (pPackage->Exe.fBundle)
454 {
455 hr = StrAllocConcat(&sczCommand, L" -norestart", 0);
456 ExitOnFailure(hr, "Failed to append quiet argument.");
457
458 // Add the list of dependencies to ignore, if any, to the burn command line.
459 if (pExecuteAction->exePackage.sczIgnoreDependencies)
460 {
461 hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
462 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
463 }
464
465 // Add the list of ancestors, if any, to the burn command line.
466 if (pExecuteAction->exePackage.sczAncestors)
467 {
468 hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
469 ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
470 }
471
472 if (pExecuteAction->exePackage.sczEngineWorkingDirectory)
473 {
474 hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, NULL);
475 ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line.");
476 }
477
478 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL);
479 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
480 }
481
482 // Always add user supplied arguments last.
483 if (sczArguments && *sczArguments)
410 { 484 {
411 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); 485 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
412 ExitOnFailure(hr, "Failed to format argument string."); 486 ExitOnFailure(hr, "Failed to format argument string.");
413 487
414 hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsFormatted);
415 ExitOnFailure(hr, "Failed to create executable command.");
416
417 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); 488 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
418 ExitOnFailure(hr, "Failed to format obfuscated argument string."); 489 ExitOnFailure(hr, "Failed to format obfuscated argument string.");
419 490
420 hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsObfuscated); 491 hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated);
421 } 492 ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments.");
422 else
423 {
424 hr = StrAllocFormatted(&sczCommand, L"\"%ls\"", sczExecutablePath);
425 ExitOnFailure(hr, "Failed to create executable command.");
426 493
427 hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\"", sczExecutablePath); 494 hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
495 ExitOnFailure(hr, "Failed to copy formatted arguments.");
428 } 496 }
429 ExitOnFailure(hr, "Failed to create obfuscated executable command.");
430 497
431 // Log before we add the secret pipe name and client token for embedded processes. 498 // Log before we add the secret pipe name and client token for embedded processes.
432 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated); 499 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index e3e39c51..deab47b7 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -324,7 +324,11 @@ typedef struct _BURN_PACKAGE
324 LPWSTR sczInstallArguments; 324 LPWSTR sczInstallArguments;
325 LPWSTR sczRepairArguments; 325 LPWSTR sczRepairArguments;
326 LPWSTR sczUninstallArguments; 326 LPWSTR sczUninstallArguments;
327 LPWSTR sczIgnoreDependencies;
328 LPCWSTR wzAncestors; // points directly into engine state.
329 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
327 330
331 BOOL fBundle;
328 BOOL fPseudoPackage; 332 BOOL fPseudoPackage;
329 BOOL fFireAndForget; 333 BOOL fFireAndForget;
330 BOOL fRepairable; 334 BOOL fRepairable;
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 5e1d2654..cb50b0c9 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -291,6 +291,12 @@ extern "C" void PlanUninitializeExecuteAction(
291 ReleaseStr(pExecuteAction->relatedBundle.sczEngineWorkingDirectory); 291 ReleaseStr(pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
292 break; 292 break;
293 293
294 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
295 ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies);
296 ReleaseStr(pExecuteAction->exePackage.sczAncestors);
297 ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory);
298 break;
299
294 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 300 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
295 ReleaseStr(pExecuteAction->msiPackage.sczLogPath); 301 ReleaseStr(pExecuteAction->msiPackage.sczLogPath);
296 ReleaseMem(pExecuteAction->msiPackage.rgFeatures); 302 ReleaseMem(pExecuteAction->msiPackage.rgFeatures);
@@ -1495,26 +1501,21 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1495 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) 1501 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i)
1496 { 1502 {
1497 BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE; 1503 BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE;
1504 BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1505 BOOL fBundle = FALSE;
1498 1506
1499 switch (pPlan->rgExecuteActions[i].type) 1507 switch (pPlan->rgExecuteActions[i].type)
1500 { 1508 {
1501 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: 1509 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
1502 packageAction = pPlan->rgExecuteActions[i].relatedBundle.action; 1510 packageAction = pPlan->rgExecuteActions[i].relatedBundle.action;
1503 1511 pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1504 if (BOOTSTRAPPER_ACTION_STATE_NONE != packageAction) 1512 fBundle = TRUE;
1505 {
1506 BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1507 if (pPackage->cDependencyProviders)
1508 {
1509 // Bundles only support a single provider key.
1510 const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders;
1511 DictAddKey(sdProviderKeys, pProvider->sczKey);
1512 }
1513 }
1514 break; 1513 break;
1515 1514
1516 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 1515 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1517 packageAction = pPlan->rgExecuteActions[i].exePackage.action; 1516 packageAction = pPlan->rgExecuteActions[i].exePackage.action;
1517 pPackage = pPlan->rgExecuteActions[i].exePackage.pPackage;
1518 fBundle = TRUE;
1518 break; 1519 break;
1519 1520
1520 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 1521 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
@@ -1530,6 +1531,16 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1530 break; 1531 break;
1531 } 1532 }
1532 1533
1534 if (fBundle && BOOTSTRAPPER_ACTION_STATE_NONE != packageAction)
1535 {
1536 if (pPackage->cDependencyProviders)
1537 {
1538 // Bundles only support a single provider key.
1539 const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders;
1540 DictAddKey(sdProviderKeys, pProvider->sczKey);
1541 }
1542 }
1543
1533 fExecutingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_NONE != packageAction; 1544 fExecutingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_NONE != packageAction;
1534 fInstallingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_INSTALL == packageAction || BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE == packageAction; 1545 fInstallingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_INSTALL == packageAction || BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE == packageAction;
1535 } 1546 }
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 834d2567..6e9a1ff5 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -164,6 +164,9 @@ typedef struct _BURN_EXECUTE_ACTION
164 { 164 {
165 BURN_PACKAGE* pPackage; 165 BURN_PACKAGE* pPackage;
166 BOOTSTRAPPER_ACTION_STATE action; 166 BOOTSTRAPPER_ACTION_STATE action;
167 LPWSTR sczIgnoreDependencies;
168 LPWSTR sczAncestors;
169 LPWSTR sczEngineWorkingDirectory;
167 } exePackage; 170 } exePackage;
168 struct 171 struct
169 { 172 {
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 2febe277..143ca7d7 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -716,7 +716,7 @@ namespace Bootstrapper
716 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 716 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
717 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"ExeA"); 717 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"ExeA");
718 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 718 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
719 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL); 719 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
720 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 720 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
721 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 721 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
722 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 722 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
@@ -727,7 +727,7 @@ namespace Bootstrapper
727 dwExecuteCheckpointId = 2; 727 dwExecuteCheckpointId = 2;
728 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 728 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
729 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 729 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
730 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL); 730 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
731 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 731 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
732 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 732 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
733 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 733 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2125,7 +2125,7 @@ namespace Bootstrapper
2125 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2125 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2126 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2126 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2127 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web"); 2127 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2128 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", BOOTSTRAPPER_ACTION_STATE_INSTALL); 2128 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
2129 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2129 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2130 dwExecuteCheckpointId += 1; // cache checkpoints 2130 dwExecuteCheckpointId += 1; // cache checkpoints
2131 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2131 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2683,13 +2683,15 @@ namespace Bootstrapper
2683 __in BOOL fRollback, 2683 __in BOOL fRollback,
2684 __in DWORD dwIndex, 2684 __in DWORD dwIndex,
2685 __in LPCWSTR wzPackageId, 2685 __in LPCWSTR wzPackageId,
2686 __in BOOTSTRAPPER_ACTION_STATE action 2686 __in BOOTSTRAPPER_ACTION_STATE action,
2687 __in LPCWSTR wzIgnoreDependencies
2687 ) 2688 )
2688 { 2689 {
2689 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); 2690 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
2690 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type); 2691 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
2691 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId); 2692 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
2692 Assert::Equal<DWORD>(action, pAction->exePackage.action); 2693 Assert::Equal<DWORD>(action, pAction->exePackage.action);
2694 NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
2693 Assert::Equal<BOOL>(FALSE, pAction->fDeleted); 2695 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
2694 } 2696 }
2695 2697
diff --git a/src/ext/NetFx/wixlib/NetCore3.1.12_x64.wxs b/src/ext/NetFx/wixlib/NetCore3.1.12_x64.wxs
index 596b4b48..b69bb37f 100644
--- a/src/ext/NetFx/wixlib/NetCore3.1.12_x64.wxs
+++ b/src/ext/NetFx/wixlib/NetCore3.1.12_x64.wxs
@@ -20,7 +20,7 @@
20 <WixVariable Id="AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)RepairArguments" Value="" Overridable="yes" /> 20 <WixVariable Id="AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)RepairArguments" Value="" Overridable="yes" />
21 21
22 <PackageGroup Id="$(var.AspNetCoreRedistId)"> 22 <PackageGroup Id="$(var.AspNetCoreRedistId)">
23 <ExePackage InstallArguments="$(var.AspNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.AspNetCoreRedistId)" Vital="yes" Permanent="yes" Protocol="burn" LogPathVariable="$(var.AspNetCoreRedistLog)" Cache="remove"> 23 <ExePackage InstallArguments="$(var.AspNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.AspNetCoreRedistId)" Vital="yes" Permanent="yes" Bundle="yes" LogPathVariable="$(var.AspNetCoreRedistLog)" Cache="remove">
24 <ExePackagePayload Name="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)PackageDirectory)aspnetcore-runtime-$(var.NetCoreVersion)-win-$(var.NetCorePlatform).exe" DownloadUrl="$(var.AspNetCoreRedistLink)" ProductName="Microsoft ASP.NET Core 3.1.12 - Shared Framework" Description="Microsoft ASP.NET Core 3.1.12 - Shared Framework" CertificatePublicKey="3756E9BBF4461DCD0AA68E0D1FCFFA9CEA47AC18" CertificateThumbprint="2485A7AFA98E178CB8F30C9838346B514AEA4769" Hash="5CE9839CAE90FB2936033431F2905E97C7DC080DC50108D58714939CCCC6A265694B8259A3BF742A68BF04D9CFFB0602B0306DD401C4CE644BDB96C7D1168E59" Size="7841808" Version="3.1.12.21070" /> 24 <ExePackagePayload Name="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)PackageDirectory)aspnetcore-runtime-$(var.NetCoreVersion)-win-$(var.NetCorePlatform).exe" DownloadUrl="$(var.AspNetCoreRedistLink)" ProductName="Microsoft ASP.NET Core 3.1.12 - Shared Framework" Description="Microsoft ASP.NET Core 3.1.12 - Shared Framework" CertificatePublicKey="3756E9BBF4461DCD0AA68E0D1FCFFA9CEA47AC18" CertificateThumbprint="2485A7AFA98E178CB8F30C9838346B514AEA4769" Hash="5CE9839CAE90FB2936033431F2905E97C7DC080DC50108D58714939CCCC6A265694B8259A3BF742A68BF04D9CFFB0602B0306DD401C4CE644BDB96C7D1168E59" Size="7841808" Version="3.1.12.21070" />
25 </ExePackage> 25 </ExePackage>
26 </PackageGroup> 26 </PackageGroup>
@@ -35,7 +35,7 @@
35 <WixVariable Id="DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)RepairArguments" Value="" Overridable="yes" /> 35 <WixVariable Id="DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)RepairArguments" Value="" Overridable="yes" />
36 36
37 <PackageGroup Id="$(var.DesktopNetCoreRedistId)"> 37 <PackageGroup Id="$(var.DesktopNetCoreRedistId)">
38 <ExePackage InstallArguments="$(var.DesktopNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.DesktopNetCoreRedistId)" Vital="yes" Permanent="yes" Protocol="burn" LogPathVariable="$(var.DesktopNetCoreRedistLog)" Cache="remove"> 38 <ExePackage InstallArguments="$(var.DesktopNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.DesktopNetCoreRedistId)" Vital="yes" Permanent="yes" Bundle="yes" LogPathVariable="$(var.DesktopNetCoreRedistLog)" Cache="remove">
39 <ExePackagePayload Name="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)PackageDirectory)windowsdesktop-runtime-$(var.NetCoreVersion)-win-$(var.NetCorePlatform).exe" DownloadUrl="$(var.DesktopNetCoreRedistLink)" ProductName="Microsoft Windows Desktop Runtime - 3.1.12 (x64)" Description="Microsoft Windows Desktop Runtime - 3.1.12 (x64)" CertificatePublicKey="3756E9BBF4461DCD0AA68E0D1FCFFA9CEA47AC18" CertificateThumbprint="2485A7AFA98E178CB8F30C9838346B514AEA4769" Hash="CD69B8722B2FF175FADD6774AB6A97F89292FC57A15CEC95218E79FFF1E26F46A7EFFFB15CE0F6D22B83B991F7083BB5C04F5158F87D298EA0F204933F8ECD27" Size="54284816" Version="3.1.12.29719" /> 39 <ExePackagePayload Name="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)PackageDirectory)windowsdesktop-runtime-$(var.NetCoreVersion)-win-$(var.NetCorePlatform).exe" DownloadUrl="$(var.DesktopNetCoreRedistLink)" ProductName="Microsoft Windows Desktop Runtime - 3.1.12 (x64)" Description="Microsoft Windows Desktop Runtime - 3.1.12 (x64)" CertificatePublicKey="3756E9BBF4461DCD0AA68E0D1FCFFA9CEA47AC18" CertificateThumbprint="2485A7AFA98E178CB8F30C9838346B514AEA4769" Hash="CD69B8722B2FF175FADD6774AB6A97F89292FC57A15CEC95218E79FFF1E26F46A7EFFFB15CE0F6D22B83B991F7083BB5C04F5158F87D298EA0F204933F8ECD27" Size="54284816" Version="3.1.12.29719" />
40 </ExePackage> 40 </ExePackage>
41 </PackageGroup> 41 </PackageGroup>
diff --git a/src/ext/NetFx/wixlib/NetCore3_Platform.wxi b/src/ext/NetFx/wixlib/NetCore3_Platform.wxi
index c7aaca50..88e672be 100644
--- a/src/ext/NetFx/wixlib/NetCore3_Platform.wxi
+++ b/src/ext/NetFx/wixlib/NetCore3_Platform.wxi
@@ -6,20 +6,20 @@
6 <?define AspNetCoreId = ASPNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?> 6 <?define AspNetCoreId = ASPNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?>
7 <?define AspNetCoreRedistId = AspNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?> 7 <?define AspNetCoreRedistId = AspNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?>
8 <?define AspNetCoreRedistLog = AspNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?> 8 <?define AspNetCoreRedistLog = AspNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?>
9 <?define AspNetCoreRedistInstallArguments = /install /quiet /norestart /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?> 9 <?define AspNetCoreRedistInstallArguments = /install /quiet /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?>
10 <?define AspNetCoreRedistUninstallArguments = /uninstall /quiet /norestart /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?> 10 <?define AspNetCoreRedistUninstallArguments = /uninstall /quiet /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?>
11 11
12 <?define DesktopNetCoreId = DESKTOPNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?> 12 <?define DesktopNetCoreId = DESKTOPNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?>
13 <?define DesktopNetCoreRedistId = DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?> 13 <?define DesktopNetCoreRedistId = DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?>
14 <?define DesktopNetCoreRedistLog = DesktopNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?> 14 <?define DesktopNetCoreRedistLog = DesktopNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?>
15 <?define DesktopNetCoreRedistInstallArguments = /install /quiet /norestart /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?> 15 <?define DesktopNetCoreRedistInstallArguments = /install /quiet /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?>
16 <?define DesktopNetCoreRedistUninstallArguments = /uninstall /quiet /norestart /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?> 16 <?define DesktopNetCoreRedistUninstallArguments = /uninstall /quiet /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?>
17 17
18 <?define DotNetCoreId = DOTNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?> 18 <?define DotNetCoreId = DOTNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?>
19 <?define DotNetCoreRedistId = DotNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?> 19 <?define DotNetCoreRedistId = DotNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?>
20 <?define DotNetCoreRedistLog = DotNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?> 20 <?define DotNetCoreRedistLog = DotNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?>
21 <?define DotNetCoreRedistInstallArguments = /install /quiet /norestart /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?> 21 <?define DotNetCoreRedistInstallArguments = /install /quiet /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?>
22 <?define DotNetCoreRedistUninstallArguments = /uninstall /quiet /norestart /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?> 22 <?define DotNetCoreRedistUninstallArguments = /uninstall /quiet /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?>
23 23
24 <?define DotNetHomeId = DOTNETHOME_$(var.NetCorePlatform)?> 24 <?define DotNetHomeId = DOTNETHOME_$(var.NetCorePlatform)?>
25 <?define NetCoreEulaLink = https://go.microsoft.com/fwlink/?LinkId=329770?> 25 <?define NetCoreEulaLink = https://go.microsoft.com/fwlink/?LinkId=329770?>
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
index 38cdf943..6a684fe0 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
@@ -389,10 +389,16 @@ namespace WixToolset.Core.Burn.Bundles
389 writer.WriteAttributeString("Uninstallable", exePackage.Uninstallable ? "yes" : "no"); 389 writer.WriteAttributeString("Uninstallable", exePackage.Uninstallable ? "yes" : "no");
390 writer.WriteAttributeString("RepairArguments", exePackage.RepairCommand); 390 writer.WriteAttributeString("RepairArguments", exePackage.RepairCommand);
391 writer.WriteAttributeString("Repairable", exePackage.Repairable ? "yes" : "no"); 391 writer.WriteAttributeString("Repairable", exePackage.Repairable ? "yes" : "no");
392
392 if (!String.IsNullOrEmpty(exePackage.ExeProtocol)) 393 if (!String.IsNullOrEmpty(exePackage.ExeProtocol))
393 { 394 {
394 writer.WriteAttributeString("Protocol", exePackage.ExeProtocol); 395 writer.WriteAttributeString("Protocol", exePackage.ExeProtocol);
395 } 396 }
397
398 if (exePackage.IsBundle)
399 {
400 writer.WriteAttributeString("Bundle", "yes");
401 }
396 } 402 }
397 else if (package.SpecificPackageSymbol is WixBundleMsiPackageSymbol msiPackage) // MSI 403 else if (package.SpecificPackageSymbol is WixBundleMsiPackageSymbol msiPackage) // MSI
398 { 404 {
diff --git a/src/wix/WixToolset.Core/Compiler_Bundle.cs b/src/wix/WixToolset.Core/Compiler_Bundle.cs
index e1e26620..2f31c774 100644
--- a/src/wix/WixToolset.Core/Compiler_Bundle.cs
+++ b/src/wix/WixToolset.Core/Compiler_Bundle.cs
@@ -1999,6 +1999,7 @@ namespace WixToolset.Core
1999 var enableFeatureSelection = YesNoType.NotSet; 1999 var enableFeatureSelection = YesNoType.NotSet;
2000 var forcePerMachine = YesNoType.NotSet; 2000 var forcePerMachine = YesNoType.NotSet;
2001 CompilerPayload childPackageCompilerPayload = null; 2001 CompilerPayload childPackageCompilerPayload = null;
2002 var bundle = YesNoType.NotSet;
2002 var slipstream = YesNoType.NotSet; 2003 var slipstream = YesNoType.NotSet;
2003 var hasPayloadInfo = false; 2004 var hasPayloadInfo = false;
2004 2005
@@ -2089,6 +2090,10 @@ namespace WixToolset.Core
2089 case "Vital": 2090 case "Vital":
2090 vital = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 2091 vital = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2091 break; 2092 break;
2093 case "Bundle":
2094 bundle = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2095 allowed = (packageType == WixBundlePackageType.Exe);
2096 break;
2092 case "InstallArguments": 2097 case "InstallArguments":
2093 installArguments = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 2098 installArguments = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2094 allowed = (packageType == WixBundlePackageType.Exe); 2099 allowed = (packageType == WixBundlePackageType.Exe);
@@ -2248,12 +2253,21 @@ namespace WixToolset.Core
2248 this.Core.Write(WarningMessages.AttributeShouldContain(sourceLineNumbers, node.Name.LocalName, "UninstallArguments", uninstallArguments, expectedArgument, "Protocol", "netfx4")); 2253 this.Core.Write(WarningMessages.AttributeShouldContain(sourceLineNumbers, node.Name.LocalName, "UninstallArguments", uninstallArguments, expectedArgument, "Protocol", "netfx4"));
2249 } 2254 }
2250 } 2255 }
2256
2257 if (bundle == YesNoType.Yes)
2258 {
2259 this.Core.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "Protocol", protocol, "Bundle", "yes"));
2260 }
2251 } 2261 }
2252 else if (!protocol.Equals("burn", StringComparison.Ordinal) && !protocol.Equals("none", StringComparison.Ordinal)) 2262 else if (!protocol.Equals("burn", StringComparison.Ordinal) && !protocol.Equals("none", StringComparison.Ordinal))
2253 { 2263 {
2254 this.Core.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, node.Name.LocalName, "Protocol", protocol, "none, burn, netfx4")); 2264 this.Core.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, node.Name.LocalName, "Protocol", protocol, "none, burn, netfx4"));
2255 } 2265 }
2256 } 2266 }
2267 else if (bundle == YesNoType.Yes)
2268 {
2269 protocol = "burn";
2270 }
2257 } 2271 }
2258 else if (packageType == WixBundlePackageType.Msp) 2272 else if (packageType == WixBundlePackageType.Msp)
2259 { 2273 {
@@ -2409,9 +2423,12 @@ namespace WixToolset.Core
2409 switch (packageType) 2423 switch (packageType)
2410 { 2424 {
2411 case WixBundlePackageType.Exe: 2425 case WixBundlePackageType.Exe:
2426 WixBundleExePackageAttributes exeAttributes = 0;
2427 exeAttributes |= (YesNoType.Yes == bundle) ? WixBundleExePackageAttributes.Bundle : 0;
2428
2412 this.Core.AddSymbol(new WixBundleExePackageSymbol(sourceLineNumbers, id) 2429 this.Core.AddSymbol(new WixBundleExePackageSymbol(sourceLineNumbers, id)
2413 { 2430 {
2414 Attributes = WixBundleExePackageAttributes.None, 2431 Attributes = exeAttributes,
2415 DetectCondition = detectCondition, 2432 DetectCondition = detectCondition,
2416 InstallCommand = installArguments, 2433 InstallCommand = installArguments,
2417 RepairCommand = repairArguments, 2434 RepairCommand = repairArguments,
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs
index e5d6ecf1..ab38e9ae 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs
@@ -86,6 +86,29 @@ namespace WixToolsetTest.CoreIntegration
86 } 86 }
87 87
88 [Fact] 88 [Fact]
89 public void BundleExePackageWithNetfxProtocolIsRejected()
90 {
91 var folder = TestData.Get(@"TestData\BadInput");
92
93 using (var fs = new DisposableFileSystem())
94 {
95 var baseFolder = fs.GetFolder();
96 var intermediateFolder = Path.Combine(baseFolder, "obj");
97 var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib");
98
99 var result = WixRunner.Execute(new[]
100 {
101 "build",
102 Path.Combine(folder, "BundleExePackageWithNetfxProtocol.wxs"),
103 "-intermediateFolder", intermediateFolder,
104 "-o", wixlibPath,
105 });
106
107 Assert.Equal(193, result.ExitCode);
108 }
109 }
110
111 [Fact]
89 public void BundleVariableWithBadTypeIsRejected() 112 public void BundleVariableWithBadTypeIsRejected()
90 { 113 {
91 var folder = TestData.Get(@"TestData\BadInput"); 114 var folder = TestData.Get(@"TestData\BadInput");
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
index 7f92f90b..08ffea33 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
@@ -354,8 +354,8 @@ namespace WixToolsetTest.CoreIntegration
354 { "ExePackage", new List<string> { "CacheId", "InstallSize", "Size" } }, 354 { "ExePackage", new List<string> { "CacheId", "InstallSize", "Size" } },
355 }; 355 };
356 Assert.Equal(2, exePackageElements.Count); 356 Assert.Equal(2, exePackageElements.Count);
357 Assert.Equal("<ExePackage Id='credwiz.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' LogPathVariable='WixBundleLog_credwiz.exe' RollbackLogPathVariable='WixBundleRollbackLog_credwiz.exe' DetectCondition='none' InstallArguments='' UninstallArguments='-foo' Uninstallable='yes' RepairArguments='' Repairable='no'><PayloadRef Id='credwiz.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[0].GetTestXml(ignoreAttributesByElementName)); 357 Assert.Equal("<ExePackage Id='credwiz.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' LogPathVariable='WixBundleLog_credwiz.exe' RollbackLogPathVariable='WixBundleRollbackLog_credwiz.exe' DetectCondition='none' InstallArguments='' UninstallArguments='-foo' Uninstallable='yes' RepairArguments='' Repairable='no' Protocol='burn' Bundle='yes'><PayloadRef Id='credwiz.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[0].GetTestXml(ignoreAttributesByElementName));
358 Assert.Equal("<ExePackage Id='cscript.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_cscript.exe' RollbackLogPathVariable='WixBundleRollbackLog_cscript.exe' DetectCondition='none' InstallArguments='' UninstallArguments='' Uninstallable='yes' RepairArguments='' Repairable='no'><PayloadRef Id='cscript.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[1].GetTestXml(ignoreAttributesByElementName)); 358 Assert.Equal("<ExePackage Id='cscript.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_cscript.exe' RollbackLogPathVariable='WixBundleRollbackLog_cscript.exe' DetectCondition='none' InstallArguments='' UninstallArguments='' Uninstallable='yes' RepairArguments='' Repairable='no' Protocol='none' Bundle='yes'><PayloadRef Id='cscript.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[1].GetTestXml(ignoreAttributesByElementName));
359 } 359 }
360 } 360 }
361 361
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BadInput/BundleExePackageWithNetfxProtocol.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BadInput/BundleExePackageWithNetfxProtocol.wxs
new file mode 100644
index 00000000..ab82f60d
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BadInput/BundleExePackageWithNetfxProtocol.wxs
@@ -0,0 +1,8 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment>
4 <PackageGroup Id="BundlePackages">
5 <ExePackage SourceFile="burn.exe" Bundle="yes" Protocol="netfx4" DetectCondition="none" InstallArguments="/q /norestart" UninstallArguments="/q /norestart" />
6 </PackageGroup>
7 </Fragment>
8</Wix>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SharedPayloadsBetweenPackages/SharedPayloadsBetweenPackages.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SharedPayloadsBetweenPackages/SharedPayloadsBetweenPackages.wxs
index 2897a4ac..55f9d110 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SharedPayloadsBetweenPackages/SharedPayloadsBetweenPackages.wxs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SharedPayloadsBetweenPackages/SharedPayloadsBetweenPackages.wxs
@@ -2,10 +2,10 @@
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment> 3 <Fragment>
4 <PackageGroup Id="BundlePackages"> 4 <PackageGroup Id="BundlePackages">
5 <ExePackage SourceFile="C:\Windows\system32\credwiz.exe" Permanent="yes" DetectCondition="none" UninstallArguments="-foo"> 5 <ExePackage SourceFile="C:\Windows\system32\credwiz.exe" Permanent="yes" DetectCondition="none" UninstallArguments="-foo" Bundle="yes">
6 <PayloadGroupRef Id="SharedPayloads" /> 6 <PayloadGroupRef Id="SharedPayloads" />
7 </ExePackage> 7 </ExePackage>
8 <ExePackage SourceFile="C:\Windows\system32\cscript.exe" Permanent="yes" DetectCondition="none" UninstallArguments=""> 8 <ExePackage SourceFile="C:\Windows\system32\cscript.exe" Permanent="yes" DetectCondition="none" UninstallArguments="" Bundle="yes" Protocol="none">
9 <PayloadGroupRef Id="SharedPayloads" /> 9 <PayloadGroupRef Id="SharedPayloads" />
10 </ExePackage> 10 </ExePackage>
11 </PackageGroup> 11 </PackageGroup>