diff --git a/src/ext/Util/ca/test.cpp b/src/ext/Util/ca/test.cpp
index e9d02ed39..8f1c238b7 100644
--- a/src/ext/Util/ca/test.cpp
+++ b/src/ext/Util/ca/test.cpp
@@ -39,6 +39,21 @@ static LRESULT CALLBACK WndProc(
);
+/******************************************************************
+WixCancelWhenDeferred - entry point for WixCancelWhenDeferred
+ custom action which always cancels when running as a deferred
+ custom action (otherwise it blindly succeeds). It's useful when
+ testing the rollback of deferred custom actions: Schedule it
+ immediately after the rollback/deferred CA pair you're testing
+ and it will fail, causing your rollback CA to get invoked.
+********************************************************************/
+extern "C" UINT __stdcall WixCancelWhenDeferred(
+ __in MSIHANDLE hInstall
+)
+{
+ return ::MsiGetMode(hInstall, MSIRUNMODE_SCHEDULED) ? ERROR_INSTALL_USEREXIT : ERROR_SUCCESS;
+}
+
/******************************************************************
WixFailWhenDeferred - entry point for WixFailWhenDeferred
custom action which always fails when running as a deferred
diff --git a/src/ext/Util/ca/utilca.def b/src/ext/Util/ca/utilca.def
index 2aeb54f4c..f525233dd 100644
--- a/src/ext/Util/ca/utilca.def
+++ b/src/ext/Util/ca/utilca.def
@@ -82,6 +82,7 @@ EXPORTS
WixShellExecBinary
WixUnelevatedShellExec
; test.cpp
+ WixCancelWhenDeferred
WixFailWhenDeferred
WixWaitForEvent
; TouchFile.cpp
diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/Failures/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/Failures/Package.wxs
new file mode 100644
index 000000000..76975b696
--- /dev/null
+++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/Failures/Package.wxs
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
index b29607c7e..1f39601d9 100644
--- a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
+++ b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
@@ -100,6 +100,21 @@ public void CanBuildCloseApplication()
}, results.OrderBy(s => s).ToArray());
}
+ [TestMethod]
+ public void CanBuildWithFailures()
+ {
+ var folder = TestData.Get(@"TestData\Failures");
+ var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder });
+
+ var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction");
+ WixAssert.CompareLineByLine(
+ [
+ "Binary:Wix4UtilCA_X64\t[Binary data]",
+ "CustomAction:Wix4FailWhenDeferred_X64\t1025\tWix4UtilCA_X64\tWixFailWhenDeferred\t",
+ "CustomAction:Wix8CancelWhenDeferred_X64\t1025\tWix4UtilCA_X64\tWixCancelWhenDeferred\t",
+ ], [.. results.OrderBy(s => s)]);
+ }
+
[TestMethod]
public void CanBuildInternetShortcutInProduct()
{
diff --git a/src/ext/Util/wixext/UtilCompiler.cs b/src/ext/Util/wixext/UtilCompiler.cs
index 919cc49b2..1d11f37fa 100644
--- a/src/ext/Util/wixext/UtilCompiler.cs
+++ b/src/ext/Util/wixext/UtilCompiler.cs
@@ -210,6 +210,7 @@ public override IComponentKeyPath ParsePossibleKeyPathElement(Intermediate inter
break;
case "BroadcastEnvironmentChange":
case "BroadcastSettingChange":
+ case "CancelWhenDeferred":
case "CheckRebootRequired":
case "ExitEarlyWithSuccess":
case "FailWhenDeferred":
@@ -328,6 +329,7 @@ public override IComponentKeyPath ParsePossibleKeyPathElement(Intermediate inter
{
case "BroadcastEnvironmentChange":
case "BroadcastSettingChange":
+ case "CancelWhenDeferred":
case "CheckRebootRequired":
case "ExitEarlyWithSuccess":
case "FailWhenDeferred":
@@ -358,6 +360,7 @@ private void AddCustomActionReference(Intermediate intermediate, IntermediateSec
return;
}
+ var prefix = "Wix4";
var customAction = element.Name.LocalName;
switch (element.Name.LocalName)
{
@@ -370,6 +373,10 @@ private void AddCustomActionReference(Intermediate intermediate, IntermediateSec
case "WaitForEventDeferred":
//default: customAction = element.Name.LocalName;
break;
+ case "CancelWhenDeferred":
+ prefix = "Wix8";
+ //default: customAction = element.Name.LocalName;
+ break;
case "QueryWindowsDirectories":
customAction = "QueryOsDirs";
break;
@@ -400,7 +407,7 @@ private void AddCustomActionReference(Intermediate intermediate, IntermediateSec
this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
- this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4" + customAction, this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
+ this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, prefix + customAction, this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
}
///
diff --git a/src/ext/Util/wixlib/UtilExtension_Platform.wxi b/src/ext/Util/wixlib/UtilExtension_Platform.wxi
index d28c8df93..6316eaf1b 100644
--- a/src/ext/Util/wixlib/UtilExtension_Platform.wxi
+++ b/src/ext/Util/wixlib/UtilExtension_Platform.wxi
@@ -4,6 +4,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/ext/caDecor.h b/src/ext/caDecor.h
index 4a09e0759..9484d74ca 100644
--- a/src/ext/caDecor.h
+++ b/src/ext/caDecor.h
@@ -31,3 +31,13 @@
#else
#define CUSTOM_ACTION_DECORATION6(f) L"Wix6" f L"_X86"
#endif
+
+#if defined(_M_ARM64)
+#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_A64"
+#elif defined(_M_AMD64)
+#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_X64"
+#elif defined(_M_ARM)
+#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_ARM"
+#else
+#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_X86"
+#endif
diff --git a/src/ext/caDecor.wxi b/src/ext/caDecor.wxi
index 236b21540..c92af980a 100644
--- a/src/ext/caDecor.wxi
+++ b/src/ext/caDecor.wxi
@@ -19,6 +19,12 @@
+
+
+
+
+
+
diff --git a/src/wix/Directory.Build.targets b/src/wix/Directory.Build.targets
index 78b83e604..287499325 100644
--- a/src/wix/Directory.Build.targets
+++ b/src/wix/Directory.Build.targets
@@ -4,7 +4,7 @@
-
+
diff --git a/src/xsd/util/CancelWhenDeferred.xsd b/src/xsd/util/CancelWhenDeferred.xsd
new file mode 100644
index 000000000..062be147b
--- /dev/null
+++ b/src/xsd/util/CancelWhenDeferred.xsd
@@ -0,0 +1,11 @@
+
+
+ Schedules the CancelWhenDeferred custom action for the current platform.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/xsd/util/order.txt b/src/xsd/util/order.txt
index 63f854aea..1181e97a1 100644
--- a/src/xsd/util/order.txt
+++ b/src/xsd/util/order.txt
@@ -33,6 +33,7 @@ element|XmlFile
element|XmlConfig
element|BroadcastEnvironmentChange
element|BroadcastSettingChange
+element|CancelWhenDeferred
element|CheckRebootRequired
element|ExitEarlyWithSuccess
element|FailWhenDeferred