Implement IWindowsInstallerDecompileExtensions
Update Util extension to validate extension model and fix some small issues in MSI decompiling. Fixes 6367
Rob Mensching committed
Mar 30, 2022 at 10:35 UTC
5d08e0a4bbf4e4ba28300b8bace1089b64b198d7
46 files changed
+1644
-1390
src/api/wix/WixToolset.Extensibility/BaseWindowsInstallerBackendBinderExtension.cs
+5
-3
@@ -4,7 +4,6 @@ namespace WixToolset.Extensibility
4
{
5
using System;
6
using System.Collections.Generic;
7
- using System.Linq;
7
using WixToolset.Data;
8
using WixToolset.Data.Symbols;
9
using WixToolset.Data.WindowsInstaller;
@@ -12,7 +11,7 @@ namespace WixToolset.Extensibility
11
using WixToolset.Extensibility.Services;
12
13
/// <summary>
15
- /// Base class for creating a preprocessor extension.
14
+ /// Base class for creating a windows installer backend extension.
15
/// </summary>
16
public abstract class BaseWindowsInstallerBackendBinderExtension : IWindowsInstallerBackendBinderExtension
17
{
@@ -39,7 +38,10 @@ namespace WixToolset.Extensibility
38
/// <summary>
39
/// Creates a resolved cabinet result.
40
/// </summary>
42
- protected IResolvedCabinet CreateResolvedCabinet() => this.Context.ServiceProvider.GetService<IResolvedCabinet>();
41
+ protected IResolvedCabinet CreateResolvedCabinet()
42
+ {
43
+ return this.Context.ServiceProvider.GetService<IResolvedCabinet>();
44
+ }
45
46
/// <summary>
47
/// See <see cref="IWindowsInstallerBackendBinderExtension.PreBackendBind(IBindContext)"/>
src/api/wix/WixToolset.Extensibility/BaseWindowsInstallerDecompilerExtension.cs
new
+77
@@ -0,0 +1,77 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Extensibility
4
+{
5
+ using System.Collections.Generic;
6
+ using WixToolset.Data;
7
+ using WixToolset.Data.WindowsInstaller;
8
+ using WixToolset.Extensibility.Data;
9
+ using WixToolset.Extensibility.Services;
10
+
11
+ /// <summary>
12
+ /// Base class for creating a windows installer decompiler extensions.
13
+ /// </summary>
14
+ public abstract class BaseWindowsInstallerDecompilerExtension : IWindowsInstallerDecompilerExtension
15
+ {
16
+ /// <summary>
17
+ /// Context for use by the extension.
18
+ /// </summary>
19
+ protected IWindowsInstallerDecompileContext Context { get; private set; }
20
+
21
+ /// <summary>
22
+ /// Messaging for use by the extension.
23
+ /// </summary>
24
+ protected IMessaging Messaging { get; private set; }
25
+
26
+ /// <summary>
27
+ /// Decompiler helper for use by the extension.
28
+ /// </summary>
29
+ protected IWindowsInstallerDecompilerHelper DecompilerHelper { get; private set; }
30
+
31
+ /// <summary>
32
+ /// See <see cref="IWindowsInstallerDecompilerExtension.TableDefinitions"/>
33
+ /// </summary>
34
+ public virtual IReadOnlyCollection<TableDefinition> TableDefinitions { get; }
35
+
36
+ /// <summary>
37
+ /// See <see cref="IWindowsInstallerDecompilerExtension.PostDecompile(IWindowsInstallerDecompileResult)"/>
38
+ /// </summary>
39
+ public virtual void PreDecompile(IWindowsInstallerDecompileContext context)
40
+ {
41
+ this.Context = context;
42
+
43
+ this.Messaging = context.ServiceProvider.GetService<IMessaging>();
44
+
45
+ this.DecompilerHelper = context.ServiceProvider.GetService<IWindowsInstallerDecompilerHelper>();
46
+ }
47
+
48
+ /// <summary>
49
+ /// See <see cref="IWindowsInstallerDecompilerExtension.PreDecompileTables(TableIndexedCollection)"/>
50
+ /// </summary>
51
+ public virtual void PreDecompileTables(TableIndexedCollection tables)
52
+ {
53
+ }
54
+
55
+ /// <summary>
56
+ /// See <see cref="IWindowsInstallerDecompilerExtension.TryDecompileTable(Table)"/>
57
+ /// </summary>
58
+ public virtual bool TryDecompileTable(Table table)
59
+ {
60
+ return false;
61
+ }
62
+
63
+ /// <summary>
64
+ /// See <see cref="IWindowsInstallerDecompilerExtension.PostDecompileTables(TableIndexedCollection)"/>
65
+ /// </summary>
66
+ public virtual void PostDecompileTables(TableIndexedCollection tables)
67
+ {
68
+ }
69
+
70
+ /// <summary>
71
+ /// See <see cref="IWindowsInstallerDecompilerExtension.PostDecompile(IWindowsInstallerDecompileResult)"/>
72
+ /// </summary>
73
+ public virtual void PostDecompile(IWindowsInstallerDecompileResult result)
74
+ {
75
+ }
76
+ }
77
+}
src/api/wix/WixToolset.Extensibility/Data/IWindowsInstallerDecompileContext.cs
+11
-1
@@ -7,7 +7,7 @@ namespace WixToolset.Extensibility.Data
7
using WixToolset.Data;
8
9
/// <summary>
10
- /// The context used to decompile Windows Installer packages.
10
+ /// The context used to decompile a Windows Installer database.
11
/// </summary>
12
public interface IWindowsInstallerDecompileContext
13
{
@@ -31,6 +31,16 @@ namespace WixToolset.Extensibility.Data
31
/// </summary>
32
IReadOnlyCollection<IWindowsInstallerDecompilerExtension> Extensions { get; set; }
33
34
+ /// <summary>
35
+ /// Collection of extension data to use during decompiling.
36
+ /// </summary>
37
+ IReadOnlyCollection<IExtensionData> ExtensionData { get; set; }
38
+
39
+ /// <summary>
40
+ /// Symbol definition creator used to load extension data.
41
+ /// </summary>
42
+ ISymbolDefinitionCreator SymbolDefinitionCreator { get; set; }
43
+
44
/// <summary>
45
/// Gets or sets the folder where content is extracted.
46
/// </summary>
src/api/wix/WixToolset.Extensibility/Data/IWindowsInstallerDecompileResult.cs
+13
-2
@@ -6,13 +6,24 @@ namespace WixToolset.Extensibility.Data
6
using System.Xml.Linq;
7
using WixToolset.Data;
8
9
-#pragma warning disable 1591 // TODO: add documentation
9
+ /// <summary>
10
+ /// The result from decompiling a Windows Installer database.
11
+ /// </summary>
12
public interface IWindowsInstallerDecompileResult
13
{
14
+ /// <summary>
15
+ /// Decompiled document.
16
+ /// </summary>
17
XDocument Document { get; set; }
18
14
- IReadOnlyCollection<string> ExtractedFilePaths { get; set; }
19
+ /// <summary>
20
+ /// Extracted paths.
21
+ /// </summary>
22
+ IList<string> ExtractedFilePaths { get; set; }
23
24
+ /// <summary>
25
+ /// Decompiled platform.
26
+ /// </summary>
27
Platform? Platform { get; set; }
28
}
29
}
src/api/wix/WixToolset.Extensibility/DecompilerExtension.cs
deleted
-61
@@ -1,61 +0,0 @@
1
-// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
-
3
-namespace WixToolset.Extensibility
4
-{
5
- using WixToolset.Data;
6
-
7
-#if BRING_BACK_LATER
8
- /// <summary>
9
- /// Base class for creating a decompiler extension.
10
- /// </summary>
11
- public abstract class DecompilerExtension : IDecompilerExtension
12
- {
13
- /// <summary>
14
- /// Gets or sets the decompiler core for the extension.
15
- /// </summary>
16
- /// <value>The decompiler core for the extension.</value>
17
- public IDecompilerCore Core { get; set; }
18
-
19
- /// <summary>
20
- /// Gets the table definitions this extension decompiles.
21
- /// </summary>
22
- /// <value>Table definitions this extension decompiles.</value>
23
- public virtual TableDefinitionCollection TableDefinitions { get; protected set; }
24
-
25
- /// <summary>
26
- /// Gets the library that this decompiler wants removed from the decomipiled output.
27
- /// </summary>
28
- /// <param name="tableDefinitions">The table definitions to use while loading the library.</param>
29
- /// <returns>The library for this extension or null if there is no library to be removed.</returns>
30
- public virtual Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
31
- {
32
- return null;
33
- }
34
-
35
- /// <summary>
36
- /// Called at the beginning of the decompilation of a database.
37
- /// </summary>
38
- /// <param name="tables">The collection of all tables.</param>
39
- public virtual void Initialize(TableIndexedCollection tables)
40
- {
41
- }
42
-
43
- /// <summary>
44
- /// Decompiles an extension table.
45
- /// </summary>
46
- /// <param name="table">The table to decompile.</param>
47
- public virtual void DecompileTable(Table table)
48
- {
49
- this.Core.UnexpectedTable(table);
50
- }
51
-
52
- /// <summary>
53
- /// Finalize decompilation.
54
- /// </summary>
55
- /// <param name="tables">The collection of all tables.</param>
56
- public virtual void Finish(TableIndexedCollection tables)
57
- {
58
- }
59
- }
60
-#endif
61
-}
src/api/wix/WixToolset.Extensibility/IWindowsInstallerDecompilerExtension.cs
+27
-3
@@ -2,21 +2,45 @@
2
3
namespace WixToolset.Extensibility
4
{
5
- using WixToolset.Data;
5
+ using System.Collections.Generic;
6
using WixToolset.Data.WindowsInstaller;
7
using WixToolset.Extensibility.Data;
8
9
/// <summary>
10
- /// Interface all binder extensions implement.
10
+ /// Interface all windows installer decompiler extensions implement.
11
/// </summary>
12
public interface IWindowsInstallerDecompilerExtension
13
{
14
+ /// <summary>
15
+ /// Gets the table definitions this extension decompiles.
16
+ /// </summary>
17
+ /// <value>Table definitions this extension decompiles.</value>
18
+ IReadOnlyCollection<TableDefinition> TableDefinitions { get; }
19
+
20
/// <summary>
21
/// Called before decompiling occurs.
22
/// </summary>
23
+ /// <param name="context">Decompile context.</param>
24
void PreDecompile(IWindowsInstallerDecompileContext context);
25
19
- // TODO: Redesign this interface to be useful.
26
+ /// <summary>
27
+ /// Called before decompiling occurs.
28
+ /// </summary>
29
+ /// <param name="tables">The collection of all tables.</param>
30
+ void PreDecompileTables(TableIndexedCollection tables);
31
+
32
+ /// <summary>
33
+ /// Try to decompile an extension table.
34
+ /// </summary>
35
+ /// <param name="table">The table to decompile.</param>
36
+ /// <returns>True if the table was decompiled, false otherwise.</returns>
37
+ bool TryDecompileTable(Table table);
38
+
39
+ /// <summary>
40
+ /// After decompilation tables.
41
+ /// </summary>
42
+ /// <param name="tables">The collection of all tables.</param>
43
+ void PostDecompileTables(TableIndexedCollection tables);
44
45
/// <summary>
46
/// Called after all output changes occur and right before the output is bound into its final format.
src/api/wix/WixToolset.Extensibility/Services/IWindowsInstallerDecompilerHelper.cs
new
+180
@@ -0,0 +1,180 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Extensibility.Services
4
+{
5
+ using System.Xml.Linq;
6
+ using WixToolset.Data.WindowsInstaller;
7
+
8
+ /// <summary>
9
+ /// Interface provided to help Windows Installer decompiler extensions.
10
+ /// </summary>
11
+ public interface IWindowsInstallerDecompilerHelper
12
+ {
13
+ /// <summary>
14
+ /// Gets or sets the root element of the decompiled output.
15
+ /// </summary>
16
+ XElement RootElement { get; set; }
17
+
18
+ /// <summary>
19
+ /// Creates an element from the standard WiX Toolset namespace and adds it to the root document.
20
+ /// </summary>
21
+ /// <param name="name">Name of the element to create and add.</param>
22
+ /// <param name="content">Optional content to add to the new element.</param>
23
+ /// <returns>Element in the standard namespace.</returns>
24
+ XElement AddElementToRoot(string name, params object[] content);
25
+
26
+ /// <summary>
27
+ /// Creates an element with the specified name and adds it to the root document.
28
+ /// </summary>
29
+ /// <param name="name">Name of the element to create and add.</param>
30
+ /// <param name="content">Optional content to add to the new element.</param>
31
+ /// <returns>Element in the standard namespace.</returns>
32
+ XElement AddElementToRoot(XName name, params object[] content);
33
+
34
+ /// <summary>
35
+ /// Adds an existing element to the root document.
36
+ /// </summary>
37
+ /// <param name="element">Element to add.</param>
38
+ /// <returns>Same element provided.</returns>
39
+ XElement AddElementToRoot(XElement element);
40
+
41
+ /// <summary>
42
+ /// Creates an element from the standard WiX Toolset namespace.
43
+ /// </summary>
44
+ /// <param name="name">Name of the element to create.</param>
45
+ /// <param name="content">Optional content to add to the new element.</param>
46
+ /// <returns>Element in the standard namespace.</returns>
47
+ XElement CreateElement(string name, params object[] content);
48
+
49
+ /// <summary>
50
+ /// Get an element index by a row's table and primary keys.
51
+ /// </summary>
52
+ /// <param name="row">Row to get element.</param>
53
+ /// <returns>Element indexed for the row or null if not found.</returns>
54
+ XElement GetIndexedElement(Row row);
55
+
56
+ /// <summary>
57
+ /// Get an element index by table and primary key.
58
+ /// </summary>
59
+ /// <param name="table">Table name for indexed element.</param>
60
+ /// <param name="primaryKey">Primary key for indexed element.</param>
61
+ /// <returns>Element indexed for the table and primary key or null if not found.</returns>
62
+ XElement GetIndexedElement(string table, string primaryKey);
63
+
64
+ /// <summary>
65
+ /// Get an element index by table and primary keys.
66
+ /// </summary>
67
+ /// <param name="table">Table name for indexed element.</param>
68
+ /// <param name="primaryKey1">Primary key for first column indexed element.</param>
69
+ /// <param name="primaryKey2">Primary key for second column indexed element.</param>
70
+ /// <returns>Element indexed for the table and primary keys or null if not found.</returns>
71
+ XElement GetIndexedElement(string table, string primaryKey1, string primaryKey2);
72
+
73
+ /// <summary>
74
+ /// Get an element index by table and primary keys.
75
+ /// </summary>
76
+ /// <param name="table">Table name for indexed element.</param>
77
+ /// <param name="primaryKey1">Primary key for first column indexed element.</param>
78
+ /// <param name="primaryKey2">Primary key for second column indexed element.</param>
79
+ /// <param name="primaryKey3">Primary key for third column indexed element.</param>
80
+ /// <returns>Element indexed for the table and primary keys or null if not found.</returns>
81
+ XElement GetIndexedElement(string table, string primaryKey1, string primaryKey2, string primaryKey3);
82
+
83
+ /// <summary>
84
+ /// Get an element index by table and primary keys.
85
+ /// </summary>
86
+ /// <param name="table">Table name for indexed element.</param>
87
+ /// <param name="primaryKeys">Primary keys for indexed element.</param>
88
+ /// <returns>Element indexed for the table and primary keys or null if not found.</returns>
89
+ XElement GetIndexedElement(string table, string[] primaryKeys);
90
+
91
+ /// <summary>
92
+ /// Try to get an element index by a row's table and primary keys.
93
+ /// </summary>
94
+ /// <param name="row">Row to get element.</param>
95
+ /// <param name="element">Element indexed for the row.</param>
96
+ /// <returns>True if the element was index otherwise false.</returns>
97
+ bool TryGetIndexedElement(Row row, out XElement element);
98
+
99
+ /// <summary>
100
+ /// Try to get an element index by table name and primary key.
101
+ /// </summary>
102
+ /// <param name="table">Table name for indexed element.</param>
103
+ /// <param name="primaryKey">Primary key for indexed element.</param>
104
+ /// <param name="element">Element indexed for the table and primary key.</param>
105
+ /// <returns>True if the element was index otherwise false.</returns>
106
+ bool TryGetIndexedElement(string table, string primaryKey, out XElement element);
107
+
108
+ /// <summary>
109
+ /// Try to get an element index by table name and primary keys.
110
+ /// </summary>
111
+ /// <param name="table">Table name for indexed element.</param>
112
+ /// <param name="primaryKey1">First column's primary key for indexed element.</param>
113
+ /// <param name="primaryKey2">Second column's primary key for indexed element.</param>
114
+ /// <param name="element">Element indexed for the table and primary key.</param>
115
+ /// <returns>True if the element was index otherwise false.</returns>
116
+ bool TryGetIndexedElement(string table, string primaryKey1, string primaryKey2, out XElement element);
117
+
118
+ /// <summary>
119
+ /// Try to get an element index by table name and primary keys.
120
+ /// </summary>
121
+ /// <param name="table">Table name for indexed element.</param>
122
+ /// <param name="primaryKey1">First column's primary key for indexed element.</param>
123
+ /// <param name="primaryKey2">Second column's primary key for indexed element.</param>
124
+ /// <param name="primaryKey3">Third column's primary key for indexed element.</param>
125
+ /// <param name="element">Element indexed for the table and primary key.</param>
126
+ /// <returns>True if the element was index otherwise false.</returns>
127
+ bool TryGetIndexedElement(string table, string primaryKey1, string primaryKey2, string primaryKey3, out XElement element);
128
+
129
+ /// <summary>
130
+ /// Try to get an element index by table name and primary keys.
131
+ /// </summary>
132
+ /// <param name="table">Table name for indexed element.</param>
133
+ /// <param name="primaryKeys">Primary keys for indexed element.</param>
134
+ /// <param name="element">Element indexed for the table and primary key.</param>
135
+ /// <returns>True if the element was index otherwise false.</returns>
136
+ bool TryGetIndexedElement(string table, string[] primaryKeys, out XElement element);
137
+
138
+ /// <summary>
139
+ /// Index an element by a row's table and primary keys.
140
+ /// </summary>
141
+ /// <param name="row">Row to index element.</param>
142
+ /// <param name="element">Element to index.</param>
143
+ void IndexElement(Row row, XElement element);
144
+
145
+ /// <summary>
146
+ /// Index an element by table and primary key.
147
+ /// </summary>
148
+ /// <param name="table">Table name to index element.</param>
149
+ /// <param name="primaryKey">Primary key to index element.</param>
150
+ /// <param name="element">Element to index.</param>
151
+ void IndexElement(string table, string primaryKey, XElement element);
152
+
153
+ /// <summary>
154
+ /// Index an element by table and primary keys.
155
+ /// </summary>
156
+ /// <param name="table">Table name to index element.</param>
157
+ /// <param name="primaryKey1">First column's primary key to index element.</param>
158
+ /// <param name="primaryKey2">Second column's primary key to index element.</param>
159
+ /// <param name="element">Element to index.</param>
160
+ void IndexElement(string table, string primaryKey1, string primaryKey2, XElement element);
161
+
162
+ /// <summary>
163
+ /// Index an element by table and primary keys.
164
+ /// </summary>
165
+ /// <param name="table">Table name to index element.</param>
166
+ /// <param name="primaryKey1">First column's primary key to index element.</param>
167
+ /// <param name="primaryKey2">Second column's primary key to index element.</param>
168
+ /// <param name="primaryKey3">Third column's primary key to index element.</param>
169
+ /// <param name="element">Element to index.</param>
170
+ void IndexElement(string table, string primaryKey1, string primaryKey2, string primaryKey3, XElement element);
171
+
172
+ /// <summary>
173
+ /// Index an element by table and primary keys.
174
+ /// </summary>
175
+ /// <param name="table">Table name to index element.</param>
176
+ /// <param name="primaryKeys">Column's primary key to index element.</param>
177
+ /// <param name="element">Element to index.</param>
178
+ void IndexElement(string table, string[] primaryKeys, XElement element);
179
+ }
180
+}
src/ext/Util/Util.wixext.sln
+2
-2
@@ -1,7 +1,7 @@
1
2
Microsoft Visual Studio Solution File, Format Version 12.00
3
-# Visual Studio Version 16
4
-VisualStudioVersion = 16.0.30204.135
3
+# Visual Studio Version 17
4
+VisualStudioVersion = 17.1.32228.430
5
MinimumVisualStudioVersion = 15.0.26124.0
6
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utilbe", "be\utilbe.vcxproj", "{630C1EE7-2517-4A8C-83E3-DA1150308B58}"
7
EndProject
src/ext/Util/Util.wixext.v3.ncrunchsolution
new
+6
@@ -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
src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
+18
-2
@@ -6,8 +6,6 @@ namespace WixToolsetTest.Util
6
using System.Linq;
7
using WixBuildTools.TestSupport;
8
using WixToolset.Core.TestPackage;
9
- using WixToolset.Data;
10
- using WixToolset.Data.Symbols;
9
using WixToolset.Util;
10
using Xunit;
11
@@ -55,6 +53,18 @@ namespace WixToolsetTest.Util
53
}, results.OrderBy(s => s).ToArray());
54
}
55
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]
69
public void CanBuildCloseApplication()
70
{
@@ -313,5 +323,11 @@ namespace WixToolsetTest.Util
323
var result = WixRunner.Execute(newArgs.ToArray());
324
result.AssertSuccess();
325
}
326
+
327
+ private static void Decompile(string[] args)
328
+ {
329
+ var result = WixRunner.Execute(args);
330
+ result.AssertSuccess();
331
+ }
332
}
333
}
src/ext/Util/wixext/UtilCompiler.cs
+11
-25
@@ -19,7 +19,7 @@ namespace WixToolset.Util
19
/// <summary>
20
/// The compiler for the WiX Toolset Utility Extension.
21
/// </summary>
22
- public sealed class UtilCompiler : BaseCompilerExtension
22
+ internal sealed class UtilCompiler : BaseCompilerExtension
23
{
24
// user creation attributes definitions (from sca.h)
25
internal const int UserDontExpirePasswrd = 0x00000001;
@@ -37,7 +37,7 @@ namespace WixToolset.Util
37
38
private static readonly Regex FindPropertyBrackets = new Regex(@"\[(?!\\|\])|(?<!\[\\\]|\[\\|\\\[)\]", RegexOptions.ExplicitCapture | RegexOptions.Compiled);
39
40
- public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/util";
40
+ public override XNamespace Namespace => UtilConstants.Namespace;
41
42
/// <summary>
43
/// Types of Internet shortcuts.
@@ -94,13 +94,10 @@ namespace WixToolset.Util
94
var createFolderId = context["DirectoryId"];
95
var createFolderComponentId = context["ComponentId"];
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
-
97
switch (element.Name.LocalName)
98
{
99
case "PermissionEx":
103
- this.ParsePermissionExElement(intermediate, section, element, createFolderId, createFolderComponentId, createFolderWin64, "CreateFolder");
100
+ this.ParsePermissionExElement(intermediate, section, element, createFolderId, createFolderComponentId, "CreateFolder");
101
break;
102
default:
103
this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -159,16 +156,13 @@ namespace WixToolset.Util
156
var fileId = context["FileId"];
157
var fileComponentId = context["ComponentId"];
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
-
159
switch (element.Name.LocalName)
160
{
161
case "PerfCounter":
162
this.ParsePerfCounterElement(intermediate, section, element, fileComponentId, fileId);
163
break;
164
case "PermissionEx":
171
- this.ParsePermissionExElement(intermediate, section, element, fileId, fileComponentId, fileWin64, "File");
165
+ this.ParsePermissionExElement(intermediate, section, element, fileId, fileComponentId, "File");
166
break;
167
case "PerfCounterManifest":
168
this.ParsePerfCounterManifestElement(intermediate, section, element, fileComponentId, fileId);
@@ -177,7 +171,7 @@ namespace WixToolset.Util
171
this.ParseEventManifestElement(intermediate, section, element, fileComponentId, fileId);
172
break;
173
case "FormatFile":
180
- this.ParseFormatFileElement(intermediate, section, element, fileId, fileWin64);
174
+ this.ParseFormatFileElement(intermediate, section, element, fileId);
175
break;
176
default:
177
this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -296,13 +290,10 @@ namespace WixToolset.Util
290
var registryId = context["RegistryId"];
291
var registryComponentId = context["ComponentId"];
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
-
293
switch (element.Name.LocalName)
294
{
295
case "PermissionEx":
305
- this.ParsePermissionExElement(intermediate, section, element, registryId, registryComponentId, registryWin64, "Registry");
296
+ this.ParsePermissionExElement(intermediate, section, element, registryId, registryComponentId, "Registry");
297
break;
298
default:
299
this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -314,13 +305,10 @@ namespace WixToolset.Util
305
var serviceInstallName = context["ServiceInstallName"];
306
var serviceInstallComponentId = context["ServiceInstallComponentId"];
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
-
308
switch (element.Name.LocalName)
309
{
310
case "PermissionEx":
323
- this.ParsePermissionExElement(intermediate, section, element, serviceInstallId, serviceInstallComponentId, serviceInstallWin64, "ServiceInstall");
311
+ this.ParsePermissionExElement(intermediate, section, element, serviceInstallId, serviceInstallComponentId, "ServiceInstall");
312
break;
313
case "ServiceConfig":
314
this.ParseServiceConfigElement(intermediate, section, element, serviceInstallComponentId, "ServiceInstall", serviceInstallName);
@@ -536,7 +524,6 @@ namespace WixToolset.Util
524
private void ParseComponentSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element)
525
{
526
var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
539
- string refId = null;
527
528
foreach (var attrib in element.Attributes())
529
{
@@ -545,7 +532,7 @@ namespace WixToolset.Util
532
switch (attrib.Name.LocalName)
533
{
534
case "Id":
548
- refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
535
+ var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
536
this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixComponentSearch, refId);
537
break;
538
default:
@@ -2284,7 +2271,7 @@ namespace WixToolset.Util
2271
/// <param name="element">Element to parse.</param>
2272
/// <param name="fileId">Identifier of referenced file.</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)
2275
{
2276
var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2277
string binaryId = null;
@@ -2415,7 +2402,6 @@ namespace WixToolset.Util
2402
ComponentRef = componentId,
2403
});
2404
}
2418
-
2405
}
2406
2407
this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureEventManifestRegister", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
@@ -2435,7 +2421,7 @@ namespace WixToolset.Util
2421
/// <param name="componentId">Identifier of component, used to determine install state.</param>
2422
/// <param name="win64">Flag to determine whether the component is 64-bit.</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)
2425
{
2426
var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2427
var bits = new BitArray(32);
@@ -2623,7 +2609,7 @@ namespace WixToolset.Util
2609
2610
if (null == id)
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());
2613
}
2614
2615
this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
src/ext/Util/wixext/UtilConstants.cs
+21
@@ -2,11 +2,32 @@
2
3
namespace WixToolset.Util
4
{
5
+ using System.Xml.Linq;
6
+
7
/// <summary>
8
/// Constants used by Utility Extension.
9
/// </summary>
10
internal static class UtilConstants
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
+
31
internal static readonly string[] FilePermissions = { "Read", "Write", "Append", "ReadExtendedAttributes", "WriteExtendedAttributes", "Execute", null, "ReadAttributes", "WriteAttributes" };
32
internal static readonly string[] FolderPermissions = { "Read", "CreateFile", "CreateChild", "ReadExtendedAttributes", "WriteExtendedAttributes", "Traverse", "DeleteChild", "ReadAttributes", "WriteAttributes" };
33
internal static readonly string[] GenericPermissions = { "GenericAll", "GenericExecute", "GenericWrite", "GenericRead" };
src/ext/Util/wixext/UtilDecompiler.cs
+456
-816
@@ -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.
2
3
-namespace WixToolset.Extensions
3
+namespace WixToolset.Util
4
{
5
-#if TODO_CONSIDER_DECOMPILER
5
using System;
6
using System.IO;
7
using System.Text;
8
using System.Collections;
9
using System.Diagnostics;
11
- using System.Globalization;
10
13
- using Util = WixToolset.Extensions.Serialize.Util;
11
using WixToolset.Data;
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
18
/// <summary>
19
/// The decompiler for the WiX Toolset Utility Extension.
20
/// </summary>
21
- public sealed class UtilDecompiler : DecompilerExtension
21
+ internal sealed class UtilDecompiler : BaseWindowsInstallerDecompilerExtension
22
{
23
- /// <summary>
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
- }
23
+ public override IReadOnlyCollection<TableDefinition> TableDefinitions => UtilTableDefinitions.All;
24
25
/// <summary>
26
/// Called at the beginning of the decompilation of a database.
27
/// </summary>
28
/// <param name="tables">The collection of all tables.</param>
45
- public override void Initialize(TableIndexedCollection tables)
29
+ public override void PreDecompileTables(TableIndexedCollection tables)
30
{
31
this.CleanupSecureCustomProperties(tables);
32
this.CleanupInternetShortcutRemoveFileTables(tables);
@@ -61,24 +45,22 @@ namespace WixToolset.Extensions
45
/// <param name="tables">The collection of all tables.</param>
46
private void CleanupSecureCustomProperties(TableIndexedCollection tables)
47
{
64
- Table propertyTable = tables["Property"];
48
+ var propertyTable = tables["Property"];
49
50
if (null != propertyTable)
51
{
68
- foreach (Row row in propertyTable.Rows)
52
+ foreach (var row in propertyTable.Rows)
53
{
54
if ("SecureCustomProperties" == row[0].ToString())
55
{
72
- StringBuilder remainingProperties = new StringBuilder();
73
- string[] secureCustomProperties = row[1].ToString().Split(';');
74
- foreach (string property in secureCustomProperties)
56
+ var remainingProperties = new StringBuilder();
57
+ var secureCustomProperties = row[1].ToString().Split(';');
58
+ foreach (var property in secureCustomProperties)
59
{
60
if (property.StartsWith("WIX_SUITE_", StringComparison.Ordinal) || property.StartsWith("WIX_DIR_", StringComparison.Ordinal)
61
|| property.StartsWith("WIX_ACCOUNT_", StringComparison.Ordinal))
62
{
79
- Wix.PropertyRef propertyRef = new Wix.PropertyRef();
80
- propertyRef.Id = property;
81
- this.Core.RootElement.AddChild(propertyRef);
63
+ this.DecompilerHelper.AddElementToRoot("PropertyRef", new XAttribute("Id", property));
64
}
65
else
66
{
@@ -104,21 +86,21 @@ namespace WixToolset.Extensions
86
private void CleanupInternetShortcutRemoveFileTables(TableIndexedCollection tables)
87
{
88
// index the WixInternetShortcut table
107
- Table wixInternetShortcutTable = tables["WixInternetShortcut"];
108
- Hashtable wixInternetShortcuts = new Hashtable();
89
+ var wixInternetShortcutTable = tables["WixInternetShortcut"];
90
+ var wixInternetShortcuts = new Hashtable();
91
if (null != wixInternetShortcutTable)
92
{
111
- foreach (Row row in wixInternetShortcutTable.Rows)
93
+ foreach (var row in wixInternetShortcutTable.Rows)
94
{
113
- wixInternetShortcuts.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row);
95
+ wixInternetShortcuts.Add(row.GetPrimaryKey(), row);
96
}
97
}
98
99
// remove the RemoveFile rows with primary keys that match the WixInternetShortcut table's
118
- Table removeFileTable = tables["RemoveFile"];
100
+ var removeFileTable = tables["RemoveFile"];
101
if (null != removeFileTable)
102
{
121
- for (int i = removeFileTable.Rows.Count - 1; 0 <= i; i--)
103
+ for (var i = removeFileTable.Rows.Count - 1; 0 <= i; i--)
104
{
105
if (null != wixInternetShortcuts[removeFileTable.Rows[i][0]])
106
{
@@ -132,69 +114,86 @@ namespace WixToolset.Extensions
114
/// Decompiles an extension table.
115
/// </summary>
116
/// <param name="table">The table to decompile.</param>
135
- public override void DecompileTable(Table table)
117
+ public override bool TryDecompileTable(Table table)
118
{
119
switch (table.Name)
120
{
121
case "WixCloseApplication":
122
+ case "Wix4CloseApplication":
123
this.DecompileWixCloseApplicationTable(table);
124
break;
125
case "WixRemoveFolderEx":
126
+ case "Wix4RemoveFolderEx":
127
this.DecompileWixRemoveFolderExTable(table);
128
break;
129
case "WixRestartResource":
130
+ case "Wix4RestartResource":
131
this.DecompileWixRestartResourceTable(table);
132
break;
133
case "FileShare":
134
+ case "Wix4FileShare":
135
this.DecompileFileShareTable(table);
136
break;
137
case "FileSharePermissions":
138
+ case "Wix4FileSharePermissions":
139
this.DecompileFileSharePermissionsTable(table);
140
break;
141
case "WixInternetShortcut":
142
+ case "Wix4InternetShortcut":
143
this.DecompileWixInternetShortcutTable(table);
144
break;
145
case "Group":
146
+ case "Wix4Group":
147
this.DecompileGroupTable(table);
148
break;
149
case "Perfmon":
150
+ case "Wix4Perfmon":
151
this.DecompilePerfmonTable(table);
152
break;
153
case "PerfmonManifest":
154
+ case "Wix4PerfmonManifest":
155
this.DecompilePerfmonManifestTable(table);
156
break;
157
case "EventManifest":
158
+ case "Wix4EventManifest":
159
this.DecompileEventManifestTable(table);
160
break;
161
case "SecureObjects":
162
+ case "Wix4SecureObjects":
163
this.DecompileSecureObjectsTable(table);
164
break;
165
case "ServiceConfig":
166
+ case "Wix4ServiceConfig":
167
this.DecompileServiceConfigTable(table);
168
break;
169
case "User":
170
+ case "Wix4User":
171
this.DecompileUserTable(table);
172
break;
173
case "UserGroup":
174
+ case "Wix4UserGroup":
175
this.DecompileUserGroupTable(table);
176
break;
177
case "XmlConfig":
178
+ case "Wix4XmlConfig":
179
this.DecompileXmlConfigTable(table);
180
break;
181
case "XmlFile":
182
+ case "Wix4XmlFile":
183
// XmlFile decompilation has been moved to FinalizeXmlFileTable function
184
break;
185
default:
188
- base.DecompileTable(table);
189
- break;
186
+ return false;
187
}
188
+
189
+ return true;
190
}
191
192
/// <summary>
193
/// Finalize decompilation.
194
/// </summary>
195
/// <param name="tables">The collection of all tables.</param>
197
- public override void Finish(TableIndexedCollection tables)
196
+ public override void PostDecompileTables(TableIndexedCollection tables)
197
{
198
this.FinalizePerfmonTable(tables);
199
this.FinalizePerfmonManifestTable(tables);
@@ -211,49 +210,21 @@ namespace WixToolset.Extensions
210
/// <param name="table">The table to decompile.</param>
211
private void DecompileWixCloseApplicationTable(Table table)
212
{
214
- foreach (Row row in table.Rows)
213
+ foreach (var row in table.Rows)
214
{
216
- Util.CloseApplication closeApplication = new Util.CloseApplication();
217
-
218
- closeApplication.Id = (string)row[0];
219
-
220
- closeApplication.Target = (string)row[1];
221
-
222
- if (null != row[2])
223
- {
224
- closeApplication.Description = (string)row[2];
225
- }
226
-
227
- if (null != row[3])
228
- {
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);
215
+ var attribute = row.FieldAsNullableInteger(4) ?? 0x2;
216
+
217
+ this.DecompilerHelper.AddElementToRoot(UtilConstants.CloseApplicationName,
218
+ new XAttribute("Id", row.FieldAsString(0)),
219
+ new XAttribute("Target", row.FieldAsString(1)),
220
+ AttributeIfNotNull("Description", row, 2),
221
+ AttributeIfNotNull("Content", row, 3),
222
+ AttributeIfNotNull("CloseMessage", 0x1 == (attribute & 0x1)),
223
+ AttributeIfNotNull("RebootPrompt", 0x2 == (attribute & 0x2)),
224
+ AttributeIfNotNull("ElevatedCloseMessage", 0x4 == (attribute & 0x4)),
225
+ NumericAttributeIfNotNull("Sequence", row, 5),
226
+ NumericAttributeIfNotNull("Property", row, 6)
227
+ );
228
}
229
}
230
@@ -263,43 +234,45 @@ namespace WixToolset.Extensions
234
/// <param name="table">The table to decompile.</param>
235
private void DecompileWixRemoveFolderExTable(Table table)
236
{
266
- foreach (Row row in table.Rows)
237
+ foreach (var row in table.Rows)
238
{
268
- // Set the Id even if auto-generated previously.
269
- Util.RemoveFolderEx removeFolder = new Util.RemoveFolderEx();
270
- removeFolder.Id = (string)row[0];
271
- removeFolder.Property = (string)row[2];
272
-
273
- int installMode = (int)row[3];
274
- switch ((UtilCompiler.WixRemoveFolderExOn)installMode)
239
+ var on = String.Empty;
240
+ var installMode = row.FieldAsInteger(3);
241
+ switch (installMode)
242
{
276
- case UtilCompiler.WixRemoveFolderExOn.Install:
277
- removeFolder.On = Util.RemoveFolderEx.OnType.install;
243
+ case (int)WixRemoveFolderExInstallMode.Install:
244
+ on = "install";
245
break;
279
-
280
- case UtilCompiler.WixRemoveFolderExOn.Uninstall:
281
- removeFolder.On = Util.RemoveFolderEx.OnType.uninstall;
246
+
247
+ case (int)WixRemoveFolderExInstallMode.Uninstall:
248
+ on = "uninstall";
249
break;
283
-
284
- case UtilCompiler.WixRemoveFolderExOn.Both:
285
- removeFolder.On = Util.RemoveFolderEx.OnType.both;
250
+
251
+ case (int)WixRemoveFolderExInstallMode.Both:
252
+ on = "both";
253
break;
254
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));
257
break;
258
}
259
260
+ var removeFolder = new XElement(UtilConstants.RemoveFolderExName,
261
+ AttributeIfNotNull("Id", row, 0),
262
+ AttributeIfNotNull("Property", row, 2),
263
+ AttributeIfNotNull("On", on)
264
+ );
265
+
266
// Add to the appropriate Component or section element.
294
- string componentId = (string)row[1];
295
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId);
296
- if (null != component)
267
+ var componentId = row.FieldAsString(1);
268
+
269
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
270
{
298
- component.AddChild(removeFolder);
271
+ component.Add(removeFolder);
272
}
273
else
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"));
276
}
277
}
278
}
@@ -310,53 +283,51 @@ namespace WixToolset.Extensions
283
/// <param name="table">The table to decompile.</param>
284
private void DecompileWixRestartResourceTable(Table table)
285
{
313
- foreach (Row row in table.Rows)
286
+ foreach (var row in table.Rows)
287
{
315
- // Set the Id even if auto-generated previously.
316
- Util.RestartResource restartResource = new Util.RestartResource();
317
- restartResource.Id = (string)row[0];
288
+ var restartResource = new XElement(UtilConstants.RestartResourceName,
289
+ new XAttribute("Id", row.FieldAsString(0)));
290
291
// Determine the resource type and set accordingly.
320
- string resource = (string)row[2];
321
- int attributes = (int)row[3];
322
- UtilCompiler.WixRestartResourceAttributes type = (UtilCompiler.WixRestartResourceAttributes)(attributes & (int)UtilCompiler.WixRestartResourceAttributes.TypeMask);
292
+ var resource = row.FieldAsString(2);
293
+ var attributes = row.FieldAsInteger(3);
294
+ var type = (WixRestartResourceAttributes)attributes;
295
296
switch (type)
297
{
326
- case UtilCompiler.WixRestartResourceAttributes.Filename:
327
- restartResource.Path = resource;
298
+ case WixRestartResourceAttributes.Filename:
299
+ restartResource.Add(new XAttribute("Path", resource));
300
break;
301
330
- case UtilCompiler.WixRestartResourceAttributes.ProcessName:
331
- restartResource.ProcessName = resource;
302
+ case WixRestartResourceAttributes.ProcessName:
303
+ restartResource.Add(new XAttribute("ProcessName", resource));
304
break;
305
334
- case UtilCompiler.WixRestartResourceAttributes.ServiceName:
335
- restartResource.ServiceName = resource;
306
+ case WixRestartResourceAttributes.ServiceName:
307
+ restartResource.Add(new XAttribute("ServiceName", resource));
308
break;
309
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));
312
break;
313
}
314
315
// Add to the appropriate Component or section element.
344
- string componentId = (string)row[1];
316
+ var componentId = row.FieldAsString(1);
317
if (!String.IsNullOrEmpty(componentId))
318
{
347
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", componentId);
348
- if (null != component)
319
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
320
{
350
- component.AddChild(restartResource);
321
+ component.Add(restartResource);
322
}
323
else
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"));
326
}
327
}
328
else
329
{
359
- this.Core.RootElement.AddChild(restartResource);
330
+ this.DecompilerHelper.AddElementToRoot(restartResource);
331
}
332
}
333
}
@@ -367,33 +338,28 @@ namespace WixToolset.Extensions
338
/// <param name="table">The table to decompile.</param>
339
private void DecompileFileShareTable(Table table)
340
{
370
- foreach (Row row in table.Rows)
341
+ foreach (var row in table.Rows)
342
{
372
- Util.FileShare fileShare = new Util.FileShare();
373
-
374
- fileShare.Id = (string)row[0];
375
-
376
- fileShare.Name = (string)row[1];
377
-
378
- if (null != row[3])
379
- {
380
- fileShare.Description = (string)row[3];
381
- }
343
+ var fileShare = new XElement(UtilConstants.FileShareName,
344
+ new XAttribute("Id", row.FieldAsString(0)),
345
+ new XAttribute("Name", row.FieldAsString(1)),
346
+ AttributeIfNotNull("Description", row, 3)
347
+ );
348
349
// the Directory_ column is set by the parent Component
350
351
// the User_ and Permissions columns are deprecated
352
387
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
388
- if (null != component)
353
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(2), out var component))
354
{
390
- component.AddChild(fileShare);
355
+ component.Add(fileShare);
356
}
357
else
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"));
360
}
396
- this.Core.IndexElement(row, fileShare);
361
+
362
+ this.DecompilerHelper.IndexElement(row, fileShare);
363
}
364
}
365
@@ -403,111 +369,21 @@ namespace WixToolset.Extensions
369
/// <param name="table">The table to decompile.</param>
370
private void DecompileFileSharePermissionsTable(Table table)
371
{
406
- foreach (Row row in table.Rows)
372
+ foreach (var row in table.Rows)
373
{
408
- Util.FileSharePermission fileSharePermission = new Util.FileSharePermission();
409
-
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;
374
+ var fileSharePermission = new XElement(UtilConstants.FileSharePermissionName,
375
+ new XAttribute("User", row.FieldAsString(1)));
376
420
- if (16 > i && specialPermissions.Length > i)
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
- }
377
+ this.AddPermissionAttributes(fileSharePermission, row, 2, UtilConstants.FolderPermissions);
378
503
- Util.FileShare fileShare = (Util.FileShare)this.Core.GetIndexedElement("FileShare", (string)row[0]);
504
- if (null != fileShare)
379
+ if (this.DecompilerHelper.TryGetIndexedElement("Wix4FileShare", row.FieldAsString(0), out var fileShare) ||
380
+ this.DecompilerHelper.TryGetIndexedElement("FileShare", row.FieldAsString(0), out fileShare))
381
{
506
- fileShare.AddChild(fileSharePermission);
382
+ fileShare.Add(fileSharePermission);
383
}
384
else
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"));
387
}
388
}
389
}
@@ -518,25 +394,18 @@ namespace WixToolset.Extensions
394
/// <param name="table">The table to decompile.</param>
395
private void DecompileGroupTable(Table table)
396
{
521
- foreach (Row row in table.Rows)
397
+ foreach (var row in table.Rows)
398
{
523
- Util.Group group = new Util.Group();
524
-
525
- group.Id = (string)row[0];
526
-
399
if (null != row[1])
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]));
402
}
403
532
- group.Name = (string)row[2];
533
-
534
- if (null != row[3])
535
- {
536
- group.Domain = (string)row[3];
537
- }
538
-
539
- this.Core.RootElement.AddChild(group);
404
+ this.DecompilerHelper.AddElementToRoot(UtilConstants.GroupName,
405
+ new XAttribute("Id", row.FieldAsString(0)),
406
+ new XAttribute("Name", row.FieldAsString(1)),
407
+ AttributeIfNotNull("Domain", row, 3)
408
+ );
409
}
410
}
411
@@ -546,39 +415,41 @@ namespace WixToolset.Extensions
415
/// <param name="table">The table to decompile.</param>
416
private void DecompileWixInternetShortcutTable(Table table)
417
{
549
- foreach (Row row in table.Rows)
418
+ foreach (var row in table.Rows)
419
{
551
- Util.InternetShortcut internetShortcut = new Util.InternetShortcut();
552
- internetShortcut.Id = (string)row[0];
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];
420
+ var type = String.Empty;
421
+ var shortcutType = (UtilCompiler.InternetShortcutType)row.FieldAsInteger(5);
422
switch (shortcutType)
423
{
424
case UtilCompiler.InternetShortcutType.Link:
564
- internetShortcut.Type = Util.InternetShortcut.TypeType.link;
425
+ type = "link";
426
break;
427
case UtilCompiler.InternetShortcutType.Url:
567
- internetShortcut.Type = Util.InternetShortcut.TypeType.url;
428
+ type = "url";
429
break;
430
}
431
571
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
572
- if (null != component)
432
+ var internetShortcut = new XElement(UtilConstants.InternetShortcutName,
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))
444
{
574
- component.AddChild(internetShortcut);
445
+ component.Add(internetShortcut);
446
}
447
else
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"));
450
}
451
581
- this.Core.IndexElement(row, internetShortcut);
452
+ this.DecompilerHelper.IndexElement(row, internetShortcut);
453
}
454
}
455
@@ -588,54 +459,48 @@ namespace WixToolset.Extensions
459
/// <param name="table">The table to decompile.</param>
460
private void DecompilePerfmonTable(Table table)
461
{
591
- foreach (Row row in table.Rows)
462
+ foreach (var row in table.Rows)
463
{
593
- Util.PerfCounter perfCounter = new Util.PerfCounter();
594
-
595
- perfCounter.Name = (string)row[2];
596
-
597
- this.Core.IndexElement(row, perfCounter);
464
+ this.DecompilerHelper.IndexElement(row, new XElement(UtilConstants.PerfCounterName, new XAttribute("Name", row.FieldAsString(2))));
465
}
466
}
600
-
467
+
468
/// <summary>
469
/// Decompile the PerfmonManifest table.
470
/// </summary>
471
/// <param name="table">The table to decompile.</param>
472
private void DecompilePerfmonManifestTable(Table table)
473
{
607
- foreach (Row row in table.Rows)
474
+ foreach (var row in table.Rows)
475
{
609
- Util.PerfCounterManifest perfCounterManifest = new Util.PerfCounterManifest();
610
-
611
- perfCounterManifest.ResourceFileDirectory = (string)row[2];
612
-
613
- this.Core.IndexElement(row, perfCounterManifest);
476
+ this.DecompilerHelper.IndexElement(row, new XElement(UtilConstants.PerfCounterManifestName, new XAttribute("ResourceFileDirectory", row.FieldAsString(2))));
477
}
478
}
616
-
479
+
480
/// <summary>
481
/// Decompile the EventManifest table.
482
/// </summary>
483
/// <param name="table">The table to decompile.</param>
484
private void DecompileEventManifestTable(Table table)
485
{
623
- foreach (Row row in table.Rows)
486
+ foreach (var row in table.Rows)
487
{
625
- Util.EventManifest eventManifest = new Util.EventManifest();
626
- this.Core.IndexElement(row, eventManifest);
488
+ this.DecompilerHelper.IndexElement(row, new XElement(UtilConstants.EventManifestName));
489
}
490
}
629
-
491
+
492
/// <summary>
493
/// Decompile the SecureObjects table.
494
/// </summary>
495
/// <param name="table">The table to decompile.</param>
496
private void DecompileSecureObjectsTable(Table table)
497
{
636
- foreach (Row row in table.Rows)
498
+ foreach (var row in table.Rows)
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
+ );
504
505
string[] specialPermissions;
506
switch ((string)row[1])
@@ -653,155 +518,13 @@ namespace WixToolset.Extensions
518
specialPermissions = UtilConstants.ServicePermissions;
519
break;
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]));
522
return;
523
}
524
660
- int permissionBits = (int)row[4];
661
- for (int i = 0; i < 32; i++)
662
- {
663
- if (0 != ((permissionBits >> i) & 1))
664
- {
665
- string name = null;
525
+ this.AddPermissionAttributes(permissionEx, row, 4, specialPermissions);
526
667
- if (16 > i && specialPermissions.Length > i)
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);
527
+ this.DecompilerHelper.IndexElement(row, permissionEx);
528
}
529
}
530
@@ -811,90 +534,20 @@ namespace WixToolset.Extensions
534
/// <param name="table">The table to decompile.</param>
535
private void DecompileServiceConfigTable(Table table)
536
{
814
- foreach (Row row in table.Rows)
537
+ foreach (var row in table.Rows)
538
{
816
- Util.ServiceConfig serviceConfig = new Util.ServiceConfig();
817
-
818
- serviceConfig.ServiceName = (string)row[0];
819
-
820
- switch ((string)row[3])
821
- {
822
- case "none":
823
- serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.none;
824
- break;
825
- case "reboot":
826
- serviceConfig.FirstFailureActionType = Util.ServiceConfig.FirstFailureActionTypeType.reboot;
827
- break;
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);
539
+ var serviceConfig = new XElement(UtilConstants.ServiceConfigName,
540
+ new XAttribute("ServiceName", row.FieldAsString(0)),
541
+ AttributeIfNotNull("FirstFailureActionType", row, 3),
542
+ AttributeIfNotNull("SecondFailureActionType", row, 4),
543
+ AttributeIfNotNull("ThirdFailureActionType", row, 5),
544
+ NumericAttributeIfNotNull("ResetPeriodInDays", row, 6),
545
+ NumericAttributeIfNotNull("RestartServiceDelayInSeconds", row, 7),
546
+ AttributeIfNotNull("ProgramCommandLine", row, 8),
547
+ AttributeIfNotNull("RebootMessage", row, 9)
548
+ );
549
+
550
+ this.DecompilerHelper.IndexElement(row, serviceConfig);
551
}
552
}
553
@@ -904,97 +557,58 @@ namespace WixToolset.Extensions
557
/// <param name="table">The table to decompile.</param>
558
private void DecompileUserTable(Table table)
559
{
907
- foreach (Row row in table.Rows)
560
+ foreach (var row in table.Rows)
561
{
909
- Util.User user = new Util.User();
910
-
911
- user.Id = (string)row[0];
912
-
913
- user.Name = (string)row[2];
914
-
915
- if (null != row[3])
562
+ var attributes = row.FieldAsNullableInteger(5) ?? 0;
563
+
564
+ var user = new XElement(UtilConstants.UserName,
565
+ new XAttribute("Id", row.FieldAsString(0)),
566
+ new XAttribute("Name", row.FieldAsString(2)),
567
+ AttributeIfNotNull("Domain", 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))
580
{
917
- user.Domain = (string)row[3];
581
+ user.Add(new XAttribute("RemoveOnUninstall", "no"));
582
}
583
920
- if (null != row[4])
584
+ if (UtilCompiler.UserDontCreateUser == (attributes & UtilCompiler.UserDontCreateUser))
585
{
922
- user.Password = (string)row[4];
586
+ user.Add(new XAttribute("CreateUser", "no"));
587
}
588
925
- if (null != row[5])
589
+ if (UtilCompiler.UserNonVital == (attributes & UtilCompiler.UserNonVital))
590
{
927
- int attributes = (int)row[5];
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
- }
591
+ user.Add(new XAttribute("Vital", "no"));
592
}
593
980
- if (null != row[1])
594
+ var componentId = row.FieldAsString(1);
595
+ if (!String.IsNullOrEmpty(componentId))
596
{
982
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
983
-
984
- if (null != component)
597
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
598
{
986
- component.AddChild(user);
599
+ component.Add(user);
600
}
601
else
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"));
604
}
605
}
606
else
607
{
995
- this.Core.RootElement.AddChild(user);
608
+ this.DecompilerHelper.AddElementToRoot(user);
609
}
997
- this.Core.IndexElement(row, user);
610
+
611
+ this.DecompilerHelper.IndexElement(row, user);
612
}
613
}
614
@@ -1004,21 +618,16 @@ namespace WixToolset.Extensions
618
/// <param name="table">The table to decompile.</param>
619
private void DecompileUserGroupTable(Table table)
620
{
1007
- foreach (Row row in table.Rows)
621
+ foreach (var row in table.Rows)
622
{
1009
- Util.User user = (Util.User)this.Core.GetIndexedElement("User", (string)row[0]);
1010
-
1011
- if (null != user)
623
+ var userId = row.FieldAsString(0);
624
+ if (this.DecompilerHelper.TryGetIndexedElement("User", userId, out var user))
625
{
1013
- Util.GroupRef groupRef = new Util.GroupRef();
1014
-
1015
- groupRef.Id = (string)row[1];
1016
-
1017
- user.AddChild(groupRef);
626
+ user.Add(new XElement(UtilConstants.GroupRefName, new XAttribute("Id", row.FieldAsString(1))));
627
}
628
else
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"));
631
}
632
}
633
}
@@ -1029,75 +638,58 @@ namespace WixToolset.Extensions
638
/// <param name="table">The table to decompile.</param>
639
private void DecompileXmlConfigTable(Table table)
640
{
1032
- foreach (Row row in table.Rows)
641
+ foreach (var row in table.Rows)
642
{
1034
- Util.XmlConfig xmlConfig = new Util.XmlConfig();
1035
-
1036
- xmlConfig.Id = (string)row[0];
1037
-
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];
643
+ var flags = row.FieldAsNullableInteger(6) ?? 0;
644
+ string node = null;
645
+ string action = null;
646
+ string on = null;
647
648
if (0x1 == (flags & 0x1))
649
{
1061
- xmlConfig.Node = Util.XmlConfig.NodeType.element;
650
+ node = "element";
651
}
652
else if (0x2 == (flags & 0x2))
653
{
1065
- xmlConfig.Node = Util.XmlConfig.NodeType.value;
654
+ node = "value";
655
}
656
else if (0x4 == (flags & 0x4))
657
{
1069
- xmlConfig.Node = Util.XmlConfig.NodeType.document;
658
+ node = "document";
659
}
660
661
if (0x10 == (flags & 0x10))
662
{
1074
- xmlConfig.Action = Util.XmlConfig.ActionType.create;
663
+ action = "create";
664
}
665
else if (0x20 == (flags & 0x20))
666
{
1078
- xmlConfig.Action = Util.XmlConfig.ActionType.delete;
667
+ action = "delete";
668
}
669
670
if (0x100 == (flags & 0x100))
671
{
1083
- xmlConfig.On = Util.XmlConfig.OnType.install;
672
+ on = "install";
673
}
674
else if (0x200 == (flags & 0x200))
675
{
1087
- xmlConfig.On = Util.XmlConfig.OnType.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];
676
+ on = "uninstall";
677
}
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);
693
}
694
}
695
@@ -1114,34 +706,30 @@ namespace WixToolset.Extensions
706
/// </remarks>
707
private void FinalizePerfmonTable(TableIndexedCollection tables)
708
{
1117
- Table perfmonTable = tables["Perfmon"];
1118
-
1119
- if (null != perfmonTable)
709
+ if (tables.TryGetTable("Perfmon", out var perfmonTable))
710
{
1121
- foreach (Row row in perfmonTable.Rows)
711
+ foreach (var row in perfmonTable.Rows)
712
{
1123
- string formattedFile = (string)row[1];
1124
- Util.PerfCounter perfCounter = (Util.PerfCounter)this.Core.GetIndexedElement(row);
713
+ var formattedFile = row.FieldAsString(1);
714
715
// try to "de-format" the File column's value to determine the proper parent File element
716
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
717
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
718
{
1130
- string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1131
-
1132
- Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
1133
- if (null != file)
719
+ var fileId = formattedFile.Substring(2, formattedFile.Length - 3);
720
+ if (this.DecompilerHelper.TryGetIndexedElement("File", fileId, out var file))
721
{
1135
- file.AddChild(perfCounter);
722
+ var perfCounter = this.DecompilerHelper.GetIndexedElement(row);
723
+ file.Add(perfCounter);
724
}
725
else
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"));
728
}
729
}
730
else
731
{
1144
- this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon"));
732
+ this.Messaging.Write(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "Perfmon"));
733
}
734
}
735
}
@@ -1153,34 +741,33 @@ namespace WixToolset.Extensions
741
/// <param name="tables">The collection of all tables.</param>
742
private void FinalizePerfmonManifestTable(TableIndexedCollection tables)
743
{
1156
- Table perfmonManifestTable = tables["PerfmonManifest"];
1157
-
1158
- if (null != perfmonManifestTable)
744
+ if (tables.TryGetTable("PerfmonManifest", out var perfmonManifestTable))
745
{
1160
- foreach (Row row in perfmonManifestTable.Rows)
746
+ foreach (var row in perfmonManifestTable.Rows)
747
{
1162
- string formattedFile = (string)row[1];
1163
- Util.PerfCounterManifest perfCounterManifest = (Util.PerfCounterManifest)this.Core.GetIndexedElement(row);
748
+ var formattedFile = row.FieldAsString(1);
749
750
// try to "de-format" the File column's value to determine the proper parent File element
751
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
752
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
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);
756
1171
- Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
1172
- if (null != file)
757
+ if (this.DecompilerHelper.TryGetIndexedElement("File", fileId, out var file))
758
{
1174
- file.AddChild(perfCounterManifest);
759
+ file.Add(perfCounterManifest);
760
}
761
else
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"));
766
}
767
}
768
else
769
{
1183
- this.Core.OnMessage(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest"));
770
+ this.Messaging.Write(UtilErrors.IllegalFileValueInPerfmonOrManifest(formattedFile, "PerfmonManifest"));
771
}
772
}
773
}
@@ -1196,64 +783,61 @@ namespace WixToolset.Extensions
783
/// </remarks>
784
private void FinalizeSecureObjectsTable(TableIndexedCollection tables)
785
{
1199
- Table createFolderTable = tables["CreateFolder"];
1200
- Table secureObjectsTable = tables["SecureObjects"];
1201
-
1202
- Hashtable createFolders = new Hashtable();
786
+ var createFolderElementsByDirectoryId = new Dictionary<string, List<XElement>>();
787
788
// index the CreateFolder table because the foreign key to this table from the
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))
791
{
1208
- foreach (Row row in createFolderTable.Rows)
792
+ foreach (var row in createFolderTable.Rows)
793
{
1210
- Wix.CreateFolder createFolder = (Wix.CreateFolder)this.Core.GetIndexedElement(row);
1211
- string directoryId = (string)row[0];
794
+ var directoryId = row.FieldAsString(0);
795
1213
- if (!createFolders.Contains(directoryId))
796
+ if (!createFolderElementsByDirectoryId.TryGetValue(directoryId, out var createFolderElements))
797
{
1215
- createFolders.Add(directoryId, new ArrayList());
798
+ createFolderElements = new List<XElement>();
799
+ createFolderElementsByDirectoryId.Add(directoryId, createFolderElements);
800
}
1217
- ((ArrayList)createFolders[directoryId]).Add(createFolder);
801
+
802
+ var createFolder = this.DecompilerHelper.GetIndexedElement(row);
803
+ createFolderElements.Add(createFolder);
804
}
805
}
806
1221
- if (null != secureObjectsTable)
807
+ if (tables.TryGetTable("SecureObjects", out var secureObjectsTable))
808
{
1223
- foreach (Row row in secureObjectsTable.Rows)
809
+ foreach (var row in secureObjectsTable.Rows)
810
{
1225
- string id = (string)row[0];
1226
- string table = (string)row[1];
811
+ var id = row.FieldAsString(0);
812
+ var table = row.FieldAsString(1);
813
1228
- Util.PermissionEx permissionEx = (Util.PermissionEx)this.Core.GetIndexedElement(row);
814
+ var permissionEx = this.DecompilerHelper.GetIndexedElement(row);
815
1230
- if ("CreateFolder" == table)
816
+ if (table == "CreateFolder")
817
{
1232
- ArrayList createFolderElements = (ArrayList)createFolders[id];
1233
-
1234
- if (null != createFolderElements)
818
+ if (createFolderElementsByDirectoryId.TryGetValue(id, out var createFolderElements))
819
{
1236
- foreach (Wix.CreateFolder createFolder in createFolderElements)
820
+ foreach (var createFolder in createFolderElements)
821
{
1238
- createFolder.AddChild(permissionEx);
822
+ createFolder.Add(permissionEx);
823
}
824
}
825
else
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));
828
}
829
}
830
else
831
{
1248
- Wix.IParentElement parentElement = (Wix.IParentElement)this.Core.GetIndexedElement(table, id);
832
+ var parentElement = this.DecompilerHelper.GetIndexedElement(table, id);
833
1250
- if (null != parentElement)
834
+ if (parentElement != null)
835
{
1252
- parentElement.AddChild(permissionEx);
836
+ parentElement.Add(permissionEx);
837
}
838
else
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));
841
}
842
}
843
}
@@ -1270,10 +854,8 @@ namespace WixToolset.Extensions
854
/// </remarks>
855
private void FinalizeServiceConfigTable(TableIndexedCollection tables)
856
{
1273
- Table serviceConfigTable = tables["ServiceConfig"];
1274
- Table serviceInstallTable = tables["ServiceInstall"];
1275
-
1276
- Hashtable serviceInstalls = new Hashtable();
857
+ //var serviceInstalls = new Hashtable();
858
+ var serviceInstallElementsByName = new Dictionary<string, List<XElement>>();
859
860
// index the ServiceInstall table because the foreign key used by the ServiceConfig
861
// table is actually the ServiceInstall.Name, not the ServiceInstall.ServiceInstall
@@ -1281,55 +863,54 @@ namespace WixToolset.Extensions
863
// decompiler must assume there could be multiple matches and add the ServiceConfig to each
864
// TODO: the Component column information should be taken into acount to accurately identify
865
// the correct column to use
1284
- if (null != serviceInstallTable)
866
+ if (tables.TryGetTable("ServiceInstall", out var serviceInstallTable))
867
{
1286
- foreach (Row row in serviceInstallTable.Rows)
868
+ foreach (var row in serviceInstallTable.Rows)
869
{
1288
- string name = (string)row[1];
1289
- Wix.ServiceInstall serviceInstall = (Wix.ServiceInstall)this.Core.GetIndexedElement(row);
870
+ var name = row.FieldAsString(1);
871
1291
- if (!serviceInstalls.Contains(name))
872
+ if (!serviceInstallElementsByName.TryGetValue(name, out var serviceInstallElements))
873
{
1293
- serviceInstalls.Add(name, new ArrayList());
874
+ serviceInstallElements = new List<XElement>();
875
+ serviceInstallElementsByName.Add(name, serviceInstallElements);
876
}
877
1296
- ((ArrayList)serviceInstalls[name]).Add(serviceInstall);
878
+ var serviceInstall = this.DecompilerHelper.GetIndexedElement(row);
879
+ serviceInstallElements.Add(serviceInstall);
880
}
881
}
882
1300
- if (null != serviceConfigTable)
883
+ if (tables.TryGetTable("ServiceConfig", out var serviceConfigTable))
884
{
1302
- foreach (Row row in serviceConfigTable.Rows)
885
+ foreach (var row in serviceConfigTable.Rows)
886
{
1304
- Util.ServiceConfig serviceConfig = (Util.ServiceConfig)this.Core.GetIndexedElement(row);
887
+ var serviceConfig = this.DecompilerHelper.GetIndexedElement(row);
888
1306
- if (0 == (int)row[2])
889
+ if (row.FieldAsInteger(2) == 0)
890
{
1308
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
1309
-
1310
- if (null != component)
891
+ var componentId = row.FieldAsString(1);
892
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
893
{
1312
- component.AddChild(serviceConfig);
894
+ component.Add(serviceConfig);
895
}
896
else
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"));
899
}
900
}
901
else
902
{
1321
- ArrayList serviceInstallElements = (ArrayList)serviceInstalls[row[0]];
1322
-
1323
- if (null != serviceInstallElements)
903
+ var name = row.FieldAsString(0);
904
+ if (serviceInstallElementsByName.TryGetValue(name, out var serviceInstallElements))
905
{
1325
- foreach (Wix.ServiceInstall serviceInstall in serviceInstallElements)
906
+ foreach (var serviceInstall in serviceInstallElements)
907
{
1327
- serviceInstall.AddChild(serviceConfig);
908
+ serviceInstall.Add(serviceConfig);
909
}
910
}
911
else
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"));
914
}
915
}
916
}
@@ -1342,38 +923,34 @@ namespace WixToolset.Extensions
923
/// <param name="tables">Collection of all tables.</param>
924
private void FinalizeXmlConfigTable(TableIndexedCollection tables)
925
{
1345
- Table xmlConfigTable = tables["XmlConfig"];
1346
-
1347
- if (null != xmlConfigTable)
926
+ if (tables.TryGetTable("XmlConfig", out var xmlConfigTable))
927
{
1349
- foreach (Row row in xmlConfigTable.Rows)
928
+ foreach (var row in xmlConfigTable.Rows)
929
{
1351
- Util.XmlConfig xmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement(row);
930
+ var xmlConfig = this.DecompilerHelper.GetIndexedElement(row);
931
932
if (null == row[6] || 0 == (int)row[6])
933
{
1355
- Util.XmlConfig parentXmlConfig = (Util.XmlConfig)this.Core.GetIndexedElement("XmlConfig", (string)row[2]);
1356
-
1357
- if (null != parentXmlConfig)
934
+ var id = row.FieldAsString(2);
935
+ if (this.DecompilerHelper.TryGetIndexedElement("XmlConfig", id, out var parentXmlConfig))
936
{
1359
- parentXmlConfig.AddChild(xmlConfig);
937
+ parentXmlConfig.Add(xmlConfig);
938
}
939
else
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"));
942
}
943
}
944
else
945
{
1368
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[7]);
1369
-
1370
- if (null != component)
946
+ var componentId = row.FieldAsString(7);
947
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
948
{
1372
- component.AddChild(xmlConfig);
949
+ component.Add(xmlConfig);
950
}
951
else
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"));
954
}
955
}
956
}
@@ -1391,113 +968,88 @@ namespace WixToolset.Extensions
968
/// </remarks>
969
private void FinalizeXmlFileTable(TableIndexedCollection tables)
970
{
1394
- Table xmlFileTable = tables["XmlFile"];
1395
- Table eventManifestTable = tables["EventManifest"];
1396
-
1397
- if (null != xmlFileTable)
971
+ if (tables.TryGetTable("XmlFile", out var xmlFileTable))
972
{
1399
- foreach (Row row in xmlFileTable.Rows)
973
+ var eventManifestTable = tables["EventManifest"];
974
+
975
+ foreach (var row in xmlFileTable.Rows)
976
{
1401
- bool bManifestGenerated = false;
1402
- string xmlFileConfigId = (string)row[0];
977
+ var manifestGenerated = false;
978
+ var xmlFileConfigId = (string)row[0];
979
if (null != eventManifestTable)
980
{
1405
- foreach (Row emrow in eventManifestTable.Rows)
981
+ foreach (var emrow in eventManifestTable.Rows)
982
{
1407
- string formattedFile = (string)emrow[1];
983
+ var formattedFile = (string)emrow[1];
984
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
985
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
986
{
1411
- string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
987
+ var fileId = formattedFile.Substring(2, formattedFile.Length - 3);
988
if (String.Equals(String.Concat("Config_", fileId, "ResourceFile"), xmlFileConfigId))
989
{
1414
- Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow);
1415
- if (null != eventManifest)
990
+ if (this.DecompilerHelper.TryGetIndexedElement(emrow, out var eventManifest))
991
{
1417
- eventManifest.ResourceFile = (string)row[4];
992
+ eventManifest.Add(new XAttribute("ResourceFile", row.FieldAsString(4)));
993
}
1419
- bManifestGenerated = true;
994
+ manifestGenerated = true;
995
}
1421
-
996
+
997
else if (String.Equals(String.Concat("Config_", fileId, "MessageFile"), xmlFileConfigId))
998
{
1424
- Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(emrow);
1425
- if (null != eventManifest)
999
+ if (this.DecompilerHelper.TryGetIndexedElement(emrow, out var eventManifest))
1000
{
1427
- eventManifest.MessageFile = (string)row[4];
1001
+ eventManifest.Add(new XAttribute("MessageFile", row.FieldAsString(4)));
1002
}
1429
- bManifestGenerated = true;
1003
+ manifestGenerated = true;
1004
}
1005
}
1006
}
1007
}
1008
1435
- if (true == bManifestGenerated)
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])
1009
+ if (manifestGenerated)
1010
{
1451
- xmlFile.Value = (string)row[4];
1011
+ continue;
1012
}
1013
1454
- int flags = (int)row[5];
1014
+ var action = "setValue";
1015
+ var flags = row.FieldAsInteger(5);
1016
if (0x1 == (flags & 0x1) && 0x2 == (flags & 0x2))
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]));
1019
}
1020
else if (0x1 == (flags & 0x1))
1021
{
1461
- xmlFile.Action = Util.XmlFile.ActionType.createElement;
1022
+ action = "createElement";
1023
}
1024
else if (0x2 == (flags & 0x2))
1025
{
1465
- xmlFile.Action = Util.XmlFile.ActionType.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;
1026
+ action = "deleteValue";
1027
}
1028
1482
- if (0x00010000 == (flags & 0x00010000))
1483
- {
1484
- xmlFile.Permanent = Util.YesNoType.yes;
1485
- }
1029
+ var selectionLanguage = (0x100 == (flags & 0x100)) ? "XPath" : null;
1030
+ var preserveModifiedDate = 0x00001000 == (flags & 0x00001000);
1031
+ var permanent = 0x00010000 == (flags & 0x00010000);
1032
1487
- if (null != row[7])
1033
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(6), out var component))
1034
{
1489
- xmlFile.Sequence = (int)row[7];
1490
- }
1491
-
1492
- Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[6]);
1493
-
1494
- if (null != component)
1495
- {
1496
- component.AddChild(xmlFile);
1035
+ var xmlFile = new XElement(UtilConstants.XmlFileName,
1036
+ AttributeIfNotNull("Id", row, 0),
1037
+ AttributeIfNotNull("File", row, 1),
1038
+ AttributeIfNotNull("ElementPath", row, 2),
1039
+ AttributeIfNotNull("Name", row, 3),
1040
+ AttributeIfNotNull("Value", row, 4),
1041
+ AttributeIfNotNull("Action", action),
1042
+ AttributeIfNotNull("SelectionLanguage", selectionLanguage),
1043
+ AttributeIfTrue("PreserveModifiedDate", preserveModifiedDate),
1044
+ AttributeIfTrue("Permanent", permanent),
1045
+ NumericAttributeIfNotNull("Sequence", row, 7)
1046
+ );
1047
+
1048
+ component.Add(xmlFile);
1049
}
1050
else
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"));
1053
}
1054
}
1055
}
@@ -1510,34 +1062,122 @@ namespace WixToolset.Extensions
1062
/// <param name="tables">The collection of all tables.</param>
1063
private void FinalizeEventManifestTable(TableIndexedCollection tables)
1064
{
1513
- Table eventManifestTable = tables["EventManifest"];
1514
-
1515
- if (null != eventManifestTable)
1065
+ if (tables.TryGetTable("EventManifest", out var eventManifestTable))
1066
{
1517
- foreach (Row row in eventManifestTable.Rows)
1067
+ foreach (var row in eventManifestTable.Rows)
1068
{
1519
- string formattedFile = (string)row[1];
1520
- Util.EventManifest eventManifest = (Util.EventManifest)this.Core.GetIndexedElement(row);
1069
+ var eventManifest = this.DecompilerHelper.GetIndexedElement(row);
1070
+ var formattedFile = row.FieldAsString(1);
1071
1072
// try to "de-format" the File column's value to determine the proper parent File element
1073
if ((formattedFile.StartsWith("[#", StringComparison.Ordinal) || formattedFile.StartsWith("[!", StringComparison.Ordinal))
1074
&& formattedFile.EndsWith("]", StringComparison.Ordinal))
1075
{
1526
- string fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1076
+ var fileId = formattedFile.Substring(2, formattedFile.Length - 3);
1077
1528
- Wix.File file = (Wix.File)this.Core.GetIndexedElement("File", fileId);
1529
- if (null != file)
1078
+ if (this.DecompilerHelper.TryGetIndexedElement("File", fileId, out var file))
1079
{
1531
- file.AddChild(eventManifest);
1080
+ file.Add(eventManifest);
1081
}
1082
}
1083
else
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));
1120
}
1121
}
1122
}
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
+ }
1182
}
1542
-#endif
1183
}
src/ext/Util/wixext/UtilExtensionFactory.cs
+1
@@ -11,6 +11,7 @@ namespace WixToolset.Util
11
protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
12
{
13
typeof(UtilCompiler),
14
+ typeof(UtilDecompiler),
15
typeof(UtilExtensionData),
16
typeof(UtilWindowsInstallerBackendBinderExtension),
17
};
src/ext/Util/wixext/UtilTableDefinitions.cs
+1
-1
@@ -85,7 +85,7 @@ namespace WixToolset.Util
85
UtilSymbolDefinitions.FileSharePermissions,
86
new[]
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),
90
new ColumnDefinition("Permissions", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Unknown, description: "Permissions int, as in EXPLICIT_ACCESS.grfAccessPermissions in MSDN"),
91
},
src/internal/WixBuildTools.TestSupport/Builder.cs
+88
@@ -66,5 +66,93 @@ namespace WixBuildTools.TestSupport
66
return Query.QueryDatabase(outputPath, tables);
67
}
68
}
69
+
70
+ public void BuildAndDecompileAndBuild(Action<string[]> buildFunc, Action<string[]> decompileFunc, string decompilePath)
71
+ {
72
+ var sourceFiles = Directory.GetFiles(this.SourceFolder, "*.wxs");
73
+ var wxlFiles = Directory.GetFiles(this.SourceFolder, "*.wxl");
74
+
75
+ using (var fs = new DisposableFileSystem())
76
+ {
77
+ var intermediateFolder = fs.GetFolder();
78
+ var outputFolder = Path.Combine(intermediateFolder, "bin");
79
+ var decompileExtractFolder = Path.Combine(intermediateFolder, "decompiled", "extract");
80
+ var decompileIntermediateFolder = Path.Combine(intermediateFolder, "decompiled", "obj");
81
+ var decompileBuildFolder = Path.Combine(intermediateFolder, "decompiled", "bin");
82
+ var outputPath = Path.Combine(outputFolder, this.OutputFile);
83
+ var decompileBuildPath = Path.Combine(decompileBuildFolder, this.OutputFile);
84
+
85
+ // First build.
86
+ var firstBuildArgs = new List<string>
87
+ {
88
+ "build",
89
+ "-o", outputPath,
90
+ "-intermediateFolder", intermediateFolder,
91
+ };
92
+
93
+ if (this.ExtensionType != null)
94
+ {
95
+ firstBuildArgs.Add("-ext");
96
+ firstBuildArgs.Add(Path.GetFullPath(new Uri(this.ExtensionType.Assembly.CodeBase).LocalPath));
97
+ }
98
+
99
+ firstBuildArgs.AddRange(sourceFiles);
100
+
101
+ foreach (var wxlFile in wxlFiles)
102
+ {
103
+ firstBuildArgs.Add("-loc");
104
+ firstBuildArgs.Add(wxlFile);
105
+ }
106
+
107
+ foreach (var bindPath in this.BindPaths)
108
+ {
109
+ firstBuildArgs.Add("-bindpath");
110
+ firstBuildArgs.Add(bindPath);
111
+ }
112
+
113
+ buildFunc(firstBuildArgs.ToArray());
114
+
115
+ // Decompile built output.
116
+ var decompileArgs = new List<string>
117
+ {
118
+ "msi", "decompile",
119
+ outputPath,
120
+ "-intermediateFolder", decompileIntermediateFolder,
121
+ "-x", decompileExtractFolder,
122
+ "-o", decompilePath
123
+ };
124
+
125
+ if (this.ExtensionType != null)
126
+ {
127
+ decompileArgs.Add("-ext");
128
+ decompileArgs.Add(Path.GetFullPath(new Uri(this.ExtensionType.Assembly.CodeBase).LocalPath));
129
+ }
130
+
131
+ decompileFunc(decompileArgs.ToArray());
132
+
133
+ // Build decompiled output.
134
+ var secondBuildArgs = new List<string>
135
+ {
136
+ "build",
137
+ decompilePath,
138
+ "-o", decompileBuildPath,
139
+ "-intermediateFolder", decompileIntermediateFolder
140
+ };
141
+
142
+ if (this.ExtensionType != null)
143
+ {
144
+ secondBuildArgs.Add("-ext");
145
+ secondBuildArgs.Add(Path.GetFullPath(new Uri(this.ExtensionType.Assembly.CodeBase).LocalPath));
146
+ }
147
+
148
+ secondBuildArgs.Add("-bindpath");
149
+ secondBuildArgs.Add(outputFolder);
150
+
151
+ secondBuildArgs.Add("-bindpath");
152
+ secondBuildArgs.Add(decompileExtractFolder);
153
+
154
+ buildFunc(secondBuildArgs.ToArray());
155
+ }
156
+ }
157
}
158
}
src/wix/WixToolset.Core.Burn/BurnExtensionFactory.cs
+1
-1
@@ -22,7 +22,7 @@ namespace WixToolset.Core.Burn
22
{
23
extension = new BurnExtensionCommandLine(this.ServiceProvider);
24
}
25
- if (extensionType == typeof(IBackendFactory))
25
+ else if (extensionType == typeof(IBackendFactory))
26
{
27
extension = new BurnBackendFactory();
28
}
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs
+6
-1
@@ -66,11 +66,16 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
66
this.OutputPath = Path.ChangeExtension(this.InputPath, ".wxs");
67
}
68
69
+ var extensionManager = this.ServiceProvider.GetService<IExtensionManager>();
70
+ var creator = this.ServiceProvider.GetService<ISymbolDefinitionCreator>();
71
+
72
var context = this.ServiceProvider.GetService<IWindowsInstallerDecompileContext>();
70
- context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().GetServices<IWindowsInstallerDecompilerExtension>();
73
+ context.Extensions = extensionManager.GetServices<IWindowsInstallerDecompilerExtension>();
74
+ context.ExtensionData = extensionManager.GetServices<IExtensionData>();
75
context.DecompilePath = this.InputPath;
76
context.DecompileType = decompileType;
77
context.IntermediateFolder = this.IntermediateFolder;
78
+ context.SymbolDefinitionCreator = creator;
79
context.OutputPath = this.OutputPath;
80
81
context.ExtractFolder = this.ExportBasePath ?? this.IntermediateFolder;
src/wix/WixToolset.Core.WindowsInstaller/Decompile/DecompileMsiOrMsmCommand.cs
deleted
-91
@@ -1,91 +0,0 @@
1
- // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
-
3
-namespace WixToolset.Core.WindowsInstaller.Decompile
4
-{
5
- using System;
6
- using System.Collections.Generic;
7
- using System.ComponentModel;
8
- using System.IO;
9
- using System.Linq;
10
- using WixToolset.Core.Native.Msi;
11
- using WixToolset.Core.WindowsInstaller.Unbind;
12
- using WixToolset.Data;
13
- using WixToolset.Data.WindowsInstaller;
14
- using WixToolset.Extensibility.Data;
15
- using WixToolset.Extensibility.Services;
16
-
17
- internal class DecompileMsiOrMsmCommand
18
- {
19
- public DecompileMsiOrMsmCommand(IWindowsInstallerDecompileContext context)
20
- {
21
- this.Context = context;
22
- this.Messaging = context.ServiceProvider.GetService<IMessaging>();
23
- }
24
-
25
- private IWindowsInstallerDecompileContext Context { get; }
26
-
27
- private IMessaging Messaging { get; }
28
-
29
- public IWindowsInstallerDecompileResult Execute()
30
- {
31
- var result = this.Context.ServiceProvider.GetService<IWindowsInstallerDecompileResult>();
32
-
33
- try
34
- {
35
- using (var database = new Database(this.Context.DecompilePath, OpenDatabase.ReadOnly))
36
- {
37
- // Delete the directory and its files to prevent cab extraction failure due to an existing file.
38
- if (Directory.Exists(this.Context.ExtractFolder))
39
- {
40
- Directory.Delete(this.Context.ExtractFolder, true);
41
- }
42
-
43
- var backendHelper = this.Context.ServiceProvider.GetService<IBackendHelper>();
44
-
45
- var unbindCommand = new UnbindDatabaseCommand(this.Messaging, backendHelper, database, this.Context.DecompilePath, this.Context.DecompileType, this.Context.ExtractFolder, this.Context.IntermediateFolder, this.Context.IsAdminImage, suppressDemodularization: false, skipSummaryInfo: false);
46
- var output = unbindCommand.Execute();
47
- var extractedFilePaths = new List<string>(unbindCommand.ExportedFiles);
48
-
49
- var decompiler = new Decompiler(this.Messaging, backendHelper, this.Context.Extensions, this.Context.BaseSourcePath, this.Context.SuppressCustomTables, this.Context.SuppressDroppingEmptyTables, this.Context.SuppressRelativeActionSequencing, this.Context.SuppressUI, this.Context.TreatProductAsModule);
50
- result.Document = decompiler.Decompile(output);
51
-
52
- result.Platform = GetPlatformFromOutput(output);
53
-
54
- // extract the files from the cabinets
55
- if (!String.IsNullOrEmpty(this.Context.ExtractFolder) && !this.Context.SuppressExtractCabinets)
56
- {
57
- var fileDirectory = String.IsNullOrEmpty(this.Context.CabinetExtractFolder) ? Path.Combine(this.Context.ExtractFolder, "File") : this.Context.CabinetExtractFolder;
58
-
59
- var extractCommand = new ExtractCabinetsCommand(output, database, this.Context.DecompilePath, fileDirectory, this.Context.IntermediateFolder, this.Context.TreatProductAsModule);
60
- extractCommand.Execute();
61
-
62
- extractedFilePaths.AddRange(extractCommand.ExtractedFiles);
63
- result.ExtractedFilePaths = extractedFilePaths;
64
- }
65
- else
66
- {
67
- result.ExtractedFilePaths = new string[0];
68
- }
69
- }
70
- }
71
- catch (Win32Exception e)
72
- {
73
- if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED
74
- {
75
- throw new WixException(ErrorMessages.OpenDatabaseFailed(this.Context.DecompilePath));
76
- }
77
-
78
- throw;
79
- }
80
-
81
- return result;
82
- }
83
-
84
- private static Platform? GetPlatformFromOutput(WindowsInstallerData output)
85
- {
86
- var template = output.Tables["_SummaryInformation"]?.Rows.SingleOrDefault(row => row.FieldAsInteger(0) == 7)?.FieldAsString(1);
87
-
88
- return Decompiler.GetPlatformFromTemplateSummaryInformation(template?.Split(';'));
89
- }
90
- }
91
-}
src/wix/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
+326
-336
@@ -43,11 +43,14 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
43
/// <summary>
44
/// Creates a new decompiler object with a default set of table definitions.
45
/// </summary>
46
- public Decompiler(IMessaging messaging, IBackendHelper backendHelper, IEnumerable<IWindowsInstallerDecompilerExtension> extensions, string baseSourcePath, bool suppressCustomTables, bool suppressDroppingEmptyTables, bool suppressRelativeActionSequencing, bool suppressUI, bool treatProductAsModule)
46
+ public Decompiler(IMessaging messaging, IBackendHelper backendHelper, IWindowsInstallerDecompilerHelper decompilerHelper, IEnumerable<IWindowsInstallerDecompilerExtension> extensions, IEnumerable<IExtensionData> extensionData, ISymbolDefinitionCreator creator, string baseSourcePath, bool suppressCustomTables, bool suppressDroppingEmptyTables, bool suppressRelativeActionSequencing, bool suppressUI, bool treatProductAsModule)
47
{
48
this.Messaging = messaging;
49
this.BackendHelper = backendHelper;
50
+ this.DecompilerHelper = decompilerHelper;
51
this.Extensions = extensions;
52
+ this.ExtensionData = extensionData;
53
+ this.SymbolDefinitionCreator = creator;
54
this.BaseSourcePath = baseSourcePath ?? "SourceDir";
55
this.SuppressCustomTables = suppressCustomTables;
56
this.SuppressDroppingEmptyTables = suppressDroppingEmptyTables;
@@ -65,8 +68,14 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
68
69
private IBackendHelper BackendHelper { get; }
70
71
+ private IWindowsInstallerDecompilerHelper DecompilerHelper { get; }
72
+
73
private IEnumerable<IWindowsInstallerDecompilerExtension> Extensions { get; }
74
75
+ private IEnumerable<IExtensionData> ExtensionData { get; }
76
+
77
+ private ISymbolDefinitionCreator SymbolDefinitionCreator { get; }
78
+
79
private Dictionary<string, IWindowsInstallerDecompilerExtension> ExtensionsByTableName { get; }
80
81
private string BaseSourcePath { get; }
@@ -87,8 +96,6 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
96
97
private bool Compressed { get; set; }
98
90
- private XElement RootElement { get; set; }
91
-
99
private TableDefinitionCollection TableDefinitions { get; }
100
101
private bool ShortNames { get; set; }
@@ -101,8 +108,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
108
{
109
if (null == this.uiElement)
110
{
104
- this.uiElement = new XElement(Names.UIElement);
105
- this.RootElement.Add(this.uiElement);
111
+ this.uiElement = this.DecompilerHelper.AddElementToRoot(new XElement(Names.UIElement));
112
}
113
114
return this.uiElement;
@@ -111,8 +117,6 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
117
118
private Dictionary<string, XElement> Singletons { get; } = new Dictionary<string, XElement>();
119
114
- private Dictionary<string, XElement> IndexedElements { get; } = new Dictionary<string, XElement>();
115
-
120
private Dictionary<string, XElement> PatchTargetFiles { get; } = new Dictionary<string, XElement>();
121
122
/// <summary>
@@ -122,13 +126,23 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
126
/// <returns>The serialized WiX source code.</returns>
127
public XDocument Decompile(WindowsInstallerData output)
128
{
125
- if (null == output)
129
+ this.OutputType = output.Type;
130
+
131
+ switch (this.OutputType)
132
{
127
- throw new ArgumentNullException(nameof(output));
133
+ case OutputType.Module:
134
+ this.DecompilerHelper.RootElement = new XElement(Names.ModuleElement);
135
+ break;
136
+ case OutputType.PatchCreation:
137
+ this.DecompilerHelper.RootElement = new XElement(Names.PatchCreationElement);
138
+ break;
139
+ case OutputType.Product:
140
+ this.DecompilerHelper.RootElement = new XElement(Names.PackageElement);
141
+ break;
142
+ default:
143
+ throw new InvalidOperationException("Unknown output type.");
144
}
145
130
- this.OutputType = output.Type;
131
-
146
// collect the table definitions from the output
147
this.TableDefinitions.Clear();
148
foreach (var table in output.Tables)
@@ -146,30 +160,11 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
160
}
161
162
// add any missing extension table definitions
149
-#if TODO_DECOMPILER_EXTENSIONS
163
foreach (var extension in this.Extensions)
164
{
152
- this.AddExtension(extension);
153
- }
154
-#endif
155
-
156
- switch (this.OutputType)
157
- {
158
- case OutputType.Module:
159
- this.RootElement = new XElement(Names.ModuleElement);
160
- break;
161
- case OutputType.PatchCreation:
162
- this.RootElement = new XElement(Names.PatchCreationElement);
163
- break;
164
- case OutputType.Product:
165
- this.RootElement = new XElement(Names.PackageElement);
166
- break;
167
- default:
168
- throw new InvalidOperationException("Unknown output type.");
165
+ this.AddExtensionTableDefinitions(extension);
166
}
167
171
- var xWix = new XElement(Names.WixElement, this.RootElement);
172
-
168
// try to decompile the database file
169
// stop processing if an error previously occurred
170
if (this.Messaging.EncounteredError)
@@ -192,16 +187,14 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
187
this.FinalizeDecompile(output.Tables);
188
189
// return the XML document only if decompilation completed successfully
195
- var document = new XDocument(xWix);
196
- return this.Messaging.EncounteredError ? null : document;
190
+ return this.Messaging.EncounteredError ? null : new XDocument(new XElement(Names.WixElement, this.DecompilerHelper.RootElement));
191
}
192
199
-#if TODO_DECOMPILER_EXTENSIONS
200
- private void AddExtension(IWindowsInstallerBackendDecompilerExtension extension)
193
+ private void AddExtensionTableDefinitions(IWindowsInstallerDecompilerExtension extension)
194
{
195
if (null != extension.TableDefinitions)
196
{
204
- foreach (TableDefinition tableDefinition in extension.TableDefinitions)
197
+ foreach (var tableDefinition in extension.TableDefinitions)
198
{
199
if (!this.ExtensionsByTableName.ContainsKey(tableDefinition.Name))
200
{
@@ -214,7 +207,6 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
207
}
208
}
209
}
217
-#endif
210
211
internal static Platform? GetPlatformFromTemplateSummaryInformation(string[] template)
212
{
@@ -234,75 +226,10 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
226
return null;
227
}
228
237
- /// <summary>
238
- /// Gets the element corresponding to the row it came from.
239
- /// </summary>
240
- /// <param name="row">The row corresponding to the element.</param>
241
- /// <returns>The indexed element.</returns>
242
- private XElement GetIndexedElement(Row row)
243
- {
244
- return this.GetIndexedElement(row.TableDefinition.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter));
245
- }
246
-
247
- /// <summary>
248
- /// Gets the element corresponding to the primary key of the given table.
249
- /// </summary>
250
- /// <param name="table">The table corresponding to the element.</param>
251
- /// <param name="primaryKey">The primary key corresponding to the element.</param>
252
- /// <returns>The indexed element.</returns>
253
- private XElement GetIndexedElement(string table, params string[] primaryKey)
254
- {
255
- return this.TryGetIndexedElement(table, out var element, primaryKey) ? element : null;
256
- }
257
-
258
- /// <summary>
259
- /// Tries to get the element corresponding to the primary key of the given table.
260
- /// </summary>
261
- /// <param name="row">The table corresponding to the element.</param>
262
- /// <param name="xElement">The indexed element.</param>
263
- /// <returns>Whether the element was found.</returns>
264
- private bool TryGetIndexedElement(Row row, out XElement xElement)
265
- {
266
- return this.TryGetIndexedElement(row.TableDefinition.Name, out xElement, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter));
267
- }
268
-
269
- /// <summary>
270
- /// Tries to get the element corresponding to the primary key of the given table.
271
- /// </summary>
272
- /// <param name="table">The table corresponding to the element.</param>
273
- /// <param name="xElement">The indexed element.</param>
274
- /// <param name="primaryKey">The primary key corresponding to the element.</param>
275
- /// <returns>Whether the element was found.</returns>
276
- private bool TryGetIndexedElement(string table, out XElement xElement, params string[] primaryKey)
277
- {
278
- return this.IndexedElements.TryGetValue(String.Concat(table, ':', String.Join(DecompilerConstants.PrimaryKeyDelimiterString, primaryKey)), out xElement);
279
- }
280
-
281
- /// <summary>
282
- /// Index an element by its corresponding row.
283
- /// </summary>
284
- /// <param name="row">The row corresponding to the element.</param>
285
- /// <param name="element">The element to index.</param>
286
- private void IndexElement(Row row, XElement element)
287
- {
288
- this.IndexedElements.Add(String.Concat(row.TableDefinition.Name, ':', row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)), element);
289
- }
290
-
291
- /// <summary>
292
- /// Index an element by its corresponding row.
293
- /// </summary>
294
- /// <param name="element">The element to index.</param>
295
- /// <param name="table"></param>
296
- /// <param name="primaryKey"></param>
297
- private void IndexElement(XElement element, string table, params string[] primaryKey)
298
- {
299
- this.IndexedElements.Add(String.Concat(table, ':', String.Join(DecompilerConstants.PrimaryKeyDelimiterString, primaryKey)), element);
300
- }
301
-
229
private Dictionary<string, List<XElement>> IndexTableOneToMany(IEnumerable<Row> rows, int column = 0)
230
{
231
return rows
305
- .ToLookup(row => row.FieldAsString(column), row => this.GetIndexedElement(row))
232
+ .ToLookup(row => row.FieldAsString(column), row => this.DecompilerHelper.GetIndexedElement(row))
233
.ToDictionary(lookup => lookup.Key, lookup => lookup.ToList());
234
}
235
@@ -319,7 +246,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
246
private void AddChildToParent(string parentName, XElement xChild, Row row, int column)
247
{
248
var key = row.FieldAsString(column);
322
- if (this.TryGetIndexedElement(parentName, out var xParent, key))
249
+ if (this.DecompilerHelper.TryGetIndexedElement(parentName, key, out var xParent))
250
{
251
xParent.Add(xChild);
252
}
@@ -419,7 +346,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
346
{
347
XElement xAction;
348
422
- if (this.TryGetIndexedElement("CustomAction", out var _, actionSymbol.Action)) // custom action
349
+ if (this.DecompilerHelper.TryGetIndexedElement("CustomAction", actionSymbol.Action, out var _)) // custom action
350
{
351
xAction = new XElement(Names.CustomElement,
352
new XAttribute("Action", actionSymbol.Action),
@@ -455,7 +382,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
382
break;
383
}
384
}
458
- else if (this.TryGetIndexedElement("Dialog", out var _, actionSymbol.Action)) // dialog
385
+ else if (this.DecompilerHelper.TryGetIndexedElement("Dialog", actionSymbol.Action, out var _)) // dialog
386
{
387
xAction = new XElement(Names.CustomElement,
388
new XAttribute("Dialog", actionSymbol.Action),
@@ -495,7 +422,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
422
{
423
xSequence = new XElement(Names.WxsNamespace + sequenceTable);
424
498
- this.RootElement.Add(xSequence);
425
+ this.DecompilerHelper.AddElementToRoot(xSequence);
426
this.Singletons.Add(sequenceTable, xSequence);
427
}
428
@@ -669,14 +596,12 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
596
/// <returns>The property element.</returns>
597
private XElement EnsureProperty(string id)
598
{
672
- XElement xProperty;
673
-
674
- if (!this.TryGetIndexedElement("Property", out xProperty, id))
599
+ if (!this.DecompilerHelper.TryGetIndexedElement("Property", id, out var xProperty))
600
{
601
xProperty = new XElement(Names.PropertyElement, new XAttribute("Id", id));
602
678
- this.RootElement.Add(xProperty);
679
- this.IndexElement(xProperty, "Property", id);
603
+ this.DecompilerHelper.AddElementToRoot(xProperty);
604
+ this.DecompilerHelper.IndexElement("Property", id, xProperty);
605
}
606
607
return xProperty;
@@ -713,6 +638,11 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
638
this.FinalizeSequenceTables(tables);
639
this.FinalizeVerbTable(tables);
640
}
641
+
642
+ foreach (var extension in this.Extensions)
643
+ {
644
+ extension.PostDecompileTables(tables);
645
+ }
646
}
647
648
/// <summary>
@@ -743,7 +673,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
673
{
674
foreach (var row in controlTable.Rows)
675
{
746
- var xControl = this.GetIndexedElement(row);
676
+ var xControl = this.DecompilerHelper.GetIndexedElement(row);
677
678
if ("CheckBox" == row.FieldAsString(2))
679
{
@@ -791,9 +721,9 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
721
{
722
// Add the TARGETDIR StandardDirectory if a component is directly parented there.
723
if (componentTable.Rows.Any(row => row.FieldAsString(2) == "TARGETDIR")
794
- && this.TryGetIndexedElement("Directory", out var xDirectory, "TARGETDIR"))
724
+ && this.DecompilerHelper.TryGetIndexedElement("Directory", "TARGETDIR", out var xDirectory))
725
{
796
- this.RootElement.Add(xDirectory);
726
+ this.DecompilerHelper.AddElementToRoot(xDirectory);
727
}
728
729
foreach (var row in componentTable.Rows)
@@ -803,12 +733,12 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
733
734
if (String.IsNullOrEmpty(keyPath))
735
{
806
- var xComponent = this.GetIndexedElement("Component", row.FieldAsString(0));
736
+ var xComponent = this.DecompilerHelper.GetIndexedElement("Component", row.FieldAsString(0));
737
xComponent.SetAttributeValue("KeyPath", "yes");
738
}
739
else if (WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath == (attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath))
740
{
811
- if (this.TryGetIndexedElement("Registry", out var xRegistry, keyPath))
741
+ if (this.DecompilerHelper.TryGetIndexedElement("Registry", keyPath, out var xRegistry))
742
{
743
if (xRegistry.Name.LocalName == "RegistryValue")
744
{
@@ -826,7 +756,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
756
}
757
else if (WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource == (attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource))
758
{
829
- if (this.TryGetIndexedElement("ODBCDataSource", out var xOdbcDataSource, keyPath))
759
+ if (this.DecompilerHelper.TryGetIndexedElement("ODBCDataSource", keyPath, out var xOdbcDataSource))
760
{
761
xOdbcDataSource.SetAttributeValue("KeyPath", "yes");
762
}
@@ -837,7 +767,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
767
}
768
else
769
{
840
- if (this.TryGetIndexedElement("File", out var xFile, keyPath))
770
+ if (this.DecompilerHelper.TryGetIndexedElement("File", keyPath, out var xFile))
771
{
772
xFile.SetAttributeValue("KeyPath", "yes");
773
}
@@ -854,8 +784,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
784
{
785
foreach (FileRow fileRow in fileTable.Rows)
786
{
857
- if (this.TryGetIndexedElement("Component", out var xComponent, fileRow.Component)
858
- && this.TryGetIndexedElement(fileRow, out var xFile))
787
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", fileRow.Component, out var xComponent)
788
+ && this.DecompilerHelper.TryGetIndexedElement(fileRow, out var xFile))
789
{
790
xComponent.Add(xFile);
791
}
@@ -871,8 +801,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
801
{
802
foreach (var row in odbcDataSourceTable.Rows)
803
{
874
- if (this.TryGetIndexedElement("Component", out var xComponent, row.FieldAsString(1))
875
- && this.TryGetIndexedElement(row, out var xOdbcDataSource))
804
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(1), out var xComponent)
805
+ && this.DecompilerHelper.TryGetIndexedElement(row, out var xOdbcDataSource))
806
{
807
xComponent.Add(xOdbcDataSource);
808
}
@@ -888,8 +818,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
818
{
819
foreach (var row in registryTable.Rows)
820
{
891
- if (this.TryGetIndexedElement("Component", out var xComponent, row.FieldAsString(5))
892
- && this.TryGetIndexedElement(row, out var xRegistry))
821
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(5), out var xComponent)
822
+ && this.DecompilerHelper.TryGetIndexedElement(row, out var xRegistry))
823
{
824
xComponent.Add(xRegistry);
825
}
@@ -927,10 +857,10 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
857
{
858
foreach (var dialogRow in dialogTable.Rows)
859
{
930
- var xDialog = this.GetIndexedElement(dialogRow);
860
+ var xDialog = this.DecompilerHelper.GetIndexedElement(dialogRow);
861
var dialogId = dialogRow.FieldAsString(0);
862
933
- if (!this.TryGetIndexedElement("Control", out var xControl, dialogId, dialogRow.FieldAsString(7)))
863
+ if (!this.DecompilerHelper.TryGetIndexedElement("Control", dialogId, dialogRow.FieldAsString(7), out var xControl))
864
{
865
this.Messaging.Write(WarningMessages.ExpectedForeignRow(dialogRow.SourceLineNumbers, "Dialog", dialogRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_First", dialogRow.FieldAsString(7), "Control"));
866
}
@@ -949,7 +879,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
879
var controlNext = controlRow.FieldAsString(10);
880
if (!String.IsNullOrEmpty(controlNext))
881
{
952
- if (this.TryGetIndexedElement("Control", out xControl, dialogId, controlNext))
882
+ if (this.DecompilerHelper.TryGetIndexedElement("Control", dialogId, controlNext, out xControl))
883
{
884
// looped back to the first control in the dialog
885
if (addedControls.Contains(xControl))
@@ -972,7 +902,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
902
var controlDefault = dialogRow.FieldAsString(8);
903
if (!String.IsNullOrEmpty(controlDefault))
904
{
975
- if (this.TryGetIndexedElement("Control", out var xDefaultControl, dialogId, controlDefault))
905
+ if (this.DecompilerHelper.TryGetIndexedElement("Control", dialogId, controlDefault, out var xDefaultControl))
906
{
907
xDefaultControl.SetAttributeValue("Default", "yes");
908
}
@@ -986,7 +916,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
916
var controlCancel = dialogRow.FieldAsString(8);
917
if (!String.IsNullOrEmpty(controlCancel))
918
{
989
- if (this.TryGetIndexedElement("Control", out var xCancelControl, dialogId, controlCancel))
919
+ if (this.DecompilerHelper.TryGetIndexedElement("Control", dialogId, controlCancel, out var xCancelControl))
920
{
921
xCancelControl.SetAttributeValue("Cancel", "yes");
922
}
@@ -1004,13 +934,13 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
934
foreach (var controlRow in controlTable.Rows)
935
{
936
var dialogId = controlRow.FieldAsString(0);
1007
- if (!this.TryGetIndexedElement("Dialog", out var xDialog, dialogId))
937
+ if (!this.DecompilerHelper.TryGetIndexedElement("Dialog", dialogId, out var xDialog))
938
{
939
this.Messaging.Write(WarningMessages.ExpectedForeignRow(controlRow.SourceLineNumbers, "Control", controlRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", dialogId, "Dialog"));
940
continue;
941
}
942
1013
- var xControl = this.GetIndexedElement(controlRow);
943
+ var xControl = this.DecompilerHelper.GetIndexedElement(controlRow);
944
if (!addedControls.Contains(xControl))
945
{
946
xControl.SetAttributeValue("TabSkip", "yes");
@@ -1035,11 +965,11 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
965
{
966
foreach (var row in duplicateFileTable.Rows)
967
{
1038
- var xCopyFile = this.GetIndexedElement(row);
968
+ var xCopyFile = this.DecompilerHelper.GetIndexedElement(row);
969
var destination = row.FieldAsString(4);
970
if (!String.IsNullOrEmpty(destination))
971
{
1042
- if (this.TryGetIndexedElement("Directory", out var _, destination))
972
+ if (this.DecompilerHelper.TryGetIndexedElement("Directory", destination, out var _))
973
{
974
xCopyFile.SetAttributeValue("DestinationDirectory", destination);
975
}
@@ -1056,11 +986,11 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
986
{
987
foreach (var row in moveFileTable.Rows)
988
{
1059
- var xCopyFile = this.GetIndexedElement(row);
989
+ var xCopyFile = this.DecompilerHelper.GetIndexedElement(row);
990
var source = row.FieldAsString(4);
991
if (!String.IsNullOrEmpty(source))
992
{
1063
- if (this.TryGetIndexedElement("Directory", out var _, source))
993
+ if (this.DecompilerHelper.TryGetIndexedElement("Directory", source, out var _))
994
{
995
xCopyFile.SetAttributeValue("SourceDirectory", source);
996
}
@@ -1071,7 +1001,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1001
}
1002
1003
var destination = row.FieldAsString(5);
1074
- if (this.TryGetIndexedElement("Directory", out var _, destination))
1004
+ if (this.DecompilerHelper.TryGetIndexedElement("Directory", destination, out var _))
1005
{
1006
xCopyFile.SetAttributeValue("DestinationDirectory", destination);
1007
}
@@ -1134,7 +1064,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1064
// TODO: warn about mismatch between columns
1065
}
1066
1137
- this.IndexElement(row, xProtectRange);
1067
+ this.DecompilerHelper.IndexElement(row, xProtectRange);
1068
}
1069
}
1070
@@ -1144,8 +1074,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1074
{
1075
foreach (var row in externalFilesTable.Rows)
1076
{
1147
- if (this.TryGetIndexedElement(row, out var xExternalFile)
1148
- && this.TryGetIndexedElement("FamilyFileRanges", out var xProtectRange, row.FieldAsString(0), row.FieldAsString(0)))
1077
+ if (this.DecompilerHelper.TryGetIndexedElement(row, out var xExternalFile)
1078
+ && this.DecompilerHelper.TryGetIndexedElement("FamilyFileRanges", row.FieldAsString(0), row.FieldAsString(0), out var xProtectRange))
1079
{
1080
xExternalFile.Add(xProtectRange);
1081
usedProtectRanges.Add(xProtectRange);
@@ -1178,7 +1108,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1108
continue;
1109
}
1110
1181
- if (this.TryGetIndexedElement("FamilyFileRanges", out var xProtectRange, upgradedImagesRow.FieldAsString(4), row.FieldAsString(1)))
1111
+ if (this.DecompilerHelper.TryGetIndexedElement("FamilyFileRanges", upgradedImagesRow.FieldAsString(4), row.FieldAsString(1), out var xProtectRange))
1112
{
1113
xTargetFile.Add(xProtectRange);
1114
usedProtectRanges.Add(xProtectRange);
@@ -1190,7 +1120,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1120
{
1121
foreach (var row in familyFileRangesTable.Rows)
1122
{
1193
- var xProtectRange = this.GetIndexedElement(row);
1123
+ var xProtectRange = this.DecompilerHelper.GetIndexedElement(row);
1124
1125
if (!usedProtectRanges.Contains(xProtectRange))
1126
{
@@ -1276,7 +1206,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1206
// set the disk identifiers and sources for files
1207
foreach (var fileRow in tables["File"]?.Rows.Cast<FileRow>() ?? Enumerable.Empty<FileRow>())
1208
{
1279
- var xFile = this.GetIndexedElement("File", fileRow.File);
1209
+ var xFile = this.DecompilerHelper.GetIndexedElement("File", fileRow.File);
1210
1211
// Don't bother processing files that are orphaned (and won't show up in the output anyway)
1212
if (null != xFile.Parent)
@@ -1328,7 +1258,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1258
// set the file assemblies and manifests
1259
foreach (var row in tables["MsiAssembly"]?.Rows ?? Enumerable.Empty<Row>())
1260
{
1331
- if (this.TryGetIndexedElement("Component", out var xComponent, row.FieldAsString(0)))
1261
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(0), out var xComponent))
1262
{
1263
foreach (var xFile in xComponent.Elements(Names.FileElement).Where(x => x.Attribute("KeyPath")?.Value == "yes"))
1264
{
@@ -1346,8 +1276,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1276
// nest the TypeLib elements
1277
foreach (var row in tables["TypeLib"]?.Rows ?? Enumerable.Empty<Row>())
1278
{
1349
- var xComponent = this.GetIndexedElement("Component", row.FieldAsString(2));
1350
- var xTypeLib = this.GetIndexedElement(row);
1279
+ var xComponent = this.DecompilerHelper.GetIndexedElement("Component", row.FieldAsString(2));
1280
+ var xTypeLib = this.DecompilerHelper.GetIndexedElement(row);
1281
1282
foreach (var xFile in xComponent.Elements(Names.FileElement).Where(x => x.Attribute("KeyPath")?.Value == "yes"))
1283
{
@@ -1374,7 +1304,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1304
var mimeRef = row.FieldAsString(3);
1305
if (null != mimeRef)
1306
{
1377
- if (this.TryGetIndexedElement("MIME", out var xMime, mimeRef))
1307
+ if (this.DecompilerHelper.TryGetIndexedElement("MIME", mimeRef, out var xMime))
1308
{
1309
xMime.SetAttributeValue("Default", "yes");
1310
}
@@ -1389,7 +1319,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1319
1320
foreach (var row in tables["MIME"]?.Rows ?? Enumerable.Empty<Row>())
1321
{
1392
- var xMime = this.GetIndexedElement(row);
1322
+ var xMime = this.DecompilerHelper.GetIndexedElement(row);
1323
1324
if (extensionsByExtensionId.TryGetValue(row.FieldAsString(1), out var xExtensions))
1325
{
@@ -1427,9 +1357,9 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1357
foreach (var row in classRows)
1358
{
1359
var clsid = row.FieldAsString(0);
1430
- var xClass = this.GetIndexedElement(row);
1360
+ var xClass = this.DecompilerHelper.GetIndexedElement(row);
1361
1432
- if (this.TryGetIndexedElement("ProgId", out var xProgId, row.FieldAsString(3)))
1362
+ if (this.DecompilerHelper.TryGetIndexedElement("ProgId", row.FieldAsString(3), out var xProgId))
1363
{
1364
if (addedProgIds.TryGetValue(xProgId, out var progid))
1365
{
@@ -1451,7 +1381,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1381
foreach (var row in tables["ProgId"]?.Rows ?? Enumerable.Empty<Row>())
1382
{
1383
var clsid = row.FieldAsString(2);
1454
- var xProgId = this.GetIndexedElement(row);
1384
+ var xProgId = this.DecompilerHelper.GetIndexedElement(row);
1385
1386
if (!addedProgIds.ContainsKey(xProgId) && null != clsid && null == xProgId.Parent)
1387
{
@@ -1475,7 +1405,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1405
1406
foreach (var row in tables["Extension"]?.Rows?.Where(row => row.FieldAsString(2) != null) ?? Enumerable.Empty<Row>())
1407
{
1478
- var xProgId = this.GetIndexedElement("ProgId", row.FieldAsString(2));
1408
+ var xProgId = this.DecompilerHelper.GetIndexedElement("ProgId", row.FieldAsString(2));
1409
1410
// Haven't added the progId yet and it doesn't have a parent progId
1411
if (!addedProgIds.ContainsKey(xProgId) && null == xProgId.Parent)
@@ -1510,7 +1440,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1440
var bits = row.FieldAsInteger(1);
1441
if (WindowsInstallerConstants.MsidbCustomActionTypeHideTarget == (bits & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget)
1442
&& WindowsInstallerConstants.MsidbCustomActionTypeInScript == (bits & WindowsInstallerConstants.MsidbCustomActionTypeInScript)
1513
- && this.TryGetIndexedElement("Property", out var xProperty, row.FieldAsString(0))
1443
+ && this.DecompilerHelper.TryGetIndexedElement("Property", row.FieldAsString(0), out var xProperty)
1444
&& String.IsNullOrEmpty(xProperty.Attribute("Value")?.Value)
1445
&& xProperty.Attribute("Secure")?.Value != "yes"
1446
&& xProperty.Attribute("SuppressModularization")?.Value != "yes")
@@ -1531,10 +1461,10 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1461
{
1462
foreach (var row in tables["RemoveFile"]?.Rows ?? Enumerable.Empty<Row>())
1463
{
1534
- var xRemove = this.GetIndexedElement(row);
1464
+ var xRemove = this.DecompilerHelper.GetIndexedElement(row);
1465
var property = row.FieldAsString(3);
1466
1537
- if (this.TryGetIndexedElement("Directory", out var _, property))
1467
+ if (this.DecompilerHelper.TryGetIndexedElement("Directory", property, out var _))
1468
{
1469
xRemove.SetAttributeValue("Directory", property);
1470
}
@@ -1562,7 +1492,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1492
{
1493
var id = row.FieldAsString(0);
1494
var table = row.FieldAsString(1);
1565
- var xPermission = this.GetIndexedElement(row);
1495
+ var xPermission = this.DecompilerHelper.GetIndexedElement(row);
1496
1497
if ("CreateFolder" == table)
1498
{
@@ -1580,7 +1510,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1510
}
1511
else
1512
{
1583
- if (this.TryGetIndexedElement(table, out var xParent, id))
1513
+ if (this.DecompilerHelper.TryGetIndexedElement(table, id, out var xParent))
1514
{
1515
xParent.Add(xPermission);
1516
}
@@ -1651,12 +1581,12 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1581
{
1582
var appSearches = IndexTable(tables["AppSearch"], keyColumn: 1, dataColumn: 0);
1583
var ccpSearches = IndexTable(tables["CCPSearch"], keyColumn: 0, dataColumn: null);
1654
- var drLocators = tables["DrLocator"]?.Rows.ToDictionary(row => this.GetIndexedElement(row), row => row);
1584
+ var drLocators = tables["DrLocator"]?.Rows.ToDictionary(row => this.DecompilerHelper.GetIndexedElement(row), row => row);
1585
1586
var xComplianceCheck = new XElement(Names.ComplianceCheckElement);
1587
if (ccpSearches.Keys.Any(ccpSignature => !appSearches.ContainsKey(ccpSignature)))
1588
{
1659
- this.RootElement.Add(xComplianceCheck);
1589
+ this.DecompilerHelper.AddElementToRoot(xComplianceCheck);
1590
}
1591
1592
// index the locator tables by their signatures
@@ -1703,7 +1633,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1633
foreach (var locatorRow in locatorRows)
1634
{
1635
var used = true;
1706
- var xSearch = this.GetIndexedElement(locatorRow);
1636
+ var xSearch = this.DecompilerHelper.GetIndexedElement(locatorRow);
1637
1638
if ("Signature" == locatorRow.TableDefinition.Name && 0 < xSignatureSearches.Count)
1639
{
@@ -1791,7 +1721,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1721
{
1722
if ("DrLocator" == parentLocatorRow.TableDefinition.Name)
1723
{
1794
- var xParentSearch = this.GetIndexedElement(parentLocatorRow);
1724
+ var xParentSearch = this.DecompilerHelper.GetIndexedElement(parentLocatorRow);
1725
1726
if (xParentSearch.HasElements)
1727
{
@@ -1824,7 +1754,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1754
}
1755
else if ("RegLocator" == parentLocatorRow.TableDefinition.Name)
1756
{
1827
- var xParentSearch = this.GetIndexedElement(parentLocatorRow);
1757
+ var xParentSearch = this.DecompilerHelper.GetIndexedElement(parentLocatorRow);
1758
1759
xParentSearch.Add(xSearch);
1760
xUsedSearches.Add(xSearch);
@@ -1982,11 +1912,11 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
1912
1913
foreach (var row in shortcutTable.Rows)
1914
{
1985
- var xShortcut = this.GetIndexedElement(row);
1915
+ var xShortcut = this.DecompilerHelper.GetIndexedElement(row);
1916
1917
var target = row.FieldAsString(4);
1918
1989
- if (this.TryGetIndexedElement("Feature", out var _, target))
1919
+ if (this.DecompilerHelper.TryGetIndexedElement("Feature", target, out var _))
1920
{
1921
xShortcut.SetAttributeValue("Advertise", "yes");
1922
this.SetPrimaryFeature(row, 4, 3);
@@ -2301,7 +2231,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2231
xMajorUpgrade.SetAttributeValue("Schedule", scheduledType);
2232
}
2233
2304
- this.RootElement.Add(xMajorUpgrade);
2234
+ this.DecompilerHelper.AddElementToRoot(xMajorUpgrade);
2235
}
2236
}
2237
}
@@ -2326,7 +2256,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2256
{
2257
if (xExtensions.TryGetValue(row.FieldAsString(0), out var xVerbExtensions))
2258
{
2329
- var xVerb = this.GetIndexedElement(row);
2259
+ var xVerb = this.DecompilerHelper.GetIndexedElement(row);
2260
2261
foreach (var xVerbExtension in xVerbExtensions)
2262
{
@@ -2351,8 +2281,9 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2281
var sourcePath = new StringBuilder();
2282
2283
var component = xFile.Parent;
2284
+ var xDirectory = component.Parent;
2285
2355
- for (var xDirectory = component.Parent; null != xDirectory && xDirectory.Name.LocalName == "Directory"; xDirectory = xDirectory.Parent)
2286
+ while (xDirectory?.Name.LocalName == "Directory")
2287
{
2288
string name;
2289
@@ -2387,6 +2318,14 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2318
sourcePath.Insert(0, Path.DirectorySeparatorChar);
2319
sourcePath.Insert(0, name);
2320
}
2321
+
2322
+ xDirectory = xDirectory.Parent;
2323
+ }
2324
+
2325
+ if (xDirectory?.Name.LocalName == "StandardDirectory" && WindowsInstallerStandard.TryGetStandardDirectory(xDirectory.Attribute("Id").Value, out var standardDirectory))
2326
+ {
2327
+ sourcePath.Insert(0, Path.DirectorySeparatorChar);
2328
+ sourcePath.Insert(0, standardDirectory.Name);
2329
}
2330
2331
return sourcePath.ToString();
@@ -2470,13 +2409,13 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2409
this.ShortNames = false;
2410
2411
this.Singletons.Clear();
2473
- this.IndexedElements.Clear();
2412
+ //this.IndexedElements.Clear();
2413
this.PatchTargetFiles.Clear();
2414
2415
// set the codepage if its not neutral (0)
2416
if (0 != codepage)
2417
{
2479
- this.RootElement.SetAttributeValue("Codepage", codepage);
2418
+ this.DecompilerHelper.RootElement.SetAttributeValue("Codepage", codepage);
2419
}
2420
2421
if (this.OutputType == OutputType.Module)
@@ -2484,44 +2423,51 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2423
var table = tables["_SummaryInformation"];
2424
var row = table.Rows.SingleOrDefault(r => r.FieldAsInteger(0) == 9);
2425
this.ModularizationGuid = row?.FieldAsString(1);
2487
- this.RootElement.SetAttributeValue("Guid", this.ModularizationGuid);
2426
+ this.DecompilerHelper.RootElement.SetAttributeValue("Guid", this.ModularizationGuid);
2427
+ }
2428
+
2429
+ this.RemoveExtensionDataFromTables(tables);
2430
+
2431
+ foreach (var extension in this.Extensions)
2432
+ {
2433
+ extension.PreDecompileTables(tables);
2434
}
2435
+ }
2436
+
2437
+ private void RemoveExtensionDataFromTables(TableIndexedCollection tables)
2438
+ {
2439
+ var tableDefinitionBySymbolDefinitionName = this.TableDefinitions.Where(t => t.SymbolDefinition != null).ToDictionary(t => t.SymbolDefinition.Name);
2440
2441
// index the rows from the extension libraries
2442
var indexedExtensionTables = new Dictionary<string, HashSet<string>>();
2492
-#if TODO_DECOMPILER_EXTENSIONS
2493
- foreach (var extension in this.Extensions)
2443
+ foreach (var extension in this.ExtensionData)
2444
{
2445
// Get the optional library from the extension with the rows to be removed.
2496
- var library = extension.GetLibraryToRemove(this.tableDefinitions);
2446
+ var library = extension.GetLibrary(this.SymbolDefinitionCreator);
2447
if (library != null)
2448
{
2499
- foreach (var row in library.Sections.SelectMany(s => s.Tables).SelectMany(t => t.Rows))
2449
+ foreach (var symbol in library.Sections.SelectMany(s => s.Symbols))
2450
{
2501
- string primaryKey;
2502
- string tableName;
2503
-
2504
- // the Actions table needs to be handled specially
2505
- if (table.Name == "WixAction")
2451
+ if (this.TryGetPrimaryKeyFromSymbol(tableDefinitionBySymbolDefinitionName, symbol, out var tableName, out var primaryKey))
2452
{
2507
- primaryKey = row.FieldAsString(1);
2508
- tableName = row.FieldAsString(0);
2509
-
2510
- if (this.outputType == OutputType.Module)
2511
- {
2512
- tableName = "Module" + tableName;
2513
- }
2514
- }
2515
- else
2516
- {
2517
- primaryKey = row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter);
2518
- tableName = table.Name;
2519
- }
2520
-
2521
- if (primaryKey != null)
2522
- {
2523
- HashSet<string> indexedExtensionRows;
2524
- if (!indexedExtensionTables.TryGetValue(tableName, out indexedExtensionRows))
2453
+ //// the Actions table needs to be handled specially
2454
+ //if (table.Name == "WixAction")
2455
+ //{
2456
+ // primaryKey = symbol.FieldAsString(1);
2457
+ // tableName = symbol.FieldAsString(0);
2458
+
2459
+ // if (this.outputType == OutputType.Module)
2460
+ // {
2461
+ // tableName = "Module" + tableName;
2462
+ // }
2463
+ //}
2464
+ //else
2465
+ //{
2466
+ // primaryKey = symbol.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter);
2467
+ // tableName = table.Name;
2468
+ //}
2469
+
2470
+ if (!indexedExtensionTables.TryGetValue(tableName, out var indexedExtensionRows))
2471
{
2472
indexedExtensionRows = new HashSet<string>();
2473
indexedExtensionTables.Add(tableName, indexedExtensionRows);
@@ -2532,7 +2478,6 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2478
}
2479
}
2480
}
2535
-#endif
2481
2482
// remove the rows from the extension libraries (to allow full round-tripping)
2483
foreach (var kvp in indexedExtensionTables)
@@ -2540,8 +2485,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2485
var tableName = kvp.Key;
2486
var indexedExtensionRows = kvp.Value;
2487
2543
- var table = tables[tableName];
2544
- if (null != table)
2488
+ if (tables.TryGetTable(tableName, out var table))
2489
{
2490
var originalRows = new RowDictionary<Row>(table);
2491
@@ -2550,7 +2494,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2494
2495
foreach (var row in originalRows.Values)
2496
{
2553
- if (!indexedExtensionRows.Contains(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)))
2497
+ if (!indexedExtensionRows.Contains(row.GetPrimaryKey()))
2498
{
2499
table.Rows.Add(row);
2500
}
@@ -2559,6 +2503,55 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2503
}
2504
}
2505
2506
+ private bool TryGetPrimaryKeyFromSymbol(Dictionary<string, TableDefinition> tableDefinitionBySymbolDefinitionName, IntermediateSymbol symbol, out string tableName, out string primaryKey)
2507
+ {
2508
+ tableName = null;
2509
+ primaryKey = null;
2510
+
2511
+ if (symbol is WixActionSymbol actionSymbol)
2512
+ {
2513
+ tableName = actionSymbol.SequenceTable.WindowsInstallerTableName();
2514
+ primaryKey = actionSymbol.Action;
2515
+ return true;
2516
+ }
2517
+
2518
+ if (!tableDefinitionBySymbolDefinitionName.TryGetValue(symbol.Definition.Name, out var tableDefinition))
2519
+ {
2520
+ return false;
2521
+ }
2522
+
2523
+ tableName = tableDefinition.Name;
2524
+
2525
+ if (tableDefinition.SymbolIdIsPrimaryKey)
2526
+ {
2527
+ primaryKey = symbol.Id.Id;
2528
+ }
2529
+ else
2530
+ {
2531
+ var sb = new StringBuilder();
2532
+
2533
+ for (var i = 0; i < symbol.Fields.Length && i < tableDefinition.Columns.Length; ++i)
2534
+ {
2535
+ var column = tableDefinition.Columns[i];
2536
+ var field = symbol.Fields[i];
2537
+
2538
+ if (column.PrimaryKey)
2539
+ {
2540
+ if (sb.Length > 0)
2541
+ {
2542
+ sb.Append('/');
2543
+ }
2544
+
2545
+ sb.Append(field.AsString());
2546
+ }
2547
+ }
2548
+
2549
+ primaryKey = sb.ToString();
2550
+ }
2551
+
2552
+ return true;
2553
+ }
2554
+
2555
/// <summary>
2556
/// Decompile the tables.
2557
/// </summary>
@@ -2581,7 +2574,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2574
// empty tables may be kept with EnsureTable if the user set the proper option
2575
if (0 == table.Rows.Count && this.SuppressDroppingEmptyTables)
2576
{
2584
- this.RootElement.Add(new XElement(Names.EnsureTableElement, new XAttribute("Id", table.Name)));
2577
+ this.DecompilerHelper.AddElementToRoot(new XElement(Names.EnsureTableElement, new XAttribute("Id", table.Name)));
2578
}
2579
2580
switch (table.Name)
@@ -2901,14 +2894,11 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
2894
break;
2895
2896
default:
2904
-#if TODO_DECOMPILER_EXTENSIONS
2905
- if (this.ExtensionsByTableName.TryGetValue(table.Name, out var extension)
2906
- {
2907
- extension.DecompileTable(table);
2908
- }
2909
- else
2910
-#endif
2911
- if (!this.SuppressCustomTables)
2897
+ if (this.ExtensionsByTableName.TryGetValue(table.Name, out var extension))
2898
+ {
2899
+ extension.TryDecompileTable(table);
2900
+ }
2901
+ else if (!this.SuppressCustomTables)
2902
{
2903
this.DecompileCustomTable(table);
2904
}
@@ -3039,7 +3029,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3029
break;
3030
case 3:
3031
{
3042
- var productName = this.RootElement.Attribute("Name")?.Value;
3032
+ var productName = this.DecompilerHelper.RootElement.Attribute("Name")?.Value;
3033
if (value != productName)
3034
{
3035
xSummaryInformation.SetAttributeValue("Description", value);
@@ -3048,7 +3038,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3038
}
3039
case 4:
3040
{
3051
- var productManufacturer = this.RootElement.Attribute("Manufacturer")?.Value;
3041
+ var productManufacturer = this.DecompilerHelper.RootElement.Attribute("Manufacturer")?.Value;
3042
if (value != productManufacturer)
3043
{
3044
xSummaryInformation.SetAttributeValue("Manufacturer", value);
@@ -3065,7 +3055,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3055
var template = value.Split(';');
3056
if (0 < template.Length && 0 < template[template.Length - 1].Length)
3057
{
3068
- this.RootElement.SetAttributeValue("Language", template[template.Length - 1]);
3058
+ this.DecompilerHelper.RootElement.SetAttributeValue("Language", template[template.Length - 1]);
3059
}
3060
break;
3061
case 14:
@@ -3073,7 +3063,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3063
// Default InstallerVersion.
3064
if (installerVersion != 500)
3065
{
3076
- this.RootElement.SetAttributeValue("InstallerVersion", installerVersion);
3066
+ this.DecompilerHelper.RootElement.SetAttributeValue("InstallerVersion", installerVersion);
3067
}
3068
break;
3069
case 15:
@@ -3083,29 +3073,24 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3073
this.ShortNames = true;
3074
if (OutputType.Product == this.OutputType)
3075
{
3086
- this.RootElement.SetAttributeValue("ShortNames", "yes");
3076
+ this.DecompilerHelper.RootElement.SetAttributeValue("ShortNames", "yes");
3077
}
3078
}
3079
3080
if (0x2 == (wordCount & 0x2))
3081
{
3082
this.Compressed = true;
3093
-
3094
- if (OutputType.Product == this.OutputType)
3095
- {
3096
- this.RootElement.SetAttributeValue("Compressed", "yes");
3097
- }
3083
}
3084
3085
if (OutputType.Product == this.OutputType)
3086
{
3087
if (0x8 == (wordCount & 0x8))
3088
{
3104
- this.RootElement.SetAttributeValue("Scope", "perUser");
3089
+ this.DecompilerHelper.RootElement.SetAttributeValue("Scope", "perUser");
3090
}
3091
else
3092
{
3108
- var xAllUsers = this.RootElement.Elements(Names.PropertyElement).SingleOrDefault(p => p.Attribute("Id")?.Value == "ALLUSERS");
3093
+ var xAllUsers = this.DecompilerHelper.RootElement.Elements(Names.PropertyElement).SingleOrDefault(p => p.Attribute("Id")?.Value == "ALLUSERS");
3094
if (xAllUsers?.Attribute("Value")?.Value == "1")
3095
{
3096
xAllUsers?.Remove();
@@ -3118,9 +3103,14 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3103
}
3104
}
3105
3106
+ if (OutputType.Product == this.OutputType && !this.Compressed)
3107
+ {
3108
+ this.DecompilerHelper.RootElement.SetAttributeValue("Compressed", "no");
3109
+ }
3110
+
3111
if (xSummaryInformation.HasAttributes)
3112
{
3123
- this.RootElement.Add(xSummaryInformation);
3113
+ this.DecompilerHelper.AddElementToRoot(xSummaryInformation);
3114
}
3115
}
3116
else
@@ -3173,7 +3163,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3163
}
3164
}
3165
3176
- this.RootElement.Add(xPatchInformation);
3166
+ this.DecompilerHelper.AddElementToRoot(xPatchInformation);
3167
}
3168
}
3169
@@ -3212,8 +3202,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3202
row.IsColumnNull(5) || row.FieldAsInteger(5) != 1 ? null : new XAttribute("ActivateAtStorage", "yes"),
3203
row.IsColumnNull(6) || row.FieldAsInteger(6) != 1 ? null : new XAttribute("RunAsInteractiveUser", "yes"));
3204
3215
- this.RootElement.Add(appId);
3216
- this.IndexElement(row, appId);
3205
+ this.DecompilerHelper.AddElementToRoot(appId);
3206
+ this.DecompilerHelper.IndexElement(row, appId);
3207
}
3208
}
3209
@@ -3239,7 +3229,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3229
SetControlAttributes(bbControlRow.Attributes, xControl);
3230
}
3231
3242
- if (this.TryGetIndexedElement("Billboard", out var xBillboard, bbControlRow.Billboard))
3232
+ if (this.DecompilerHelper.TryGetIndexedElement("Billboard", bbControlRow.Billboard, out var xBillboard))
3233
{
3234
xBillboard.Add(xControl);
3235
}
@@ -3264,7 +3254,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3254
new XAttribute("Id", row.FieldAsString(0)),
3255
new XAttribute("Feature", row.FieldAsString(1)));
3256
3267
- this.IndexElement(row, xBillboard);
3257
+ this.DecompilerHelper.IndexElement(row, xBillboard);
3258
billboards.Add(String.Format(CultureInfo.InvariantCulture, "{0}|{1:0000000000}", row[0], row[3]), row);
3259
}
3260
@@ -3272,7 +3262,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3262
3263
foreach (var row in billboards.Values)
3264
{
3275
- var xBillboard = this.GetIndexedElement(row);
3265
+ var xBillboard = this.DecompilerHelper.GetIndexedElement(row);
3266
3267
if (!billboardActions.TryGetValue(row.FieldAsString(2), out var xBillboardAction))
3268
{
@@ -3299,7 +3289,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3289
new XAttribute("Id", row.FieldAsString(0)),
3290
new XAttribute("SourceFile", row.FieldAsString(1)));
3291
3302
- this.RootElement.Add(xBinary);
3292
+ this.DecompilerHelper.AddElementToRoot(xBinary);
3293
}
3294
}
3295
@@ -3311,7 +3301,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3301
{
3302
foreach (var row in table.Rows)
3303
{
3314
- if (this.TryGetIndexedElement("File", out var xFile, row.FieldAsString(0)))
3304
+ if (this.DecompilerHelper.TryGetIndexedElement("File", row.FieldAsString(0), out var xFile))
3305
{
3306
xFile.SetAttributeValue("BindPath", row.FieldAsString(1));
3307
}
@@ -3389,7 +3379,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3379
}
3380
3381
this.AddChildToParent("Component", xClass, row, 2);
3392
- this.IndexElement(row, xClass);
3382
+ this.DecompilerHelper.IndexElement(row, xClass);
3383
}
3384
}
3385
@@ -3656,7 +3646,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3646
}
3647
}
3648
3659
- this.IndexElement(controlRow, xControl);
3649
+ this.DecompilerHelper.IndexElement(controlRow, xControl);
3650
}
3651
}
3652
@@ -3668,7 +3658,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3658
{
3659
foreach (var row in table.Rows)
3660
{
3671
- if (this.TryGetIndexedElement("Control", out var xControl, row.FieldAsString(0), row.FieldAsString(1)))
3661
+ if (this.DecompilerHelper.TryGetIndexedElement("Control", row.FieldAsString(0), row.FieldAsString(1), out var xControl))
3662
{
3663
switch (row.FieldAsString(2))
3664
{
@@ -3730,14 +3720,14 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3720
3721
controlEvents.Add(String.Format(CultureInfo.InvariantCulture, "{0}|{1}|{2:0000000000}|{3}|{4}|{5}", row.FieldAsString(0), row.FieldAsString(1), row.FieldAsNullableInteger(5) ?? 0, row.FieldAsString(2), row.FieldAsString(3), row.FieldAsString(4)), row);
3722
3733
- this.IndexElement(row, xPublish);
3723
+ this.DecompilerHelper.IndexElement(row, xPublish);
3724
}
3725
3726
foreach (var row in controlEvents.Values)
3727
{
3738
- if (this.TryGetIndexedElement("Control", out var xControl, row.FieldAsString(0), row.FieldAsString(1)))
3728
+ if (this.DecompilerHelper.TryGetIndexedElement("Control", row.FieldAsString(0), row.FieldAsString(1), out var xControl))
3729
{
3740
- var xPublish = this.GetIndexedElement(row);
3730
+ var xPublish = this.DecompilerHelper.GetIndexedElement(row);
3731
xControl.Add(xPublish);
3732
}
3733
else
@@ -3928,7 +3918,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3918
xCustomTable.Add(xRow);
3919
}
3920
3931
- this.RootElement.Add(xCustomTable);
3921
+ this.DecompilerHelper.AddElementToRoot(xCustomTable);
3922
}
3923
}
3924
@@ -3944,7 +3934,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
3934
new XAttribute("Directory", row.FieldAsString(0)));
3935
3936
this.AddChildToParent("Component", xCreateFolder, row, 1);
3947
- this.IndexElement(row, xCreateFolder);
3937
+ this.DecompilerHelper.IndexElement(row, xCreateFolder);
3938
}
3939
}
3940
@@ -4115,8 +4105,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4105
xCustomAction.SetAttributeValue("PatchUninstall", "yes");
4106
}
4107
4118
- this.RootElement.Add(xCustomAction);
4119
- this.IndexElement(row, xCustomAction);
4108
+ this.DecompilerHelper.AddElementToRoot(xCustomAction);
4109
+ this.DecompilerHelper.IndexElement(row, xCustomAction);
4110
}
4111
}
4112
@@ -4148,7 +4138,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4138
}
4139
}
4140
4151
- this.IndexElement(row, xComponentSearch);
4141
+ this.DecompilerHelper.IndexElement(row, xComponentSearch);
4142
}
4143
}
4144
@@ -4162,7 +4152,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4152
{
4153
if (!row.IsColumnNull(1))
4154
{
4165
- if (this.TryGetIndexedElement("Component", out var xComponent, row.FieldAsString(0)))
4155
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", row.FieldAsString(0), out var xComponent))
4156
{
4157
xComponent.SetAttributeValue("ComPlusFlags", row.FieldAsInteger(1));
4158
}
@@ -4247,7 +4237,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4237
}
4238
4239
this.AddChildToParent("Directory", xComponent, row, 2);
4250
- this.IndexElement(row, xComponent);
4240
+ this.DecompilerHelper.IndexElement(row, xComponent);
4241
}
4242
}
4243
@@ -4259,7 +4249,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4249
{
4250
foreach (var row in table.Rows)
4251
{
4262
- if (this.TryGetIndexedElement("Feature", out var xFeature, row.FieldAsString(0)))
4252
+ if (this.DecompilerHelper.TryGetIndexedElement("Feature", row.FieldAsString(0), out var xFeature))
4253
{
4254
var xLevel = new XElement(Names.LevelElement,
4255
row.IsColumnNull(2) ? null : new XAttribute("Condition", row.FieldAsString(2)),
@@ -4303,7 +4293,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4293
!row.IsColumnNull(6) ? new XAttribute("Title", row.FieldAsString(6)) : null);
4294
4295
this.UIElement.Add(xDialog);
4306
- this.IndexElement(row, xDialog);
4296
+ this.DecompilerHelper.IndexElement(row, xDialog);
4297
}
4298
}
4299
@@ -4367,13 +4357,13 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4357
}
4358
}
4359
4370
- this.IndexElement(row, xDirectory);
4360
+ this.DecompilerHelper.IndexElement(row, xDirectory);
4361
}
4362
4363
// nest the directories
4364
foreach (var row in table.Rows)
4365
{
4376
- var xDirectory = this.GetIndexedElement(row);
4366
+ var xDirectory = this.DecompilerHelper.GetIndexedElement(row);
4367
4368
var id = row.FieldAsString(0);
4369
@@ -4383,26 +4373,26 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4373
}
4374
else if (row.IsColumnNull(1) || WindowsInstallerStandard.IsStandardDirectory(id))
4375
{
4386
- this.RootElement.Add(xDirectory);
4376
+ this.DecompilerHelper.AddElementToRoot(xDirectory);
4377
}
4378
else
4379
{
4380
var parentDirectoryId = row.FieldAsString(1);
4381
4392
- if (!this.TryGetIndexedElement("Directory", out var xParentDirectory, parentDirectoryId))
4382
+ if (!this.DecompilerHelper.TryGetIndexedElement("Directory", parentDirectoryId, out var xParentDirectory))
4383
{
4384
this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Directory_Parent", row.FieldAsString(1), "Directory"));
4385
}
4386
else if (xParentDirectory == xDirectory) // another way to specify a root directory
4387
{
4398
- this.RootElement.Add(xDirectory);
4388
+ this.DecompilerHelper.AddElementToRoot(xDirectory);
4389
}
4390
else
4391
{
4392
// TARGETDIR is omitted but if this directory is a first-generation descendant, add it as a root.
4393
if (parentDirectoryId == "TARGETDIR")
4394
{
4405
- this.RootElement.Add(xDirectory);
4395
+ this.DecompilerHelper.AddElementToRoot(xDirectory);
4396
}
4397
else
4398
{
@@ -4426,7 +4416,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4416
XAttributeIfNotNull("Path", row, 2),
4417
XAttributeIfNotNull("Depth", row, 3));
4418
4429
- this.IndexElement(row, xDirectorySearch);
4419
+ this.DecompilerHelper.IndexElement(row, xDirectorySearch);
4420
}
4421
}
4422
@@ -4459,7 +4449,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4449
// destination directory/property is set in FinalizeDuplicateMoveFileTables
4450
4451
this.AddChildToParent("Component", xCopyFile, row, 1);
4462
- this.IndexElement(row, xCopyFile);
4452
+ this.DecompilerHelper.IndexElement(row, xCopyFile);
4453
}
4454
}
4455
@@ -4570,7 +4560,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4560
new XAttribute("Event", row.FieldAsString(2)),
4561
new XAttribute("Attribute", row.FieldAsString(3)));
4562
4573
- if (this.TryGetIndexedElement("Control", out var xControl, row.FieldAsString(0), row.FieldAsString(1)))
4563
+ if (this.DecompilerHelper.TryGetIndexedElement("Control", row.FieldAsString(0), row.FieldAsString(1), out var xControl))
4564
{
4565
xControl.Add(xSubscribe);
4566
}
@@ -4595,7 +4585,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4585
4586
if (!row.IsColumnNull(3))
4587
{
4598
- if (this.TryGetIndexedElement("MIME", out var xMime, row.FieldAsString(3)))
4588
+ if (this.DecompilerHelper.TryGetIndexedElement("MIME", row.FieldAsString(3), out var xMime))
4589
{
4590
xMime.SetAttributeValue("Default", "yes");
4591
}
@@ -4614,7 +4604,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4604
this.AddChildToParent("Component", xExtension, row, 1);
4605
}
4606
4617
- this.IndexElement(row, xExtension);
4607
+ this.DecompilerHelper.IndexElement(row, xExtension);
4608
}
4609
}
4610
@@ -4682,7 +4672,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4672
}
4673
4674
this.AddChildToParent("ImageFamilies", xExternalFile, row, 0);
4685
- this.IndexElement(row, xExternalFile);
4675
+ this.DecompilerHelper.IndexElement(row, xExternalFile);
4676
}
4677
}
4678
@@ -4761,7 +4751,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4751
feature.SetAttributeValue("Absent", "disallow");
4752
}
4753
4764
- this.IndexElement(row, feature);
4754
+ this.DecompilerHelper.IndexElement(row, feature);
4755
4756
// sort the features by their display column (and append the identifier to ensure unique keys)
4757
sortedFeatures.Add(String.Format(CultureInfo.InvariantCulture, "{0:00000}|{1}", row.FieldAsInteger(4), row[0]), row);
@@ -4770,15 +4760,15 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4760
// nest the features
4761
foreach (var row in sortedFeatures.Values)
4762
{
4773
- var xFeature = this.GetIndexedElement("Feature", row.FieldAsString(0));
4763
+ var xFeature = this.DecompilerHelper.GetIndexedElement("Feature", row.FieldAsString(0));
4764
4765
if (row.IsColumnNull(1))
4766
{
4777
- this.RootElement.Add(xFeature);
4767
+ this.DecompilerHelper.AddElementToRoot(xFeature);
4768
}
4769
else
4770
{
4781
- if (this.TryGetIndexedElement("Feature", out var xParentFeature, row.FieldAsString(1)))
4771
+ if (this.DecompilerHelper.TryGetIndexedElement("Feature", row.FieldAsString(1), out var xParentFeature))
4772
{
4773
if (xParentFeature == xFeature)
4774
{
@@ -4809,7 +4799,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4799
new XAttribute("Id", row.FieldAsString(1)));
4800
4801
this.AddChildToParent("Feature", xComponentRef, row, 0);
4812
- this.IndexElement(row, xComponentRef);
4802
+ this.DecompilerHelper.IndexElement(row, xComponentRef);
4803
}
4804
}
4805
@@ -4855,7 +4845,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4845
xFile.SetAttributeValue("Compressed", "yes");
4846
}
4847
4858
- this.IndexElement(fileRow, xFile);
4848
+ this.DecompilerHelper.IndexElement(fileRow, xFile);
4849
}
4850
}
4851
@@ -4882,7 +4872,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4872
{
4873
foreach (var row in table.Rows)
4874
{
4885
- if (this.TryGetIndexedElement("File", out var xFile, row.FieldAsString(0)))
4875
+ if (this.DecompilerHelper.TryGetIndexedElement("File", row.FieldAsString(0), out var xFile))
4876
{
4877
if (!row.IsColumnNull(1))
4878
{
@@ -4912,7 +4902,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4902
new XAttribute("Id", row.FieldAsString(0)),
4903
new XAttribute("SourceFile", row.FieldAsString(1)));
4904
4915
- this.RootElement.Add(icon);
4905
+ this.DecompilerHelper.AddElementToRoot(icon);
4906
}
4907
}
4908
@@ -4932,8 +4922,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
4922
row.IsColumnNull(4) ? null : new XAttribute("DiskPrompt", row.FieldAsString(4)),
4923
row.IsColumnNull(5) ? null : new XAttribute("VolumeLabel", row.FieldAsString(5)));
4924
4935
- this.RootElement.Add(family);
4936
- this.IndexElement(row, family);
4925
+ this.DecompilerHelper.AddElementToRoot(family);
4926
+ this.DecompilerHelper.IndexElement(row, family);
4927
}
4928
}
4929
@@ -5035,7 +5025,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5025
}
5026
}
5027
5038
- this.IndexElement(row, xIniFileSearch);
5028
+ this.DecompilerHelper.IndexElement(row, xIniFileSearch);
5029
}
5030
}
5031
@@ -5071,7 +5061,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5061
new XAttribute("Condition", row.FieldAsString(0)),
5062
new XAttribute("Message", row.FieldAsString(1)));
5063
5074
- this.RootElement.Add(condition);
5064
+ this.DecompilerHelper.AddElementToRoot(condition);
5065
}
5066
}
5067
@@ -5230,7 +5220,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5220
}
5221
}
5222
5233
- this.IndexElement(row, xPermission);
5223
+ this.DecompilerHelper.IndexElement(row, xPermission);
5224
}
5225
}
5226
@@ -5260,8 +5250,8 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5250
xMedia.SetAttributeValue("Cabinet", cabinet);
5251
}
5252
5263
- this.RootElement.Add(xMedia);
5264
- this.IndexElement(mediaRow, xMedia);
5253
+ this.DecompilerHelper.AddElementToRoot(xMedia);
5254
+ this.DecompilerHelper.IndexElement(mediaRow, xMedia);
5255
}
5256
}
5257
@@ -5277,7 +5267,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5267
new XAttribute("ContentType", row.FieldAsString(0)),
5268
row.IsColumnNull(2) ? null : new XAttribute("Class", row.FieldAsString(2)));
5269
5280
- this.IndexElement(row, mime);
5270
+ this.DecompilerHelper.IndexElement(row, mime);
5271
}
5272
}
5273
@@ -5338,7 +5328,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5328
}
5329
}
5330
5341
- this.RootElement.Add(configuration);
5331
+ this.DecompilerHelper.AddElementToRoot(configuration);
5332
}
5333
}
5334
@@ -5355,7 +5345,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5345
new XAttribute("RequiredLanguage", row.FieldAsString(3)),
5346
XAttributeIfNotNull("RequiredVersion", row, 4));
5347
5358
- this.RootElement.Add(xDependency);
5348
+ this.DecompilerHelper.AddElementToRoot(xDependency);
5349
}
5350
}
5351
@@ -5382,7 +5372,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5372
xExclusion.SetAttributeValue("ExcludeExceptLanguage", -excludedLanguage);
5373
}
5374
5385
- this.RootElement.Add(xExclusion);
5375
+ this.DecompilerHelper.AddElementToRoot(xExclusion);
5376
}
5377
}
5378
@@ -5402,7 +5392,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5392
var xIgnoreTable = new XElement(Names.IgnoreTableElement,
5393
new XAttribute("Id", tableName));
5394
5405
- this.RootElement.Add(xIgnoreTable);
5395
+ this.DecompilerHelper.AddElementToRoot(xIgnoreTable);
5396
}
5397
}
5398
}
@@ -5417,10 +5407,10 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5407
{
5408
var row = table.Rows[0];
5409
5420
- this.RootElement.SetAttributeValue("Id", row.FieldAsString(0));
5410
+ this.DecompilerHelper.RootElement.SetAttributeValue("Id", row.FieldAsString(0));
5411
// support Language columns that are treated as integers as well as strings (the WiX default, to support localizability)
5422
- this.RootElement.SetAttributeValue("Language", row.FieldAsString(1));
5423
- this.RootElement.SetAttributeValue("Version", row.FieldAsString(2));
5412
+ this.DecompilerHelper.RootElement.SetAttributeValue("Language", row.FieldAsString(1));
5413
+ this.DecompilerHelper.RootElement.SetAttributeValue("Version", row.FieldAsString(2));
5414
}
5415
else
5416
{
@@ -5442,7 +5432,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5432
new XAttribute("Column", row.FieldAsString(2)),
5433
XAttributeIfNotNull("Value", row, 3));
5434
5445
- this.RootElement.Add(xSubstitution);
5435
+ this.DecompilerHelper.AddElementToRoot(xSubstitution);
5436
}
5437
}
5438
@@ -5487,7 +5477,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5477
}
5478
5479
this.AddChildToParent("Component", xCopyFile, row, 1);
5490
- this.IndexElement(row, xCopyFile);
5480
+ this.DecompilerHelper.IndexElement(row, xCopyFile);
5481
}
5482
}
5483
@@ -5503,7 +5493,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5493
new XAttribute("Id", row.FieldAsString(0)),
5494
new XAttribute("SourceFile", row.FieldAsString(1)));
5495
5506
- this.IndexElement(row, xDigitalCertificate);
5496
+ this.DecompilerHelper.IndexElement(row, xDigitalCertificate);
5497
}
5498
}
5499
@@ -5520,7 +5510,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5510
5511
this.AddChildToParent("MsiDigitalCertificate", xDigitalSignature, row, 2);
5512
5523
- if (this.TryGetIndexedElement(row.FieldAsString(0), out var xParentElement, row.FieldAsString(1)))
5513
+ if (this.DecompilerHelper.TryGetIndexedElement(row.FieldAsString(0), row.FieldAsString(1), out var xParentElement))
5514
{
5515
xParentElement.Add(xDigitalSignature);
5516
}
@@ -5560,7 +5550,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5550
break;
5551
}
5552
5563
- this.RootElement.Add(xEmbeddedChainer);
5553
+ this.DecompilerHelper.AddElementToRoot(xEmbeddedChainer);
5554
}
5555
}
5556
@@ -5735,7 +5725,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5725
return;
5726
}
5727
5738
- this.IndexElement(row, xPermissionEx);
5728
+ this.DecompilerHelper.IndexElement(row, xPermissionEx);
5729
}
5730
}
5731
@@ -5748,7 +5738,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5738
if (0 < table.Rows.Count)
5739
{
5740
var xPackageCertificates = new XElement(Names.PatchCertificatesElement);
5751
- this.RootElement.Add(xPackageCertificates);
5741
+ this.DecompilerHelper.AddElementToRoot(xPackageCertificates);
5742
this.AddCertificates(table, xPackageCertificates);
5743
}
5744
}
@@ -5762,7 +5752,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5752
if (0 < table.Rows.Count)
5753
{
5754
var xPatchCertificates = new XElement(Names.PatchCertificatesElement);
5765
- this.RootElement.Add(xPatchCertificates);
5755
+ this.DecompilerHelper.AddElementToRoot(xPatchCertificates);
5756
this.AddCertificates(table, xPatchCertificates);
5757
}
5758
}
@@ -5776,7 +5766,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5766
{
5767
foreach (var row in table.Rows)
5768
{
5779
- if (this.TryGetIndexedElement("MsiDigitalCertificate", out var xDigitalCertificate, row.FieldAsString(1)))
5769
+ if (this.DecompilerHelper.TryGetIndexedElement("MsiDigitalCertificate", row.FieldAsString(1), out var xDigitalCertificate))
5770
{
5771
parent.Add(xDigitalCertificate);
5772
}
@@ -5846,7 +5836,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5836
break;
5837
}
5838
5849
- this.IndexElement(row, xOdbcDataSource);
5839
+ this.DecompilerHelper.IndexElement(row, xOdbcDataSource);
5840
}
5841
}
5842
@@ -5865,7 +5855,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
5855
XAttributeIfNotNull("SetupFile", row, 4));
5856
5857
this.AddChildToParent("Component", xOdbcDriver, row, 1);
5868
- this.IndexElement(row, xOdbcDriver);
5858
+ this.DecompilerHelper.IndexElement(row, xOdbcDriver);
5859
}
5860
}
5861
@@ -6010,7 +6000,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6000
}
6001
}
6002
6013
- this.RootElement.Add(xPatchMetadata);
6003
+ this.DecompilerHelper.AddElementToRoot(xPatchMetadata);
6004
}
6005
}
6006
@@ -6049,7 +6039,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6039
patchSequence.SetAttributeValue("Supersede", "yes");
6040
}
6041
6052
- this.RootElement.Add(patchSequence);
6042
+ this.DecompilerHelper.AddElementToRoot(patchSequence);
6043
}
6044
}
6045
@@ -6068,13 +6058,13 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6058
XAttributeIfNotNull("Icon", row, 4),
6059
XAttributeIfNotNull("IconIndex", row, 5));
6060
6071
- this.IndexElement(row, xProgId);
6061
+ this.DecompilerHelper.IndexElement(row, xProgId);
6062
}
6063
6064
// nest the ProgIds
6065
foreach (var row in table.Rows)
6066
{
6077
- var xProgId = this.GetIndexedElement(row);
6067
+ var xProgId = this.DecompilerHelper.GetIndexedElement(row);
6068
6069
if (!row.IsColumnNull(1))
6070
{
@@ -6107,13 +6097,13 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6097
case "AllowProductCodeMismatches":
6098
if ("1" == value)
6099
{
6110
- this.RootElement.SetAttributeValue("AllowProductCodeMismatches", "yes");
6100
+ this.DecompilerHelper.RootElement.SetAttributeValue("AllowProductCodeMismatches", "yes");
6101
}
6102
break;
6103
case "AllowProductVersionMajorMismatches":
6104
if ("1" == value)
6105
{
6116
- this.RootElement.SetAttributeValue("AllowMajorVersionMismatches", "yes");
6106
+ this.DecompilerHelper.RootElement.SetAttributeValue("AllowMajorVersionMismatches", "yes");
6107
}
6108
break;
6109
case "ApiPatchingSymbolFlags":
@@ -6127,7 +6117,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6117
value = value.Substring(2);
6118
}
6119
6130
- this.RootElement.SetAttributeValue("SymbolFlags", Convert.ToInt32(value, 16));
6120
+ this.DecompilerHelper.RootElement.SetAttributeValue("SymbolFlags", Convert.ToInt32(value, 16));
6121
}
6122
catch
6123
{
@@ -6138,13 +6128,13 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6128
case "DontRemoveTempFolderWhenFinished":
6129
if ("1" == value)
6130
{
6141
- this.RootElement.SetAttributeValue("CleanWorkingFolder", "no");
6131
+ this.DecompilerHelper.RootElement.SetAttributeValue("CleanWorkingFolder", "no");
6132
}
6133
break;
6134
case "IncludeWholeFilesOnly":
6135
if ("1" == value)
6136
{
6147
- this.RootElement.SetAttributeValue("WholeFilesOnly", "yes");
6137
+ this.DecompilerHelper.RootElement.SetAttributeValue("WholeFilesOnly", "yes");
6138
}
6139
break;
6140
case "ListOfPatchGUIDsToReplace":
@@ -6158,7 +6148,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6148
var xReplacePatch = new XElement(Names.ReplacePatchElement,
6149
new XAttribute("Id", guidMatch.Value));
6150
6161
- this.RootElement.Add(xReplacePatch);
6151
+ this.DecompilerHelper.AddElementToRoot(xReplacePatch);
6152
}
6153
}
6154
break;
@@ -6172,25 +6162,25 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6162
var xTargetProductCode = new XElement(Names.TargetProductCodeElement,
6163
new XAttribute("Id", targetProductCodeString));
6164
6175
- this.RootElement.Add(xTargetProductCode);
6165
+ this.DecompilerHelper.AddElementToRoot(xTargetProductCode);
6166
}
6167
}
6168
break;
6169
case "PatchGUID":
6180
- this.RootElement.SetAttributeValue("Id", value);
6170
+ this.DecompilerHelper.RootElement.SetAttributeValue("Id", value);
6171
break;
6172
case "PatchSourceList":
6183
- this.RootElement.SetAttributeValue("SourceList", value);
6173
+ this.DecompilerHelper.RootElement.SetAttributeValue("SourceList", value);
6174
break;
6175
case "PatchOutputPath":
6186
- this.RootElement.SetAttributeValue("OutputPath", value);
6176
+ this.DecompilerHelper.RootElement.SetAttributeValue("OutputPath", value);
6177
break;
6178
default:
6179
var patchProperty = new XElement(Names.PatchPropertyElement,
6180
new XAttribute("Name", name),
6181
new XAttribute("Value", value));
6182
6193
- this.RootElement.Add(patchProperty);
6183
+ this.DecompilerHelper.AddElementToRoot(patchProperty);
6184
break;
6185
}
6186
}
@@ -6260,22 +6250,22 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6250
switch (id)
6251
{
6252
case "Manufacturer":
6263
- this.RootElement.SetAttributeValue("Manufacturer", value);
6253
+ this.DecompilerHelper.RootElement.SetAttributeValue("Manufacturer", value);
6254
continue;
6255
case "ProductCode":
6266
- this.RootElement.SetAttributeValue("ProductCode", value.ToUpper(CultureInfo.InvariantCulture));
6256
+ this.DecompilerHelper.RootElement.SetAttributeValue("ProductCode", value.ToUpper(CultureInfo.InvariantCulture));
6257
continue;
6258
case "ProductLanguage":
6269
- this.RootElement.SetAttributeValue("Language", value);
6259
+ this.DecompilerHelper.RootElement.SetAttributeValue("Language", value);
6260
continue;
6261
case "ProductName":
6272
- this.RootElement.SetAttributeValue("Name", value);
6262
+ this.DecompilerHelper.RootElement.SetAttributeValue("Name", value);
6263
continue;
6264
case "ProductVersion":
6275
- this.RootElement.SetAttributeValue("Version", value);
6265
+ this.DecompilerHelper.RootElement.SetAttributeValue("Version", value);
6266
continue;
6267
case "UpgradeCode":
6278
- this.RootElement.SetAttributeValue("UpgradeCode", value);
6268
+ this.DecompilerHelper.RootElement.SetAttributeValue("UpgradeCode", value);
6269
continue;
6270
}
6271
}
@@ -6340,14 +6330,14 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6330
}
6331
}
6332
6343
- this.IndexElement(row, radioButton);
6333
+ this.DecompilerHelper.IndexElement(row, radioButton);
6334
}
6335
6336
// nest the radio buttons
6337
var xRadioButtonGroups = new Dictionary<string, XElement>();
6338
foreach (var row in table.Rows.OrderBy(row => row.FieldAsString(0)).ThenBy(row => row.FieldAsInteger(1)))
6339
{
6350
- var xRadioButton = this.GetIndexedElement(row);
6340
+ var xRadioButton = this.DecompilerHelper.GetIndexedElement(row);
6341
6342
if (!xRadioButtonGroups.TryGetValue(row.FieldAsString(0), out var xRadioButtonGroup))
6343
{
@@ -6395,7 +6385,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6385
break;
6386
}
6387
6398
- this.IndexElement(row, xRegistryKey);
6388
+ this.DecompilerHelper.IndexElement(row, xRegistryKey);
6389
}
6390
else
6391
{
@@ -6480,7 +6470,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6470
xRegistryValue.SetAttributeValue("Value", String.Empty);
6471
}
6472
6483
- this.IndexElement(row, xRegistryValue);
6473
+ this.DecompilerHelper.IndexElement(row, xRegistryValue);
6474
}
6475
}
6476
}
@@ -6552,7 +6542,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6542
}
6543
}
6544
6555
- this.IndexElement(row, xRegistrySearch);
6545
+ this.DecompilerHelper.IndexElement(row, xRegistrySearch);
6546
}
6547
}
6548
@@ -6588,7 +6578,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6578
}
6579
6580
this.AddChildToParent("Component", xRemoveFolder, row, 1);
6591
- this.IndexElement(row, xRemoveFolder);
6581
+ this.DecompilerHelper.IndexElement(row, xRemoveFolder);
6582
}
6583
else
6584
{
@@ -6625,7 +6615,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6615
}
6616
6617
this.AddChildToParent("Component", xRemoveFile, row, 1);
6628
- this.IndexElement(row, xRemoveFile);
6618
+ this.DecompilerHelper.IndexElement(row, xRemoveFile);
6619
}
6620
}
6621
}
@@ -6738,7 +6728,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6728
{
6729
foreach (var row in table.Rows)
6730
{
6741
- if (this.TryGetIndexedElement("File", out var xFile, row.FieldAsString(0)))
6731
+ if (this.DecompilerHelper.TryGetIndexedElement("File", row.FieldAsString(0), out var xFile))
6732
{
6733
xFile.SetAttributeValue("SelfRegCost", row.IsColumnNull(1) ? 0 : row.FieldAsInteger(1));
6734
}
@@ -6927,7 +6917,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6917
}
6918
6919
this.AddChildToParent("Component", xServiceInstall, row, 11);
6930
- this.IndexElement(row, xServiceInstall);
6920
+ this.DecompilerHelper.IndexElement(row, xServiceInstall);
6921
}
6922
}
6923
@@ -6943,17 +6933,17 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6933
new XAttribute("Name", row.FieldAsString(0)),
6934
new XAttribute("SourceFile", row.FieldAsString(1)));
6935
6946
- this.IndexElement(row, xSfpCatalog);
6936
+ this.DecompilerHelper.IndexElement(row, xSfpCatalog);
6937
}
6938
6939
// nest the SFPCatalog elements
6940
foreach (var row in table.Rows)
6941
{
6952
- var xSfpCatalog = this.GetIndexedElement(row);
6942
+ var xSfpCatalog = this.DecompilerHelper.GetIndexedElement(row);
6943
6944
if (!row.IsColumnNull(2))
6945
{
6956
- if (this.TryGetIndexedElement("SFPCatalog", out var xParentSFPCatalog, row.FieldAsString(2)))
6946
+ if (this.DecompilerHelper.TryGetIndexedElement("SFPCatalog", row.FieldAsString(2), out var xParentSFPCatalog))
6947
{
6948
xParentSFPCatalog.Add(xSfpCatalog);
6949
}
@@ -6961,12 +6951,12 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
6951
{
6952
xSfpCatalog.SetAttributeValue("Dependency", row.FieldAsString(2));
6953
6964
- this.RootElement.Add(xSfpCatalog);
6954
+ this.DecompilerHelper.AddElementToRoot(xSfpCatalog);
6955
}
6956
}
6957
else
6958
{
6969
- this.RootElement.Add(xSfpCatalog);
6959
+ this.DecompilerHelper.AddElementToRoot(xSfpCatalog);
6960
}
6961
}
6962
}
@@ -7044,7 +7034,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7034
}
7035
7036
this.AddChildToParent("Component", xShortcut, row, 3);
7047
- this.IndexElement(row, xShortcut);
7037
+ this.DecompilerHelper.IndexElement(row, xShortcut);
7038
}
7039
}
7040
@@ -7093,7 +7083,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7083
fileSearch.SetAttributeValue("MaxDate", ConvertIntegerToDateTime(row.FieldAsInteger(7)));
7084
}
7085
7096
- this.IndexElement(row, fileSearch);
7086
+ this.DecompilerHelper.IndexElement(row, fileSearch);
7087
}
7088
}
7089
@@ -7110,7 +7100,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7100
xPatchTargetFile = new XElement(Names.TargetFileElement,
7101
new XAttribute("Id", row.FieldAsString(1)));
7102
7113
- if (this.TryGetIndexedElement("TargetImages", out var xTargetImage, row.FieldAsString(0)))
7103
+ if (this.DecompilerHelper.TryGetIndexedElement("TargetImages", row.FieldAsString(0), out var xTargetImage))
7104
{
7105
xTargetImage.Add(xPatchTargetFile);
7106
}
@@ -7192,7 +7182,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7182
}
7183
7184
this.AddChildToParent("UpgradedImages", xTargetImage, row, 3);
7195
- this.IndexElement(row, xTargetImage);
7185
+ this.DecompilerHelper.IndexElement(row, xTargetImage);
7186
}
7187
}
7188
@@ -7282,7 +7272,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7272
}
7273
7274
// nested under the appropriate File element in FinalizeFileTable
7285
- this.IndexElement(row, xTypeLib);
7275
+ this.DecompilerHelper.IndexElement(row, xTypeLib);
7276
}
7277
}
7278
@@ -7306,7 +7296,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7296
xUpgrade = new XElement(Names.UpgradeElement,
7297
new XAttribute("Id", upgradeRow.UpgradeCode));
7298
7309
- this.RootElement.Add(xUpgrade);
7299
+ this.DecompilerHelper.AddElementToRoot(xUpgrade);
7300
xUpgrades.Add(upgradeRow.UpgradeCode, xUpgrade);
7301
}
7302
@@ -7435,7 +7425,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7425
AddSymbolPaths(row, 3, xUpgradeImage);
7426
7427
this.AddChildToParent("ImageFamilies", xUpgradeImage, row, 4);
7438
- this.IndexElement(row, xUpgradeImage);
7428
+ this.DecompilerHelper.IndexElement(row, xUpgradeImage);
7429
}
7430
}
7431
@@ -7485,7 +7475,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7475
XAttributeIfNotNull("Command", row, 3),
7476
XAttributeIfNotNull("Argument", row, 4));
7477
7488
- this.IndexElement(row, verb);
7478
+ this.DecompilerHelper.IndexElement(row, verb);
7479
}
7480
}
7481
@@ -7537,7 +7527,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile
7527
var featureField = row.Fields[featureColumnIndex];
7528
var componentField = row.Fields[componentColumnIndex];
7529
7540
- if (this.TryGetIndexedElement("FeatureComponents", out var xComponentRef, Convert.ToString(featureField.Data), Convert.ToString(componentField.Data)))
7530
+ if (this.DecompilerHelper.TryGetIndexedElement("FeatureComponents", featureField.AsString(), componentField.AsString(), out var xComponentRef))
7531
{
7532
xComponentRef.SetAttributeValue("Primary", "yes");
7533
}
src/wix/WixToolset.Core.WindowsInstaller/ExtensibilityServices/WindowsInstallerDecompilerHelper.cs
new
+133
@@ -0,0 +1,133 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core.WindowsInstaller.ExtensibilityServices
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.Xml.Linq;
8
+ using WixToolset.Core.WindowsInstaller.Decompile;
9
+ using WixToolset.Data.WindowsInstaller;
10
+ using WixToolset.Extensibility.Services;
11
+
12
+ internal class WindowsInstallerDecompilerHelper : IWindowsInstallerDecompilerHelper
13
+ {
14
+ public WindowsInstallerDecompilerHelper(IServiceProvider _)
15
+ {
16
+ }
17
+
18
+ private Dictionary<string, XElement> IndexedElements { get; } = new Dictionary<string, XElement>();
19
+
20
+ #region IWindowsInstallerDecompilerHelper interfaces
21
+
22
+ public XElement RootElement { get; set; }
23
+
24
+ public XElement AddElementToRoot(string name, params object[] content)
25
+ {
26
+ var element = new XElement(Names.WxsNamespace + name, content);
27
+
28
+ this.RootElement.Add(element);
29
+
30
+ return element;
31
+ }
32
+
33
+ public XElement AddElementToRoot(XName name, params object[] content)
34
+ {
35
+ var element = new XElement(name, content);
36
+
37
+ this.RootElement.Add(element);
38
+
39
+ return element;
40
+ }
41
+
42
+ public XElement AddElementToRoot(XElement element)
43
+ {
44
+ this.RootElement.Add(element);
45
+
46
+ return element;
47
+ }
48
+
49
+ public XElement CreateElement(string name, params object[] content)
50
+ {
51
+ return new XElement(Names.WxsNamespace + name, content);
52
+ }
53
+
54
+ public XElement GetIndexedElement(Row row)
55
+ {
56
+ return this.GetIndexedElement(row.TableDefinition.Name, row.GetPrimaryKey());
57
+ }
58
+
59
+ public XElement GetIndexedElement(string table, string primaryKey)
60
+ {
61
+ return this.TryGetIndexedElement(table, primaryKey, out var element) ? element : null;
62
+ }
63
+
64
+ public XElement GetIndexedElement(string table, string primaryKey1, string primaryKey2)
65
+ {
66
+ return this.TryGetIndexedElement(table, primaryKey1, primaryKey2, out var element) ? element : null;
67
+ }
68
+
69
+ public XElement GetIndexedElement(string table, string primaryKey1, string primaryKey2, string primaryKey3)
70
+ {
71
+ return this.TryGetIndexedElement(table, primaryKey1, primaryKey2, primaryKey3, out var element) ? element : null;
72
+ }
73
+
74
+ public XElement GetIndexedElement(string table, string[] primaryKeys)
75
+ {
76
+ return this.TryGetIndexedElement(table, primaryKeys, out var element) ? element : null;
77
+ }
78
+
79
+ public void IndexElement(Row row, XElement element)
80
+ {
81
+ this.IndexElement(row.Table.Name, row.GetPrimaryKey(), element);
82
+ }
83
+
84
+ public void IndexElement(string table, string primaryKey, XElement element)
85
+ {
86
+ var key = String.Concat(table, ':', primaryKey);
87
+ this.IndexedElements.Add(key, element);
88
+ }
89
+
90
+ public void IndexElement(string table, string primaryKey1, string primaryKey2, XElement element)
91
+ {
92
+ this.IndexElement(table, String.Join("/", primaryKey1, primaryKey2), element);
93
+ }
94
+
95
+ public void IndexElement(string table, string primaryKey1, string primaryKey2, string primaryKey3, XElement element)
96
+ {
97
+ this.IndexElement(table, String.Join("/", primaryKey1, primaryKey2, primaryKey3), element);
98
+ }
99
+
100
+ public void IndexElement(string table, string[] primaryKeys, XElement element)
101
+ {
102
+ this.IndexElement(table, String.Join("/", primaryKeys), element);
103
+ }
104
+
105
+ public bool TryGetIndexedElement(Row row, out XElement element)
106
+ {
107
+ return this.TryGetIndexedElement(row.TableDefinition.Name, row.GetPrimaryKey(), out element);
108
+ }
109
+
110
+ public bool TryGetIndexedElement(string table, string primaryKey, out XElement element)
111
+ {
112
+ var key = String.Concat(table, ':', primaryKey);
113
+ return this.IndexedElements.TryGetValue(key, out element);
114
+ }
115
+
116
+ public bool TryGetIndexedElement(string table, string primaryKey1, string primaryKey2, out XElement element)
117
+ {
118
+ return this.TryGetIndexedElement(table, String.Join("/", primaryKey1, primaryKey2), out element);
119
+ }
120
+
121
+ public bool TryGetIndexedElement(string table, string primaryKey1, string primaryKey2, string primaryKey3, out XElement element)
122
+ {
123
+ return this.TryGetIndexedElement(table, String.Join("/", primaryKey1, primaryKey2, primaryKey3), out element);
124
+ }
125
+
126
+ public bool TryGetIndexedElement(string table, string[] primaryKeys, out XElement element)
127
+ {
128
+ return this.TryGetIndexedElement(table, String.Join("/", primaryKeys), out element);
129
+ }
130
+
131
+ #endregion
132
+ }
133
+}
src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
+1
-1
@@ -171,7 +171,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
171
}
172
break;
173
case ColumnType.Object:
174
- var sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES";
174
+ var sourceFile = "FILE NOT EXPORTED";
175
176
if (null != this.ExportBasePath)
177
{
src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompileContext.cs
+4
@@ -23,6 +23,10 @@ namespace WixToolset.Core.WindowsInstaller
23
24
public IReadOnlyCollection<IWindowsInstallerDecompilerExtension> Extensions { get; set; }
25
26
+ public IReadOnlyCollection<IExtensionData> ExtensionData { get; set; }
27
+
28
+ public ISymbolDefinitionCreator SymbolDefinitionCreator { get; set; }
29
+
30
public string ExtractFolder { get; set; }
31
32
public string CabinetExtractFolder { get; set; }
src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompileResult.cs
+1
-1
@@ -11,7 +11,7 @@ namespace WixToolset.Core.WindowsInstaller
11
{
12
public XDocument Document { get; set; }
13
14
- public IReadOnlyCollection<string> ExtractedFilePaths { get; set; }
14
+ public IList<string> ExtractedFilePaths { get; set; }
15
16
public Platform? Platform { get; set; }
17
}
src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompiler.cs
+81
-4
@@ -3,8 +3,15 @@
3
namespace WixToolset.Core.WindowsInstaller
4
{
5
using System;
6
+ using System.Collections.Generic;
7
+ using System.ComponentModel;
8
+ using System.IO;
9
+ using System.Linq;
10
+ using WixToolset.Core.Native.Msi;
11
using WixToolset.Core.WindowsInstaller.Decompile;
7
- using WixToolset.Extensibility;
12
+ using WixToolset.Core.WindowsInstaller.Unbind;
13
+ using WixToolset.Data;
14
+ using WixToolset.Data.WindowsInstaller;
15
using WixToolset.Extensibility.Data;
16
using WixToolset.Extensibility.Services;
17
@@ -16,12 +23,20 @@ namespace WixToolset.Core.WindowsInstaller
23
internal WindowsInstallerDecompiler(IServiceProvider serviceProvider)
24
{
25
this.ServiceProvider = serviceProvider;
26
+ this.Messaging = serviceProvider.GetService<IMessaging>();
27
}
28
21
- public IServiceProvider ServiceProvider { get; }
29
+ private IServiceProvider ServiceProvider { get; }
30
+
31
+ private IMessaging Messaging { get; }
32
33
public IWindowsInstallerDecompileResult Decompile(IWindowsInstallerDecompileContext context)
34
{
35
+ if (context.SymbolDefinitionCreator == null)
36
+ {
37
+ context.SymbolDefinitionCreator = this.ServiceProvider.GetService<ISymbolDefinitionCreator>();
38
+ }
39
+
40
// Pre-decompile.
41
//
42
foreach (var extension in context.Extensions)
@@ -31,8 +46,7 @@ namespace WixToolset.Core.WindowsInstaller
46
47
// Decompile.
48
//
34
- var command = new DecompileMsiOrMsmCommand(context);
35
- var result = command.Execute();
49
+ var result = this.Execute(context);
50
51
if (result != null)
52
{
@@ -46,5 +60,68 @@ namespace WixToolset.Core.WindowsInstaller
60
61
return result;
62
}
63
+
64
+ private IWindowsInstallerDecompileResult Execute(IWindowsInstallerDecompileContext context)
65
+ {
66
+ var result = context.ServiceProvider.GetService<IWindowsInstallerDecompileResult>();
67
+
68
+ try
69
+ {
70
+ using (var database = new Database(context.DecompilePath, OpenDatabase.ReadOnly))
71
+ {
72
+ // Delete the directory and its files to prevent cab extraction failure due to an existing file.
73
+ if (Directory.Exists(context.ExtractFolder))
74
+ {
75
+ Directory.Delete(context.ExtractFolder, true);
76
+ }
77
+
78
+ var backendHelper = context.ServiceProvider.GetService<IWindowsInstallerBackendHelper>();
79
+ var decompilerHelper = context.ServiceProvider.GetService<IWindowsInstallerDecompilerHelper>();
80
+
81
+ var unbindCommand = new UnbindDatabaseCommand(this.Messaging, backendHelper, database, context.DecompilePath, context.DecompileType, context.ExtractFolder, context.IntermediateFolder, context.IsAdminImage, suppressDemodularization: false, skipSummaryInfo: false);
82
+ var output = unbindCommand.Execute();
83
+ var extractedFilePaths = new List<string>(unbindCommand.ExportedFiles);
84
+
85
+ var decompiler = new Decompiler(this.Messaging, backendHelper, decompilerHelper, context.Extensions, context.ExtensionData, context.SymbolDefinitionCreator, context.BaseSourcePath, context.SuppressCustomTables, context.SuppressDroppingEmptyTables, context.SuppressRelativeActionSequencing, context.SuppressUI, context.TreatProductAsModule);
86
+ result.Document = decompiler.Decompile(output);
87
+
88
+ result.Platform = GetPlatformFromOutput(output);
89
+
90
+ // extract the files from the cabinets
91
+ if (!String.IsNullOrEmpty(context.ExtractFolder) && !context.SuppressExtractCabinets)
92
+ {
93
+ var fileDirectory = String.IsNullOrEmpty(context.CabinetExtractFolder) ? Path.Combine(context.ExtractFolder, "File") : context.CabinetExtractFolder;
94
+
95
+ var extractCommand = new ExtractCabinetsCommand(output, database, context.DecompilePath, fileDirectory, context.IntermediateFolder, context.TreatProductAsModule);
96
+ extractCommand.Execute();
97
+
98
+ extractedFilePaths.AddRange(extractCommand.ExtractedFiles);
99
+ result.ExtractedFilePaths = extractedFilePaths;
100
+ }
101
+ else
102
+ {
103
+ result.ExtractedFilePaths = new string[0];
104
+ }
105
+ }
106
+ }
107
+ catch (Win32Exception e)
108
+ {
109
+ if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED
110
+ {
111
+ throw new WixException(ErrorMessages.OpenDatabaseFailed(context.DecompilePath));
112
+ }
113
+
114
+ throw;
115
+ }
116
+
117
+ return result;
118
+ }
119
+
120
+ private static Platform? GetPlatformFromOutput(WindowsInstallerData output)
121
+ {
122
+ var template = output.Tables["_SummaryInformation"]?.Rows.SingleOrDefault(row => row.FieldAsInteger(0) == 7)?.FieldAsString(1);
123
+
124
+ return Decompiler.GetPlatformFromTemplateSummaryInformation(template?.Split(';'));
125
+ }
126
}
127
}
src/wix/WixToolset.Core.WindowsInstaller/WixToolsetCoreServiceProviderExtensions.cs
+3
-2
@@ -16,8 +16,8 @@ namespace WixToolset.Core.WindowsInstaller
16
/// <summary>
17
/// Adds WindowsInstaller services.
18
/// </summary>
19
- /// <param name="coreProvider"></param>
20
- /// <returns></returns>
19
+ /// <param name="coreProvider">Core service provider.</param>
20
+ /// <returns>The core service provider provided to this method.</returns>
21
public static IWixToolsetCoreServiceProvider AddWindowsInstallerBackend(this IWixToolsetCoreServiceProvider coreProvider)
22
{
23
AddServices(coreProvider);
@@ -32,6 +32,7 @@ namespace WixToolset.Core.WindowsInstaller
32
{
33
// Singletons.
34
coreProvider.AddService((provider, singletons) => AddSingleton<IWindowsInstallerBackendHelper>(singletons, new WindowsInstallerBackendHelper(provider)));
35
+ coreProvider.AddService((provider, singletons) => AddSingleton<IWindowsInstallerDecompilerHelper>(singletons, new WindowsInstallerDecompilerHelper(provider)));
36
37
// Transients.
38
coreProvider.AddService<IWindowsInstallerDecompiler>((provider, singletons) => new WindowsInstallerDecompiler(provider));
src/wix/test/Example.Extension/ExampleCompilerExtension.cs
+11
-7
@@ -10,8 +10,9 @@ namespace Example.Extension
10
11
internal class ExampleCompilerExtension : BaseCompilerExtension
12
{
13
- public override XNamespace Namespace => "http://www.example.com/scheams/v1/wxs";
14
- public string BundleExtensionId => "ExampleBundleExtension";
13
+ private const string BundleExtensionId = "ExampleBundleExtension";
14
+
15
+ public override XNamespace Namespace => ExampleConstants.Namespace;
16
17
public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
18
{
@@ -38,10 +39,12 @@ namespace Example.Extension
39
}
40
break;
41
case "Component":
42
+ var componentId = context["ComponentId"];
43
+
44
switch (element.Name.LocalName)
45
{
46
case "Example":
44
- this.ParseExampleElement(intermediate, section, element);
47
+ this.ParseExampleElement(intermediate, section, element, componentId);
48
processed = true;
49
break;
50
}
@@ -54,7 +57,7 @@ namespace Example.Extension
57
}
58
}
59
57
- private void ParseExampleElement(Intermediate intermediate, IntermediateSection section, XElement element)
60
+ private void ParseExampleElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
61
{
62
var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
63
Identifier id = null;
@@ -93,7 +96,8 @@ namespace Example.Extension
96
if (!this.Messaging.EncounteredError)
97
{
98
var symbol = this.ParseHelper.CreateSymbol(section, sourceLineNumbers, "Example", id);
96
- symbol.Set(0, value);
99
+ symbol.Set(0, componentId);
100
+ symbol.Set(1, value);
101
}
102
}
103
@@ -152,12 +156,12 @@ namespace Example.Extension
156
157
if (!this.Messaging.EncounteredError)
158
{
155
- this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, this.BundleExtensionId);
159
+ this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, BundleExtensionId);
160
}
161
162
if (!this.Messaging.EncounteredError)
163
{
160
- var symbol = section.AddSymbol(new ExampleSearchSymbol(sourceLineNumbers, id)
164
+ section.AddSymbol(new ExampleSearchSymbol(sourceLineNumbers, id)
165
{
166
SearchFor = searchFor,
167
});
src/wix/test/Example.Extension/ExampleConstants.cs
new
+13
@@ -0,0 +1,13 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace Example.Extension
4
+{
5
+ using System.Xml.Linq;
6
+
7
+ internal class ExampleConstants
8
+ {
9
+ public static readonly XNamespace Namespace = "http://www.example.com/scheams/v1/wxs";
10
+
11
+ public static readonly XName ExampleName = Namespace + "Example";
12
+ }
13
+}
src/wix/test/Example.Extension/ExampleExtensionFactory.cs
+4
@@ -43,6 +43,10 @@ namespace Example.Extension
43
{
44
extension = new ExampleWindowsInstallerBackendExtension();
45
}
46
+ else if (extensionType == typeof(IWindowsInstallerDecompilerExtension))
47
+ {
48
+ extension = new ExampleWindowsInstallerDecompilerExtension();
49
+ }
50
else
51
{
52
extension = null;
src/wix/test/Example.Extension/ExampleRow.cs
+7
-1
@@ -23,10 +23,16 @@ namespace Example.Extension
23
set { this.Fields[0].Data = value; }
24
}
25
26
- public string Value
26
+ public string ComponentRef
27
{
28
get { return (string)this.Fields[1].Data; }
29
set { this.Fields[1].Data = value; }
30
}
31
+
32
+ public string Value
33
+ {
34
+ get { return (string)this.Fields[2].Data; }
35
+ set { this.Fields[2].Data = value; }
36
+ }
37
}
38
}
src/wix/test/Example.Extension/ExampleSymbol.cs
+7
@@ -6,6 +6,7 @@ namespace Example.Extension
6
7
public enum ExampleSymbolFields
8
{
9
+ ComponentRef,
10
Value,
11
}
12
@@ -21,6 +22,12 @@ namespace Example.Extension
22
23
public IntermediateField this[ExampleSymbolFields index] => this.Fields[(int)index];
24
25
+ public string ComponentRef
26
+ {
27
+ get => this.Fields[(int)ExampleSymbolFields.ComponentRef]?.AsString();
28
+ set => this.Set((int)ExampleSymbolFields.ComponentRef, value);
29
+ }
30
+
31
public string Value
32
{
33
get => this.Fields[(int)ExampleSymbolFields.Value]?.AsString();
src/wix/test/Example.Extension/ExampleSymbolDefinitions.cs
+1
@@ -18,6 +18,7 @@ namespace Example.Extension
18
ExampleSymbolDefinitionType.Example.ToString(),
19
new[]
20
{
21
+ new IntermediateFieldDefinition(nameof(ExampleSymbolFields.ComponentRef), IntermediateFieldType.String),
22
new IntermediateFieldDefinition(nameof(ExampleSymbolFields.Value), IntermediateFieldType.String),
23
},
24
typeof(ExampleSymbol));
src/wix/test/Example.Extension/ExampleTableDefinitions.cs
+2
-1
@@ -11,7 +11,8 @@ namespace Example.Extension
11
ExampleSymbolDefinitions.Example,
12
new[]
13
{
14
- new ColumnDefinition("Example", ColumnType.String, 72, true, false, ColumnCategory.Identifier),
14
+ new ColumnDefinition("Example", ColumnType.String, 72, true, false, ColumnCategory.Identifier, modularizeType: ColumnModularizeType.Column),
15
+ new ColumnDefinition("Component_", ColumnType.String, 72, false, false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, modularizeType: ColumnModularizeType.Column),
16
new ColumnDefinition("Value", ColumnType.String, 0, false, false, ColumnCategory.Formatted),
17
},
18
strongRowType: typeof(ExampleRow),
src/wix/test/Example.Extension/ExampleWindowsInstallerBackendExtension.cs
+6
-5
@@ -18,12 +18,13 @@ namespace Example.Extension
18
switch (symbolType)
19
{
20
case ExampleSymbolDefinitionType.Example:
21
- {
22
- var row = (ExampleRow)this.BackendHelper.CreateRow(section, symbol, output, ExampleTableDefinitions.ExampleTable);
23
- row.Example = symbol.Id.Id;
24
- row.Value = symbol[0].AsString();
25
- }
21
+ {
22
+ var row = (ExampleRow)this.BackendHelper.CreateRow(section, symbol, output, ExampleTableDefinitions.ExampleTable);
23
+ row.Example = symbol.Id.Id;
24
+ row.ComponentRef = symbol[0].AsString();
25
+ row.Value = symbol[1].AsString();
26
return true;
27
+ }
28
}
29
}
30
src/wix/test/Example.Extension/ExampleWindowsInstallerDecompilerExtension.cs
new
+42
@@ -0,0 +1,42 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace Example.Extension
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.Xml.Linq;
8
+ using WixToolset.Data.WindowsInstaller;
9
+ using WixToolset.Extensibility;
10
+
11
+ internal class ExampleWindowsInstallerDecompilerExtension : BaseWindowsInstallerDecompilerExtension
12
+ {
13
+ public override IReadOnlyCollection<TableDefinition> TableDefinitions => ExampleTableDefinitions.All;
14
+
15
+ public override bool TryDecompileTable(Table table)
16
+ {
17
+ switch (table.Name)
18
+ {
19
+ case "Wix4Example":
20
+ this.ProcessExampleTable(table);
21
+ return true;
22
+ }
23
+
24
+ return false;
25
+ }
26
+
27
+ private void ProcessExampleTable(Table table)
28
+ {
29
+ foreach (var row in table.Rows)
30
+ {
31
+ var componentId = row.FieldAsString(1);
32
+ if (this.DecompilerHelper.TryGetIndexedElement("Component", componentId, out var component))
33
+ {
34
+ component.Add(new XElement(ExampleConstants.ExampleName,
35
+ new XAttribute("Id", row.FieldAsString(0)),
36
+ new XAttribute("Value", row.FieldAsString(2))
37
+ ));
38
+ }
39
+ }
40
+ }
41
+ }
42
+}
src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
+39
-4
@@ -5,6 +5,7 @@ namespace WixToolsetTest.CoreIntegration
5
using System;
6
using System.IO;
7
using System.Linq;
8
+ using System.Text.RegularExpressions;
9
using Example.Extension;
10
using WixBuildTools.TestSupport;
11
using WixToolset.Core.TestPackage;
@@ -23,10 +24,37 @@ namespace WixToolsetTest.CoreIntegration
24
var results = build.BuildAndQuery(Build, "Wix4Example");
25
WixAssert.CompareLineByLine(new[]
26
{
26
- "Wix4Example:Foo\tBar"
27
+ "Wix4Example:Foo\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tBar"
28
}, results);
29
}
30
31
+ [Fact]
32
+ public void CanRoundtripExampleExtension()
33
+ {
34
+ var folder = TestData.Get(@"TestData", "ExampleExtension");
35
+ var expectedOutputPath = Path.Combine(folder, "Decompiled-Expected.xml");
36
+
37
+ var build = new Builder(folder, typeof(ExampleExtensionFactory), new[] { Path.Combine(folder, "data") });
38
+ using (var fs = new DisposableFileSystem())
39
+ {
40
+ var decompileFolder = fs.GetFolder();
41
+ var actualOutputPath = Path.Combine(decompileFolder, "decompiled.xml");
42
+
43
+ build.BuildAndDecompileAndBuild(Build, Decompile, actualOutputPath);
44
+
45
+ var expected = File.ReadAllLines(expectedOutputPath);
46
+ var actual = File.ReadAllLines(actualOutputPath).Select(ReplaceGuids).ToArray(); ;
47
+ WixAssert.CompareLineByLine(expected, actual);
48
+ }
49
+ }
50
+
51
+ private static string ReplaceGuids(string value)
52
+ {
53
+ value = String.IsNullOrWhiteSpace(value) ? value : Regex.Replace(value, @" ProductCode=\""\{[a-fA-F0-9\-]+\}\""", " ProductCode=\"{GUID}\"");
54
+ return String.IsNullOrWhiteSpace(value) ? value : Regex.Replace(value, @" Guid=\""\{[a-fA-F0-9\-]+\}\""", " Guid=\"{GUID}\"");
55
+
56
+ }
57
+
58
[Fact]
59
public void CanBuildWithExampleExtension()
60
{
@@ -64,7 +92,8 @@ namespace WixToolsetTest.CoreIntegration
92
93
var example = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).Single();
94
Assert.Equal("Foo", example.Id?.Id);
67
- Assert.Equal("Bar", example[0].AsString());
95
+ Assert.Equal("filF5_pLhBuF5b4N9XEo52g_hUM5Lo", example[0].AsString());
96
+ Assert.Equal("Bar", example[1].AsString());
97
}
98
}
99
@@ -192,8 +221,14 @@ namespace WixToolsetTest.CoreIntegration
221
222
private static void Build(string[] args)
223
{
195
- var result = WixRunner.Execute(args)
196
- .AssertSuccess();
224
+ var result = WixRunner.Execute(args);
225
+ result.AssertSuccess();
226
+ }
227
+
228
+ private static void Decompile(string[] args)
229
+ {
230
+ var result = WixRunner.Execute(args);
231
+ result.AssertSuccess();
232
}
233
}
234
}
src/wix/test/WixToolsetTest.CoreIntegration/TestData/AppSearch/DecompiledNestedDirSearchUnderRegSearch.wxs
+3
-3
@@ -1,9 +1,9 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{33C58183-7333-4257-AEFD-6705DA66E617}">
2
+ <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{33C58183-7333-4257-AEFD-6705DA66E617}" Compressed="no">
3
<StandardDirectory Id="ProgramFilesFolder">
4
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="ykd0udtb">
5
<Component Id="test.txt" Guid="{E597A58A-03CB-50D8-93E3-DABA263F233A}" Bitness="always32">
6
- <File Id="test.txt" Name="test.txt" KeyPath="yes" Source="MsiPackage\test.txt" />
6
+ <File Id="test.txt" Name="test.txt" KeyPath="yes" Source="PFiles\MsiPackage\test.txt" />
7
</Component>
8
</Directory>
9
</StandardDirectory>
@@ -39,4 +39,4 @@
39
</RegistrySearch>
40
</Property>
41
</Package>
42
-</Wix>
\ No newline at end of file
42
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/Class/DecompiledOldClassTableDef.wxs
+3
-3
@@ -1,12 +1,12 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{FE17A505-11A9-44D2-8D94-EB6BEAB8FF93}">
2
+ <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{FE17A505-11A9-44D2-8D94-EB6BEAB8FF93}" Compressed="no">
3
<StandardDirectory Id="ProgramFilesFolder">
4
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="oekcr5lq">
5
<Component Id="ProgIdComp" Guid="{5B3B3FC1-533D-4C29-BFB3-0E88B51E59D8}" Bitness="always32">
6
<Class Id="{F12A6F69-117F-471F-AE73-F8E74218F498}" Context="LocalServer32" Description="FakeClassF12A" Advertise="yes">
7
<ProgId Id="73E7DF7E-EFAC-4E11-90E2-6EBAEB8DE58D" Description="FakeClassF12A" Advertise="yes" />
8
</Class>
9
- <File Id="filTki4JQ2gSapF7wK4K1vd.4mDSFQ" Name="ProgIdComp.txt" KeyPath="yes" ShortName="bnvvntsc.txt" Source="MsiPackage\ProgIdComp.txt" />
9
+ <File Id="filTki4JQ2gSapF7wK4K1vd.4mDSFQ" Name="ProgIdComp.txt" KeyPath="yes" ShortName="bnvvntsc.txt" Source="PFiles\MsiPackage\ProgIdComp.txt" />
10
<RegistryValue Id="regUIIK326nDZpkWHuexeF58EikQvA" Root="HKCR" Key="73E7DF7E-EFAC-4E11-90E2-6EBAEB8DE58D" Name="NoOpen" Value="NoOpen73E7" Type="string" />
11
<RegistryValue Id="regY1F4E2lvu_Up6gV6c3jeN5ukn8s" Root="HKCR" Key="CLSID\{F12A6F69-117F-471F-AE73-F8E74218F498}\LocalServer32" Name="ThreadingModel" Value="Apartment" Type="string" />
12
<RegistryValue Id="regvrhMurMp98anbQJkpgA8yJCefdM" Root="HKCR" Key="CLSID\{F12A6F69-117F-471F-AE73-F8E74218F498}\Version" Value="0.0.0.1" Type="string" />
@@ -19,4 +19,4 @@
19
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
20
<Media Id="1" />
21
</Package>
22
-</Wix>
\ No newline at end of file
22
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable-Expected.wxs
+2
-2
@@ -1,5 +1,5 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{83F9C623-26FE-42AB-951E-170022117F54}">
2
+ <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{83F9C623-26FE-42AB-951E-170022117F54}" Compressed="no">
3
<CustomTable Id="CustomTable1">
4
<Column Id="Column1" PrimaryKey="yes" Type="string" Width="0" Category="text" Description="The first custom column." />
5
<Column Id="Component_" Type="string" Width="72" KeyTable="Component" KeyColumn="1" Description="The custom table's Component reference" />
@@ -15,7 +15,7 @@
15
<StandardDirectory Id="ProgramFiles6432Folder">
16
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="1egc1laj">
17
<Component Id="filcV1yrx0x8wJWj4qMzcH21jwkPko" Guid="{E597A58A-03CB-50D8-93E3-DABA263F233A}" Bitness="always32">
18
- <File Id="filcV1yrx0x8wJWj4qMzcH21jwkPko" Name="test.txt" KeyPath="yes" Source="MsiPackage\test.txt" />
18
+ <File Id="filcV1yrx0x8wJWj4qMzcH21jwkPko" Name="test.txt" KeyPath="yes" Source=".\MsiPackage\test.txt" />
19
</Component>
20
</Directory>
21
</StandardDirectory>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/DecompileNullComponent/Expected.wxs
+1
-1
@@ -1,5 +1,5 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="65001" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{047730A5-30FE-4A62-A520-DA9381B8226A}" Version="1.0.0.0" Compressed="yes" InstallerVersion="200" ProductCode="{6F9B5694-F0F1-437C-919B-0D2DAF2D9DEA}">
2
+ <Package Codepage="65001" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{047730A5-30FE-4A62-A520-DA9381B8226A}" Version="1.0.0.0" InstallerVersion="200" ProductCode="{6F9B5694-F0F1-437C-919B-0D2DAF2D9DEA}">
3
<StandardDirectory Id="ProgramFilesFolder">
4
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="oekcr5lq">
5
<Component Id="filcV1yrx0x8wJWj4qMzcH21jwkPko" Guid="" Bitness="always32">
src/wix/test/WixToolsetTest.CoreIntegration/TestData/DecompileSingleFileCompressed/Expected.wxs
+1
-1
@@ -1,5 +1,5 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="65001" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{047730A5-30FE-4A62-A520-DA9381B8226A}" Version="1.0.0.0" Compressed="yes" InstallerVersion="200" ProductCode="{6F9B5694-F0F1-437C-919B-0D2DAF2D9DEA}">
2
+ <Package Codepage="65001" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{047730A5-30FE-4A62-A520-DA9381B8226A}" Version="1.0.0.0" InstallerVersion="200" ProductCode="{6F9B5694-F0F1-437C-919B-0D2DAF2D9DEA}">
3
<StandardDirectory Id="ProgramFilesFolder">
4
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="oekcr5lq">
5
<Component Id="filcV1yrx0x8wJWj4qMzcH21jwkPko" Guid="{E597A58A-03CB-50D8-93E3-DABA263F233A}" Bitness="always32">
src/wix/test/WixToolsetTest.CoreIntegration/TestData/DecompileSingleFileCompressed64/Expected.wxs
+1
-1
@@ -1,5 +1,5 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="65001" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{047730A5-30FE-4A62-A520-DA9381B8226A}" Version="1.0.0.0" Compressed="yes" ProductCode="{C51B773A-B3BE-4F29-A8A9-549AAF7FF6EC}">
2
+ <Package Codepage="65001" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{047730A5-30FE-4A62-A520-DA9381B8226A}" Version="1.0.0.0" ProductCode="{C51B773A-B3BE-4F29-A8A9-549AAF7FF6EC}">
3
<StandardDirectory Id="ProgramFiles64Folder">
4
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="oekcr5lq">
5
<Component Id="filcV1yrx0x8wJWj4qMzcH21jwkPko" Guid="{E597A58A-03CB-50D8-93E3-DABA263F233A}" Bitness="always64">
src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtension/Decompiled-Expected.xml
new
+19
@@ -0,0 +1,19 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3
+ <Package Codepage="1252" Manufacturer="Example Corporation" ProductCode="{GUID}" Language="1033" Name="MsiPackage" Version="1.0.0.0" UpgradeCode="{047730A5-30FE-4A62-A520-DA9381B8226A}" InstallerVersion="200" Compressed="no">
4
+ <Property Id="ExampleProperty" Value="(null)" />
5
+ <StandardDirectory Id="ProgramFilesFolder">
6
+ <Directory Id="INSTALLFOLDER" ShortName="oekcr5lq" Name="MsiPackage">
7
+ <Component Id="filF5_pLhBuF5b4N9XEo52g_hUM5Lo" Guid="{GUID}" Bitness="always32">
8
+ <Example Id="Foo" Value="Bar" xmlns="http://www.example.com/scheams/v1/wxs" />
9
+ <File Id="filF5_pLhBuF5b4N9XEo52g_hUM5Lo" Name="example.txt" KeyPath="yes" Source="PFiles\MsiPackage\example.txt" />
10
+ </Component>
11
+ </Directory>
12
+ </StandardDirectory>
13
+ <Feature Id="ProductFeature" Title="MsiPackage" Level="1">
14
+ <ComponentRef Id="filF5_pLhBuF5b4N9XEo52g_hUM5Lo" />
15
+ </Feature>
16
+ <Media Id="1" />
17
+ <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
18
+ </Package>
19
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/SequenceTables/DecompiledSequenceTables.wxs
+3
-3
@@ -1,10 +1,10 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{74C29381-1915-4948-B8B4-5646806A0BD4}">
2
+ <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{74C29381-1915-4948-B8B4-5646806A0BD4}" Compressed="no">
3
<CustomAction Id="CustomAction2" Property="TestAdvtExecuteSequenceProperty" Value="1" />
4
<StandardDirectory Id="ProgramFilesFolder">
5
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="ykd0udtb">
6
<Component Id="test.txt" Guid="{E597A58A-03CB-50D8-93E3-DABA263F233A}" Bitness="always32">
7
- <File Id="test.txt" Name="test.txt" KeyPath="yes" Source="MsiPackage\test.txt" />
7
+ <File Id="test.txt" Name="test.txt" KeyPath="yes" Source="PFiles\MsiPackage\test.txt" />
8
</Component>
9
</Directory>
10
</StandardDirectory>
@@ -29,4 +29,4 @@
29
<Custom Action="CustomAction2" After="CostInitialize" />
30
</AdvertiseExecuteSequence>
31
</Package>
32
-</Wix>
\ No newline at end of file
32
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/Shortcut/DecompiledShortcuts.wxs
+3
-3
@@ -1,9 +1,9 @@
1
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
- <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{6CA94D1D-B568-4ED6-9EBC-3534C85970BB}">
2
+ <Package Codepage="1252" Language="1033" Manufacturer="Example Corporation" Name="MsiPackage" UpgradeCode="{12E4699F-E774-4D05-8A01-5BDD41BBA127}" Version="1.0.0.0" ProductCode="{6CA94D1D-B568-4ED6-9EBC-3534C85970BB}" Compressed="no">
3
<StandardDirectory Id="ProgramFilesFolder">
4
<Directory Id="INSTALLFOLDER" Name="MsiPackage" ShortName="ykd0udtb">
5
<Component Id="ShortcutComp" Guid="{5B3B3FC1-533D-4C29-BFB3-0E88B51E59D8}" Bitness="always32">
6
- <File Id="test.txt" Name="test.txt" KeyPath="yes" Source="MsiPackage\test.txt" />
6
+ <File Id="test.txt" Name="test.txt" KeyPath="yes" Source="PFiles\MsiPackage\test.txt" />
7
<Shortcut Id="FileTargetShortcut" Directory="INSTALLFOLDER" Name="FileTargetShortcut" ShortName="lm2tdtqp" Target="[#test.txt]" />
8
<Shortcut Id="CustomTargetShortcut" Directory="INSTALLFOLDER" Name="Planner" ShortName="PLANNER" Target="[INSTALLFOLDER]custom.target" />
9
<Shortcut Id="AdvtShortcut" Directory="INSTALLFOLDER" Name="AdvtShortcut" ShortName="mdbqel9r" Advertise="yes" />
@@ -16,4 +16,4 @@
16
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
17
<Media Id="1" />
18
</Package>
19
-</Wix>
\ No newline at end of file
19
+</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs
+3
-2
@@ -289,7 +289,7 @@ namespace WixToolsetTest.CoreIntegration
289
290
var example = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).Single();
291
Assert.Equal("Foo", example.Id?.Id);
292
- Assert.Equal("Bar", example[0].AsString());
292
+ Assert.Equal("Bar", example[1].AsString());
293
}
294
}
295
@@ -352,7 +352,8 @@ namespace WixToolsetTest.CoreIntegration
352
353
var examples = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).ToArray();
354
WixAssert.CompareLineByLine(new string[] { "Foo", "Other" }, examples.Select(t => t.Id?.Id).ToArray());
355
- WixAssert.CompareLineByLine(new[] { "Bar", "Value" }, examples.Select(t => t[0].AsString()).ToArray());
355
+ WixAssert.CompareLineByLine(new[] { "filF5_pLhBuF5b4N9XEo52g_hUM5Lo", "filvxdStJhRE_M5kbpLsTZJXbs34Sg" }, examples.Select(t => t[0].AsString()).ToArray());
356
+ WixAssert.CompareLineByLine(new[] { "Bar", "Value" }, examples.Select(t => t[1].AsString()).ToArray());
357
}
358
}
359
}