From 5f744a8c7da649721f7022dc174febd79e7e3e14 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Sat, 14 Jan 2023 17:29:40 -0800 Subject: Remove extension data after extensions get PreDecompileTables callback Also update Util.wixext decompiler extension to handle the new elements that compile into CustomActions with no additional table data. These exposed the weakness in the decompiler where extension data was removed before extensions got a chance to pre-decompile. Fixes 7151 --- .../TestData/Queries/Package.wxs | 10 ++-- .../WixToolsetTest.Util/UtilExtensionFixture.cs | 43 +++++++++++++++- src/ext/Util/wixext/UtilConstants.cs | 6 +++ src/ext/Util/wixext/UtilDecompiler.cs | 58 +++++++++++++++++++--- 4 files changed, 102 insertions(+), 15 deletions(-) (limited to 'src/ext') diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs index abf0dbb4..d85db478 100644 --- a/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/Queries/Package.wxs @@ -1,4 +1,4 @@ - + @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs index 2b59b2a9..a9b37870 100644 --- a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs +++ b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs @@ -9,6 +9,7 @@ namespace WixToolsetTest.Util using WixInternal.Core.TestPackage; using WixToolset.Util; using Xunit; + using System.Xml.Linq; public class UtilExtensionFixture { @@ -62,9 +63,20 @@ namespace WixToolsetTest.Util var output = Path.Combine(folder, "decompile.xml"); build.BuildAndDecompileAndBuild(Build, Decompile, output); - File.Exists(output); - } + var doc = XDocument.Load(output); + var utilElementNames = doc.Descendants() + .Where(e => e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/util") + .Select(e => e.Name.LocalName) + .OrderBy(s => s) + .ToArray(); + WixAssert.CompareLineByLine(new[] + { + "FileShare", + "FileSharePermission", + "User", + }, utilElementNames); + } [Fact] public void CanBuildCloseApplication() @@ -225,11 +237,38 @@ namespace WixToolsetTest.Util "CustomAction:Wix4BroadcastEnvironmentChange_A64\t65\tWix4UtilCA_A64\tWixBroadcastEnvironmentChange\t", "CustomAction:Wix4BroadcastSettingChange_A64\t65\tWix4UtilCA_A64\tWixBroadcastSettingChange\t", "CustomAction:Wix4CheckRebootRequired_A64\t65\tWix4UtilCA_A64\tWixCheckRebootRequired\t", + "CustomAction:Wix4QueryNativeMachine_A64\t257\tWix4UtilCA_A64\tWixQueryNativeMachine\t", "CustomAction:Wix4QueryOsDriverInfo_A64\t257\tWix4UtilCA_A64\tWixQueryOsDriverInfo\t", "CustomAction:Wix4QueryOsInfo_A64\t257\tWix4UtilCA_A64\tWixQueryOsInfo\t", }, results.OrderBy(s => s).ToArray()); } + [Fact] + public void CanBuildAndDecompiileQueries() + { + var folder = TestData.Get(@"TestData\Queries"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + var output = Path.Combine(folder, "decompile.xml"); + + build.BuildAndDecompileAndBuild(Build, Decompile, output); + + var doc = XDocument.Load(output); + var utilElementNames = doc.Descendants() + .Where(e => e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/util") + .Select(e => e.Name.LocalName) + .OrderBy(s => s) + .ToArray(); + WixAssert.CompareLineByLine(new[] + { + "BroadcastEnvironmentChange", + "BroadcastSettingChange", + "CheckRebootRequired", + "QueryNativeMachine", + "QueryWindowsDriverInfo", + "QueryWindowsSuiteInfo", + }, utilElementNames); + } + [Fact] public void CanBuildWithXmlConfig() { diff --git a/src/ext/Util/wixext/UtilConstants.cs b/src/ext/Util/wixext/UtilConstants.cs index 93616e44..c1f5f820 100644 --- a/src/ext/Util/wixext/UtilConstants.cs +++ b/src/ext/Util/wixext/UtilConstants.cs @@ -11,6 +11,9 @@ namespace WixToolset.Util { internal static readonly XNamespace Namespace = "http://wixtoolset.org/schemas/v4/wxs/util"; + internal static readonly XName BroadcastEnvironmentChange = Namespace + "BroadcastEnvironmentChange"; + internal static readonly XName BroadcastSettingChange = Namespace + "BroadcastSettingChange"; + internal static readonly XName CheckRebootRequired = Namespace + "CheckRebootRequired"; internal static readonly XName CloseApplicationName = Namespace + "CloseApplication"; internal static readonly XName EventManifestName = Namespace + "EventManifest"; internal static readonly XName FileShareName = Namespace + "FileShare"; @@ -21,6 +24,9 @@ namespace WixToolset.Util internal static readonly XName PerfCounterName = Namespace + "PerfCounter"; internal static readonly XName PerfCounterManifestName = Namespace + "PerfCounterManifest"; internal static readonly XName PermissionExName = Namespace + "PermissionEx"; + internal static readonly XName QueryNativeMachine = Namespace + "QueryNativeMachine"; + internal static readonly XName QueryWindowsDriverInfo = Namespace + "QueryWindowsDriverInfo"; + internal static readonly XName QueryWindowsSuiteInfo = Namespace + "QueryWindowsSuiteInfo"; internal static readonly XName RemoveFolderExName = Namespace + "RemoveFolderEx"; internal static readonly XName RestartResourceName = Namespace + "RestartResource"; internal static readonly XName ServiceConfigName = Namespace + "ServiceConfig"; diff --git a/src/ext/Util/wixext/UtilDecompiler.cs b/src/ext/Util/wixext/UtilDecompiler.cs index 1201fdd5..0a78201e 100644 --- a/src/ext/Util/wixext/UtilDecompiler.cs +++ b/src/ext/Util/wixext/UtilDecompiler.cs @@ -3,16 +3,15 @@ namespace WixToolset.Util { using System; + using System.Collections; + using System.Collections.Generic; using System.IO; + using System.Linq; using System.Text; - using System.Collections; - using System.Diagnostics; - + using System.Xml.Linq; using WixToolset.Data; - using WixToolset.Extensibility; using WixToolset.Data.WindowsInstaller; - using System.Collections.Generic; - using System.Xml.Linq; + using WixToolset.Extensibility; using WixToolset.Util.Symbols; /// @@ -22,16 +21,47 @@ namespace WixToolset.Util { public override IReadOnlyCollection TableDefinitions => UtilTableDefinitions.All; + private static readonly Dictionary CustomActionMapping = new Dictionary() + { + { "Wix4BroadcastEnvironmentChange_X86", UtilConstants.BroadcastEnvironmentChange }, + { "Wix4BroadcastEnvironmentChange_X64", UtilConstants.BroadcastEnvironmentChange }, + { "Wix4BroadcastEnvironmentChange_ARM64", UtilConstants.BroadcastEnvironmentChange }, + { "Wix4BroadcastSettingChange_X86", UtilConstants.BroadcastSettingChange }, + { "Wix4BroadcastSettingChange_X64", UtilConstants.BroadcastSettingChange }, + { "Wix4BroadcastSettingChange_ARM64", UtilConstants.BroadcastSettingChange }, + { "Wix4CheckRebootRequired_X86", UtilConstants.CheckRebootRequired }, + { "Wix4CheckRebootRequired_X64", UtilConstants.CheckRebootRequired }, + { "Wix4CheckRebootRequired_ARM64", UtilConstants.CheckRebootRequired }, + { "Wix4QueryNativeMachine_X86", UtilConstants.QueryNativeMachine }, + { "Wix4QueryNativeMachine_X64", UtilConstants.QueryNativeMachine }, + { "Wix4QueryNativeMachine_ARM64", UtilConstants.QueryNativeMachine }, + { "Wix4QueryOsDriverInfo_X86", UtilConstants.QueryWindowsDriverInfo }, + { "Wix4QueryOsDriverInfo_X64", UtilConstants.QueryWindowsDriverInfo }, + { "Wix4QueryOsDriverInfo_ARM64", UtilConstants.QueryWindowsDriverInfo }, + { "Wix4QueryOsInfo_X86", UtilConstants.QueryWindowsSuiteInfo }, + { "Wix4QueryOsInfo_X64", UtilConstants.QueryWindowsSuiteInfo }, + { "Wix4QueryOsInfo_ARM64", UtilConstants.QueryWindowsSuiteInfo }, + }; + + private IReadOnlyCollection customActionNames; + /// /// Called at the beginning of the decompilation of a database. /// /// The collection of all tables. public override void PreDecompileTables(TableIndexedCollection tables) { + this.RememberCustomActionNames(tables); this.CleanupSecureCustomProperties(tables); this.CleanupInternetShortcutRemoveFileTables(tables); } + private void RememberCustomActionNames(TableIndexedCollection tables) + { + var customActionTable = tables["CustomAction"]; + this.customActionNames = customActionTable?.Rows.Select(r => r.GetPrimaryKey()).Distinct().ToList() ?? (IReadOnlyCollection)Array.Empty(); + } + /// /// Decompile the SecureCustomProperties field to PropertyRefs for known extension properties. /// @@ -195,6 +225,7 @@ namespace WixToolset.Util /// The collection of all tables. public override void PostDecompileTables(TableIndexedCollection tables) { + this.FinalizeCustomActions(); this.FinalizePerfmonTable(tables); this.FinalizePerfmonManifestTable(tables); this.FinalizeSecureObjectsTable(tables); @@ -223,7 +254,7 @@ namespace WixToolset.Util AttributeIfNotNull("RebootPrompt", 0x2 == (attribute & 0x2)), AttributeIfNotNull("ElevatedCloseMessage", 0x4 == (attribute & 0x4)), NumericAttributeIfNotNull("Sequence", row, 5), - NumericAttributeIfNotNull("Property", row, 6) + AttributeIfNotNull("Property", row, 6) ); } } @@ -379,7 +410,7 @@ namespace WixToolset.Util if (this.DecompilerHelper.TryGetIndexedElement("Wix4FileShare", row.FieldAsString(0), out var fileShare) || this.DecompilerHelper.TryGetIndexedElement("FileShare", row.FieldAsString(0), out fileShare)) { - fileShare.Add(fileSharePermission); + fileShare.Add(fileSharePermission); } else { @@ -695,6 +726,17 @@ namespace WixToolset.Util } } + private void FinalizeCustomActions() + { + foreach (var customActionName in this.customActionNames) + { + if (CustomActionMapping.TryGetValue(customActionName, out var elementName)) + { + this.DecompilerHelper.AddElementToRoot(elementName); + } + } + } + /// /// Finalize the Perfmon table. /// -- cgit v1.2.3-55-g6feb