aboutsummaryrefslogtreecommitdiff
path: root/src/ext
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext')
-rw-r--r--src/ext/Util/Util.wixext.sln4
-rw-r--r--src/ext/Util/Util.wixext.v3.ncrunchsolution6
-rw-r--r--src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs20
-rw-r--r--src/ext/Util/wixext/UtilCompiler.cs36
-rw-r--r--src/ext/Util/wixext/UtilConstants.cs21
-rw-r--r--src/ext/Util/wixext/UtilDecompiler.cs1272
-rw-r--r--src/ext/Util/wixext/UtilExtensionFactory.cs1
-rw-r--r--src/ext/Util/wixext/UtilTableDefinitions.cs2
8 files changed, 516 insertions, 846 deletions
diff --git a/src/ext/Util/Util.wixext.sln b/src/ext/Util/Util.wixext.sln
index 259a8164..0168dab9 100644
--- a/src/ext/Util/Util.wixext.sln
+++ b/src/ext/Util/Util.wixext.sln
@@ -1,7 +1,7 @@
1 1
2Microsoft Visual Studio Solution File, Format Version 12.00 2Microsoft Visual Studio Solution File, Format Version 12.00
3# Visual Studio Version 16 3# Visual Studio Version 17
4VisualStudioVersion = 16.0.30204.135 4VisualStudioVersion = 17.1.32228.430
5MinimumVisualStudioVersion = 15.0.26124.0 5MinimumVisualStudioVersion = 15.0.26124.0
6Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilbe", "be\utilbe.vcxproj", "{630C1EE7-2517-4A8C-83E3-DA1150308B58}" 6Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilbe", "be\utilbe.vcxproj", "{630C1EE7-2517-4A8C-83E3-DA1150308B58}"
7EndProject 7EndProject
diff --git a/src/ext/Util/Util.wixext.v3.ncrunchsolution b/src/ext/Util/Util.wixext.v3.ncrunchsolution
new file mode 100644
index 00000000..10420ac9
--- /dev/null
+++ b/src/ext/Util/Util.wixext.v3.ncrunchsolution
@@ -0,0 +1,6 @@
1<SolutionConfiguration>
2 <Settings>
3 <AllowParallelTestExecution>True</AllowParallelTestExecution>
4 <SolutionConfigured>True</SolutionConfigured>
5 </Settings>
6</SolutionConfiguration> \ No newline at end of file
diff --git a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
index 883f9794..d2a4e34b 100644
--- a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
+++ b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
@@ -6,8 +6,6 @@ namespace WixToolsetTest.Util
6 using System.Linq; 6 using System.Linq;
7 using WixBuildTools.TestSupport; 7 using WixBuildTools.TestSupport;
8 using WixToolset.Core.TestPackage; 8 using WixToolset.Core.TestPackage;
9 using WixToolset.Data;
10 using WixToolset.Data.Symbols;
11 using WixToolset.Util; 9 using WixToolset.Util;
12 using Xunit; 10 using Xunit;
13 11
@@ -56,6 +54,18 @@ namespace WixToolsetTest.Util
56 } 54 }
57 55
58 [Fact] 56 [Fact]
57 public void CanRoundtripFileShare()
58 {
59 var folder = TestData.Get(@"TestData", "UsingFileShare");
60 var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder });
61 var output = Path.Combine(folder, "decompile.xml");
62
63 build.BuildAndDecompileAndBuild(Build, Decompile, output);
64 File.Exists(output);
65 }
66
67
68 [Fact]
59 public void CanBuildCloseApplication() 69 public void CanBuildCloseApplication()
60 { 70 {
61 var folder = TestData.Get(@"TestData\CloseApplication"); 71 var folder = TestData.Get(@"TestData\CloseApplication");
@@ -313,5 +323,11 @@ namespace WixToolsetTest.Util
313 var result = WixRunner.Execute(newArgs.ToArray()); 323 var result = WixRunner.Execute(newArgs.ToArray());
314 result.AssertSuccess(); 324 result.AssertSuccess();
315 } 325 }
326
327 private static void Decompile(string[] args)
328 {
329 var result = WixRunner.Execute(args);
330 result.AssertSuccess();
331 }
316 } 332 }
317} 333}
diff --git a/src/ext/Util/wixext/UtilCompiler.cs b/src/ext/Util/wixext/UtilCompiler.cs
index 45079150..09a90928 100644
--- a/src/ext/Util/wixext/UtilCompiler.cs
+++ b/src/ext/Util/wixext/UtilCompiler.cs
@@ -19,7 +19,7 @@ namespace WixToolset.Util
19 /// <summary> 19 /// <summary>
20 /// The compiler for the WiX Toolset Utility Extension. 20 /// The compiler for the WiX Toolset Utility Extension.
21 /// </summary> 21 /// </summary>
22 public sealed class UtilCompiler : BaseCompilerExtension 22 internal sealed class UtilCompiler : BaseCompilerExtension
23 { 23 {
24 // user creation attributes definitions (from sca.h) 24 // user creation attributes definitions (from sca.h)
25 internal const int UserDontExpirePasswrd = 0x00000001; 25 internal const int UserDontExpirePasswrd = 0x00000001;
@@ -37,7 +37,7 @@ namespace WixToolset.Util
37 37
38 private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(?<!\[\\\]|\[\\|\\\[)\]", RegexOptions.ExplicitCapture | RegexOptions.Compiled); 38 private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(?<!\[\\\]|\[\\|\\\[)\]", RegexOptions.ExplicitCapture | RegexOptions.Compiled);
39 39
40 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/util"; 40 public override XNamespace Namespace => UtilConstants.Namespace;
41 41
42 /// <summary> 42 /// <summary>
43 /// Types of Internet shortcuts. 43 /// Types of Internet shortcuts.
@@ -94,13 +94,10 @@ namespace WixToolset.Util
94 var createFolderId = context["DirectoryId"]; 94 var createFolderId = context["DirectoryId"];
95 var createFolderComponentId = context["ComponentId"]; 95 var createFolderComponentId = context["ComponentId"];
96 96
97 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
98 var createFolderWin64 = Boolean.Parse(context["Win64"]);
99
100 switch (element.Name.LocalName) 97 switch (element.Name.LocalName)
101 { 98 {
102 case "PermissionEx": 99 case "PermissionEx":
103 this.ParsePermissionExElement(intermediate, section, element, createFolderId, createFolderComponentId, createFolderWin64, "CreateFolder"); 100 this.ParsePermissionExElement(intermediate, section, element, createFolderId, createFolderComponentId, "CreateFolder");
104 break; 101 break;
105 default: 102 default:
106 this.ParseHelper.UnexpectedElement(parentElement, element); 103 this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -159,16 +156,13 @@ namespace WixToolset.Util
159 var fileId = context["FileId"]; 156 var fileId = context["FileId"];
160 var fileComponentId = context["ComponentId"]; 157 var fileComponentId = context["ComponentId"];
161 158
162 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
163 var fileWin64 = Boolean.Parse(context["Win64"]);
164
165 switch (element.Name.LocalName) 159 switch (element.Name.LocalName)
166 { 160 {
167 case "PerfCounter": 161 case "PerfCounter":
168 this.ParsePerfCounterElement(intermediate, section, element, fileComponentId, fileId); 162 this.ParsePerfCounterElement(intermediate, section, element, fileComponentId, fileId);
169 break; 163 break;
170 case "PermissionEx": 164 case "PermissionEx":
171 this.ParsePermissionExElement(intermediate, section, element, fileId, fileComponentId, fileWin64, "File"); 165 this.ParsePermissionExElement(intermediate, section, element, fileId, fileComponentId, "File");
172 break; 166 break;
173 case "PerfCounterManifest": 167 case "PerfCounterManifest":
174 this.ParsePerfCounterManifestElement(intermediate, section, element, fileComponentId, fileId); 168 this.ParsePerfCounterManifestElement(intermediate, section, element, fileComponentId, fileId);
@@ -177,7 +171,7 @@ namespace WixToolset.Util
177 this.ParseEventManifestElement(intermediate, section, element, fileComponentId, fileId); 171 this.ParseEventManifestElement(intermediate, section, element, fileComponentId, fileId);
178 break; 172 break;
179 case "FormatFile": 173 case "FormatFile":
180 this.ParseFormatFileElement(intermediate, section, element, fileId, fileWin64); 174 this.ParseFormatFileElement(intermediate, section, element, fileId);
181 break; 175 break;
182 default: 176 default:
183 this.ParseHelper.UnexpectedElement(parentElement, element); 177 this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -296,13 +290,10 @@ namespace WixToolset.Util
296 var registryId = context["RegistryId"]; 290 var registryId = context["RegistryId"];
297 var registryComponentId = context["ComponentId"]; 291 var registryComponentId = context["ComponentId"];
298 292
299 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
300 var registryWin64 = Boolean.Parse(context["Win64"]);
301
302 switch (element.Name.LocalName) 293 switch (element.Name.LocalName)
303 { 294 {
304 case "PermissionEx": 295 case "PermissionEx":
305 this.ParsePermissionExElement(intermediate, section, element, registryId, registryComponentId, registryWin64, "Registry"); 296 this.ParsePermissionExElement(intermediate, section, element, registryId, registryComponentId, "Registry");
306 break; 297 break;
307 default: 298 default:
308 this.ParseHelper.UnexpectedElement(parentElement, element); 299 this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -314,13 +305,10 @@ namespace WixToolset.Util
314 var serviceInstallName = context["ServiceInstallName"]; 305 var serviceInstallName = context["ServiceInstallName"];
315 var serviceInstallComponentId = context["ServiceInstallComponentId"]; 306 var serviceInstallComponentId = context["ServiceInstallComponentId"];
316 307
317 // If this doesn't parse successfully, something really odd is going on, so let the exception get thrown
318 var serviceInstallWin64 = Boolean.Parse(context["Win64"]);
319
320 switch (element.Name.LocalName) 308 switch (element.Name.LocalName)
321 { 309 {
322 case "PermissionEx": 310 case "PermissionEx":
323 this.ParsePermissionExElement(intermediate, section, element, serviceInstallId, serviceInstallComponentId, serviceInstallWin64, "ServiceInstall"); 311 this.ParsePermissionExElement(intermediate, section, element, serviceInstallId, serviceInstallComponentId, "ServiceInstall");
324 break; 312 break;
325 case "ServiceConfig": 313 case "ServiceConfig":
326 this.ParseServiceConfigElement(intermediate, section, element, serviceInstallComponentId, "ServiceInstall", serviceInstallName); 314 this.ParseServiceConfigElement(intermediate, section, element, serviceInstallComponentId, "ServiceInstall", serviceInstallName);
@@ -536,7 +524,6 @@ namespace WixToolset.Util
536 private void ParseComponentSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element) 524 private void ParseComponentSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element)
537 { 525 {
538 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); 526 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
539 string refId = null;
540 527
541 foreach (var attrib in element.Attributes()) 528 foreach (var attrib in element.Attributes())
542 { 529 {
@@ -545,7 +532,7 @@ namespace WixToolset.Util
545 switch (attrib.Name.LocalName) 532 switch (attrib.Name.LocalName)
546 { 533 {
547 case "Id": 534 case "Id":
548 refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); 535 var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
549 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixComponentSearch, refId); 536 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixComponentSearch, refId);
550 break; 537 break;
551 default: 538 default:
@@ -2284,7 +2271,7 @@ namespace WixToolset.Util
2284 /// <param name="element">Element to parse.</param> 2271 /// <param name="element">Element to parse.</param>
2285 /// <param name="fileId">Identifier of referenced file.</param> 2272 /// <param name="fileId">Identifier of referenced file.</param>
2286 /// <param name="win64">Flag to determine whether the component is 64-bit.</param> 2273 /// <param name="win64">Flag to determine whether the component is 64-bit.</param>
2287 private void ParseFormatFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string fileId, bool win64) 2274 private void ParseFormatFileElement(Intermediate intermediate, IntermediateSection section, XElement element, string fileId)
2288 { 2275 {
2289 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); 2276 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2290 string binaryId = null; 2277 string binaryId = null;
@@ -2415,7 +2402,6 @@ namespace WixToolset.Util
2415 ComponentRef = componentId, 2402 ComponentRef = componentId,
2416 }); 2403 });
2417 } 2404 }
2418
2419 } 2405 }
2420 2406
2421 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); 2407 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
@@ -2435,7 +2421,7 @@ namespace WixToolset.Util
2435 /// <param name="componentId">Identifier of component, used to determine install state.</param> 2421 /// <param name="componentId">Identifier of component, used to determine install state.</param>
2436 /// <param name="win64">Flag to determine whether the component is 64-bit.</param> 2422 /// <param name="win64">Flag to determine whether the component is 64-bit.</param>
2437 /// <param name="tableName">Name of table that contains objectId.</param> 2423 /// <param name="tableName">Name of table that contains objectId.</param>
2438 private void ParsePermissionExElement(Intermediate intermediate, IntermediateSection section, XElement element, string objectId, string componentId, bool win64, string tableName) 2424 private void ParsePermissionExElement(Intermediate intermediate, IntermediateSection section, XElement element, string objectId, string componentId, string tableName)
2439 { 2425 {
2440 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); 2426 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2441 var bits = new BitArray(32); 2427 var bits = new BitArray(32);
@@ -2623,7 +2609,7 @@ namespace WixToolset.Util
2623 2609
2624 if (null == id) 2610 if (null == id)
2625 { 2611 {
2626 id = this.ParseHelper.CreateIdentifier("wps", variable, condition, after, (productCode == null ? upgradeCode : productCode), attributes.ToString()); 2612 id = this.ParseHelper.CreateIdentifier("wps", variable, condition, after, productCode ?? upgradeCode, attributes.ToString());
2627 } 2613 }
2628 2614
2629 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); 2615 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
diff --git a/src/ext/Util/wixext/UtilConstants.cs b/src/ext/Util/wixext/UtilConstants.cs
index 28ff368f..93616e44 100644
--- a/src/ext/Util/wixext/UtilConstants.cs
+++ b/src/ext/Util/wixext/UtilConstants.cs
@@ -2,11 +2,32 @@
2 2
3namespace WixToolset.Util 3namespace WixToolset.Util
4{ 4{
5 using System.Xml.Linq;
6
5 /// <summary> 7 /// <summary>
6 /// Constants used by Utility Extension. 8 /// Constants used by Utility Extension.
7 /// </summary> 9 /// </summary>
8 internal static class UtilConstants 10 internal static class UtilConstants
9 { 11 {
12 internal static readonly XNamespace Namespace = "http://wixtoolset.org/schemas/v4/wxs/util";
13
14 internal static readonly XName CloseApplicationName = Namespace + "CloseApplication";
15 internal static readonly XName EventManifestName = Namespace + "EventManifest";
16 internal static readonly XName FileShareName = Namespace + "FileShare";
17 internal static readonly XName FileSharePermissionName = Namespace + "FileSharePermission";
18 internal static readonly XName GroupName = Namespace + "Group";
19 internal static readonly XName GroupRefName = Namespace + "GroupRef";
20 internal static readonly XName InternetShortcutName = Namespace + "InternetShortcut";
21 internal static readonly XName PerfCounterName = Namespace + "PerfCounter";
22 internal static readonly XName PerfCounterManifestName = Namespace + "PerfCounterManifest";
23 internal static readonly XName PermissionExName = Namespace + "PermissionEx";
24 internal static readonly XName RemoveFolderExName = Namespace + "RemoveFolderEx";
25 internal static readonly XName RestartResourceName = Namespace + "RestartResource";
26 internal static readonly XName ServiceConfigName = Namespace + "ServiceConfig";
27 internal static readonly XName UserName = Namespace + "User";
28 internal static readonly XName XmlConfigName = Namespace + "XmlConfig";
29 internal static readonly XName XmlFileName = Namespace + "XmlFile";
30
10 internal static readonly string[] FilePermissions = { "Read", "Write", "Append", "ReadExtendedAttributes", "WriteExtendedAttributes", "Execute", null, "ReadAttributes", "WriteAttributes" }; 31 internal static readonly string[] FilePermissions = { "Read", "Write", "Append", "ReadExtendedAttributes", "WriteExtendedAttributes", "Execute", null, "ReadAttributes", "WriteAttributes" };
11 internal static readonly string[] FolderPermissions = { "Read", "CreateFile", "CreateChild", "ReadExtendedAttributes", "WriteExtendedAttributes", "Traverse", "DeleteChild", "ReadAttributes", "WriteAttributes" }; 32 internal static readonly string[] FolderPermissions = { "Read", "CreateFile", "CreateChild", "ReadExtendedAttributes", "WriteExtendedAttributes", "Traverse", "DeleteChild", "ReadAttributes", "WriteAttributes" };
12 internal static readonly string[] GenericPermissions = { "GenericAll", "GenericExecute", "GenericWrite", "GenericRead" }; 33 internal static readonly string[] GenericPermissions = { "GenericAll", "GenericExecute", "GenericWrite", "GenericRead" };
diff --git a/src/ext/Util/wixext/UtilDecompiler.cs b/src/ext/Util/wixext/UtilDecompiler.cs
index 9ef3390f..7d95fcef 100644
--- a/src/ext/Util/wixext/UtilDecompiler.cs
+++ b/src/ext/Util/wixext/UtilDecompiler.cs
@@ -1,48 +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. 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 2
3namespace WixToolset.Extensions 3namespace WixToolset.Util
4{ 4{
5#if TODO_CONSIDER_DECOMPILER
6 using System; 5 using System;
7 using System.IO; 6 using System.IO;
8 using System.Text; 7 using System.Text;
9 using System.Collections; 8 using System.Collections;
10 using System.Diagnostics; 9 using System.Diagnostics;
11 using System.Globalization;
12 10
13 using Util = WixToolset.Extensions.Serialize.Util;
14 using WixToolset.Data; 11 using WixToolset.Data;
15 using WixToolset.Extensibility; 12 using WixToolset.Extensibility;
16 using Wix = WixToolset.Data.Serialize; 13 using WixToolset.Data.WindowsInstaller;
14 using System.Collections.Generic;
15 using System.Xml.Linq;
16 using WixToolset.Util.Symbols;
17 17
18 /// <summary> 18 /// <summary>
19 /// The decompiler for the WiX Toolset Utility Extension. 19 /// The decompiler for the WiX Toolset Utility Extension.
20 /// </summary> 20 /// </summary>
21 public sealed class UtilDecompiler : DecompilerExtension 21 internal sealed class UtilDecompiler : BaseWindowsInstallerDecompilerExtension
22 { 22 {
23 /// <summary> 23 public override IReadOnlyCollection<TableDefinition> TableDefinitions => UtilTableDefinitions.All;
24 /// Creates a decompiler for Utility Extension.
25 /// </summary>
26 public UtilDecompiler()
27 {
28 this.TableDefinitions = UtilExtensionData.GetExtensionTableDefinitions();
29 }
30
31 /// <summary>
32 /// Get the extensions library to be removed.
33 /// </summary>
34 /// <param name="tableDefinitions">Table definitions for library.</param>
35 /// <returns>Library to remove from decompiled output.</returns>
36 public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
37 {
38 return UtilExtensionData.GetExtensionLibrary(tableDefinitions);
39 }
40 24
41 /// <summary> 25 /// <summary>
42 /// Called at the beginning of the decompilation of a database. 26 /// Called at the beginning of the decompilation of a database.
43 /// </summary> 27 /// </summary>
44 /// <param name="tables">The collection of all tables.</param> 28 /// <param name="tables">The collection of all tables.</param>
45 public override void Initialize(TableIndexedCollection tables) 29 public override void PreDecompileTables(TableIndexedCollection tables)
46 { 30 {
47 this.CleanupSecureCustomProperties(tables); 31 this.CleanupSecureCustomProperties(tables);
48 this.CleanupInternetShortcutRemoveFileTables(tables); 32 this.CleanupInternetShortcutRemoveFileTables(tables);
@@ -61,24 +45,22 @@ namespace WixToolset.Extensions
61 /// <param name="tables">The collection of all tables.</param> 45 /// <param name="tables">The collection of all tables.</param>
62 private void CleanupSecureCustomProperties(TableIndexedCollection tables) 46 private void CleanupSecureCustomProperties(TableIndexedCollection tables)
63 { 47 {
64 Table propertyTable = tables["Property"]; 48 var propertyTable = tables["Property"];
65 49
66 if (null != propertyTable) 50 if (null != propertyTable)
67 { 51 {
68 foreach (Row row in propertyTable.Rows) 52 foreach (var row in propertyTable.Rows)
69 { 53 {
70 if ("SecureCustomProperties" == row[0].ToString()) 54 if ("SecureCustomProperties" == row[0].ToString())
71 { 55 {
72 StringBuilder remainingProperties = new StringBuilder(); 56 var remainingProperties = new StringBuilder();
73 string[] secureCustomProperties = row[1].ToString().Split(';'); 57 var secureCustomProperties = row[1].ToString().Split(';');
74 foreach (string property in secureCustomProperties) 58 foreach (var property in secureCustomProperties)
75 { 59 {
76 if (property.StartsWith("WIX_SUITE_", StringComparison.Ordinal) || property.StartsWith("WIX_DIR_", StringComparison.Ordinal) 60 if (property.StartsWith("WIX_SUITE_", StringComparison.Ordinal) || property.StartsWith("WIX_DIR_", StringComparison.Ordinal)
77 || property.StartsWith("WIX_ACCOUNT_", StringComparison.Ordinal)) 61 || property.StartsWith("WIX_ACCOUNT_", StringComparison.Ordinal))
78 { 62 {
79 Wix.PropertyRef propertyRef = new Wix.PropertyRef(); 63 this.DecompilerHelper.AddElementToRoot("PropertyRef", new XAttribute("Id", property));
80 propertyRef.Id = property;
81 this.Core.RootElement.AddChild(propertyRef);
82 } 64 }
83 else 65 else
84 { 66 {
@@ -104,21 +86,21 @@ namespace WixToolset.Extensions
104 private void CleanupInternetShortcutRemoveFileTables(TableIndexedCollection tables) 86 private void CleanupInternetShortcutRemoveFileTables(TableIndexedCollection tables)
105 { 87 {
106 // index the WixInternetShortcut table 88 // index the WixInternetShortcut table
107 Table wixInternetShortcutTable = tables["WixInternetShortcut"]; 89 var wixInternetShortcutTable = tables["WixInternetShortcut"];
108 Hashtable wixInternetShortcuts = new Hashtable(); 90 var wixInternetShortcuts = new Hashtable();
109 if (null != wixInternetShortcutTable) 91 if (null != wixInternetShortcutTable)
110 { 92 {
111 foreach (Row row in wixInternetShortcutTable.Rows) 93 foreach (var row in wixInternetShortcutTable.Rows)
112 { 94 {
113 wixInternetShortcuts.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row); 95 wixInternetShortcuts.Add(row.GetPrimaryKey(), row);
114 } 96 }
115 } 97 }
116 98
117 // remove the RemoveFile rows with primary keys that match the WixInternetShortcut table's 99 // remove the RemoveFile rows with primary keys that match the WixInternetShortcut table's
118 Table removeFileTable = tables["RemoveFile"]; 100 var removeFileTable = tables["RemoveFile"];
119 if (null != removeFileTable) 101 if (null != removeFileTable)
120 { 102 {
121 for (int i = removeFileTable.Rows.Count - 1; 0 <= i; i--) 103 for (var i = removeFileTable.Rows.Count - 1; 0 <= i; i--)
122 { 104 {
123 if (null != wixInternetShortcuts[removeFileTable.Rows[i][0]]) 105 if (null != wixInternetShortcuts[removeFileTable.Rows[i][0]])
124 { 106 {
@@ -132,69 +114,86 @@ namespace WixToolset.Extensions
132 /// Decompiles an extension table. 114 /// Decompiles an extension table.
133 /// </summary> 115 /// </summary>
134 /// <param name="table">The table to decompile.</param> 116 /// <param name="table">The table to decompile.</param>
135 public override void DecompileTable(Table table) 117 public override bool TryDecompileTable(Table table)
136 { 118 {
137 switch (table.Name) 119 switch (table.Name)
138 { 120 {
139 case "WixCloseApplication": 121 case "WixCloseApplication":
122 case "Wix4CloseApplication":
140 this.DecompileWixCloseApplicationTable(table); 123 this.DecompileWixCloseApplicationTable(table);
141 break; 124 break;
142 case "WixRemoveFolderEx": 125 case "WixRemoveFolderEx":
126 case "Wix4RemoveFolderEx":
143 this.DecompileWixRemoveFolderExTable(table); 127 this.DecompileWixRemoveFolderExTable(table);
144 break; 128 break;
145 case "WixRestartResource": 129 case "WixRestartResource":
130 case "Wix4RestartResource":
146 this.DecompileWixRestartResourceTable(table); 131 this.DecompileWixRestartResourceTable(table);
147 break; 132 break;
148 case "FileShare": 133 case "FileShare":
134 case "Wix4FileShare":
149 this.DecompileFileShareTable(table); 135 this.DecompileFileShareTable(table);
150 break; 136 break;
151 case "FileSharePermissions": 137 case "FileSharePermissions":
138 case "Wix4FileSharePermissions":
152 this.DecompileFileSharePermissionsTable(table); 139 this.DecompileFileSharePermissionsTable(table);
153 break; 140 break;
154 case "WixInternetShortcut": 141 case "WixInternetShortcut":
142 case "Wix4InternetShortcut":
155 this.DecompileWixInternetShortcutTable(table); 143 this.DecompileWixInternetShortcutTable(table);
156 break; 144 break;
157 case "Group": 145 case "Group":
146 case "Wix4Group":
158 this.DecompileGroupTable(table); 147 this.DecompileGroupTable(table);
159 break; 148 break;
160 case "Perfmon": 149 case "Perfmon":
150 case "Wix4Perfmon":
161 this.DecompilePerfmonTable(table); 151 this.DecompilePerfmonTable(table);
162 break; 152 break;
163 case "PerfmonManifest": 153 case "PerfmonManifest":
154 case "Wix4PerfmonManifest":
164 this.DecompilePerfmonManifestTable(table); 155 this.DecompilePerfmonManifestTable(table);
165 break; 156 break;
166 case "EventManifest": 157 case "EventManifest":
158 case "Wix4EventManifest":
167 this.DecompileEventManifestTable(table); 159 this.DecompileEventManifestTable(table);
168 break; 160 break;
169 case "SecureObjects": 161 case "SecureObjects":
162 case "Wix4SecureObjects":
170 this.DecompileSecureObjectsTable(table); 163 this.DecompileSecureObjectsTable(table);
171 break; 164 break;
172 case "ServiceConfig": 165 case "ServiceConfig":
166 case "Wix4ServiceConfig":
173 this.DecompileServiceConfigTable(table); 167 this.DecompileServiceConfigTable(table);
174 break; 168 break;
175 case "User": 169 case "User":
170 case "Wix4User":
176 this.DecompileUserTable(table); 171 this.DecompileUserTable(table);
177 break; 172 break;
178 case "UserGroup": 173 case "UserGroup":
174 case "Wix4UserGroup":
179 this.DecompileUserGroupTable(table); 175 this.DecompileUserGroupTable(table);
180 break; 176 break;
181 case "XmlConfig": 177 case "XmlConfig":
178 case "Wix4XmlConfig":
182 this.DecompileXmlConfigTable(table); 179 this.DecompileXmlConfigTable(table);
183 break; 180 break;
184 case "XmlFile": 181 case "XmlFile":
182 case "Wix4XmlFile":
185 // XmlFile decompilation has been moved to FinalizeXmlFileTable function 183 // XmlFile decompilation has been moved to FinalizeXmlFileTable function
186 break; 184 break;
187 default: 185 default:
188 base.DecompileTable(table); 186 return false;
189 break;
190 } 187 }
188
189 return true;
191 } 190 }
192 191
193 /// <summary> 192 /// <summary>
194 /// Finalize decompilation. 193 /// Finalize decompilation.
195 /// </summary> 194 /// </summary>
196 /// <param name="tables">The collection of all tables.</param> 195 /// <param name="tables">The collection of all tables.</param>
197 public override void Finish(TableIndexedCollection tables) 196 public override void PostDecompileTables(TableIndexedCollection tables)
198 { 197 {
199 this.FinalizePerfmonTable(tables); 198 this.FinalizePerfmonTable(tables);
200 this.FinalizePerfmonManifestTable(tables); 199 this.FinalizePerfmonManifestTable(tables);
@@ -211,49 +210,21 @@ namespace WixToolset.Extensions
211 /// <param name="table">The table to decompile.</param> 210 /// <param name="table">The table to decompile.</param>
212 private void DecompileWixCloseApplicationTable(Table table) 211 private void DecompileWixCloseApplicationTable(Table table)
213 { 212 {
214 foreach (Row row in table.Rows) 213 foreach (var row in table.Rows)
215 { 214 {
216 Util.CloseApplication closeApplication = new Util.CloseApplication(); 215 var attribute = row.FieldAsNullableInteger(4) ?? 0x2;
217 216
218 closeApplication.Id = (string)row[0]; 217 this.DecompilerHelper.AddElementToRoot(UtilConstants.CloseApplicationName,
219 218 new XAttribute("Id", row.FieldAsString(0)),
220 closeApplication.Target = (string)row[1]; 219 new XAttribute("Target", row.FieldAsString(1)),
221 220 AttributeIfNotNull("Description", row, 2),
222 if (null != row[2]) 221 AttributeIfNotNull("Content", row, 3),
223 { 222 AttributeIfNotNull("CloseMessage", 0x1 == (attribute & 0x1)),
224 closeApplication.Description = (string)row[2]; 223 AttributeIfNotNull("RebootPrompt", 0x2 == (attribute & 0x2)),
225 } 224 AttributeIfNotNull("ElevatedCloseMessage", 0x4 == (attribute & 0x4)),
226 225 NumericAttributeIfNotNull("Sequence", row, 5),
227 if (null != row[3]) 226 NumericAttributeIfNotNull("Property", row, 6)
228 { 227 );
229 closeApplication.Content = (string)row[3];
230 }
231
232 // set defaults
233 closeApplication.CloseMessage = Util.YesNoType.no;
234 closeApplication.RebootPrompt = Util.YesNoType.yes;
235 closeApplication.ElevatedCloseMessage = Util.YesNoType.no;
236
237 if (null != row[4])
238 {
239 int attribute = (int)row[4];
240
241 closeApplication.CloseMessage = (0x1 == (attribute & 0x1)) ? Util.YesNoType.yes : Util.YesNoType.no;
242 closeApplication.RebootPrompt = (0x2 == (attribute & 0x2)) ? Util.YesNoType.yes : Util.YesNoType.no;
243 closeApplication.ElevatedCloseMessage = (0x4 == (attribute & 0x4)) ? Util.YesNoType.yes : Util.YesNoType.no;
244 }
245
246 if (null != row[5])
247 {
248 closeApplication.Sequence = (int)row[5];
249 }
250
251 if (null != row[6])
252 {
253 closeApplication.Property = (string)row[6];
254 }
255
256 this.Core.RootElement.AddChild(closeApplication);
257 } 228 }
258 } 229 }
259 230
@@ -263,43 +234,45 @@ namespace WixToolset.Extensions
263 /// <param name="table">The table to decompile.</param> 234 /// <param name="table">The table to decompile.</param>
264 private void DecompileWixRemoveFolderExTable(Table table) 235 private void DecompileWixRemoveFolderExTable(Table table)
265 { 236 {
266 foreach (Row row in table.Rows) 237 foreach (var row in table.Rows)
267 { 238 {
268 // Set the Id even if auto-generated previously. 239 var on = String.Empty;
269 Util.RemoveFolderEx removeFolder = new Util.RemoveFolderEx(); 240 var installMode = row.FieldAsInteger(3);
270 removeFolder.Id = (string)row[0]; 241 switch (installMode)
271 removeFolder.Property = (string)row[2];
272
273 int installMode = (int)row[3];
274 switch ((UtilCompiler.WixRemoveFolderExOn)installMode)
275 { 242 {
276 case UtilCompiler.WixRemoveFolderExOn.Install: 243 case (int)WixRemoveFolderExInstallMode.Install:
277 removeFolder.On = Util.RemoveFolderEx.OnType.install; 244 on = "install";
278 break; 245 break;
279 246
280 case UtilCompiler.WixRemoveFolderExOn.Uninstall: 247 case (int)WixRemoveFolderExInstallMode.Uninstall:
281 removeFolder.On = Util.RemoveFolderEx.OnType.uninstall; 248 on = "uninstall";
282 break; 249 break;
283 250
284 case UtilCompiler.WixRemoveFolderExOn.Both: 251 case (int)WixRemoveFolderExInstallMode.Both:
285 removeFolder.On = Util.RemoveFolderEx.OnType.both; 252 on = "both";
286 break; 253 break;
287 254
288 default: 255 default:
289 this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "InstallMode", installMode)); 256 this.Messaging.Write(WarningMessages.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "InstallMode", installMode));
290 break; 257 break;
291 } 258 }
292 259
260 var removeFolder = new XElement(UtilConstants.RemoveFolderExName,
261 AttributeIfNotNull("Id", row, 0),
262 AttributeIfNotNull("Property", row, 2),
263 AttributeIfNotNull("On", on)
264 );
265
293 // Add to the appropriate Component or section element. 266 // Add to the appropriate Component or section element.
294 string componentId = (string)row[1]; 267 var componentId = row.FieldAsString(1);
295 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId); 268
296 if (null != component) 269 if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
297 { 270 {
298 component.AddChild(removeFolder); 271 component.Add(removeFolder);
299 } 272 }
300 else 273 else
301 { 274 {
302 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component")); 275 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(), "Component_", componentId, "Component"));
303 } 276 }
304 } 277 }
305 } 278 }
@@ -310,53 +283,51 @@ namespace WixToolset.Extensions
310 /// <param name="table">The table to decompile.</param> 283 /// <param name="table">The table to decompile.</param>
311 private void DecompileWixRestartResourceTable(Table table) 284 private void DecompileWixRestartResourceTable(Table table)
312 { 285 {
313 foreach (Row row in table.Rows) 286 foreach (var row in table.Rows)
314 { 287 {
315 // Set the Id even if auto-generated previously. 288 var restartResource = new XElement(UtilConstants.RestartResourceName,
316 Util.RestartResource restartResource = new Util.RestartResource(); 289 new XAttribute("Id", row.FieldAsString(0)));
317 restartResource.Id = (string)row[0];
318 290
319 // Determine the resource type and set accordingly. 291 // Determine the resource type and set accordingly.
320 string resource = (string)row[2]; 292 var resource = row.FieldAsString(2);
321 int attributes = (int)row[3]; 293 var attributes = row.FieldAsInteger(3);
322 UtilCompiler.WixRestartResourceAttributes type = (UtilCompiler.WixRestartResourceAttributes)(attributes & (int)UtilCompiler.WixRestartResourceAttributes.TypeMask); 294 var type = (WixRestartResourceAttributes)attributes;
323 295
324 switch (type) 296 switch (type)
325 { 297 {
326 case UtilCompiler.WixRestartResourceAttributes.Filename: 298 case WixRestartResourceAttributes.Filename:
327 restartResource.Path = resource; 299 restartResource.Add(new XAttribute("Path", resource));
328 break; 300 break;
329 301
330 case UtilCompiler.WixRestartResourceAttributes.ProcessName: 302 case WixRestartResourceAttributes.ProcessName:
331 restartResource.ProcessName = resource; 303 restartResource.Add(new XAttribute("ProcessName", resource));
332 break; 304 break;
333 305
334 case UtilCompiler.WixRestartResourceAttributes.ServiceName: 306 case WixRestartResourceAttributes.ServiceName:
335 restartResource.ServiceName = resource; 307 restartResource.Add(new XAttribute("ServiceName", resource));
336 break; 308 break;
337 309
338 default: 310 default:
339 this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Attributes", attributes)); 311 this.Messaging.Write(WarningMessages.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Attributes", attributes));
340 break; 312 break;
341 } 313 }
342 314
343 // Add to the appropriate Component or section element. 315 // Add to the appropriate Component or section element.
344 string componentId = (string)row[1]; 316 var componentId = row.FieldAsString(1);
345 if (!String.IsNullOrEmpty(componentId)) 317 if (!String.IsNullOrEmpty(componentId))
346 { 318 {
347 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId); 319 if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
348 if (null != component)
349 { 320 {
350 component.AddChild(restartResource); 321 component.Add(restartResource);
351 } 322 }
352 else 323 else
353 { 324 {
354 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", componentId, "Component")); 325 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(), "Component_", componentId, "Component"));
355 } 326 }
356 } 327 }
357 else 328 else
358 { 329 {
359 this.Core.RootElement.AddChild(restartResource); 330 this.DecompilerHelper.AddElementToRoot(restartResource);
360 } 331 }
361 } 332 }
362 } 333 }
@@ -367,33 +338,28 @@ namespace WixToolset.Extensions
367 /// <param name="table">The table to decompile.</param> 338 /// <param name="table">The table to decompile.</param>
368 private void DecompileFileShareTable(Table table) 339 private void DecompileFileShareTable(Table table)
369 { 340 {
370 foreach (Row row in table.Rows) 341 foreach (var row in table.Rows)
371 { 342 {
372 Util.FileShare fileShare = new Util.FileShare(); 343 var fileShare = new XElement(UtilConstants.FileShareName,
373 344 new XAttribute("Id", row.FieldAsString(0)),
374 fileShare.Id = (string)row[0]; 345 new XAttribute("Name", row.FieldAsString(1)),
375 346 AttributeIfNotNull("Description", row, 3)
376 fileShare.Name = (string)row[1]; 347 );
377
378 if (null != row[3])
379 {
380 fileShare.Description = (string)row[3];
381 }
382 348
383 // the Directory_ column is set by the parent Component 349 // the Directory_ column is set by the parent Component
384 350
385 // the User_ and Permissions columns are deprecated 351 // the User_ and Permissions columns are deprecated
386 352
387 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); 353 if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(2), out var component))
388 if (null != component)
389 { 354 {
390 component.AddChild(fileShare); 355 component.Add(fileShare);
391 } 356 }
392 else 357 else
393 { 358 {
394 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); 359 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(), "Component_", (string)row[2], "Component"));
395 } 360 }
396 this.Core.IndexElement(row, fileShare); 361
362 this.DecompilerHelper.IndexElement(row, fileShare);
397 } 363 }
398 } 364 }
399 365
@@ -403,111 +369,21 @@ namespace WixToolset.Extensions
403 /// <param name="table">The table to decompile.</param> 369 /// <param name="table">The table to decompile.</param>
404 private void DecompileFileSharePermissionsTable(Table table) 370 private void DecompileFileSharePermissionsTable(Table table)
405 { 371 {
406 foreach (Row row in table.Rows) 372 foreach (var row in table.Rows)
407 { 373 {
408 Util.FileSharePermission fileSharePermission = new Util.FileSharePermission(); 374 var fileSharePermission = new XElement(UtilConstants.FileSharePermissionName,
409 375 new XAttribute("User", row.FieldAsString(1)));
410 fileSharePermission.User = (string)row[1];
411
412 string[] specialPermissions = UtilConstants.FolderPermissions;
413 int permissions = (int)row[2];
414 for (int i = 0; i < 32; i++)
415 {
416 if (0 != ((permissions >> i) & 1))
417 {
418 string name = null;
419 376
420 if (16 > i && specialPermissions.Length > i) 377 this.AddPermissionAttributes(fileSharePermission, row, 2, UtilConstants.FolderPermissions);
421 {
422 name = specialPermissions[i];
423 }
424 else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16))
425 {
426 name = UtilConstants.StandardPermissions[i - 16];
427 }
428 else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28))
429 {
430 name = UtilConstants.GenericPermissions[i - 28];
431 }
432
433 if (null == name)
434 {
435 this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i));
436 }
437 else
438 {
439 switch (name)
440 {
441 case "ChangePermission":
442 fileSharePermission.ChangePermission = Util.YesNoType.yes;
443 break;
444 case "CreateChild":
445 fileSharePermission.CreateChild = Util.YesNoType.yes;
446 break;
447 case "CreateFile":
448 fileSharePermission.CreateFile = Util.YesNoType.yes;
449 break;
450 case "Delete":
451 fileSharePermission.Delete = Util.YesNoType.yes;
452 break;
453 case "DeleteChild":
454 fileSharePermission.DeleteChild = Util.YesNoType.yes;
455 break;
456 case "GenericAll":
457 fileSharePermission.GenericAll = Util.YesNoType.yes;
458 break;
459 case "GenericExecute":
460 fileSharePermission.GenericExecute = Util.YesNoType.yes;
461 break;
462 case "GenericRead":
463 fileSharePermission.GenericRead = Util.YesNoType.yes;
464 break;
465 case "GenericWrite":
466 fileSharePermission.GenericWrite = Util.YesNoType.yes;
467 break;
468 case "Read":
469 fileSharePermission.Read = Util.YesNoType.yes;
470 break;
471 case "ReadAttributes":
472 fileSharePermission.ReadAttributes = Util.YesNoType.yes;
473 break;
474 case "ReadExtendedAttributes":
475 fileSharePermission.ReadExtendedAttributes = Util.YesNoType.yes;
476 break;
477 case "ReadPermission":
478 fileSharePermission.ReadPermission = Util.YesNoType.yes;
479 break;
480 case "Synchronize":
481 fileSharePermission.Synchronize = Util.YesNoType.yes;
482 break;
483 case "TakeOwnership":
484 fileSharePermission.TakeOwnership = Util.YesNoType.yes;
485 break;
486 case "Traverse":
487 fileSharePermission.Traverse = Util.YesNoType.yes;
488 break;
489 case "WriteAttributes":
490 fileSharePermission.WriteAttributes = Util.YesNoType.yes;
491 break;
492 case "WriteExtendedAttributes":
493 fileSharePermission.WriteExtendedAttributes = Util.YesNoType.yes;
494 break;
495 default:
496 Debug.Fail(String.Format("Unknown permission '{0}'.", name));
497 break;
498 }
499 }
500 }
501 }
502 378
503 Util.FileShare fileShare = (Util.FileShare)this.Core.GetIndexedElement("FileShare", (string)row[0]); 379 if (this.DecompilerHelper.TryGetIndexedElement("Wix4FileShare", row.FieldAsString(0), out var fileShare) ||
504 if (null != fileShare) 380 this.DecompilerHelper.TryGetIndexedElement("FileShare", row.FieldAsString(0), out fileShare))
505 { 381 {
506 fileShare.AddChild(fileSharePermission); 382 fileShare.Add(fileSharePermission);
507 } 383 }
508 else 384 else
509 { 385 {
510 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileShare_", (string)row[0], "FileShare")); 386 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(), "FileShare_", (string)row[0], "Wix4FileShare"));
511 } 387 }
512 } 388 }
513 } 389 }
@@ -518,25 +394,18 @@ namespace WixToolset.Extensions
518 /// <param name="table">The table to decompile.</param> 394 /// <param name="table">The table to decompile.</param>
519 private void DecompileGroupTable(Table table) 395 private void DecompileGroupTable(Table table)
520 { 396 {
521 foreach (Row row in table.Rows) 397 foreach (var row in table.Rows)
522 { 398 {
523 Util.Group group = new Util.Group();
524
525 group.Id = (string)row[0];
526
527 if (null != row[1]) 399 if (null != row[1])
528 { 400 {
529 this.Core.OnMessage(WixWarnings.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Component_", (string)row[1])); 401 this.Messaging.Write(WarningMessages.UnrepresentableColumnValue(row.SourceLineNumbers, table.Name, "Component_", (string)row[1]));
530 } 402 }
531 403
532 group.Name = (string)row[2]; 404 this.DecompilerHelper.AddElementToRoot(UtilConstants.GroupName,
533 405 new XAttribute("Id", row.FieldAsString(0)),
534 if (null != row[3]) 406 new XAttribute("Name", row.FieldAsString(1)),
535 { 407 AttributeIfNotNull("Domain", row, 3)
536 group.Domain = (string)row[3]; 408 );
537 }
538
539 this.Core.RootElement.AddChild(group);
540 } 409 }
541 } 410 }
542 411
@@ -546,39 +415,41 @@ namespace WixToolset.Extensions
546 /// <param name="table">The table to decompile.</param> 415 /// <param name="table">The table to decompile.</param>
547 private void DecompileWixInternetShortcutTable(Table table) 416 private void DecompileWixInternetShortcutTable(Table table)
548 { 417 {
549 foreach (Row row in table.Rows) 418 foreach (var row in table.Rows)
550 { 419 {
551 Util.InternetShortcut internetShortcut = new Util.InternetShortcut(); 420 var type = String.Empty;
552 internetShortcut.Id = (string)row[0]; 421 var shortcutType = (UtilCompiler.InternetShortcutType)row.FieldAsInteger(5);
553 internetShortcut.Directory = (string)row[2];
554 // remove .lnk/.url extension because compiler extension adds it back for us
555 internetShortcut.Name = Path.ChangeExtension((string)row[3], null);
556 internetShortcut.Target = (string)row[4];
557 internetShortcut.IconFile = (string)row[6];
558 internetShortcut.IconIndex = (int)row[7];
559
560 UtilCompiler.InternetShortcutType shortcutType = (UtilCompiler.InternetShortcutType)row[5];
561 switch (shortcutType) 422 switch (shortcutType)
562 { 423 {
563 case UtilCompiler.InternetShortcutType.Link: 424 case UtilCompiler.InternetShortcutType.Link:
564 internetShortcut.Type = Util.InternetShortcut.TypeType.link; 425 type = "link";
565 break; 426 break;
566 case UtilCompiler.InternetShortcutType.Url: 427 case UtilCompiler.InternetShortcutType.Url:
567 internetShortcut.Type = Util.InternetShortcut.TypeType.url; 428 type = "url";
568 break; 429 break;
569 } 430 }
570 431
571 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); 432 var internetShortcut = new XElement(UtilConstants.InternetShortcutName,
572 if (null != component) 433 new XAttribute("Id", row.FieldAsString(0)),
434 new XAttribute("Directory", row.FieldAsString(2)),
435 new XAttribute("Name", Path.GetFileNameWithoutExtension(row.FieldAsString(3))), // remove .lnk/.url extension because compiler extension adds it back for us
436 new XAttribute("Type", type),
437 new XAttribute("Target", row.FieldAsString(4)),
438 new XAttribute("IconFile", row.FieldAsString(6)),
439 NumericAttributeIfNotNull("IconIndex", row, 7)
440 );
441
442 var componentId = row.FieldAsString(1);
443 if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
573 { 444 {
574 component.AddChild(internetShortcut); 445 component.Add(internetShortcut);
575 } 446 }
576 else 447 else
577 { 448 {
578 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); 449 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(), "Component_", componentId, "Component"));
579 } 450 }
580 451
581 this.Core.IndexElement(row, internetShortcut); 452 this.DecompilerHelper.IndexElement(row, internetShortcut);
582 } 453 }
583 } 454 }
584 455
@@ -588,54 +459,48 @@ namespace WixToolset.Extensions
588 /// <param name="table">The table to decompile.</param> 459 /// <param name="table">The table to decompile.</param>
589 private void DecompilePerfmonTable(Table table) 460 private void DecompilePerfmonTable(Table table)
590 { 461 {
591 foreach (Row row in table.Rows) 462 foreach (var row in table.Rows)
592 { 463 {
593 Util.PerfCounter perfCounter = new Util.PerfCounter(); 464 this.DecompilerHelper.IndexElement(row, new XElement(UtilConstants.PerfCounterName, new XAttribute("Name", row.FieldAsString(2))));
594
595 perfCounter.Name = (string)row[2];
596
597 this.Core.IndexElement(row, perfCounter);
598 } 465 }
599 } 466 }
600 467
601 /// <summary> 468 /// <summary>
602 /// Decompile the PerfmonManifest table. 469 /// Decompile the PerfmonManifest table.
603 /// </summary> 470 /// </summary>
604 /// <param name="table">The table to decompile.</param> 471 /// <param name="table">The table to decompile.</param>
605 private void DecompilePerfmonManifestTable(Table table) 472 private void DecompilePerfmonManifestTable(Table table)
606 { 473 {
607 foreach (Row row in table.Rows) 474 foreach (var row in table.Rows)
608 { 475 {
609 Util.PerfCounterManifest perfCounterManifest = new Util.PerfCounterManifest(); 476 this.DecompilerHelper.IndexElement(row, new XElement(UtilConstants.PerfCounterManifestName, new XAttribute("ResourceFileDirectory", row.FieldAsString(2))));
610
611 perfCounterManifest.ResourceFileDirectory = (string)row[2];
612
613 this.Core.IndexElement(row, perfCounterManifest);
614 } 477 }
615 } 478 }
616 479
617 /// <summary> 480 /// <summary>
618 /// Decompile the EventManifest table. 481 /// Decompile the EventManifest table.
619 /// </summary> 482 /// </summary>
620 /// <param name="table">The table to decompile.</param> 483 /// <param name="table">The table to decompile.</param>
621 private void DecompileEventManifestTable(Table table) 484 private void DecompileEventManifestTable(Table table)
622 { 485 {
623 foreach (Row row in table.Rows) 486 foreach (var row in table.Rows)
624 { 487 {
625 Util.EventManifest eventManifest = new Util.EventManifest(); 488 this.DecompilerHelper.IndexElement(row, new XElement(UtilConstants.EventManifestName));
626 this.Core.IndexElement(row, eventManifest);
627 } 489 }
628 } 490 }
629 491
630 /// <summary> 492 /// <summary>
631 /// Decompile the SecureObjects table. 493 /// Decompile the SecureObjects table.
632 /// </summary> 494 /// </summary>
633 /// <param name="table">The table to decompile.</param> 495 /// <param name="table">The table to decompile.</param>
634 private void DecompileSecureObjectsTable(Table table) 496 private void DecompileSecureObjectsTable(Table table)
635 { 497 {
636 foreach (Row row in table.Rows) 498 foreach (var row in table.Rows)
637 { 499 {
638 Util.PermissionEx permissionEx = new Util.PermissionEx(); 500 var permissionEx = new XElement(UtilConstants.PermissionExName,
501 AttributeIfNotNull("Domain", row, 2),
502 AttributeIfNotNull("User", row, 3)
503 );
639 504
640 string[] specialPermissions; 505 string[] specialPermissions;
641 switch ((string)row[1]) 506 switch ((string)row[1])
@@ -653,155 +518,13 @@ namespace WixToolset.Extensions
653 specialPermissions = UtilConstants.ServicePermissions; 518 specialPermissions = UtilConstants.ServicePermissions;
654 break; 519 break;
655 default: 520 default:
656 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1])); 521 this.Messaging.Write(WarningMessages.IllegalColumnValue(row.SourceLineNumbers, row.Table.Name, row.Fields[1].Column.Name, row[1]));
657 return; 522 return;
658 } 523 }
659 524
660 int permissionBits = (int)row[4]; 525 this.AddPermissionAttributes(permissionEx, row, 4, specialPermissions);
661 for (int i = 0; i < 32; i++)
662 {
663 if (0 != ((permissionBits >> i) & 1))
664 {
665 string name = null;
666 526
667 if (16 > i && specialPermissions.Length > i) 527 this.DecompilerHelper.IndexElement(row, permissionEx);
668 {
669 name = specialPermissions[i];
670 }
671 else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16))
672 {
673 name = UtilConstants.StandardPermissions[i - 16];
674 }
675 else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28))
676 {
677 name = UtilConstants.GenericPermissions[i - 28];
678 }
679
680 if (null == name)
681 {
682 this.Core.OnMessage(WixWarnings.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), i));
683 }
684 else
685 {
686 switch (name)
687 {
688 case "Append":
689 permissionEx.Append = Util.YesNoType.yes;
690 break;
691 case "ChangePermission":
692 permissionEx.ChangePermission = Util.YesNoType.yes;
693 break;
694 case "CreateChild":
695 permissionEx.CreateChild = Util.YesNoType.yes;
696 break;
697 case "CreateFile":
698 permissionEx.CreateFile = Util.YesNoType.yes;
699 break;
700 case "CreateLink":
701 permissionEx.CreateLink = Util.YesNoType.yes;
702 break;
703 case "CreateSubkeys":
704 permissionEx.CreateSubkeys = Util.YesNoType.yes;
705 break;
706 case "Delete":
707 permissionEx.Delete = Util.YesNoType.yes;
708 break;
709 case "DeleteChild":
710 permissionEx.DeleteChild = Util.YesNoType.yes;
711 break;
712 case "EnumerateSubkeys":
713 permissionEx.EnumerateSubkeys = Util.YesNoType.yes;
714 break;
715 case "Execute":
716 permissionEx.Execute = Util.YesNoType.yes;
717 break;
718 case "GenericAll":
719 permissionEx.GenericAll = Util.YesNoType.yes;
720 break;
721 case "GenericExecute":
722 permissionEx.GenericExecute = Util.YesNoType.yes;
723 break;
724 case "GenericRead":
725 permissionEx.GenericRead = Util.YesNoType.yes;
726 break;
727 case "GenericWrite":
728 permissionEx.GenericWrite = Util.YesNoType.yes;
729 break;
730 case "Notify":
731 permissionEx.Notify = Util.YesNoType.yes;
732 break;
733 case "Read":
734 permissionEx.Read = Util.YesNoType.yes;
735 break;
736 case "ReadAttributes":
737 permissionEx.ReadAttributes = Util.YesNoType.yes;
738 break;
739 case "ReadExtendedAttributes":
740 permissionEx.ReadExtendedAttributes = Util.YesNoType.yes;
741 break;
742 case "ReadPermission":
743 permissionEx.ReadPermission = Util.YesNoType.yes;
744 break;
745 case "ServiceChangeConfig":
746 permissionEx.ServiceChangeConfig = Util.YesNoType.yes;
747 break;
748 case "ServiceEnumerateDependents":
749 permissionEx.ServiceEnumerateDependents = Util.YesNoType.yes;
750 break;
751 case "ServiceInterrogate":
752 permissionEx.ServiceInterrogate = Util.YesNoType.yes;
753 break;
754 case "ServicePauseContinue":
755 permissionEx.ServicePauseContinue = Util.YesNoType.yes;
756 break;
757 case "ServiceQueryConfig":
758 permissionEx.ServiceQueryConfig = Util.YesNoType.yes;
759 break;
760 case "ServiceQueryStatus":
761 permissionEx.ServiceQueryStatus = Util.YesNoType.yes;
762 break;
763 case "ServiceStart":
764 permissionEx.ServiceStart = Util.YesNoType.yes;
765 break;
766 case "ServiceStop":
767 permissionEx.ServiceStop = Util.YesNoType.yes;
768 break;
769 case "ServiceUserDefinedControl":
770 permissionEx.ServiceUserDefinedControl = Util.YesNoType.yes;
771 break;
772 case "Synchronize":
773 permissionEx.Synchronize = Util.YesNoType.yes;
774 break;
775 case "TakeOwnership":
776 permissionEx.TakeOwnership = Util.YesNoType.yes;
777 break;
778 case "Traverse":
779 permissionEx.Traverse = Util.YesNoType.yes;
780 break;
781 case "Write":
782 permissionEx.Write = Util.YesNoType.yes;
783 break;
784 case "WriteAttributes":
785 permissionEx.WriteAttributes = Util.YesNoType.yes;
786 break;
787 case "WriteExtendedAttributes":
788 permissionEx.WriteExtendedAttributes = Util.YesNoType.yes;
789 break;
790 default:
791 throw new InvalidOperationException(String.Format("Unknown permission attribute '{0}'.", name));
792 }
793 }
794 }
795 }
796
797 if (null != row[2])
798 {
799 permissionEx.Domain = (string)row[2];
800 }
801
802 permissionEx.User = (string)row[3];
803
804 this.Core.IndexElement(row, permissionEx);
805 } 528 }
806 } 529 }
807 530
@@ -811,90 +534,20 @@ namespace WixToolset.Extensions
811 /// <param name="table">The table to decompile.</param> 534 /// <param name="table">The table to decompile.</param>
812 private void DecompileServiceConfigTable(Table table) 535 private void DecompileServiceConfigTable(Table table)
813 { 536 {
814 foreach (Row row in table.Rows) 537 foreach (var row in table.Rows)
815 { 538 {
816 Util.ServiceConfig serviceConfig = new Util.ServiceConfig(); 539 var serviceConfig = new XElement(UtilConstants.ServiceConfigName,
817 540 new XAttribute("ServiceName", row.FieldAsString(0)),
818 serviceConfig.ServiceName = (string)row[0]; 541 AttributeIfNotNull("FirstFailureActionType", row, 3),
819 542 AttributeIfNotNull("SecondFailureActionType", row, 4),
820 switch ((string)row[3]) 543 AttributeIfNotNull("ThirdFailureActionType", row, 5),
821 { 544 NumericAttributeIfNotNull("ResetPeriodInDays", row, 6),
822 case "none": 545 NumericAttributeIfNotNull("RestartServiceDelayInSeconds", row, 7),
823 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.none; 546 AttributeIfNotNull("ProgramCommandLine", row, 8),
824 break; 547 AttributeIfNotNull("RebootMessage", row, 9)
825 case "reboot": 548 );
826 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.reboot; 549
827 break; 550 this.DecompilerHelper.IndexElement(row, serviceConfig);
828 case "restart":
829 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.restart;
830 break;
831 case "runCommand":
832 serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.runCommand;
833 break;
834 default:
835 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3]));
836 break;
837 }
838
839 switch ((string)row[4])
840 {
841 case "none":
842 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.none;
843 break;
844 case "reboot":
845 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.reboot;
846 break;
847 case "restart":
848 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.restart;
849 break;
850 case "runCommand":
851 serviceConfig.SecondFailureActionType = Util.ServiceConfig.SecondFailureActionTypeType.runCommand;
852 break;
853 default:
854 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[4].Column.Name, row[4]));
855 break;
856 }
857
858 switch ((string)row[5])
859 {
860 case "none":
861 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.none;
862 break;
863 case "reboot":
864 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.reboot;
865 break;
866 case "restart":
867 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.restart;
868 break;
869 case "runCommand":
870 serviceConfig.ThirdFailureActionType = Util.ServiceConfig.ThirdFailureActionTypeType.runCommand;
871 break;
872 default:
873 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[5].Column.Name, row[5]));
874 break;
875 }
876
877 if (null != row[6])
878 {
879 serviceConfig.ResetPeriodInDays = (int)row[6];
880 }
881
882 if (null != row[7])
883 {
884 serviceConfig.RestartServiceDelayInSeconds = (int)row[7];
885 }
886
887 if (null != row[8])
888 {
889 serviceConfig.ProgramCommandLine = (string)row[8];
890 }
891
892 if (null != row[9])
893 {
894 serviceConfig.RebootMessage = (string)row[9];
895 }
896
897 this.Core.IndexElement(row, serviceConfig);
898 } 551 }
899 } 552 }
900 553
@@ -904,97 +557,58 @@ namespace WixToolset.Extensions
904 /// <param name="table">The table to decompile.</param> 557 /// <param name="table">The table to decompile.</param>
905 private void DecompileUserTable(Table table) 558 private void DecompileUserTable(Table table)
906 { 559 {
907 foreach (Row row in table.Rows) 560 foreach (var row in table.Rows)
908 { 561 {
909 Util.User user = new Util.User(); 562 var attributes = row.FieldAsNullableInteger(5) ?? 0;
910 563
911 user.Id = (string)row[0]; 564 var user = new XElement(UtilConstants.UserName,
912 565 new XAttribute("Id", row.FieldAsString(0)),
913 user.Name = (string)row[2]; 566 new XAttribute("Name", row.FieldAsString(2)),
914 567 AttributeIfNotNull("Domain", row, 3),
915 if (null != row[3]) 568 AttributeIfNotNull("Password", row, 4),
569 AttributeIfTrue("PasswordNeverExpires", UtilCompiler.UserDontExpirePasswrd == (attributes & UtilCompiler.UserDontExpirePasswrd)),
570 AttributeIfTrue("CanNotChangePassword", UtilCompiler.UserPasswdCantChange == (attributes & UtilCompiler.UserPasswdCantChange)),
571 AttributeIfTrue("PasswordExpired", UtilCompiler.UserPasswdChangeReqdOnLogin == (attributes & UtilCompiler.UserPasswdChangeReqdOnLogin)),
572 AttributeIfTrue("Disabled", UtilCompiler.UserDisableAccount == (attributes & UtilCompiler.UserDisableAccount)),
573 AttributeIfTrue("FailIfExists", UtilCompiler.UserFailIfExists == (attributes & UtilCompiler.UserFailIfExists)),
574 AttributeIfTrue("UpdateIfExists", UtilCompiler.UserUpdateIfExists == (attributes & UtilCompiler.UserUpdateIfExists)),
575 AttributeIfTrue("LogonAsService", UtilCompiler.UserLogonAsService == (attributes & UtilCompiler.UserLogonAsService)),
576 AttributeIfTrue("LogonAsService", UtilCompiler.UserLogonAsService == (attributes & UtilCompiler.UserLogonAsService))
577 );
578
579 if (UtilCompiler.UserDontRemoveOnUninstall == (attributes & UtilCompiler.UserDontRemoveOnUninstall))
916 { 580 {
917 user.Domain = (string)row[3]; 581 user.Add(new XAttribute("RemoveOnUninstall", "no"));
918 } 582 }
919 583
920 if (null != row[4]) 584 if (UtilCompiler.UserDontCreateUser == (attributes & UtilCompiler.UserDontCreateUser))
921 { 585 {
922 user.Password = (string)row[4]; 586 user.Add(new XAttribute("CreateUser", "no"));
923 } 587 }
924 588
925 if (null != row[5]) 589 if (UtilCompiler.UserNonVital == (attributes & UtilCompiler.UserNonVital))
926 { 590 {
927 int attributes = (int)row[5]; 591 user.Add(new XAttribute("Vital", "no"));
928
929 if (UtilCompiler.UserDontExpirePasswrd == (attributes & UtilCompiler.UserDontExpirePasswrd))
930 {
931 user.PasswordNeverExpires = Util.YesNoType.yes;
932 }
933
934 if (UtilCompiler.UserPasswdCantChange == (attributes & UtilCompiler.UserPasswdCantChange))
935 {
936 user.CanNotChangePassword = Util.YesNoType.yes;
937 }
938
939 if (UtilCompiler.UserPasswdChangeReqdOnLogin == (attributes & UtilCompiler.UserPasswdChangeReqdOnLogin))
940 {
941 user.PasswordExpired = Util.YesNoType.yes;
942 }
943
944 if (UtilCompiler.UserDisableAccount == (attributes & UtilCompiler.UserDisableAccount))
945 {
946 user.Disabled = Util.YesNoType.yes;
947 }
948
949 if (UtilCompiler.UserFailIfExists == (attributes & UtilCompiler.UserFailIfExists))
950 {
951 user.FailIfExists = Util.YesNoType.yes;
952 }
953
954 if (UtilCompiler.UserUpdateIfExists == (attributes & UtilCompiler.UserUpdateIfExists))
955 {
956 user.UpdateIfExists = Util.YesNoType.yes;
957 }
958
959 if (UtilCompiler.UserLogonAsService == (attributes & UtilCompiler.UserLogonAsService))
960 {
961 user.LogonAsService = Util.YesNoType.yes;
962 }
963
964 if (UtilCompiler.UserDontRemoveOnUninstall == (attributes & UtilCompiler.UserDontRemoveOnUninstall))
965 {
966 user.RemoveOnUninstall = Util.YesNoType.no;
967 }
968
969 if (UtilCompiler.UserDontCreateUser == (attributes & UtilCompiler.UserDontCreateUser))
970 {
971 user.CreateUser = Util.YesNoType.no;
972 }
973
974 if (UtilCompiler.UserNonVital == (attributes & UtilCompiler.UserNonVital))
975 {
976 user.Vital = Util.YesNoType.no;
977 }
978 } 592 }
979 593
980 if (null != row[1]) 594 var componentId = row.FieldAsString(1);
595 if (!String.IsNullOrEmpty(componentId))
981 { 596 {
982 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); 597 if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
983
984 if (null != component)
985 { 598 {
986 component.AddChild(user); 599 component.Add(user);
987 } 600 }
988 else 601 else
989 { 602 {
990 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); 603 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(), "Component_", componentId, "Component"));
991 } 604 }
992 } 605 }
993 else 606 else
994 { 607 {
995 this.Core.RootElement.AddChild(user); 608 this.DecompilerHelper.AddElementToRoot(user);
996 } 609 }
997 this.Core.IndexElement(row, user); 610
611 this.DecompilerHelper.IndexElement(row, user);
998 } 612 }
999 } 613 }
1000 614
@@ -1004,21 +618,16 @@ namespace WixToolset.Extensions
1004 /// <param name="table">The table to decompile.</param> 618 /// <param name="table">The table to decompile.</param>
1005 private void DecompileUserGroupTable(Table table) 619 private void DecompileUserGroupTable(Table table)
1006 { 620 {
1007 foreach (Row row in table.Rows) 621 foreach (var row in table.Rows)
1008 { 622 {
1009 Util.User user = (Util.User)this.Core.GetIndexedElement("User", (string)row[0]); 623 var userId = row.FieldAsString(0);
1010 624 if (this.DecompilerHelper.TryGetIndexedElement("User", userId, out var user))
1011 if (null != user)
1012 { 625 {
1013 Util.GroupRef groupRef = new Util.GroupRef(); 626 user.Add(new XElement(UtilConstants.GroupRefName, new XAttribute("Id", row.FieldAsString(1))));
1014
1015 groupRef.Id = (string)row[1];
1016
1017 user.AddChild(groupRef);
1018 } 627 }
1019 else 628 else
1020 { 629 {
1021 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Group_", (string)row[0], "Group")); 630 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(), "Group_", userId, "Group"));
1022 } 631 }
1023 } 632 }
1024 } 633 }
@@ -1029,75 +638,58 @@ namespace WixToolset.Extensions
1029 /// <param name="table">The table to decompile.</param> 638 /// <param name="table">The table to decompile.</param>
1030 private void DecompileXmlConfigTable(Table table) 639 private void DecompileXmlConfigTable(Table table)
1031 { 640 {
1032 foreach (Row row in table.Rows) 641 foreach (var row in table.Rows)
1033 { 642 {
1034 Util.XmlConfig xmlConfig = new Util.XmlConfig(); 643 var flags = row.FieldAsNullableInteger(6) ?? 0;
1035 644 string node = null;
1036 xmlConfig.Id = (string)row[0]; 645 string action = null;
1037 646 string on = null;
1038 xmlConfig.File = (string)row[1];
1039
1040 xmlConfig.ElementPath = (string)row[2];
1041
1042 if (null != row[3])
1043 {
1044 xmlConfig.VerifyPath = (string)row[3];
1045 }
1046
1047 if (null != row[4])
1048 {
1049 xmlConfig.Name = (string)row[4];
1050 }
1051
1052 if (null != row[5])
1053 {
1054 xmlConfig.Value = (string)row[5];
1055 }
1056
1057 int flags = (int)row[6];
1058 647
1059 if (0x1 == (flags & 0x1)) 648 if (0x1 == (flags & 0x1))
1060 { 649 {
1061 xmlConfig.Node = Util.XmlConfig.NodeType.element; 650 node = "element";
1062 } 651 }
1063 else if (0x2 == (flags & 0x2)) 652 else if (0x2 == (flags & 0x2))
1064 { 653 {
1065 xmlConfig.Node = Util.XmlConfig.NodeType.value; 654 node = "value";
1066 } 655 }
1067 else if (0x4 == (flags & 0x4)) 656 else if (0x4 == (flags & 0x4))
1068 { 657 {
1069 xmlConfig.Node = Util.XmlConfig.NodeType.document; 658 node = "document";
1070 } 659 }
1071 660
1072 if (0x10 == (flags & 0x10)) 661 if (0x10 == (flags & 0x10))
1073 { 662 {
1074 xmlConfig.Action = Util.XmlConfig.ActionType.create; 663 action = "create";
1075 } 664 }
1076 else if (0x20 == (flags & 0x20)) 665 else if (0x20 == (flags & 0x20))
1077 { 666 {
1078 xmlConfig.Action = Util.XmlConfig.ActionType.delete; 667 action = "delete";
1079 } 668 }
1080 669
1081 if (0x100 == (flags & 0x100)) 670 if (0x100 == (flags & 0x100))
1082 { 671 {
1083 xmlConfig.On = Util.XmlConfig.OnType.install; 672 on = "install";
1084 } 673 }
1085 else if (0x200 == (flags & 0x200)) 674 else if (0x200 == (flags & 0x200))
1086 { 675 {
1087 xmlConfig.On = Util.XmlConfig.OnType.uninstall; 676 on = "uninstall";
1088 }
1089
1090 if (0x00001000 == (flags & 0x00001000))
1091 {
1092 xmlConfig.PreserveModifiedDate = Util.YesNoType.yes;
1093 }
1094
1095 if (null != row[8])
1096 {
1097 xmlConfig.Sequence = (int)row[8];
1098 } 677 }
1099 678
1100 this.Core.IndexElement(row, xmlConfig); 679 var xmlConfig = new XElement(UtilConstants.XmlConfigName,
680 new XAttribute("Id", row.FieldAsString(0)),
681 new XAttribute("File", row.FieldAsString(1)),
682 new XAttribute("ElementPath", row.FieldAsString(2)),
683 AttributeIfNotNull("VerifyPath", row, 3),
684 AttributeIfNotNull("Name", row, 4),
685 AttributeIfNotNull("Node", node),
686 AttributeIfNotNull("Action", action),
687 AttributeIfNotNull("On", on),
688 AttributeIfTrue("PreserveModifiedDate", 0x00001000 == (flags & 0x00001000)),
689 NumericAttributeIfNotNull("Sequence", row, 8)
690 );
691
692 this.DecompilerHelper.IndexElement(row, xmlConfig);
1101 } 693 }
1102 } 694 }
1103 695
@@ -1114,34 +706,30 @@ namespace WixToolset.Extensions
1114 /// </remarks> 706 /// </remarks>
1115 private void FinalizePerfmonTable(TableIndexedCollection tables) 707 private void FinalizePerfmonTable(TableIndexedCollection tables)
1116 { 708 {
1117 Table perfmonTable = tables["Perfmon"]; 709 if (tables.TryGetTable("Perfmon", out var perfmonTable))
1118
1119 if (null != perfmonTable)
1120 { 710 {
1121 foreach (Row row in perfmonTable.Rows) 711 foreach (var row in perfmonTable.Rows)
1122 { 712 {
1123 string formattedFile = (string)row[1]; 713 var formattedFile = row.FieldAsString(1);
1124 Util.PerfCounter perfCounter = (Util.PerfCounter)this.Core.GetIndexedElement(row);
1125 714
1126 // try to "de-format" the File column's value to determine the proper parent File element 715 // try to "de-format" the File column's value to determine the proper parent File element
1127 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) 716 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1128 && formattedFile.EndsWith("]", StringComparison.Ordinal)) 717 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1129 { 718 {
1130 string fileId = formattedFile.Substring(2, formattedFile.Length - 3); 719 var fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1131 720 if (this.DecompilerHelper.TryGetIndexedElement("File", fileId, out var file))
1132 Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
1133 if (null != file)
1134 { 721 {
1135 file.AddChild(perfCounter); 722 var perfCounter = this.DecompilerHelper.GetIndexedElement(row);
723 file.Add(perfCounter);
1136 } 724 }
1137 else 725 else
1138 { 726 {
1139 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfmonTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File")); 727 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, perfmonTable.Name, row.GetPrimaryKey(), "File", formattedFile, "File"));
1140 } 728 }
1141 } 729 }
1142 else 730 else
1143 { 731 {
1144 this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon")); 732 this.Messaging.Write(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon"));
1145 } 733 }
1146 } 734 }
1147 } 735 }
@@ -1153,34 +741,33 @@ namespace WixToolset.Extensions
1153 /// <param name="tables">The collection of all tables.</param> 741 /// <param name="tables">The collection of all tables.</param>
1154 private void FinalizePerfmonManifestTable(TableIndexedCollection tables) 742 private void FinalizePerfmonManifestTable(TableIndexedCollection tables)
1155 { 743 {
1156 Table perfmonManifestTable = tables["PerfmonManifest"]; 744 if (tables.TryGetTable("PerfmonManifest", out var perfmonManifestTable))
1157
1158 if (null != perfmonManifestTable)
1159 { 745 {
1160 foreach (Row row in perfmonManifestTable.Rows) 746 foreach (var row in perfmonManifestTable.Rows)
1161 { 747 {
1162 string formattedFile = (string)row[1]; 748 var formattedFile = row.FieldAsString(1);
1163 Util.PerfCounterManifest perfCounterManifest = (Util.PerfCounterManifest)this.Core.GetIndexedElement(row);
1164 749
1165 // try to "de-format" the File column's value to determine the proper parent File element 750 // try to "de-format" the File column's value to determine the proper parent File element
1166 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) 751 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1167 && formattedFile.EndsWith("]", StringComparison.Ordinal)) 752 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1168 { 753 {
1169 string fileId = formattedFile.Substring(2, formattedFile.Length - 3); 754 var perfCounterManifest = this.DecompilerHelper.GetIndexedElement(row);
755 var fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1170 756
1171 Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); 757 if (this.DecompilerHelper.TryGetIndexedElement("File", fileId, out var file))
1172 if (null != file)
1173 { 758 {
1174 file.AddChild(perfCounterManifest); 759 file.Add(perfCounterManifest);
1175 } 760 }
1176 else 761 else
1177 { 762 {
1178 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, perfCounterManifest.ResourceFileDirectory, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File", formattedFile, "File")); 763 var resourceFileDirectory = perfCounterManifest.Attribute("ResourceFileDirectory")?.Value;
764
765 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, resourceFileDirectory, row.GetPrimaryKey(), "File", formattedFile, "File"));
1179 } 766 }
1180 } 767 }
1181 else 768 else
1182 { 769 {
1183 this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest")); 770 this.Messaging.Write(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest"));
1184 } 771 }
1185 } 772 }
1186 } 773 }
@@ -1196,64 +783,61 @@ namespace WixToolset.Extensions
1196 /// </remarks> 783 /// </remarks>
1197 private void FinalizeSecureObjectsTable(TableIndexedCollection tables) 784 private void FinalizeSecureObjectsTable(TableIndexedCollection tables)
1198 { 785 {
1199 Table createFolderTable = tables["CreateFolder"]; 786 var createFolderElementsByDirectoryId = new Dictionary<string, List<XElement>>();
1200 Table secureObjectsTable = tables["SecureObjects"];
1201
1202 Hashtable createFolders = new Hashtable();
1203 787
1204 // index the CreateFolder table because the foreign key to this table from the 788 // index the CreateFolder table because the foreign key to this table from the
1205 // LockPermissions table is only part of the primary key of this table 789 // LockPermissions table is only part of the primary key of this table
1206 if (null != createFolderTable) 790 if (tables.TryGetTable("CreateFolder", out var createFolderTable))
1207 { 791 {
1208 foreach (Row row in createFolderTable.Rows) 792 foreach (var row in createFolderTable.Rows)
1209 { 793 {
1210 Wix.CreateFolder createFolder = (Wix.CreateFolder)this.Core.GetIndexedElement(row); 794 var directoryId = row.FieldAsString(0);
1211 string directoryId = (string)row[0];
1212 795
1213 if (!createFolders.Contains(directoryId)) 796 if (!createFolderElementsByDirectoryId.TryGetValue(directoryId, out var createFolderElements))
1214 { 797 {
1215 createFolders.Add(directoryId, new ArrayList()); 798 createFolderElements = new List<XElement>();
799 createFolderElementsByDirectoryId.Add(directoryId, createFolderElements);
1216 } 800 }
1217 ((ArrayList)createFolders[directoryId]).Add(createFolder); 801
802 var createFolder = this.DecompilerHelper.GetIndexedElement(row);
803 createFolderElements.Add(createFolder);
1218 } 804 }
1219 } 805 }
1220 806
1221 if (null != secureObjectsTable) 807 if (tables.TryGetTable("SecureObjects", out var secureObjectsTable))
1222 { 808 {
1223 foreach (Row row in secureObjectsTable.Rows) 809 foreach (var row in secureObjectsTable.Rows)
1224 { 810 {
1225 string id = (string)row[0]; 811 var id = row.FieldAsString(0);
1226 string table = (string)row[1]; 812 var table = row.FieldAsString(1);
1227 813
1228 Util.PermissionEx permissionEx = (Util.PermissionEx)this.Core.GetIndexedElement(row); 814 var permissionEx = this.DecompilerHelper.GetIndexedElement(row);
1229 815
1230 if ("CreateFolder" == table) 816 if (table == "CreateFolder")
1231 { 817 {
1232 ArrayList createFolderElements = (ArrayList)createFolders[id]; 818 if (createFolderElementsByDirectoryId.TryGetValue(id, out var createFolderElements))
1233
1234 if (null != createFolderElements)
1235 { 819 {
1236 foreach (Wix.CreateFolder createFolder in createFolderElements) 820 foreach (var createFolder in createFolderElements)
1237 { 821 {
1238 createFolder.AddChild(permissionEx); 822 createFolder.Add(permissionEx);
1239 } 823 }
1240 } 824 }
1241 else 825 else
1242 { 826 {
1243 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table)); 827 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(), "LockObject", id, table));
1244 } 828 }
1245 } 829 }
1246 else 830 else
1247 { 831 {
1248 Wix.IParentElement parentElement = (Wix.IParentElement)this.Core.GetIndexedElement(table, id); 832 var parentElement = this.DecompilerHelper.GetIndexedElement(table, id);
1249 833
1250 if (null != parentElement) 834 if (parentElement != null)
1251 { 835 {
1252 parentElement.AddChild(permissionEx); 836 parentElement.Add(permissionEx);
1253 } 837 }
1254 else 838 else
1255 { 839 {
1256 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table)); 840 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "SecureObjects", row.GetPrimaryKey(), "LockObject", id, table));
1257 } 841 }
1258 } 842 }
1259 } 843 }
@@ -1270,10 +854,8 @@ namespace WixToolset.Extensions
1270 /// </remarks> 854 /// </remarks>
1271 private void FinalizeServiceConfigTable(TableIndexedCollection tables) 855 private void FinalizeServiceConfigTable(TableIndexedCollection tables)
1272 { 856 {
1273 Table serviceConfigTable = tables["ServiceConfig"]; 857 //var serviceInstalls = new Hashtable();
1274 Table serviceInstallTable = tables["ServiceInstall"]; 858 var serviceInstallElementsByName = new Dictionary<string, List<XElement>>();
1275
1276 Hashtable serviceInstalls = new Hashtable();
1277 859
1278 // index the ServiceInstall table because the foreign key used by the ServiceConfig 860 // index the ServiceInstall table because the foreign key used by the ServiceConfig
1279 // table is actually the ServiceInstall.Name, not the ServiceInstall.ServiceInstall 861 // table is actually the ServiceInstall.Name, not the ServiceInstall.ServiceInstall
@@ -1281,55 +863,54 @@ namespace WixToolset.Extensions
1281 // decompiler must assume there could be multiple matches and add the ServiceConfig to each 863 // decompiler must assume there could be multiple matches and add the ServiceConfig to each
1282 // TODO: the Component column information should be taken into acount to accurately identify 864 // TODO: the Component column information should be taken into acount to accurately identify
1283 // the correct column to use 865 // the correct column to use
1284 if (null != serviceInstallTable) 866 if (tables.TryGetTable("ServiceInstall", out var serviceInstallTable))
1285 { 867 {
1286 foreach (Row row in serviceInstallTable.Rows) 868 foreach (var row in serviceInstallTable.Rows)
1287 { 869 {
1288 string name = (string)row[1]; 870 var name = row.FieldAsString(1);
1289 Wix.ServiceInstall serviceInstall = (Wix.ServiceInstall)this.Core.GetIndexedElement(row);
1290 871
1291 if (!serviceInstalls.Contains(name)) 872 if (!serviceInstallElementsByName.TryGetValue(name, out var serviceInstallElements))
1292 { 873 {
1293 serviceInstalls.Add(name, new ArrayList()); 874 serviceInstallElements = new List<XElement>();
875 serviceInstallElementsByName.Add(name, serviceInstallElements);
1294 } 876 }
1295 877
1296 ((ArrayList)serviceInstalls[name]).Add(serviceInstall); 878 var serviceInstall = this.DecompilerHelper.GetIndexedElement(row);
879 serviceInstallElements.Add(serviceInstall);
1297 } 880 }
1298 } 881 }
1299 882
1300 if (null != serviceConfigTable) 883 if (tables.TryGetTable("ServiceConfig", out var serviceConfigTable))
1301 { 884 {
1302 foreach (Row row in serviceConfigTable.Rows) 885 foreach (var row in serviceConfigTable.Rows)
1303 { 886 {
1304 Util.ServiceConfig serviceConfig = (Util.ServiceConfig)this.Core.GetIndexedElement(row); 887 var serviceConfig = this.DecompilerHelper.GetIndexedElement(row);
1305 888
1306 if (0 == (int)row[2]) 889 if (row.FieldAsInteger(2) == 0)
1307 { 890 {
1308 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); 891 var componentId = row.FieldAsString(1);
1309 892 if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
1310 if (null != component)
1311 { 893 {
1312 component.AddChild(serviceConfig); 894 component.Add(serviceConfig);
1313 } 895 }
1314 else 896 else
1315 { 897 {
1316 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); 898 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(), "Component_", componentId, "Component"));
1317 } 899 }
1318 } 900 }
1319 else 901 else
1320 { 902 {
1321 ArrayList serviceInstallElements = (ArrayList)serviceInstalls[row[0]]; 903 var name = row.FieldAsString(0);
1322 904 if (serviceInstallElementsByName.TryGetValue(name, out var serviceInstallElements))
1323 if (null != serviceInstallElements)
1324 { 905 {
1325 foreach (Wix.ServiceInstall serviceInstall in serviceInstallElements) 906 foreach (var serviceInstall in serviceInstallElements)
1326 { 907 {
1327 serviceInstall.AddChild(serviceConfig); 908 serviceInstall.Add(serviceConfig);
1328 } 909 }
1329 } 910 }
1330 else 911 else
1331 { 912 {
1332 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ServiceName", (string)row[0], "ServiceInstall")); 913 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, serviceConfigTable.Name, row.GetPrimaryKey(), "ServiceName", name, "ServiceInstall"));
1333 } 914 }
1334 } 915 }
1335 } 916 }
@@ -1342,38 +923,34 @@ namespace WixToolset.Extensions
1342 /// <param name="tables">Collection of all tables.</param> 923 /// <param name="tables">Collection of all tables.</param>
1343 private void FinalizeXmlConfigTable(TableIndexedCollection tables) 924 private void FinalizeXmlConfigTable(TableIndexedCollection tables)
1344 { 925 {
1345 Table xmlConfigTable = tables["XmlConfig"]; 926 if (tables.TryGetTable("XmlConfig", out var xmlConfigTable))
1346
1347 if (null != xmlConfigTable)
1348 { 927 {
1349 foreach (Row row in xmlConfigTable.Rows) 928 foreach (var row in xmlConfigTable.Rows)
1350 { 929 {
1351 Util.XmlConfig xmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement(row); 930 var xmlConfig = this.DecompilerHelper.GetIndexedElement(row);
1352 931
1353 if (null == row[6] || 0 == (int)row[6]) 932 if (null == row[6] || 0 == (int)row[6])
1354 { 933 {
1355 Util.XmlConfig parentXmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement("XmlConfig", (string)row[2]); 934 var id = row.FieldAsString(2);
1356 935 if (this.DecompilerHelper.TryGetIndexedElement("XmlConfig", id, out var parentXmlConfig))
1357 if (null != parentXmlConfig)
1358 { 936 {
1359 parentXmlConfig.AddChild(xmlConfig); 937 parentXmlConfig.Add(xmlConfig);
1360 } 938 }
1361 else 939 else
1362 { 940 {
1363 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ElementPath", (string)row[2], "XmlConfig")); 941 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(), "ElementPath", (string)row[2], "XmlConfig"));
1364 } 942 }
1365 } 943 }
1366 else 944 else
1367 { 945 {
1368 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[7]); 946 var componentId = row.FieldAsString(7);
1369 947 if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
1370 if (null != component)
1371 { 948 {
1372 component.AddChild(xmlConfig); 949 component.Add(xmlConfig);
1373 } 950 }
1374 else 951 else
1375 { 952 {
1376 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[7], "Component")); 953 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, xmlConfigTable.Name, row.GetPrimaryKey(), "Component_", componentId, "Component"));
1377 } 954 }
1378 } 955 }
1379 } 956 }
@@ -1391,113 +968,88 @@ namespace WixToolset.Extensions
1391 /// </remarks> 968 /// </remarks>
1392 private void FinalizeXmlFileTable(TableIndexedCollection tables) 969 private void FinalizeXmlFileTable(TableIndexedCollection tables)
1393 { 970 {
1394 Table xmlFileTable = tables["XmlFile"]; 971 if (tables.TryGetTable("XmlFile", out var xmlFileTable))
1395 Table eventManifestTable = tables["EventManifest"];
1396
1397 if (null != xmlFileTable)
1398 { 972 {
1399 foreach (Row row in xmlFileTable.Rows) 973 var eventManifestTable = tables["EventManifest"];
974
975 foreach (var row in xmlFileTable.Rows)
1400 { 976 {
1401 bool bManifestGenerated = false; 977 var manifestGenerated = false;
1402 string xmlFileConfigId = (string)row[0]; 978 var xmlFileConfigId = (string)row[0];
1403 if (null != eventManifestTable) 979 if (null != eventManifestTable)
1404 { 980 {
1405 foreach (Row emrow in eventManifestTable.Rows) 981 foreach (var emrow in eventManifestTable.Rows)
1406 { 982 {
1407 string formattedFile = (string)emrow[1]; 983 var formattedFile = (string)emrow[1];
1408 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) 984 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1409 && formattedFile.EndsWith("]", StringComparison.Ordinal)) 985 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1410 { 986 {
1411 string fileId = formattedFile.Substring(2, formattedFile.Length - 3); 987 var fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1412 if (String.Equals(String.Concat("Config_", fileId, "ResourceFile"), xmlFileConfigId)) 988 if (String.Equals(String.Concat("Config_", fileId, "ResourceFile"), xmlFileConfigId))
1413 { 989 {
1414 Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow); 990 if (this.DecompilerHelper.TryGetIndexedElement(emrow, out var eventManifest))
1415 if (null != eventManifest)
1416 { 991 {
1417 eventManifest.ResourceFile = (string)row[4]; 992 eventManifest.Add(new XAttribute("ResourceFile", row.FieldAsString(4)));
1418 } 993 }
1419 bManifestGenerated = true; 994 manifestGenerated = true;
1420 } 995 }
1421 996
1422 else if (String.Equals(String.Concat("Config_", fileId, "MessageFile"), xmlFileConfigId)) 997 else if (String.Equals(String.Concat("Config_", fileId, "MessageFile"), xmlFileConfigId))
1423 { 998 {
1424 Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow); 999 if (this.DecompilerHelper.TryGetIndexedElement(emrow, out var eventManifest))
1425 if (null != eventManifest)
1426 { 1000 {
1427 eventManifest.MessageFile = (string)row[4]; 1001 eventManifest.Add(new XAttribute("MessageFile", row.FieldAsString(4)));
1428 } 1002 }
1429 bManifestGenerated = true; 1003 manifestGenerated = true;
1430 } 1004 }
1431 } 1005 }
1432 } 1006 }
1433 } 1007 }
1434 1008
1435 if (true == bManifestGenerated) 1009 if (manifestGenerated)
1436 continue;
1437
1438 Util.XmlFile xmlFile = new Util.XmlFile();
1439
1440 xmlFile.Id = (string)row[0];
1441 xmlFile.File = (string)row[1];
1442 xmlFile.ElementPath = (string)row[2];
1443
1444 if (null != row[3])
1445 {
1446 xmlFile.Name = (string)row[3];
1447 }
1448
1449 if (null != row[4])
1450 { 1010 {
1451 xmlFile.Value = (string)row[4]; 1011 continue;
1452 } 1012 }
1453 1013
1454 int flags = (int)row[5]; 1014 var action = "setValue";
1015 var flags = row.FieldAsInteger(5);
1455 if (0x1 == (flags & 0x1) && 0x2 == (flags & 0x2)) 1016 if (0x1 == (flags & 0x1) && 0x2 == (flags & 0x2))
1456 { 1017 {
1457 this.Core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, xmlFileTable.Name, row.Fields[5].Column.Name, row[5])); 1018 this.Messaging.Write(WarningMessages.IllegalColumnValue(row.SourceLineNumbers, xmlFileTable.Name, row.Fields[5].Column.Name, row[5]));
1458 } 1019 }
1459 else if (0x1 == (flags & 0x1)) 1020 else if (0x1 == (flags & 0x1))
1460 { 1021 {
1461 xmlFile.Action = Util.XmlFile.ActionType.createElement; 1022 action = "createElement";
1462 } 1023 }
1463 else if (0x2 == (flags & 0x2)) 1024 else if (0x2 == (flags & 0x2))
1464 { 1025 {
1465 xmlFile.Action = Util.XmlFile.ActionType.deleteValue; 1026 action = "deleteValue";
1466 }
1467 else
1468 {
1469 xmlFile.Action = Util.XmlFile.ActionType.setValue;
1470 }
1471
1472 if (0x100 == (flags & 0x100))
1473 {
1474 xmlFile.SelectionLanguage = Util.XmlFile.SelectionLanguageType.XPath;
1475 }
1476
1477 if (0x00001000 == (flags & 0x00001000))
1478 {
1479 xmlFile.PreserveModifiedDate = Util.YesNoType.yes;
1480 } 1027 }
1481 1028
1482 if (0x00010000 == (flags & 0x00010000)) 1029 var selectionLanguage = (0x100 == (flags & 0x100)) ? "XPath" : null;
1483 { 1030 var preserveModifiedDate = 0x00001000 == (flags & 0x00001000);
1484 xmlFile.Permanent = Util.YesNoType.yes; 1031 var permanent = 0x00010000 == (flags & 0x00010000);
1485 }
1486 1032
1487 if (null != row[7]) 1033 if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(6), out var component))
1488 { 1034 {
1489 xmlFile.Sequence = (int)row[7]; 1035 var xmlFile = new XElement(UtilConstants.XmlFileName,
1490 } 1036 AttributeIfNotNull("Id", row, 0),
1491 1037 AttributeIfNotNull("File", row, 1),
1492 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[6]); 1038 AttributeIfNotNull("ElementPath", row, 2),
1493 1039 AttributeIfNotNull("Name", row, 3),
1494 if (null != component) 1040 AttributeIfNotNull("Value", row, 4),
1495 { 1041 AttributeIfNotNull("Action", action),
1496 component.AddChild(xmlFile); 1042 AttributeIfNotNull("SelectionLanguage", selectionLanguage),
1043 AttributeIfTrue("PreserveModifiedDate", preserveModifiedDate),
1044 AttributeIfTrue("Permanent", permanent),
1045 NumericAttributeIfNotNull("Sequence", row, 7)
1046 );
1047
1048 component.Add(xmlFile);
1497 } 1049 }
1498 else 1050 else
1499 { 1051 {
1500 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, xmlFileTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component")); 1052 this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, xmlFileTable.Name, row.GetPrimaryKey(), "Component_", (string)row[6], "Component"));
1501 } 1053 }
1502 } 1054 }
1503 } 1055 }
@@ -1510,34 +1062,122 @@ namespace WixToolset.Extensions
1510 /// <param name="tables">The collection of all tables.</param> 1062 /// <param name="tables">The collection of all tables.</param>
1511 private void FinalizeEventManifestTable(TableIndexedCollection tables) 1063 private void FinalizeEventManifestTable(TableIndexedCollection tables)
1512 { 1064 {
1513 Table eventManifestTable = tables["EventManifest"]; 1065 if (tables.TryGetTable("EventManifest", out var eventManifestTable))
1514
1515 if (null != eventManifestTable)
1516 { 1066 {
1517 foreach (Row row in eventManifestTable.Rows) 1067 foreach (var row in eventManifestTable.Rows)
1518 { 1068 {
1519 string formattedFile = (string)row[1]; 1069 var eventManifest = this.DecompilerHelper.GetIndexedElement(row);
1520 Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(row); 1070 var formattedFile = row.FieldAsString(1);
1521 1071
1522 // try to "de-format" the File column's value to determine the proper parent File element 1072 // try to "de-format" the File column's value to determine the proper parent File element
1523 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal)) 1073 if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1524 && formattedFile.EndsWith("]", StringComparison.Ordinal)) 1074 && formattedFile.EndsWith("]", StringComparison.Ordinal))
1525 { 1075 {
1526 string fileId = formattedFile.Substring(2, formattedFile.Length - 3); 1076 var fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1527 1077
1528 Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId); 1078 if (this.DecompilerHelper.TryGetIndexedElement("File", fileId, out var file))
1529 if (null != file)
1530 { 1079 {
1531 file.AddChild(eventManifest); 1080 file.Add(eventManifest);
1532 } 1081 }
1533 } 1082 }
1534 else 1083 else
1535 { 1084 {
1536 this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "EventManifest")); 1085 this.Messaging.Write(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "EventManifest"));
1086 }
1087 }
1088 }
1089 }
1090
1091 private void AddPermissionAttributes(XElement element, Row row, int column, string[] specialPermissions)
1092 {
1093 var permissions = row.FieldAsInteger(column);
1094 for (var i = 0; i < 32; i++)
1095 {
1096 if (0 != ((permissions >> i) & 1))
1097 {
1098 string name = null;
1099
1100 if (16 > i && specialPermissions.Length > i)
1101 {
1102 name = specialPermissions[i];
1103 }
1104 else if (28 > i && UtilConstants.StandardPermissions.Length > (i - 16))
1105 {
1106 name = UtilConstants.StandardPermissions[i - 16];
1107 }
1108 else if (0 <= (i - 28) && UtilConstants.GenericPermissions.Length > (i - 28))
1109 {
1110 name = UtilConstants.GenericPermissions[i - 28];
1111 }
1112
1113 if (!String.IsNullOrEmpty(name))
1114 {
1115 element.Add(new XAttribute(name, "yes"));
1116 }
1117 else
1118 {
1119 this.Messaging.Write(WarningMessages.UnknownPermission(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(), i));
1537 } 1120 }
1538 } 1121 }
1539 } 1122 }
1540 } 1123 }
1124
1125 private static XAttribute AttributeIfNotNull(string name, string value)
1126 {
1127 return value == null ? null : new XAttribute(name, value);
1128 }
1129
1130 private static XAttribute AttributeIfNotNull(string name, bool value)
1131 {
1132 return new XAttribute(name, value ? "yes" : "no");
1133 }
1134
1135 private static XAttribute AttributeIfNotNull(string name, Row row, int field)
1136 {
1137 if (row[field] != null)
1138 {
1139 return new XAttribute(name, row.FieldAsString(field));
1140 }
1141
1142 return null;
1143 }
1144
1145 private static XAttribute NumericAttributeIfNotNull(string name, Row row, int field)
1146 {
1147 if (row[field] != null)
1148 {
1149 return new XAttribute(name, row.FieldAsInteger(field));
1150 }
1151
1152 return null;
1153 }
1154
1155 private static XAttribute AttributeIfTrue(string name, bool value)
1156 {
1157 return value ? new XAttribute(name, "yes") : null;
1158 }
1159 }
1160
1161 internal static class XElementExtensions
1162 {
1163 public static XElement AttributeIfNotNull(this XElement element, string name, Row row, int field)
1164 {
1165 if (row[field] != null)
1166 {
1167 element.Add(new XAttribute(name, row.FieldAsString(field)));
1168 }
1169
1170 return element;
1171 }
1172
1173 public static XElement NumericAttributeIfNotNull(this XElement element, string name, Row row, int field)
1174 {
1175 if (row[field] != null)
1176 {
1177 element.Add(new XAttribute(name, row.FieldAsInteger(field)));
1178 }
1179
1180 return element;
1181 }
1541 } 1182 }
1542#endif
1543} 1183}
diff --git a/src/ext/Util/wixext/UtilExtensionFactory.cs b/src/ext/Util/wixext/UtilExtensionFactory.cs
index 08352813..d9bf575c 100644
--- a/src/ext/Util/wixext/UtilExtensionFactory.cs
+++ b/src/ext/Util/wixext/UtilExtensionFactory.cs
@@ -11,6 +11,7 @@ namespace WixToolset.Util
11 protected override IReadOnlyCollection<Type> ExtensionTypes => new[] 11 protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
12 { 12 {
13 typeof(UtilCompiler), 13 typeof(UtilCompiler),
14 typeof(UtilDecompiler),
14 typeof(UtilExtensionData), 15 typeof(UtilExtensionData),
15 typeof(UtilWindowsInstallerBackendBinderExtension), 16 typeof(UtilWindowsInstallerBackendBinderExtension),
16 }; 17 };
diff --git a/src/ext/Util/wixext/UtilTableDefinitions.cs b/src/ext/Util/wixext/UtilTableDefinitions.cs
index c5ecab87..57c18b6c 100644
--- a/src/ext/Util/wixext/UtilTableDefinitions.cs
+++ b/src/ext/Util/wixext/UtilTableDefinitions.cs
@@ -85,7 +85,7 @@ namespace WixToolset.Util
85 UtilSymbolDefinitions.FileSharePermissions, 85 UtilSymbolDefinitions.FileSharePermissions,
86 new[] 86 new[]
87 { 87 {
88 new ColumnDefinition("FileShare_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "FileShare", keyColumn: 1, description: "FileShare that these premissions are to be applied to.", modularizeType: ColumnModularizeType.Column), 88 new ColumnDefinition("FileShare_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4FileShare", keyColumn: 1, description: "FileShare that these premissions are to be applied to.", modularizeType: ColumnModularizeType.Column),
89 new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", description: "User that these premissions are to apply to.", modularizeType: ColumnModularizeType.Column), 89 new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4User", description: "User that these premissions are to apply to.", modularizeType: ColumnModularizeType.Column),
90 new ColumnDefinition("Permissions", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Permissions int, as in EXPLICIT_ACCESS.grfAccessPermissions in MSDN"), 90 new ColumnDefinition("Permissions", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Permissions int, as in EXPLICIT_ACCESS.grfAccessPermissions in MSDN"),
91 }, 91 },