Update decompiler to use XDocument rather than generated classes.
- Use CompareXml for diffing. - Change CustomAction/@ScriptFile to @ScriptSourceFile.
Bob Arnson committed
Aug 24, 2020 at 17:25 UTC
c237bb3bb00d36c50271a70baac68f49890e35e1
9 files changed
+3467
-5270
src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
+3283
-5014
@@ -3,9 +3,7 @@
3
namespace WixToolset.Core.WindowsInstaller
4
{
5
using System;
6
- using System.Collections;
6
using System.Collections.Generic;
8
- using System.Collections.Specialized;
7
using System.Globalization;
8
using System.IO;
9
using System.Linq;
@@ -13,13 +11,13 @@ namespace WixToolset.Core.WindowsInstaller
11
using System.Text.RegularExpressions;
12
using System.Xml.Linq;
13
using WixToolset.Core;
14
+ using WixToolset.Core.WindowsInstaller.Decompile;
15
using WixToolset.Data;
16
using WixToolset.Data.Symbols;
17
using WixToolset.Data.WindowsInstaller;
18
using WixToolset.Data.WindowsInstaller.Rows;
19
using WixToolset.Extensibility;
20
using WixToolset.Extensibility.Services;
22
- using Wix = WixToolset.Data.Serialize;
21
22
/// <summary>
23
/// Decompiles an msi database into WiX source.
@@ -42,14 +40,7 @@ namespace WixToolset.Core.WindowsInstaller
40
private static readonly string[] IconControlAttributes = { "Image", null, null, null, "FixedSize", "Icon16", "Icon32" };
41
private static readonly string[] BitmapControlAttributes = { "Image", null, null, null, "FixedSize" };
42
private static readonly string[] CheckboxControlAttributes = { null, "PushLike", "Bitmap", "Icon", "FixedSize", "Icon16", "Icon32" };
45
-
46
- private bool compressed;
47
- private bool shortNames;
48
- private DecompilerCore core;
49
- private string modularizationGuid;
50
- private readonly Hashtable patchTargetFiles;
51
- private readonly Hashtable sequenceElements;
52
- private readonly TableDefinitionCollection tableDefinitions;
43
+ private XElement uiElement;
44
45
/// <summary>
46
/// Creates a new decompiler object with a default set of table definitions.
@@ -58,7 +49,7 @@ namespace WixToolset.Core.WindowsInstaller
49
{
50
this.Messaging = messaging;
51
this.Extensions = extensions;
61
- this.BaseSourcePath = String.IsNullOrEmpty(baseSourcePath) ? "SourceDir" : baseSourcePath;
52
+ this.BaseSourcePath = baseSourcePath ?? "SourceDir";
53
this.SuppressCustomTables = suppressCustomTables;
54
this.SuppressDroppingEmptyTables = suppressDroppingEmptyTables;
55
this.SuppressUI = suppressUI;
@@ -67,9 +58,7 @@ namespace WixToolset.Core.WindowsInstaller
58
this.ExtensionsByTableName = new Dictionary<string, IWindowsInstallerBackendDecompilerExtension>();
59
this.StandardActions = WindowsInstallerStandard.StandardActions().ToDictionary(a => a.Id.Id);
60
70
- this.patchTargetFiles = new Hashtable();
71
- this.sequenceElements = new Hashtable();
72
- this.tableDefinitions = new TableDefinitionCollection();
61
+ this.TableDefinitions = new TableDefinitionCollection();
62
}
63
64
private IMessaging Messaging { get; }
@@ -94,6 +83,37 @@ namespace WixToolset.Core.WindowsInstaller
83
84
private Dictionary<string, WixActionSymbol> StandardActions { get; }
85
86
+ private bool Compressed { get; set; }
87
+
88
+ private XElement RootElement { get; set; }
89
+
90
+ private TableDefinitionCollection TableDefinitions { get; }
91
+
92
+ private bool ShortNames { get; set; }
93
+
94
+ private string ModularizationGuid { get; set; }
95
+
96
+ public XElement UIElement
97
+ {
98
+ get
99
+ {
100
+ if (null == this.uiElement)
101
+ {
102
+ this.uiElement = new XElement(Names.UIElement);
103
+ this.RootElement.Add(this.uiElement);
104
+ }
105
+
106
+ return this.uiElement;
107
+ }
108
+ }
109
+
110
+ public Dictionary<string, XElement> Singletons { get; } = new Dictionary<string, XElement>();
111
+
112
+ public Dictionary<string, XElement> IndexedElements { get; } = new Dictionary<string, XElement>();
113
+
114
+ public Dictionary<string, XElement> PatchTargetFiles { get; } = new Dictionary<string, XElement>();
115
+
116
+
117
/// <summary>
118
/// Decompile the database file.
119
/// </summary>
@@ -109,18 +129,18 @@ namespace WixToolset.Core.WindowsInstaller
129
this.OutputType = output.Type;
130
131
// collect the table definitions from the output
112
- this.tableDefinitions.Clear();
132
+ this.TableDefinitions.Clear();
133
foreach (var table in output.Tables)
134
{
115
- this.tableDefinitions.Add(table.Definition);
135
+ this.TableDefinitions.Add(table.Definition);
136
}
137
138
// add any missing standard and wix-specific table definitions
139
foreach (var tableDefinition in WindowsInstallerTableDefinitions.All)
140
{
121
- if (!this.tableDefinitions.Contains(tableDefinition.Name))
141
+ if (!this.TableDefinitions.Contains(tableDefinition.Name))
142
{
123
- this.tableDefinitions.Add(tableDefinition);
143
+ this.TableDefinitions.Add(tableDefinition);
144
}
145
}
146
@@ -132,62 +152,46 @@ namespace WixToolset.Core.WindowsInstaller
152
}
153
#endif
154
135
- var wixElement = new Wix.Wix();
136
- Wix.IParentElement rootElement;
137
-
155
switch (this.OutputType)
156
{
140
- case OutputType.Module:
141
- rootElement = new Wix.Module();
142
- break;
143
- case OutputType.PatchCreation:
144
- rootElement = new Wix.PatchCreation();
145
- break;
146
- case OutputType.Product:
147
- rootElement = new Wix.Product();
148
- break;
149
- default:
150
- throw new InvalidOperationException("Unknown output type.");
157
+ case OutputType.Module:
158
+ this.RootElement = new XElement(Names.ModuleElement);
159
+ break;
160
+ case OutputType.PatchCreation:
161
+ this.RootElement = new XElement(Names.PatchCreationElement);
162
+ break;
163
+ case OutputType.Product:
164
+ this.RootElement = new XElement(Names.ProductElement);
165
+ break;
166
+ default:
167
+ throw new InvalidOperationException("Unknown output type.");
168
}
152
- wixElement.AddChild((Wix.ISchemaElement)rootElement);
169
+
170
+ var xWix = new XElement(Names.WixElement, this.RootElement);
171
172
// try to decompile the database file
155
- try
173
+ // stop processing if an error previously occurred
174
+ if (this.Messaging.EncounteredError)
175
{
157
- this.core = new DecompilerCore(rootElement);
158
-
159
- // stop processing if an error previously occurred
160
- if (this.Messaging.EncounteredError)
161
- {
162
- return null;
163
- }
164
-
165
- this.InitializeDecompile(output.Tables, output.Codepage);
166
-
167
- // stop processing if an error previously occurred
168
- if (this.Messaging.EncounteredError)
169
- {
170
- return null;
171
- }
176
+ return null;
177
+ }
178
173
- // decompile the tables
174
- this.DecompileTables(output);
179
+ this.InitializeDecompile(output.Tables, output.Codepage);
180
176
- // finalize the decompiler and its extensions
177
- this.FinalizeDecompile(output.Tables);
178
- }
179
- finally
181
+ // stop processing if an error previously occurred
182
+ if (this.Messaging.EncounteredError)
183
{
181
- this.core = null;
184
+ return null;
185
}
186
184
- var document = new XDocument();
185
- using (var writer = document.CreateWriter())
186
- {
187
- wixElement.OutputXml(writer);
188
- }
187
+ // decompile the tables
188
+ this.DecompileTables(output);
189
+
190
+ // finalize the decompiler and its extensions
191
+ this.FinalizeDecompile(output.Tables);
192
193
// return the XML document only if decompilation completed successfully
194
+ var document = new XDocument(xWix);
195
return this.Messaging.EncounteredError ? null : document;
196
}
197
@@ -211,51 +215,157 @@ namespace WixToolset.Core.WindowsInstaller
215
}
216
#endif
217
218
+ /// <summary>
219
+ /// Gets the element corresponding to the row it came from.
220
+ /// </summary>
221
+ /// <param name="row">The row corresponding to the element.</param>
222
+ /// <returns>The indexed element.</returns>
223
+ public XElement GetIndexedElement(WixToolset.Data.WindowsInstaller.Row row) => this.GetIndexedElement(row.TableDefinition.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter));
224
+
225
+ /// <summary>
226
+ /// Gets the element corresponding to the primary key of the given table.
227
+ /// </summary>
228
+ /// <param name="table">The table corresponding to the element.</param>
229
+ /// <param name="primaryKey">The primary key corresponding to the element.</param>
230
+ /// <returns>The indexed element.</returns>
231
+ public XElement GetIndexedElement(string table, params string[] primaryKey) => this.IndexedElements[String.Concat(table, ':', String.Join(DecompilerConstants.PrimaryKeyDelimiterString, primaryKey))];
232
+
233
+ /// <summary>
234
+ /// Gets the element corresponding to the primary key of the given table.
235
+ /// </summary>
236
+ /// <param name="table">The table corresponding to the element.</param>
237
+ /// <param name="primaryKey">The primary key corresponding to the element.</param>
238
+ /// <returns>The indexed element.</returns>
239
+ public bool TryGetIndexedElement(WixToolset.Data.WindowsInstaller.Row row, out XElement xElement) => this.TryGetIndexedElement(row.TableDefinition.Name, out xElement, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter));
240
+
241
+ /// <summary>
242
+ /// Gets the element corresponding to the primary key of the given table.
243
+ /// </summary>
244
+ /// <param name="table">The table corresponding to the element.</param>
245
+ /// <param name="primaryKey">The primary key corresponding to the element.</param>
246
+ /// <returns>The indexed element.</returns>
247
+ public bool TryGetIndexedElement(string table, out XElement xElement, params string[] primaryKey) => this.IndexedElements.TryGetValue(String.Concat(table, ':', String.Join(DecompilerConstants.PrimaryKeyDelimiterString, primaryKey)), out xElement);
248
+
249
+ /// <summary>
250
+ /// Index an element by its corresponding row.
251
+ /// </summary>
252
+ /// <param name="row">The row corresponding to the element.</param>
253
+ /// <param name="element">The element to index.</param>
254
+ public void IndexElement(WixToolset.Data.WindowsInstaller.Row row, XElement element)
255
+ {
256
+ this.IndexedElements.Add(String.Concat(row.TableDefinition.Name, ':', row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)), element);
257
+ }
258
+
259
+ /// <summary>
260
+ /// Index an element by its corresponding row.
261
+ /// </summary>
262
+ /// <param name="row">The row corresponding to the element.</param>
263
+ /// <param name="element">The element to index.</param>
264
+ public void IndexElement(XElement element, string table, params string[] primaryKey)
265
+ {
266
+ this.IndexedElements.Add(String.Concat(table, ':', String.Join(DecompilerConstants.PrimaryKeyDelimiterString, primaryKey)), element);
267
+ }
268
+
269
+ private Dictionary<string, List<XElement>> IndexTableOneToMany(IEnumerable<Row> rows, int column = 0)
270
+ {
271
+ return rows
272
+ .ToLookup(row => row.FieldAsString(column), row => this.GetIndexedElement(row))
273
+ .ToDictionary(lookup => lookup.Key, lookup => lookup.ToList());
274
+ }
275
+
276
+ private Dictionary<string, List<XElement>> IndexTableOneToMany(TableIndexedCollection tables, string tableName, int column = 0) => this.IndexTableOneToMany(tables[tableName]?.Rows ?? Enumerable.Empty<Row>(), column);
277
+
278
+ private Dictionary<string, List<XElement>> IndexTableOneToMany(Table table, int column = 0) => this.IndexTableOneToMany(table?.Rows ?? Enumerable.Empty<Row>(), column);
279
+
280
+ private void AddChildToParent(string parentName, XElement xChild, Row row, int column)
281
+ {
282
+ var key = row.FieldAsString(column);
283
+ if (this.TryGetIndexedElement(parentName, out var xParent, key))
284
+ {
285
+ xParent.Add(xChild);
286
+ }
287
+ else
288
+ {
289
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, row.Table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row.Fields[column].Column.Name, key, parentName));
290
+ }
291
+ }
292
+
293
+ private static XAttribute XAttributeIfNotNull(string attributeName, Row row, int column) => row.IsColumnNull(column) ? null : new XAttribute(attributeName, row.FieldAsString(column));
294
+
295
+ private static void SetAttributeIfNotNull(XElement xElement, string attributeName, string value)
296
+ {
297
+ if (!String.IsNullOrEmpty(value))
298
+ {
299
+ xElement.SetAttributeValue(attributeName, value);
300
+ }
301
+ }
302
+
303
+ private static void SetAttributeIfNotNull(XElement xElement, string attributeName, int? value)
304
+ {
305
+ if (value.HasValue)
306
+ {
307
+ xElement.SetAttributeValue(attributeName, value);
308
+ }
309
+ }
310
+
311
+ /// <summary>
312
+ /// Convert an Int32 into a DateTime.
313
+ /// </summary>
314
+ /// <param name="value">The Int32 value.</param>
315
+ /// <returns>The DateTime.</returns>
316
+ private static DateTime ConvertIntegerToDateTime(int value)
317
+ {
318
+ var date = value / 65536;
319
+ var time = value % 65536;
320
+
321
+ return new DateTime(1980 + (date / 512), (date % 512) / 32, date % 32, time / 2048, (time % 2048) / 32, (time % 32) * 2);
322
+ }
323
+
324
/// <summary>
325
/// Set the common control attributes in a control element.
326
/// </summary>
327
/// <param name="attributes">The control attributes.</param>
328
/// <param name="control">The control element.</param>
219
- private static void SetControlAttributes(int attributes, Wix.Control control)
329
+ private static void SetControlAttributes(int attributes, XElement xControl)
330
{
331
if (0 == (attributes & WindowsInstallerConstants.MsidbControlAttributesEnabled))
332
{
223
- control.Disabled = Wix.YesNoType.yes;
333
+ xControl.SetAttributeValue("Disabled", "yes");
334
}
335
336
if (WindowsInstallerConstants.MsidbControlAttributesIndirect == (attributes & WindowsInstallerConstants.MsidbControlAttributesIndirect))
337
{
228
- control.Indirect = Wix.YesNoType.yes;
338
+ xControl.SetAttributeValue("Indirect", "yes");
339
}
340
341
if (WindowsInstallerConstants.MsidbControlAttributesInteger == (attributes & WindowsInstallerConstants.MsidbControlAttributesInteger))
342
{
233
- control.Integer = Wix.YesNoType.yes;
343
+ xControl.SetAttributeValue("Integer", "yes");
344
}
345
346
if (WindowsInstallerConstants.MsidbControlAttributesLeftScroll == (attributes & WindowsInstallerConstants.MsidbControlAttributesLeftScroll))
347
{
238
- control.LeftScroll = Wix.YesNoType.yes;
348
+ xControl.SetAttributeValue("LeftScroll", "yes");
349
}
350
351
if (WindowsInstallerConstants.MsidbControlAttributesRightAligned == (attributes & WindowsInstallerConstants.MsidbControlAttributesRightAligned))
352
{
243
- control.RightAligned = Wix.YesNoType.yes;
353
+ xControl.SetAttributeValue("RightAligned", "yes");
354
}
355
356
if (WindowsInstallerConstants.MsidbControlAttributesRTLRO == (attributes & WindowsInstallerConstants.MsidbControlAttributesRTLRO))
357
{
248
- control.RightToLeft = Wix.YesNoType.yes;
358
+ xControl.SetAttributeValue("RightToLeft", "yes");
359
}
360
361
if (WindowsInstallerConstants.MsidbControlAttributesSunken == (attributes & WindowsInstallerConstants.MsidbControlAttributesSunken))
362
{
253
- control.Sunken = Wix.YesNoType.yes;
363
+ xControl.SetAttributeValue("Sunken", "yes");
364
}
365
366
if (0 == (attributes & WindowsInstallerConstants.MsidbControlAttributesVisible))
367
{
258
- control.Hidden = Wix.YesNoType.yes;
368
+ xControl.SetAttributeValue("Hidden", "yes");
369
}
370
}
371
@@ -265,137 +375,93 @@ namespace WixToolset.Core.WindowsInstaller
375
/// <param name="actionSymbol">The action from which the element should be created.</param>
376
private void CreateActionElement(WixActionSymbol actionSymbol)
377
{
268
- Wix.ISchemaElement actionElement = null;
378
+ XElement xAction;
379
270
- if (null != this.core.GetIndexedElement("CustomAction", actionSymbol.Action)) // custom action
380
+ if (this.TryGetIndexedElement("CustomAction", out var _, actionSymbol.Action)) // custom action
381
{
272
- var custom = new Wix.Custom();
273
-
274
- custom.Action = actionSymbol.Action;
275
-
276
- if (null != actionSymbol.Condition)
277
- {
278
- custom.Content = actionSymbol.Condition;
279
- }
382
+ xAction = new XElement(Names.CustomElement,
383
+ new XAttribute("Action", actionSymbol.Action),
384
+ String.IsNullOrEmpty(actionSymbol.Condition) ? null : new XAttribute("Condition", actionSymbol.Condition));
385
386
switch (actionSymbol.Sequence)
387
{
283
- case (-4):
284
- custom.OnExit = Wix.ExitType.suspend;
285
- break;
286
- case (-3):
287
- custom.OnExit = Wix.ExitType.error;
288
- break;
289
- case (-2):
290
- custom.OnExit = Wix.ExitType.cancel;
291
- break;
292
- case (-1):
293
- custom.OnExit = Wix.ExitType.success;
294
- break;
295
- default:
296
- if (null != actionSymbol.Before)
297
- {
298
- custom.Before = actionSymbol.Before;
299
- }
300
- else if (null != actionSymbol.After)
301
- {
302
- custom.After = actionSymbol.After;
303
- }
304
- else if (actionSymbol.Sequence.HasValue)
305
- {
306
- custom.Sequence = actionSymbol.Sequence.Value;
307
- }
308
- break;
388
+ case (-4):
389
+ xAction.SetAttributeValue("OnExit", "suspend");
390
+ break;
391
+ case (-3):
392
+ xAction.SetAttributeValue("OnExit", "error");
393
+ break;
394
+ case (-2):
395
+ xAction.SetAttributeValue("OnExit", "cancel");
396
+ break;
397
+ case (-1):
398
+ xAction.SetAttributeValue("OnExit", "success");
399
+ break;
400
+ default:
401
+ if (null != actionSymbol.Before)
402
+ {
403
+ xAction.SetAttributeValue("Before", actionSymbol.Before);
404
+ }
405
+ else if (null != actionSymbol.After)
406
+ {
407
+ xAction.SetAttributeValue("After", actionSymbol.After);
408
+ }
409
+ else if (actionSymbol.Sequence.HasValue)
410
+ {
411
+ xAction.SetAttributeValue("Sequence", actionSymbol.Sequence.Value);
412
+ }
413
+ break;
414
}
310
-
311
- actionElement = custom;
415
}
313
- else if (null != this.core.GetIndexedElement("Dialog", actionSymbol.Action)) // dialog
416
+ else if (this.TryGetIndexedElement("Dialog", out var _, actionSymbol.Action)) // dialog
417
{
315
- var show = new Wix.Show();
316
-
317
- show.Dialog = actionSymbol.Action;
318
-
319
- if (null != actionSymbol.Condition)
320
- {
321
- show.Content = actionSymbol.Condition;
322
- }
418
+ xAction = new XElement(Names.CustomElement,
419
+ new XAttribute("Dialog", actionSymbol.Action),
420
+ new XAttribute("Condition", actionSymbol.Condition));
421
422
switch (actionSymbol.Sequence)
423
{
326
- case (-4):
327
- show.OnExit = Wix.ExitType.suspend;
328
- break;
329
- case (-3):
330
- show.OnExit = Wix.ExitType.error;
331
- break;
332
- case (-2):
333
- show.OnExit = Wix.ExitType.cancel;
334
- break;
335
- case (-1):
336
- show.OnExit = Wix.ExitType.success;
337
- break;
338
- default:
339
- if (null != actionSymbol.Before)
340
- {
341
- show.Before = actionSymbol.Before;
342
- }
343
- else if (null != actionSymbol.After)
344
- {
345
- show.After = actionSymbol.After;
346
- }
347
- else if (actionSymbol.Sequence.HasValue)
348
- {
349
- show.Sequence = actionSymbol.Sequence.Value;
350
- }
351
- break;
424
+ case (-4):
425
+ xAction.SetAttributeValue("OnExit", "suspend");
426
+ break;
427
+ case (-3):
428
+ xAction.SetAttributeValue("OnExit", "error");
429
+ break;
430
+ case (-2):
431
+ xAction.SetAttributeValue("OnExit", "cancel");
432
+ break;
433
+ case (-1):
434
+ xAction.SetAttributeValue("OnExit", "success");
435
+ break;
436
+ default:
437
+ SetAttributeIfNotNull(xAction, "Before", actionSymbol.Before);
438
+ SetAttributeIfNotNull(xAction, "After", actionSymbol.After);
439
+ SetAttributeIfNotNull(xAction, "Sequence", actionSymbol.Sequence);
440
+ break;
441
}
353
-
354
- actionElement = show;
442
}
443
else // possibly a standard action without suggested sequence information
444
{
358
- actionElement = this.CreateStandardActionElement(actionSymbol);
445
+ xAction = this.CreateStandardActionElement(actionSymbol);
446
}
447
448
// add the action element to the appropriate sequence element
362
- if (null != actionElement)
449
+ if (null != xAction)
450
{
451
var sequenceTable = actionSymbol.SequenceTable.ToString();
365
- var sequenceElement = (Wix.IParentElement)this.sequenceElements[sequenceTable];
366
-
367
- if (null == sequenceElement)
452
+ if (!this.Singletons.TryGetValue(sequenceTable, out var xSequence))
453
{
369
- switch (actionSymbol.SequenceTable)
370
- {
371
- case SequenceTable.AdminExecuteSequence:
372
- sequenceElement = new Wix.AdminExecuteSequence();
373
- break;
374
- case SequenceTable.AdminUISequence:
375
- sequenceElement = new Wix.AdminUISequence();
376
- break;
377
- case SequenceTable.AdvertiseExecuteSequence:
378
- sequenceElement = new Wix.AdvertiseExecuteSequence();
379
- break;
380
- case SequenceTable.InstallExecuteSequence:
381
- sequenceElement = new Wix.InstallExecuteSequence();
382
- break;
383
- case SequenceTable.InstallUISequence:
384
- sequenceElement = new Wix.InstallUISequence();
385
- break;
386
- default:
387
- throw new InvalidOperationException("Unknown sequence table.");
388
- }
454
+ xSequence = new XElement(Names.WxsNamespace + sequenceTable);
455
390
- this.core.RootElement.AddChild((Wix.ISchemaElement)sequenceElement);
391
- this.sequenceElements.Add(sequenceTable, sequenceElement);
456
+ this.RootElement.Add(xSequence);
457
+ this.Singletons.Add(sequenceTable, xSequence);
458
}
459
460
try
461
{
396
- sequenceElement.AddChild(actionElement);
462
+ xSequence.Add(xAction);
463
}
398
- catch (System.ArgumentException) // action/dialog is not valid for this sequence
464
+ catch (ArgumentException) // action/dialog is not valid for this sequence
465
{
466
this.Messaging.Write(WarningMessages.IllegalActionInSequence(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
467
}
@@ -407,294 +473,129 @@ namespace WixToolset.Core.WindowsInstaller
473
/// </summary>
474
/// <param name="actionSymbol">The action row from which the element should be created.</param>
475
/// <returns>The created element.</returns>
410
- private Wix.ISchemaElement CreateStandardActionElement(WixActionSymbol actionSymbol)
476
+ private XElement CreateStandardActionElement(WixActionSymbol actionSymbol)
477
{
412
- Wix.ActionSequenceType actionElement = null;
478
+ XElement xStandardAction = null;
479
480
switch (actionSymbol.Action)
481
{
416
- case "AllocateRegistrySpace":
417
- actionElement = new Wix.AllocateRegistrySpace();
418
- break;
419
- case "AppSearch":
420
- this.StandardActions.TryGetValue(actionSymbol.Id.Id, out var appSearchActionRow);
421
-
422
- if (null != actionSymbol.Before || null != actionSymbol.After || (null != appSearchActionRow && actionSymbol.Sequence != appSearchActionRow.Sequence))
423
- {
424
- var appSearch = new Wix.AppSearch();
425
-
426
- if (null != actionSymbol.Condition)
427
- {
428
- appSearch.Content = actionSymbol.Condition;
429
- }
430
-
431
- if (null != actionSymbol.Before)
432
- {
433
- appSearch.Before = actionSymbol.Before;
434
- }
435
- else if (null != actionSymbol.After)
436
- {
437
- appSearch.After = actionSymbol.After;
438
- }
439
- else if (actionSymbol.Sequence.HasValue)
440
- {
441
- appSearch.Sequence = actionSymbol.Sequence.Value;
442
- }
443
-
444
- return appSearch;
445
- }
446
- break;
447
- case "BindImage":
448
- actionElement = new Wix.BindImage();
449
- break;
450
- case "CCPSearch":
451
- var ccpSearch = new Wix.CCPSearch();
452
- Decompiler.SequenceRelativeAction(actionSymbol, ccpSearch);
453
- return ccpSearch;
454
- case "CostFinalize":
455
- actionElement = new Wix.CostFinalize();
456
- break;
457
- case "CostInitialize":
458
- actionElement = new Wix.CostInitialize();
459
- break;
460
- case "CreateFolders":
461
- actionElement = new Wix.CreateFolders();
462
- break;
463
- case "CreateShortcuts":
464
- actionElement = new Wix.CreateShortcuts();
465
- break;
466
- case "DeleteServices":
467
- actionElement = new Wix.DeleteServices();
468
- break;
469
- case "DisableRollback":
470
- var disableRollback = new Wix.DisableRollback();
471
- Decompiler.SequenceRelativeAction(actionSymbol, disableRollback);
472
- return disableRollback;
473
- case "DuplicateFiles":
474
- actionElement = new Wix.DuplicateFiles();
475
- break;
476
- case "ExecuteAction":
477
- actionElement = new Wix.ExecuteAction();
478
- break;
479
- case "FileCost":
480
- actionElement = new Wix.FileCost();
481
- break;
482
- case "FindRelatedProducts":
483
- var findRelatedProducts = new Wix.FindRelatedProducts();
484
- Decompiler.SequenceRelativeAction(actionSymbol, findRelatedProducts);
485
- return findRelatedProducts;
486
- case "ForceReboot":
487
- var forceReboot = new Wix.ForceReboot();
488
- Decompiler.SequenceRelativeAction(actionSymbol, forceReboot);
489
- return forceReboot;
490
- case "InstallAdminPackage":
491
- actionElement = new Wix.InstallAdminPackage();
492
- break;
493
- case "InstallExecute":
494
- var installExecute = new Wix.InstallExecute();
495
- Decompiler.SequenceRelativeAction(actionSymbol, installExecute);
496
- return installExecute;
497
- case "InstallExecuteAgain":
498
- var installExecuteAgain = new Wix.InstallExecuteAgain();
499
- Decompiler.SequenceRelativeAction(actionSymbol, installExecuteAgain);
500
- return installExecuteAgain;
501
- case "InstallFiles":
502
- actionElement = new Wix.InstallFiles();
503
- break;
504
- case "InstallFinalize":
505
- actionElement = new Wix.InstallFinalize();
506
- break;
507
- case "InstallInitialize":
508
- actionElement = new Wix.InstallInitialize();
509
- break;
510
- case "InstallODBC":
511
- actionElement = new Wix.InstallODBC();
512
- break;
513
- case "InstallServices":
514
- actionElement = new Wix.InstallServices();
515
- break;
516
- case "InstallValidate":
517
- actionElement = new Wix.InstallValidate();
518
- break;
519
- case "IsolateComponents":
520
- actionElement = new Wix.IsolateComponents();
521
- break;
522
- case "LaunchConditions":
523
- var launchConditions = new Wix.LaunchConditions();
524
- Decompiler.SequenceRelativeAction(actionSymbol, launchConditions);
525
- return launchConditions;
526
- case "MigrateFeatureStates":
527
- actionElement = new Wix.MigrateFeatureStates();
528
- break;
529
- case "MoveFiles":
530
- actionElement = new Wix.MoveFiles();
531
- break;
532
- case "MsiPublishAssemblies":
533
- actionElement = new Wix.MsiPublishAssemblies();
534
- break;
535
- case "MsiUnpublishAssemblies":
536
- actionElement = new Wix.MsiUnpublishAssemblies();
537
- break;
538
- case "PatchFiles":
539
- actionElement = new Wix.PatchFiles();
540
- break;
541
- case "ProcessComponents":
542
- actionElement = new Wix.ProcessComponents();
543
- break;
544
- case "PublishComponents":
545
- actionElement = new Wix.PublishComponents();
546
- break;
547
- case "PublishFeatures":
548
- actionElement = new Wix.PublishFeatures();
549
- break;
550
- case "PublishProduct":
551
- actionElement = new Wix.PublishProduct();
552
- break;
553
- case "RegisterClassInfo":
554
- actionElement = new Wix.RegisterClassInfo();
555
- break;
556
- case "RegisterComPlus":
557
- actionElement = new Wix.RegisterComPlus();
558
- break;
559
- case "RegisterExtensionInfo":
560
- actionElement = new Wix.RegisterExtensionInfo();
561
- break;
562
- case "RegisterFonts":
563
- actionElement = new Wix.RegisterFonts();
564
- break;
565
- case "RegisterMIMEInfo":
566
- actionElement = new Wix.RegisterMIMEInfo();
567
- break;
568
- case "RegisterProduct":
569
- actionElement = new Wix.RegisterProduct();
570
- break;
571
- case "RegisterProgIdInfo":
572
- actionElement = new Wix.RegisterProgIdInfo();
573
- break;
574
- case "RegisterTypeLibraries":
575
- actionElement = new Wix.RegisterTypeLibraries();
576
- break;
577
- case "RegisterUser":
578
- actionElement = new Wix.RegisterUser();
579
- break;
580
- case "RemoveDuplicateFiles":
581
- actionElement = new Wix.RemoveDuplicateFiles();
582
- break;
583
- case "RemoveEnvironmentStrings":
584
- actionElement = new Wix.RemoveEnvironmentStrings();
585
- break;
586
- case "RemoveExistingProducts":
587
- var removeExistingProducts = new Wix.RemoveExistingProducts();
588
- Decompiler.SequenceRelativeAction(actionSymbol, removeExistingProducts);
589
- return removeExistingProducts;
590
- case "RemoveFiles":
591
- actionElement = new Wix.RemoveFiles();
592
- break;
593
- case "RemoveFolders":
594
- actionElement = new Wix.RemoveFolders();
595
- break;
596
- case "RemoveIniValues":
597
- actionElement = new Wix.RemoveIniValues();
598
- break;
599
- case "RemoveODBC":
600
- actionElement = new Wix.RemoveODBC();
601
- break;
602
- case "RemoveRegistryValues":
603
- actionElement = new Wix.RemoveRegistryValues();
604
- break;
605
- case "RemoveShortcuts":
606
- actionElement = new Wix.RemoveShortcuts();
607
- break;
608
- case "ResolveSource":
609
- var resolveSource = new Wix.ResolveSource();
610
- Decompiler.SequenceRelativeAction(actionSymbol, resolveSource);
611
- return resolveSource;
612
- case "RMCCPSearch":
613
- var rmccpSearch = new Wix.RMCCPSearch();
614
- Decompiler.SequenceRelativeAction(actionSymbol, rmccpSearch);
615
- return rmccpSearch;
616
- case "ScheduleReboot":
617
- var scheduleReboot = new Wix.ScheduleReboot();
618
- Decompiler.SequenceRelativeAction(actionSymbol, scheduleReboot);
619
- return scheduleReboot;
620
- case "SelfRegModules":
621
- actionElement = new Wix.SelfRegModules();
622
- break;
623
- case "SelfUnregModules":
624
- actionElement = new Wix.SelfUnregModules();
625
- break;
626
- case "SetODBCFolders":
627
- actionElement = new Wix.SetODBCFolders();
628
- break;
629
- case "StartServices":
630
- actionElement = new Wix.StartServices();
631
- break;
632
- case "StopServices":
633
- actionElement = new Wix.StopServices();
634
- break;
635
- case "UnpublishComponents":
636
- actionElement = new Wix.UnpublishComponents();
637
- break;
638
- case "UnpublishFeatures":
639
- actionElement = new Wix.UnpublishFeatures();
640
- break;
641
- case "UnregisterClassInfo":
642
- actionElement = new Wix.UnregisterClassInfo();
643
- break;
644
- case "UnregisterComPlus":
645
- actionElement = new Wix.UnregisterComPlus();
646
- break;
647
- case "UnregisterExtensionInfo":
648
- actionElement = new Wix.UnregisterExtensionInfo();
649
- break;
650
- case "UnregisterFonts":
651
- actionElement = new Wix.UnregisterFonts();
652
- break;
653
- case "UnregisterMIMEInfo":
654
- actionElement = new Wix.UnregisterMIMEInfo();
655
- break;
656
- case "UnregisterProgIdInfo":
657
- actionElement = new Wix.UnregisterProgIdInfo();
658
- break;
659
- case "UnregisterTypeLibraries":
660
- actionElement = new Wix.UnregisterTypeLibraries();
661
- break;
662
- case "ValidateProductID":
663
- actionElement = new Wix.ValidateProductID();
664
- break;
665
- case "WriteEnvironmentStrings":
666
- actionElement = new Wix.WriteEnvironmentStrings();
667
- break;
668
- case "WriteIniValues":
669
- actionElement = new Wix.WriteIniValues();
670
- break;
671
- case "WriteRegistryValues":
672
- actionElement = new Wix.WriteRegistryValues();
673
- break;
674
- default:
675
- this.Messaging.Write(WarningMessages.UnknownAction(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
676
- return null;
482
+ case "AllocateRegistrySpace":
483
+ case "BindImage":
484
+ case "CostFinalize":
485
+ case "CostInitialize":
486
+ case "CreateFolders":
487
+ case "CreateShortcuts":
488
+ case "DeleteServices":
489
+ case "DuplicateFiles":
490
+ case "ExecuteAction":
491
+ case "FileCost":
492
+ case "InstallAdminPackage":
493
+ case "InstallFiles":
494
+ case "InstallFinalize":
495
+ case "InstallInitialize":
496
+ case "InstallODBC":
497
+ case "InstallServices":
498
+ case "InstallValidate":
499
+ case "IsolateComponents":
500
+ case "MigrateFeatureStates":
501
+ case "MoveFiles":
502
+ case "MsiPublishAssemblies":
503
+ case "MsiUnpublishAssemblies":
504
+ case "PatchFiles":
505
+ case "ProcessComponents":
506
+ case "PublishComponents":
507
+ case "PublishFeatures":
508
+ case "PublishProduct":
509
+ case "RegisterClassInfo":
510
+ case "RegisterComPlus":
511
+ case "RegisterExtensionInfo":
512
+ case "RegisterFonts":
513
+ case "RegisterMIMEInfo":
514
+ case "RegisterProduct":
515
+ case "RegisterProgIdInfo":
516
+ case "RegisterTypeLibraries":
517
+ case "RegisterUser":
518
+ case "RemoveDuplicateFiles":
519
+ case "RemoveEnvironmentStrings":
520
+ case "RemoveFiles":
521
+ case "RemoveFolders":
522
+ case "RemoveIniValues":
523
+ case "RemoveODBC":
524
+ case "RemoveRegistryValues":
525
+ case "RemoveShortcuts":
526
+ case "SelfRegModules":
527
+ case "SelfUnregModules":
528
+ case "SetODBCFolders":
529
+ case "StartServices":
530
+ case "StopServices":
531
+ case "UnpublishComponents":
532
+ case "UnpublishFeatures":
533
+ case "UnregisterClassInfo":
534
+ case "UnregisterComPlus":
535
+ case "UnregisterExtensionInfo":
536
+ case "UnregisterFonts":
537
+ case "UnregisterMIMEInfo":
538
+ case "UnregisterProgIdInfo":
539
+ case "UnregisterTypeLibraries":
540
+ case "ValidateProductID":
541
+ case "WriteEnvironmentStrings":
542
+ case "WriteIniValues":
543
+ case "WriteRegistryValues":
544
+ xStandardAction = new XElement(Names.WxsNamespace + actionSymbol.Action);
545
+ break;
546
+
547
+ case "AppSearch":
548
+ this.StandardActions.TryGetValue(actionSymbol.Id.Id, out var appSearchActionRow);
549
+
550
+ if (null != actionSymbol.Before || null != actionSymbol.After || (null != appSearchActionRow && actionSymbol.Sequence != appSearchActionRow.Sequence))
551
+ {
552
+ xStandardAction = new XElement(Names.AppSearchElement);
553
+
554
+ SetAttributeIfNotNull(xStandardAction, "Condition", actionSymbol.Condition);
555
+ SetAttributeIfNotNull(xStandardAction, "Before", actionSymbol.Before);
556
+ SetAttributeIfNotNull(xStandardAction, "After", actionSymbol.After);
557
+ SetAttributeIfNotNull(xStandardAction, "Sequence", actionSymbol.Sequence);
558
+
559
+ return xStandardAction;
560
+ }
561
+ break;
562
+
563
+ case "CCPSearch":
564
+ case "DisableRollback":
565
+ case "FindRelatedProducts":
566
+ case "ForceReboot":
567
+ case "InstallExecute":
568
+ case "InstallExecuteAgain":
569
+ case "LaunchConditions":
570
+ case "RemoveExistingProducts":
571
+ case "ResolveSource":
572
+ case "RMCCPSearch":
573
+ case "ScheduleReboot":
574
+ xStandardAction = new XElement(Names.WxsNamespace + actionSymbol.Action);
575
+ Decompiler.SequenceRelativeAction(actionSymbol, xStandardAction);
576
+ return xStandardAction;
577
+
578
+ default:
579
+ this.Messaging.Write(WarningMessages.UnknownAction(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
580
+ return null;
581
}
582
679
- if (actionElement != null)
583
+ if (xStandardAction != null)
584
{
681
- this.SequenceStandardAction(actionSymbol, actionElement);
585
+ this.SequenceStandardAction(actionSymbol, xStandardAction);
586
}
587
684
- return actionElement;
588
+ return xStandardAction;
589
}
590
591
/// <summary>
688
- /// Applies the condition and sequence to a standard action element based on the action row data.
592
+ /// Applies the condition and sequence to a standard action element based on the action symbol data.
593
/// </summary>
594
/// <param name="actionSymbol">Action data from the database.</param>
691
- /// <param name="actionElement">Element to be sequenced.</param>
692
- private void SequenceStandardAction(WixActionSymbol actionSymbol, Wix.ActionSequenceType actionElement)
595
+ /// <param name="xAction">Element to be sequenced.</param>
596
+ private void SequenceStandardAction(WixActionSymbol actionSymbol, XElement xAction)
597
{
694
- if (null != actionSymbol.Condition)
695
- {
696
- actionElement.Content = actionSymbol.Condition;
697
- }
598
+ xAction.SetAttributeValue("Condition", actionSymbol.Condition);
599
600
if ((null != actionSymbol.Before || null != actionSymbol.After) && 0 == actionSymbol.Sequence)
601
{
@@ -702,7 +603,7 @@ namespace WixToolset.Core.WindowsInstaller
603
}
604
else if (actionSymbol.Sequence.HasValue)
605
{
705
- actionElement.Sequence = actionSymbol.Sequence.Value;
606
+ xAction.SetAttributeValue("Sequence", actionSymbol.Sequence.Value);
607
}
608
}
609
@@ -710,26 +611,13 @@ namespace WixToolset.Core.WindowsInstaller
611
/// Applies the condition and relative sequence to an action element based on the action row data.
612
/// </summary>
613
/// <param name="actionSymbol">Action data from the database.</param>
713
- /// <param name="actionElement">Element to be sequenced.</param>
714
- private static void SequenceRelativeAction(WixActionSymbol actionSymbol, Wix.ActionModuleSequenceType actionElement)
614
+ /// <param name="xAction">Element to be sequenced.</param>
615
+ private static void SequenceRelativeAction(WixActionSymbol actionSymbol, XElement xAction)
616
{
716
- if (null != actionSymbol.Condition)
717
- {
718
- actionElement.Content = actionSymbol.Condition;
719
- }
720
-
721
- if (null != actionSymbol.Before)
722
- {
723
- actionElement.Before = actionSymbol.Before;
724
- }
725
- else if (null != actionSymbol.After)
726
- {
727
- actionElement.After = actionSymbol.After;
728
- }
729
- else if (actionSymbol.Sequence.HasValue)
730
- {
731
- actionElement.Sequence = actionSymbol.Sequence.Value;
732
- }
617
+ SetAttributeIfNotNull(xAction, "Condition", actionSymbol.Condition);
618
+ SetAttributeIfNotNull(xAction, "Before", actionSymbol.Before);
619
+ SetAttributeIfNotNull(xAction, "After", actionSymbol.After);
620
+ SetAttributeIfNotNull(xAction, "Sequence", actionSymbol.Sequence);
621
}
622
623
/// <summary>
@@ -737,24 +625,19 @@ namespace WixToolset.Core.WindowsInstaller
625
/// </summary>
626
/// <param name="id">The identifier of the property.</param>
627
/// <returns>The property element.</returns>
740
- private Wix.Property EnsureProperty(string id)
628
+ private XElement EnsureProperty(string id)
629
{
742
- var property = (Wix.Property)this.core.GetIndexedElement("Property", id);
630
+ XElement xProperty;
631
744
- if (null == property)
632
+ if (!this.TryGetIndexedElement("Property", out xProperty, id))
633
{
746
- property = new Wix.Property();
747
- property.Id = id;
634
+ xProperty = new XElement(Names.PropertyElement, new XAttribute("Id", id));
635
749
- // create a dummy row for indexing
750
- var row = this.tableDefinitions["Property"].CreateRow(null);
751
- row[0] = id;
752
-
753
- this.core.RootElement.AddChild(property);
754
- this.core.IndexElement(row, property);
636
+ this.RootElement.Add(xProperty);
637
+ this.IndexElement(xProperty, "Property", id);
638
}
639
757
- return property;
640
+ return xProperty;
641
}
642
643
/// <summary>
@@ -809,51 +692,37 @@ namespace WixToolset.Core.WindowsInstaller
692
var checkBoxTable = tables["CheckBox"];
693
var controlTable = tables["Control"];
694
812
- var checkBoxes = new Hashtable();
813
- var checkBoxProperties = new Hashtable();
814
-
815
- // index the CheckBox table
816
- if (null != checkBoxTable)
817
- {
818
- foreach (var row in checkBoxTable.Rows)
819
- {
820
- checkBoxes.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row);
821
- checkBoxProperties.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), false);
822
- }
823
- }
695
+ var checkBoxes = checkBoxTable?.Rows.ToDictionary(row => row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter));
696
+ var checkBoxProperties = checkBoxTable?.Rows.ToDictionary(row => row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row => false);
697
698
// enumerate through the Control table, adding CheckBox values where appropriate
699
if (null != controlTable)
700
{
701
foreach (var row in controlTable.Rows)
702
{
830
- var control = (Wix.Control)this.core.GetIndexedElement(row);
703
+ var xControl = this.GetIndexedElement(row);
704
832
- if ("CheckBox" == Convert.ToString(row[2]) && null != row[8])
705
+ if ("CheckBox" == row.FieldAsString(2))
706
{
834
- var checkBoxRow = (Row)checkBoxes[row[8]];
835
-
836
- if (null == checkBoxRow)
837
- {
838
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Control", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Property", Convert.ToString(row[8]), "CheckBox"));
839
- }
840
- else
707
+ var property = row.FieldAsString(8);
708
+ if (!String.IsNullOrEmpty(property) && checkBoxes.TryGetValue(property, out var checkBoxRow))
709
{
710
// if we've seen this property already, create a reference to it
843
- if (Convert.ToBoolean(checkBoxProperties[row[8]]))
711
+ if (checkBoxProperties.TryGetValue(property, out var seen) && seen)
712
{
845
- control.CheckBoxPropertyRef = Convert.ToString(row[8]);
713
+ xControl.SetAttributeValue("CheckBoxPropertyRef", property);
714
}
715
else
716
{
849
- control.Property = Convert.ToString(row[8]);
850
- checkBoxProperties[row[8]] = true;
717
+ xControl.SetAttributeValue("Property", property);
718
+ checkBoxProperties[property] = true;
719
}
720
853
- if (null != checkBoxRow[1])
854
- {
855
- control.CheckBoxValue = Convert.ToString(checkBoxRow[1]);
856
- }
721
+ xControl.SetAttributeValue("CheckBoxValue", checkBoxRow.FieldAsString(1));
722
+ }
723
+ else
724
+ {
725
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Control", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Property", row.FieldAsString(8), "CheckBox"));
726
}
727
}
728
}
@@ -879,60 +748,52 @@ namespace WixToolset.Core.WindowsInstaller
748
{
749
foreach (var row in componentTable.Rows)
750
{
882
- var attributes = Convert.ToInt32(row[3]);
751
+ var attributes = row.FieldAsInteger(3);
752
+ var keyPath = row.FieldAsString(5);
753
884
- if (null == row[5])
754
+ if (String.IsNullOrEmpty(keyPath))
755
{
886
- var component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[0]));
887
-
888
- component.KeyPath = Wix.YesNoType.yes;
756
+ var xComponent = this.GetIndexedElement("Component", row.FieldAsString(0));
757
+ xComponent.SetAttributeValue("KeyPath", "yes");
758
}
759
else if (WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath == (attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath))
760
{
892
- object registryObject = this.core.GetIndexedElement("Registry", Convert.ToString(row[5]));
893
-
894
- if (null != registryObject)
761
+ if (this.TryGetIndexedElement("Registry", out var xRegistry, keyPath))
762
{
896
- var registryValue = registryObject as Wix.RegistryValue;
897
-
898
- if (null != registryValue)
763
+ if (xRegistry.Name.LocalName == "RegistryValue")
764
{
900
- registryValue.KeyPath = Wix.YesNoType.yes;
765
+ xRegistry.SetAttributeValue("KeyPath", "yes");
766
}
767
else
768
{
904
- this.Messaging.Write(WarningMessages.IllegalRegistryKeyPath(row.SourceLineNumbers, "Component", Convert.ToString(row[5])));
769
+ this.Messaging.Write(WarningMessages.IllegalRegistryKeyPath(row.SourceLineNumbers, "Component", keyPath));
770
}
771
}
772
else
773
{
909
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", Convert.ToString(row[5]), "Registry"));
774
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", keyPath, "Registry"));
775
}
776
}
777
else if (WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource == (attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource))
778
{
914
- var odbcDataSource = (Wix.ODBCDataSource)this.core.GetIndexedElement("ODBCDataSource", Convert.ToString(row[5]));
915
-
916
- if (null != odbcDataSource)
779
+ if (this.TryGetIndexedElement("ODBCDataSource", out var xOdbcDataSource, keyPath))
780
{
918
- odbcDataSource.KeyPath = Wix.YesNoType.yes;
781
+ xOdbcDataSource.SetAttributeValue("KeyPath", "yes");
782
}
783
else
784
{
922
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", Convert.ToString(row[5]), "ODBCDataSource"));
785
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", keyPath, "ODBCDataSource"));
786
}
787
}
788
else
789
{
927
- var file = (Wix.File)this.core.GetIndexedElement("File", Convert.ToString(row[5]));
928
-
929
- if (null != file)
790
+ if (this.TryGetIndexedElement("File", out var xFile, keyPath))
791
{
931
- file.KeyPath = Wix.YesNoType.yes;
792
+ xFile.SetAttributeValue("KeyPath", "yes");
793
}
794
else
795
{
935
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", Convert.ToString(row[5]), "File"));
796
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Component", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "KeyPath", keyPath, "File"));
797
}
798
}
799
}
@@ -943,12 +804,10 @@ namespace WixToolset.Core.WindowsInstaller
804
{
805
foreach (FileRow fileRow in fileTable.Rows)
806
{
946
- var component = (Wix.Component)this.core.GetIndexedElement("Component", fileRow.Component);
947
- var file = (Wix.File)this.core.GetIndexedElement(fileRow);
948
-
949
- if (null != component)
807
+ if (this.TryGetIndexedElement("Component", out var xComponent, fileRow.Component)
808
+ && this.TryGetIndexedElement(fileRow, out var xFile))
809
{
951
- component.AddChild(file);
810
+ xComponent.Add(xFile);
811
}
812
else
813
{
@@ -962,16 +821,14 @@ namespace WixToolset.Core.WindowsInstaller
821
{
822
foreach (var row in odbcDataSourceTable.Rows)
823
{
965
- var component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[1]));
966
- var odbcDataSource = (Wix.ODBCDataSource)this.core.GetIndexedElement(row);
967
-
968
- if (null != component)
824
+ if (this.TryGetIndexedElement("Component", out var xComponent, row.FieldAsString(1))
825
+ && this.TryGetIndexedElement(row, out var xOdbcDataSource))
826
{
970
- component.AddChild(odbcDataSource);
827
+ xComponent.Add(xOdbcDataSource);
828
}
829
else
830
{
974
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "ODBCDataSource", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
831
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "ODBCDataSource", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", row.FieldAsString(1), "Component"));
832
}
833
}
834
}
@@ -981,16 +838,14 @@ namespace WixToolset.Core.WindowsInstaller
838
{
839
foreach (var row in registryTable.Rows)
840
{
984
- var component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[5]));
985
- var registryElement = this.core.GetIndexedElement(row);
986
-
987
- if (null != component)
841
+ if (this.TryGetIndexedElement("Component", out var xComponent, row.FieldAsString(5))
842
+ && this.TryGetIndexedElement(row, out var xRegistry))
843
{
989
- component.AddChild(registryElement);
844
+ xComponent.Add(xRegistry);
845
}
846
else
847
{
993
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Registry", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[5]), "Component"));
848
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Registry", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", row.FieldAsString(5), "Component"));
849
}
850
}
851
}
@@ -1012,92 +867,82 @@ namespace WixToolset.Core.WindowsInstaller
867
return;
868
}
869
1015
- var controlTable = tables["Control"];
1016
- var dialogTable = tables["Dialog"];
1017
-
1018
- var addedControls = new Hashtable();
1019
- var controlRows = new Hashtable();
870
+ var addedControls = new HashSet<XElement>();
871
1021
- // index the rows in the control rows (because we need the Control_Next value)
1022
- if (null != controlTable)
1023
- {
1024
- foreach (var row in controlTable.Rows)
1025
- {
1026
- controlRows.Add(row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), row);
1027
- }
1028
- }
872
+ var controlTable = tables["Control"];
873
+ var controlRows = controlTable?.Rows.ToDictionary(row => row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter));
874
875
+ var dialogTable = tables["Dialog"];
876
if (null != dialogTable)
877
{
1032
- foreach (var row in dialogTable.Rows)
878
+ foreach (var dialogRow in dialogTable.Rows)
879
{
1034
- var dialog = (Wix.Dialog)this.core.GetIndexedElement(row);
1035
- var dialogId = Convert.ToString(row[0]);
880
+ var xDialog = this.GetIndexedElement(dialogRow);
881
+ var dialogId = dialogRow.FieldAsString(0);
882
1037
- var control = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(row[7]));
1038
- if (null == control)
883
+ if (!this.TryGetIndexedElement("Control", out var xControl, dialogId, dialogRow.FieldAsString(7)))
884
{
1040
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Dialog", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_First", Convert.ToString(row[7]), "Control"));
885
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(dialogRow.SourceLineNumbers, "Dialog", dialogRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_First", dialogRow.FieldAsString(7), "Control"));
886
}
887
888
// add tabbable controls
1044
- while (null != control)
889
+ while (null != xControl)
890
{
1046
- var controlRow = (Row)controlRows[String.Concat(dialogId, DecompilerConstants.PrimaryKeyDelimiter, control.Id)];
891
+ var controlId = xControl.Attribute("Id");
892
+ var controlRow = controlRows[String.Concat(dialogId, DecompilerConstants.PrimaryKeyDelimiter, controlId)];
893
1048
- control.TabSkip = Wix.YesNoType.no;
1049
- dialog.AddChild(control);
1050
- addedControls.Add(control, null);
894
+ xControl.SetAttributeValue("TabSkip", "no");
895
1052
- if (null != controlRow[10])
896
+ xDialog.Add(xControl);
897
+ addedControls.Add(xControl);
898
+
899
+ var controlNext = controlRow.FieldAsString(10);
900
+ if (!String.IsNullOrEmpty(controlNext))
901
{
1054
- control = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(controlRow[10]));
1055
- if (null != control)
902
+ if (this.TryGetIndexedElement("Control", out xControl, dialogId, controlNext))
903
{
904
// looped back to the first control in the dialog
1058
- if (addedControls.Contains(control))
905
+ if (addedControls.Contains(xControl))
906
{
1060
- control = null;
907
+ xControl = null;
908
}
909
}
910
else
911
{
1065
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(controlRow.SourceLineNumbers, "Control", controlRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", dialogId, "Control_Next", Convert.ToString(controlRow[10]), "Control"));
912
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(controlRow.SourceLineNumbers, "Control", controlRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", dialogId, "Control_Next", controlNext, "Control"));
913
}
914
}
915
else
916
{
1070
- control = null;
917
+ xControl = null;
918
}
919
}
920
921
// set default control
1075
- if (null != row[8])
922
+ var controlDefault = dialogRow.FieldAsString(8);
923
+ if (!String.IsNullOrEmpty(controlDefault))
924
{
1077
- var defaultControl = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(row[8]));
1078
-
1079
- if (null != defaultControl)
925
+ if (this.TryGetIndexedElement("Control", out var xDefaultControl, dialogId, controlDefault))
926
{
1081
- defaultControl.Default = Wix.YesNoType.yes;
927
+ xDefaultControl.SetAttributeValue("Default", "yes");
928
}
929
else
930
{
1085
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Dialog", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_Default", Convert.ToString(row[8]), "Control"));
931
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(dialogRow.SourceLineNumbers, "Dialog", dialogRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_Default", Convert.ToString(dialogRow[8]), "Control"));
932
}
933
}
934
935
// set cancel control
1090
- if (null != row[9])
936
+ var controlCancel = dialogRow.FieldAsString(8);
937
+ if (!String.IsNullOrEmpty(controlCancel))
938
{
1092
- var cancelControl = (Wix.Control)this.core.GetIndexedElement("Control", dialogId, Convert.ToString(row[9]));
1093
-
1094
- if (null != cancelControl)
939
+ if (this.TryGetIndexedElement("Control", out var xCancelControl, dialogId, controlCancel))
940
{
1096
- cancelControl.Cancel = Wix.YesNoType.yes;
941
+ xCancelControl.SetAttributeValue("Cancel", "yes");
942
}
943
else
944
{
1100
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Dialog", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_Cancel", Convert.ToString(row[9]), "Control"));
945
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(dialogRow.SourceLineNumbers, "Dialog", dialogRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog", dialogId, "Control_Cancel", Convert.ToString(dialogRow[9]), "Control"));
946
}
947
}
948
}
@@ -1106,21 +951,20 @@ namespace WixToolset.Core.WindowsInstaller
951
// add the non-tabbable controls to the dialog
952
if (null != controlTable)
953
{
1109
- foreach (var row in controlTable.Rows)
954
+ foreach (var controlRow in controlTable.Rows)
955
{
1111
- var control = (Wix.Control)this.core.GetIndexedElement(row);
1112
- var dialog = (Wix.Dialog)this.core.GetIndexedElement("Dialog", Convert.ToString(row[0]));
1113
-
1114
- if (null == dialog)
956
+ var dialogId = controlRow.FieldAsString(0);
957
+ if (!this.TryGetIndexedElement("Dialog", out var xDialog, dialogId))
958
{
1116
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Control", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", Convert.ToString(row[0]), "Dialog"));
959
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(controlRow.SourceLineNumbers, "Control", controlRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Dialog_", dialogId, "Dialog"));
960
continue;
961
}
962
1120
- if (!addedControls.Contains(control))
963
+ var xControl = this.GetIndexedElement(controlRow);
964
+ if (!addedControls.Contains(xControl))
965
{
1122
- control.TabSkip = Wix.YesNoType.yes;
1123
- dialog.AddChild(control);
966
+ xControl.SetAttributeValue("TabSkip", "yes");
967
+ xDialog.Add(xControl);
968
}
969
}
970
}
@@ -1137,53 +981,53 @@ namespace WixToolset.Core.WindowsInstaller
981
private void FinalizeDuplicateMoveFileTables(TableIndexedCollection tables)
982
{
983
var duplicateFileTable = tables["DuplicateFile"];
1140
- var moveFileTable = tables["MoveFile"];
1141
-
984
if (null != duplicateFileTable)
985
{
986
foreach (var row in duplicateFileTable.Rows)
987
{
1146
- var copyFile = (Wix.CopyFile)this.core.GetIndexedElement(row);
1147
-
1148
- if (null != row[4])
988
+ var xCopyFile = this.GetIndexedElement(row);
989
+ var destination = row.FieldAsString(4);
990
+ if (!String.IsNullOrEmpty(destination))
991
{
1150
- if (null != this.core.GetIndexedElement("Directory", Convert.ToString(row[4])))
992
+ if (this.TryGetIndexedElement("Directory", out var _, destination))
993
{
1152
- copyFile.DestinationDirectory = Convert.ToString(row[4]);
994
+ xCopyFile.SetAttributeValue("DestinationDirectory", destination);
995
}
996
else
997
{
1156
- copyFile.DestinationProperty = Convert.ToString(row[4]);
998
+ xCopyFile.SetAttributeValue("DestinationProperty", destination);
999
}
1000
}
1001
}
1002
}
1003
1004
+ var moveFileTable = tables["MoveFile"];
1005
if (null != moveFileTable)
1006
{
1007
foreach (var row in moveFileTable.Rows)
1008
{
1166
- var copyFile = (Wix.CopyFile)this.core.GetIndexedElement(row);
1167
-
1168
- if (null != row[4])
1009
+ var xCopyFile = this.GetIndexedElement(row);
1010
+ var source = row.FieldAsString(4);
1011
+ if (!String.IsNullOrEmpty(source))
1012
{
1170
- if (null != this.core.GetIndexedElement("Directory", Convert.ToString(row[4])))
1013
+ if (this.TryGetIndexedElement("Directory", out var _, source))
1014
{
1172
- copyFile.SourceDirectory = Convert.ToString(row[4]);
1015
+ xCopyFile.SetAttributeValue("SourceDirectory", source);
1016
}
1017
else
1018
{
1176
- copyFile.SourceProperty = Convert.ToString(row[4]);
1019
+ xCopyFile.SetAttributeValue("SourceProperty", source);
1020
}
1021
}
1022
1180
- if (null != this.core.GetIndexedElement("Directory", Convert.ToString(row[5])))
1023
+ var destination = row.FieldAsString(5);
1024
+ if (this.TryGetIndexedElement("Directory", out var _, destination))
1025
{
1182
- copyFile.DestinationDirectory = Convert.ToString(row[5]);
1026
+ xCopyFile.SetAttributeValue("DestinationDirectory", destination);
1027
}
1028
else
1029
{
1186
- copyFile.DestinationProperty = Convert.ToString(row[5]);
1030
+ xCopyFile.SetAttributeValue("DestinationProperty", destination);
1031
}
1032
}
1033
}
@@ -1195,22 +1039,17 @@ namespace WixToolset.Core.WindowsInstaller
1039
/// <param name="tables">The collection of all tables.</param>
1040
private void FinalizeFamilyFileRangesTable(TableIndexedCollection tables)
1041
{
1198
- var externalFilesTable = tables["ExternalFiles"];
1042
var familyFileRangesTable = tables["FamilyFileRanges"];
1200
- var targetFiles_OptionalDataTable = tables["TargetFiles_OptionalData"];
1201
-
1202
- var usedProtectRanges = new Hashtable();
1203
-
1043
if (null != familyFileRangesTable)
1044
{
1045
foreach (var row in familyFileRangesTable.Rows)
1046
{
1208
- var protectRange = new Wix.ProtectRange();
1047
+ var xProtectRange = new XElement(Names.ProtectRangeElement);
1048
1210
- if (null != row[2] && null != row[3])
1049
+ if (!row.IsColumnNull(2) && !row.IsColumnNull(3))
1050
{
1212
- var retainOffsets = (Convert.ToString(row[2])).Split(',');
1213
- var retainLengths = (Convert.ToString(row[3])).Split(',');
1051
+ var retainOffsets = row.FieldAsString(2).Split(',');
1052
+ var retainLengths = row.FieldAsString(3).Split(',');
1053
1054
if (retainOffsets.Length == retainLengths.Length)
1055
{
@@ -1218,20 +1057,20 @@ namespace WixToolset.Core.WindowsInstaller
1057
{
1058
if (retainOffsets[i].StartsWith("0x", StringComparison.Ordinal))
1059
{
1221
- protectRange.Offset = Convert.ToInt32(retainOffsets[i].Substring(2), 16);
1060
+ xProtectRange.SetAttributeValue("Offset", Convert.ToInt32(retainOffsets[i].Substring(2), 16));
1061
}
1062
else
1063
{
1225
- protectRange.Offset = Convert.ToInt32(retainOffsets[i], CultureInfo.InvariantCulture);
1064
+ xProtectRange.SetAttributeValue("Offset", Convert.ToInt32(retainOffsets[i], CultureInfo.InvariantCulture));
1065
}
1066
1067
if (retainLengths[i].StartsWith("0x", StringComparison.Ordinal))
1068
{
1230
- protectRange.Length = Convert.ToInt32(retainLengths[i].Substring(2), 16);
1069
+ xProtectRange.SetAttributeValue("Length", Convert.ToInt32(retainLengths[i].Substring(2), 16));
1070
}
1071
else
1072
{
1234
- protectRange.Length = Convert.ToInt32(retainLengths[i], CultureInfo.InvariantCulture);
1073
+ xProtectRange.SetAttributeValue("Length", Convert.ToInt32(retainLengths[i], CultureInfo.InvariantCulture));
1074
}
1075
}
1076
}
@@ -1240,79 +1079,59 @@ namespace WixToolset.Core.WindowsInstaller
1079
// TODO: warn
1080
}
1081
}
1243
- else if (null != row[2] || null != row[3])
1082
+ else if (!row.IsColumnNull(2) || !row.IsColumnNull(3))
1083
{
1084
// TODO: warn about mismatch between columns
1085
}
1086
1248
- this.core.IndexElement(row, protectRange);
1087
+ this.IndexElement(row, xProtectRange);
1088
}
1089
}
1090
1091
+ var usedProtectRanges = new HashSet<XElement>();
1092
+ var externalFilesTable = tables["ExternalFiles"];
1093
if (null != externalFilesTable)
1094
{
1095
foreach (var row in externalFilesTable.Rows)
1096
{
1256
- var externalFile = (Wix.ExternalFile)this.core.GetIndexedElement(row);
1257
-
1258
- var protectRange = (Wix.ProtectRange)this.core.GetIndexedElement("FamilyFileRanges", Convert.ToString(row[0]), Convert.ToString(row[1]));
1259
- if (null != protectRange)
1097
+ if (this.TryGetIndexedElement(row, out var xExternalFile)
1098
+ && this.TryGetIndexedElement("FamilyFileRanges", out var xProtectRange, row.FieldAsString(0), row.FieldAsString(0)))
1099
{
1261
- externalFile.AddChild(protectRange);
1262
- usedProtectRanges[protectRange] = null;
1100
+ xExternalFile.Add(xProtectRange);
1101
+ usedProtectRanges.Add(xProtectRange);
1102
}
1103
}
1104
}
1105
1106
+ var targetFiles_OptionalDataTable = tables["TargetFiles_OptionalData"];
1107
if (null != targetFiles_OptionalDataTable)
1108
{
1109
var targetImagesTable = tables["TargetImages"];
1270
- var upgradedImagesTable = tables["UpgradedImages"];
1271
-
1272
- var targetImageRows = new Hashtable();
1273
- var upgradedImagesRows = new Hashtable();
1274
-
1275
- // index the TargetImages table
1276
- if (null != targetImagesTable)
1277
- {
1278
- foreach (var row in targetImagesTable.Rows)
1279
- {
1280
- targetImageRows.Add(row[0], row);
1281
- }
1282
- }
1110
+ var targetImageRows = targetImagesTable?.Rows.ToDictionary(row => row.FieldAsString(0));
1111
1284
- // index the UpgradedImages table
1285
- if (null != upgradedImagesTable)
1286
- {
1287
- foreach (var row in upgradedImagesTable.Rows)
1288
- {
1289
- upgradedImagesRows.Add(row[0], row);
1290
- }
1291
- }
1112
+ var upgradedImagesTable = tables["UpgradedImages"];
1113
+ var upgradedImagesRows = upgradedImagesTable?.Rows.ToDictionary(row => row.FieldAsString(0));
1114
1115
foreach (var row in targetFiles_OptionalDataTable.Rows)
1116
{
1295
- var targetFile = (Wix.TargetFile)this.patchTargetFiles[row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)];
1117
+ var xTargetFile = this.PatchTargetFiles[row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)];
1118
1297
- var targetImageRow = (Row)targetImageRows[row[0]];
1298
- if (null == targetImageRow)
1119
+ if (!targetImageRows.TryGetValue(row.FieldAsString(0), out var targetImageRow))
1120
{
1300
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, targetFiles_OptionalDataTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Target", Convert.ToString(row[0]), "TargetImages"));
1121
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, targetFiles_OptionalDataTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Target", row.FieldAsString(0), "TargetImages"));
1122
continue;
1123
}
1124
1304
- var upgradedImagesRow = (Row)upgradedImagesRows[targetImageRow[3]];
1305
- if (null == upgradedImagesRow)
1125
+ if (!upgradedImagesRows.TryGetValue(row.FieldAsString(3), out var upgradedImagesRow))
1126
{
1307
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(targetImageRow.SourceLineNumbers, targetImageRow.Table.Name, targetImageRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Upgraded", Convert.ToString(row[3]), "UpgradedImages"));
1127
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(targetImageRow.SourceLineNumbers, targetImageRow.Table.Name, targetImageRow.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Upgraded", row.FieldAsString(3), "UpgradedImages"));
1128
continue;
1129
}
1130
1311
- var protectRange = (Wix.ProtectRange)this.core.GetIndexedElement("FamilyFileRanges", Convert.ToString(upgradedImagesRow[4]), Convert.ToString(row[1]));
1312
- if (null != protectRange)
1131
+ if (this.TryGetIndexedElement("FamilyFileRanges", out var xProtectRange, upgradedImagesRow.FieldAsString(4), row.FieldAsString(1)))
1132
{
1314
- targetFile.AddChild(protectRange);
1315
- usedProtectRanges[protectRange] = null;
1133
+ xTargetFile.Add(xProtectRange);
1134
+ usedProtectRanges.Add(xProtectRange);
1135
}
1136
}
1137
}
@@ -1321,25 +1140,14 @@ namespace WixToolset.Core.WindowsInstaller
1140
{
1141
foreach (var row in familyFileRangesTable.Rows)
1142
{
1324
- var protectRange = (Wix.ProtectRange)this.core.GetIndexedElement(row);
1143
+ var xProtectRange = this.GetIndexedElement(row);
1144
1326
- if (!usedProtectRanges.Contains(protectRange))
1145
+ if (!usedProtectRanges.Contains(xProtectRange))
1146
{
1328
- var protectFile = new Wix.ProtectFile();
1329
-
1330
- protectFile.File = Convert.ToString(row[1]);
1147
+ var xProtectFile = new XElement(Names.ProtectFileElement, new XAttribute("File", row.FieldAsString(1)));
1148
+ xProtectFile.Add(xProtectRange);
1149
1332
- protectFile.AddChild(protectRange);
1333
-
1334
- var family = (Wix.Family)this.core.GetIndexedElement("ImageFamilies", Convert.ToString(row[0]));
1335
- if (null != family)
1336
- {
1337
- family.AddChild(protectFile);
1338
- }
1339
- else
1340
- {
1341
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, familyFileRangesTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Family", Convert.ToString(row[0]), "ImageFamilies"));
1342
- }
1150
+ this.AddChildToParent("ImageFamilies", xProtectFile, row, 0);
1151
}
1152
}
1153
}
@@ -1357,11 +1165,6 @@ namespace WixToolset.Core.WindowsInstaller
1165
private void FinalizeFeatureComponentsTable(TableIndexedCollection tables)
1166
{
1167
var classTable = tables["Class"];
1360
- var extensionTable = tables["Extension"];
1361
- var msiAssemblyTable = tables["MsiAssembly"];
1362
- var publishComponentTable = tables["PublishComponent"];
1363
- var typeLibTable = tables["TypeLib"];
1364
-
1168
if (null != classTable)
1169
{
1170
foreach (var row in classTable.Rows)
@@ -1370,6 +1173,7 @@ namespace WixToolset.Core.WindowsInstaller
1173
}
1174
}
1175
1176
+ var extensionTable = tables["Extension"];
1177
if (null != extensionTable)
1178
{
1179
foreach (var row in extensionTable.Rows)
@@ -1378,6 +1182,7 @@ namespace WixToolset.Core.WindowsInstaller
1182
}
1183
}
1184
1185
+ var msiAssemblyTable = tables["MsiAssembly"];
1186
if (null != msiAssemblyTable)
1187
{
1188
foreach (var row in msiAssemblyTable.Rows)
@@ -1386,6 +1191,7 @@ namespace WixToolset.Core.WindowsInstaller
1191
}
1192
}
1193
1194
+ var publishComponentTable = tables["PublishComponent"];
1195
if (null != publishComponentTable)
1196
{
1197
foreach (var row in publishComponentTable.Rows)
@@ -1394,6 +1200,7 @@ namespace WixToolset.Core.WindowsInstaller
1200
}
1201
}
1202
1203
+ var typeLibTable = tables["TypeLib"];
1204
if (null != typeLibTable)
1205
{
1206
foreach (var row in typeLibTable.Rows)
@@ -1412,132 +1219,89 @@ namespace WixToolset.Core.WindowsInstaller
1219
/// </remarks>
1220
private void FinalizeFileTable(TableIndexedCollection tables)
1221
{
1415
- var fileTable = tables["File"];
1416
- var mediaTable = tables["Media"];
1417
- var msiAssemblyTable = tables["MsiAssembly"];
1418
- var typeLibTable = tables["TypeLib"];
1419
-
1222
// index the media table by media id
1421
- RowDictionary<MediaRow> mediaRows;
1422
- if (null != mediaTable)
1423
- {
1424
- mediaRows = new RowDictionary<MediaRow>(mediaTable);
1425
- }
1223
+ var mediaTable = tables["Media"];
1224
+ var mediaRows = new RowDictionary<MediaRow>(mediaTable);
1225
1226
// set the disk identifiers and sources for files
1428
- if (null != fileTable)
1227
+ foreach (var fileRow in tables["File"]?.Rows.Cast<FileRow>() ?? Enumerable.Empty<FileRow>())
1228
{
1430
- foreach (FileRow fileRow in fileTable.Rows)
1431
- {
1432
- var file = (Wix.File)this.core.GetIndexedElement("File", fileRow.File);
1229
+ var xFile = this.GetIndexedElement("File", fileRow.File);
1230
1434
- // Don't bother processing files that are orphaned (and won't show up in the output anyway)
1435
- if (null != file.ParentElement)
1231
+ // Don't bother processing files that are orphaned (and won't show up in the output anyway)
1232
+ if (null != xFile.Parent)
1233
+ {
1234
+ // set the diskid
1235
+ if (null != mediaTable)
1236
{
1437
- // set the diskid
1438
- if (null != mediaTable)
1237
+ foreach (MediaRow mediaRow in mediaTable.Rows)
1238
{
1440
- foreach (MediaRow mediaRow in mediaTable.Rows)
1239
+ if (fileRow.Sequence <= mediaRow.LastSequence && mediaRow.DiskId != 1)
1240
{
1442
- if (fileRow.Sequence <= mediaRow.LastSequence && mediaRow.DiskId != 1)
1443
- {
1444
- file.DiskId = Convert.ToString(mediaRow.DiskId);
1445
- break;
1446
- }
1241
+ xFile.SetAttributeValue("DiskId", mediaRow.DiskId);
1242
+ break;
1243
}
1244
}
1245
+ }
1246
1450
- // set the source (done here because it requires information from the Directory table)
1451
- if (OutputType.Module == this.OutputType)
1452
- {
1453
- file.Source = String.Concat(this.BaseSourcePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, file.Id, '.', this.modularizationGuid.Substring(1, 36).Replace('-', '_'));
1454
- }
1455
- else if (Wix.YesNoDefaultType.yes == file.Compressed || (Wix.YesNoDefaultType.no != file.Compressed && this.compressed) || (OutputType.Product == this.OutputType && this.TreatProductAsModule))
1247
+ var fileId = xFile?.Attribute("Id")?.Value;
1248
+ var fileCompressed = xFile?.Attribute("Compressed")?.Value;
1249
+ var fileShortName = xFile?.Attribute("ShortName")?.Value;
1250
+ var fileName = xFile?.Attribute("Name")?.Value;
1251
+
1252
+ // set the source (done here because it requires information from the Directory table)
1253
+ if (OutputType.Module == this.OutputType)
1254
+ {
1255
+ xFile.SetAttributeValue("Source", String.Concat(this.BaseSourcePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, fileId, '.', this.ModularizationGuid.Substring(1, 36).Replace('-', '_')));
1256
+ }
1257
+ else if (fileCompressed == "yes" || (fileCompressed != "no" && this.Compressed) || (OutputType.Product == this.OutputType && this.TreatProductAsModule))
1258
+ {
1259
+ xFile.SetAttributeValue("Source", String.Concat(this.BaseSourcePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, fileId));
1260
+ }
1261
+ else // uncompressed
1262
+ {
1263
+ var name = (!this.ShortNames && !String.IsNullOrEmpty(fileName)) ? fileName : fileShortName ?? fileName;
1264
+
1265
+ if (this.Compressed) // uncompressed at the root of the source image
1266
{
1457
- file.Source = String.Concat(this.BaseSourcePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, file.Id);
1267
+ xFile.SetAttributeValue("Source", String.Concat("SourceDir", Path.DirectorySeparatorChar, name));
1268
}
1459
- else // uncompressed
1269
+ else
1270
{
1461
- var fileName = (null != file.ShortName ? file.ShortName : file.Name);
1462
-
1463
- if (!this.shortNames && null != file.Name)
1464
- {
1465
- fileName = file.Name;
1466
- }
1467
-
1468
- if (this.compressed) // uncompressed at the root of the source image
1469
- {
1470
- file.Source = String.Concat("SourceDir", Path.DirectorySeparatorChar, fileName);
1471
- }
1472
- else
1473
- {
1474
- var sourcePath = this.GetSourcePath(file);
1475
-
1476
- file.Source = Path.Combine(sourcePath, fileName);
1477
- }
1271
+ var sourcePath = this.GetSourcePath(xFile);
1272
+ xFile.SetAttributeValue("Source", Path.Combine(sourcePath, name));
1273
}
1274
}
1275
}
1276
}
1277
1278
// set the file assemblies and manifests
1484
- if (null != msiAssemblyTable)
1279
+ foreach (var row in tables["MsiAssembly"]?.Rows ?? Enumerable.Empty<Row>())
1280
{
1486
- foreach (var row in msiAssemblyTable.Rows)
1281
+ if (this.TryGetIndexedElement("Component", out var xComponent, row.FieldAsString(0)))
1282
{
1488
- var component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[0]));
1489
-
1490
- if (null == component)
1491
- {
1492
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "MsiAssembly", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[0]), "Component"));
1493
- }
1494
- else
1283
+ foreach (var xFile in xComponent.Elements(Names.FileElement).Where(x => x.Attribute("KeyPath")?.Value == "yes"))
1284
{
1496
- foreach (Wix.ISchemaElement element in component.Children)
1497
- {
1498
- var file = element as Wix.File;
1499
-
1500
- if (null != file && Wix.YesNoType.yes == file.KeyPath)
1501
- {
1502
- if (null != row[2])
1503
- {
1504
- file.AssemblyManifest = Convert.ToString(row[2]);
1505
- }
1506
-
1507
- if (null != row[3])
1508
- {
1509
- file.AssemblyApplication = Convert.ToString(row[3]);
1510
- }
1511
-
1512
- if (null == row[4] || 0 == Convert.ToInt32(row[4]))
1513
- {
1514
- file.Assembly = Wix.File.AssemblyType.net;
1515
- }
1516
- else
1517
- {
1518
- file.Assembly = Wix.File.AssemblyType.win32;
1519
- }
1520
- }
1521
- }
1285
+ xFile.SetAttributeValue("AssemblyManifest", row.FieldAsString(2));
1286
+ xFile.SetAttributeValue("AssemblyApplication", row.FieldAsString(3));
1287
+ xFile.SetAttributeValue("Assembly", row.FieldAsInteger(4) == 0 ? ".net" : "win32");
1288
}
1289
}
1290
+ else
1291
+ {
1292
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "MsiAssembly", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", row.FieldAsString(0), "Component"));
1293
+ }
1294
}
1295
1296
// nest the TypeLib elements
1527
- if (null != typeLibTable)
1297
+ foreach (var row in tables["TypeLib"]?.Rows ?? Enumerable.Empty<Row>())
1298
{
1529
- foreach (var row in typeLibTable.Rows)
1530
- {
1531
- var component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[2]));
1532
- var typeLib = (Wix.TypeLib)this.core.GetIndexedElement(row);
1299
+ var xComponent = this.GetIndexedElement("Component", row.FieldAsString(2));
1300
+ var xTypeLib = this.GetIndexedElement(row);
1301
1534
- foreach (Wix.ISchemaElement element in component.Children)
1535
- {
1536
- if (element is Wix.File file && Wix.YesNoType.yes == file.KeyPath)
1537
- {
1538
- file.AddChild(typeLib);
1539
- }
1540
- }
1302
+ foreach (var xFile in xComponent.Elements(Names.FileElement).Where(x => x.Attribute("KeyPath")?.Value == "yes"))
1303
+ {
1304
+ xFile.Add(xTypeLib);
1305
}
1306
}
1307
}
@@ -1553,61 +1317,41 @@ namespace WixToolset.Core.WindowsInstaller
1317
/// </remarks>
1318
private void FinalizeMIMETable(TableIndexedCollection tables)
1319
{
1556
- var extensionTable = tables["Extension"];
1557
- var mimeTable = tables["MIME"];
1558
-
1559
- var comExtensions = new Hashtable();
1560
-
1561
- if (null != extensionTable)
1320
+ var extensionRows = tables["Extension"]?.Rows ?? Enumerable.Empty<Row>();
1321
+ foreach (var row in extensionRows)
1322
{
1563
- foreach (var row in extensionTable.Rows)
1323
+ // set the default MIME element for this extension
1324
+ var mimeRef = row.FieldAsString(3);
1325
+ if (null != mimeRef)
1326
{
1565
- var extension = (Wix.Extension)this.core.GetIndexedElement(row);
1566
-
1567
- // index the extension
1568
- if (!comExtensions.Contains(row[0]))
1327
+ if (this.TryGetIndexedElement("MIME", out var xMime, mimeRef))
1328
{
1570
- comExtensions.Add(row[0], new ArrayList());
1329
+ xMime.SetAttributeValue("Default", "yes");
1330
}
1572
- ((ArrayList)comExtensions[row[0]]).Add(extension);
1573
-
1574
- // set the default MIME element for this extension
1575
- if (null != row[3])
1331
+ else
1332
{
1577
- var mime = (Wix.MIME)this.core.GetIndexedElement("MIME", Convert.ToString(row[3]));
1578
-
1579
- if (null != mime)
1580
- {
1581
- mime.Default = Wix.YesNoType.yes;
1582
- }
1583
- else
1584
- {
1585
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Extension", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "MIME_", Convert.ToString(row[3]), "MIME"));
1586
- }
1333
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Extension", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "MIME_", row.FieldAsString(3), "MIME"));
1334
}
1335
}
1336
}
1337
1591
- if (null != mimeTable)
1592
- {
1593
- foreach (var row in mimeTable.Rows)
1594
- {
1595
- var mime = (Wix.MIME)this.core.GetIndexedElement(row);
1338
+ var extensionsByExtensionId = this.IndexTableOneToMany(extensionRows);
1339
1597
- if (comExtensions.Contains(row[1]))
1598
- {
1599
- var extensionElements = (ArrayList)comExtensions[row[1]];
1340
+ foreach (var row in tables["MIME"]?.Rows ?? Enumerable.Empty<Row>())
1341
+ {
1342
+ var xMime = this.GetIndexedElement(row);
1343
1601
- foreach (Wix.Extension extension in extensionElements)
1602
- {
1603
- extension.AddChild(mime);
1604
- }
1605
- }
1606
- else
1344
+ if (extensionsByExtensionId.TryGetValue(row.FieldAsString(1), out var xExtensions))
1345
+ {
1346
+ foreach (var extension in xExtensions)
1347
{
1608
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "MIME", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Extension_", Convert.ToString(row[1]), "Extension"));
1348
+ extension.Add(xMime);
1349
}
1350
}
1351
+ else
1352
+ {
1353
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "MIME", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Extension_", row.FieldAsString(1), "Extension"));
1354
+ }
1355
}
1356
}
1357
@@ -1623,125 +1367,80 @@ namespace WixToolset.Core.WindowsInstaller
1367
/// </remarks>
1368
private void FinalizeProgIdTable(TableIndexedCollection tables)
1369
{
1626
- var classTable = tables["Class"];
1627
- var progIdTable = tables["ProgId"];
1628
- var extensionTable = tables["Extension"];
1629
- var componentTable = tables["Component"];
1370
+ // add the default ProgIds for each class (and index the class table)
1371
+ var classRows = tables["Class"]?.Rows?.Where(row => row.FieldAsString(3) != null) ?? Enumerable.Empty<Row>();
1372
1631
- var addedProgIds = new Hashtable();
1632
- var classes = new Hashtable();
1633
- var components = new Hashtable();
1373
+ var classesByCLSID = this.IndexTableOneToMany(classRows);
1374
1635
- // add the default ProgIds for each class (and index the class table)
1636
- if (null != classTable)
1375
+ var addedProgIds = new Dictionary<XElement, string>();
1376
+
1377
+ foreach (var row in classRows)
1378
{
1638
- foreach (var row in classTable.Rows)
1639
- {
1640
- var wixClass = (Wix.Class)this.core.GetIndexedElement(row);
1379
+ var clsid = row.FieldAsString(0);
1380
+ var xClass = this.GetIndexedElement(row);
1381
1642
- if (null != row[3])
1382
+ if (this.TryGetIndexedElement("ProgId", out var xProgId, row.FieldAsString(3)))
1383
+ {
1384
+ if (addedProgIds.TryGetValue(xProgId, out var progid))
1385
{
1644
- var progId = (Wix.ProgId)this.core.GetIndexedElement("ProgId", Convert.ToString(row[3]));
1645
-
1646
- if (null != progId)
1647
- {
1648
- if (addedProgIds.Contains(progId))
1649
- {
1650
- this.Messaging.Write(WarningMessages.TooManyProgIds(row.SourceLineNumbers, Convert.ToString(row[0]), Convert.ToString(row[3]), Convert.ToString(addedProgIds[progId])));
1651
- }
1652
- else
1653
- {
1654
- wixClass.AddChild(progId);
1655
- addedProgIds.Add(progId, wixClass.Id);
1656
- }
1657
- }
1658
- else
1659
- {
1660
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Class", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ProgId_Default", Convert.ToString(row[3]), "ProgId"));
1661
- }
1386
+ this.Messaging.Write(WarningMessages.TooManyProgIds(row.SourceLineNumbers, row.FieldAsString(0), row.FieldAsString(3), progid));
1387
}
1663
-
1664
- // index the Class elements for nesting of ProgId elements (which don't use the full Class primary key)
1665
- if (!classes.Contains(wixClass.Id))
1388
+ else
1389
{
1667
- classes.Add(wixClass.Id, new ArrayList());
1390
+ xClass.Add(xProgId);
1391
+ addedProgIds.Add(xProgId, clsid);
1392
}
1669
- ((ArrayList)classes[wixClass.Id]).Add(wixClass);
1393
+ }
1394
+ else
1395
+ {
1396
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Class", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ProgId_Default", row.FieldAsString(3), "ProgId"));
1397
}
1398
}
1399
1400
// add the remaining non-default ProgId entries for each class
1674
- if (null != progIdTable)
1401
+ foreach (var row in tables["ProgId"]?.Rows ?? Enumerable.Empty<Row>())
1402
{
1676
- foreach (var row in progIdTable.Rows)
1677
- {
1678
- var progId = (Wix.ProgId)this.core.GetIndexedElement(row);
1403
+ var clsid = row.FieldAsString(2);
1404
+ var xProgId = this.GetIndexedElement(row);
1405
1680
- if (!addedProgIds.Contains(progId) && null != row[2] && null == progId.ParentElement)
1406
+ if (!addedProgIds.ContainsKey(xProgId) && null != clsid && null == xProgId.Parent)
1407
+ {
1408
+ if (classesByCLSID.TryGetValue(clsid, out var xClasses))
1409
{
1682
- var classElements = (ArrayList)classes[row[2]];
1683
-
1684
- if (null != classElements)
1685
- {
1686
- foreach (Wix.Class wixClass in classElements)
1687
- {
1688
- wixClass.AddChild(progId);
1689
- addedProgIds.Add(progId, wixClass.Id);
1690
- }
1691
- }
1692
- else
1410
+ foreach (var xClass in xClasses)
1411
{
1694
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "ProgId", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Class_", Convert.ToString(row[2]), "Class"));
1412
+ xClass.Add(xProgId);
1413
+ addedProgIds.Add(xProgId, clsid);
1414
}
1415
}
1697
- }
1698
- }
1699
-
1700
- if (null != componentTable)
1701
- {
1702
- foreach (var row in componentTable.Rows)
1703
- {
1704
- var wixComponent = (Wix.Component)this.core.GetIndexedElement(row);
1705
-
1706
- // index the Class elements for nesting of ProgId elements (which don't use the full Class primary key)
1707
- if (!components.Contains(wixComponent.Id))
1416
+ else
1417
{
1709
- components.Add(wixComponent.Id, new ArrayList());
1418
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "ProgId", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Class_", row.FieldAsString(2), "Class"));
1419
}
1711
- ((ArrayList)components[wixComponent.Id]).Add(wixComponent);
1420
}
1421
}
1422
1423
// Check for any progIds that are not hooked up to a class and hook them up to the component specified by the extension
1716
- if (null != extensionTable)
1717
- {
1718
- foreach (var row in extensionTable.Rows)
1719
- {
1720
- // ignore the extension if it isn't associated with a progId
1721
- if (null == row[2])
1722
- {
1723
- continue;
1724
- }
1424
+ var componentsById = this.IndexTableOneToMany(tables, "Component");
1425
1726
- var progId = (Wix.ProgId)this.core.GetIndexedElement("ProgId", Convert.ToString(row[2]));
1426
+ foreach (var row in tables["Extension"]?.Rows?.Where(row => row.FieldAsString(2) != null) ?? Enumerable.Empty<Row>())
1427
+ {
1428
+ var xProgId = this.GetIndexedElement("ProgId", row.FieldAsString(2));
1429
1728
- // Haven't added the progId yet and it doesn't have a parent progId
1729
- if (!addedProgIds.Contains(progId) && null == progId.ParentElement)
1430
+ // Haven't added the progId yet and it doesn't have a parent progId
1431
+ if (!addedProgIds.ContainsKey(xProgId) && null == xProgId.Parent)
1432
+ {
1433
+ if (componentsById.TryGetValue(row.FieldAsString(1), out var xComponents))
1434
{
1731
- var componentElements = (ArrayList)components[row[1]];
1732
-
1733
- if (null != componentElements)
1734
- {
1735
- foreach (Wix.Component wixComponent in componentElements)
1736
- {
1737
- wixComponent.AddChild(progId);
1738
- }
1739
- }
1740
- else
1435
+ foreach (var xComponent in xComponents)
1436
{
1742
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Extension", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[1]), "Component"));
1437
+ xComponent.Add(xProgId);
1438
}
1439
}
1440
+ else
1441
+ {
1442
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "Extension", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", row.FieldAsString(1), "Component"));
1443
+ }
1444
}
1445
}
1446
}
@@ -1755,25 +1454,18 @@ namespace WixToolset.Core.WindowsInstaller
1454
/// </remarks>
1455
private void FinalizePropertyTable(TableIndexedCollection tables)
1456
{
1758
- var propertyTable = tables["Property"];
1759
- var customActionTable = tables["CustomAction"];
1760
-
1761
- if (null != propertyTable && null != customActionTable)
1457
+ foreach (var row in tables["CustomAction"]?.Rows ?? Enumerable.Empty<Row>())
1458
{
1763
- foreach (var row in customActionTable.Rows)
1459
+ // If no other fields on the property are set we must have created it in the backend.
1460
+ var bits = row.FieldAsInteger(1);
1461
+ if (WindowsInstallerConstants.MsidbCustomActionTypeHideTarget == (bits & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget)
1462
+ && WindowsInstallerConstants.MsidbCustomActionTypeInScript == (bits & WindowsInstallerConstants.MsidbCustomActionTypeInScript)
1463
+ && this.TryGetIndexedElement("Property", out var xProperty, row.FieldAsString(0))
1464
+ && String.IsNullOrEmpty(xProperty.Attribute("Value")?.Value)
1465
+ && xProperty.Attribute("Secure")?.Value != "yes"
1466
+ && xProperty.Attribute("SuppressModularization")?.Value != "yes")
1467
{
1765
- var bits = Convert.ToInt32(row[1]);
1766
- if (WindowsInstallerConstants.MsidbCustomActionTypeHideTarget == (bits & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) &&
1767
- WindowsInstallerConstants.MsidbCustomActionTypeInScript == (bits & WindowsInstallerConstants.MsidbCustomActionTypeInScript))
1768
- {
1769
- var property = (Wix.Property)this.core.GetIndexedElement("Property", Convert.ToString(row[0]));
1770
-
1771
- // If no other fields on the property are set we must have created it during link
1772
- if (null != property && null == property.Value && Wix.YesNoType.yes != property.Secure && Wix.YesNoType.yes != property.SuppressModularization)
1773
- {
1774
- this.core.RootElement.RemoveChild(property);
1775
- }
1776
- }
1468
+ xProperty.Remove();
1469
}
1470
}
1471
}
@@ -1787,126 +1479,79 @@ namespace WixToolset.Core.WindowsInstaller
1479
/// </remarks>
1480
private void FinalizeRemoveFileTable(TableIndexedCollection tables)
1481
{
1790
- var removeFileTable = tables["RemoveFile"];
1791
-
1792
- if (null != removeFileTable)
1482
+ foreach (var row in tables["RemoveFile"]?.Rows ?? Enumerable.Empty<Row>())
1483
{
1794
- foreach (var row in removeFileTable.Rows)
1795
- {
1796
- var isDirectory = false;
1797
- var property = Convert.ToString(row[3]);
1798
-
1799
- // determine if the property is actually authored as a directory
1800
- if (null != this.core.GetIndexedElement("Directory", property))
1801
- {
1802
- isDirectory = true;
1803
- }
1804
-
1805
- var element = this.core.GetIndexedElement(row);
1806
-
1807
- var removeFile = element as Wix.RemoveFile;
1808
- if (null != removeFile)
1809
- {
1810
- if (isDirectory)
1811
- {
1812
- removeFile.Directory = property;
1813
- }
1814
- else
1815
- {
1816
- removeFile.Property = property;
1817
- }
1818
- }
1819
- else
1820
- {
1821
- var removeFolder = (Wix.RemoveFolder)element;
1484
+ var xRemove = this.GetIndexedElement(row);
1485
+ var property = row.FieldAsString(3);
1486
1823
- if (isDirectory)
1824
- {
1825
- removeFolder.Directory = property;
1826
- }
1827
- else
1828
- {
1829
- removeFolder.Property = property;
1830
- }
1831
- }
1487
+ if (this.TryGetIndexedElement("Directory", out var _, property))
1488
+ {
1489
+ xRemove.SetAttributeValue("Directory", property);
1490
+ }
1491
+ else
1492
+ {
1493
+ xRemove.SetAttributeValue("Property", property);
1494
}
1495
}
1496
}
1497
1498
/// <summary>
1837
- /// Finalize the LockPermissions table.
1499
+ /// Finalize the LockPermissions or MsiLockPermissionsEx table.
1500
/// </summary>
1501
/// <param name="tables">The collection of all tables.</param>
1502
+ /// <param name="tableName">Which table to finalize.</param>
1503
/// <remarks>
1504
/// Nests the Permission elements below their parent elements. There are no declared foreign
1505
/// keys for the parents of the LockPermissions table.
1506
/// </remarks>
1844
- private void FinalizeLockPermissionsTable(TableIndexedCollection tables)
1507
+ private void FinalizePermissionsTable(TableIndexedCollection tables, string tableName)
1508
{
1846
- var createFolderTable = tables["CreateFolder"];
1847
- var lockPermissionsTable = tables["LockPermissions"];
1848
-
1849
- var createFolders = new Hashtable();
1509
+ var createFoldersById = this.IndexTableOneToMany(tables, tableName);
1510
1851
- // index the CreateFolder table because the foreign key to this table from the
1852
- // LockPermissions table is only part of the primary key of this table
1853
- if (null != createFolderTable)
1511
+ foreach (var row in tables[tableName]?.Rows ?? Enumerable.Empty<Row>())
1512
{
1855
- foreach (var row in createFolderTable.Rows)
1856
- {
1857
- var createFolder = (Wix.CreateFolder)this.core.GetIndexedElement(row);
1858
- var directoryId = Convert.ToString(row[0]);
1513
+ var id = row.FieldAsString(0);
1514
+ var table = row.FieldAsString(1);
1515
+ var xPermission = this.GetIndexedElement(row);
1516
1860
- if (!createFolders.Contains(directoryId))
1517
+ if ("CreateFolder" == table)
1518
+ {
1519
+ if (createFoldersById.TryGetValue(id, out var xCreateFolders))
1520
+ {
1521
+ foreach (var xCreateFolder in xCreateFolders)
1522
+ {
1523
+ xCreateFolder.Add(xPermission);
1524
+ }
1525
+ }
1526
+ else
1527
{
1862
- createFolders.Add(directoryId, new ArrayList());
1528
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, tableName, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1529
}
1864
- ((ArrayList)createFolders[directoryId]).Add(createFolder);
1530
}
1866
- }
1867
-
1868
- if (null != lockPermissionsTable)
1869
- {
1870
- foreach (var row in lockPermissionsTable.Rows)
1531
+ else
1532
{
1872
- var id = Convert.ToString(row[0]);
1873
- var table = Convert.ToString(row[1]);
1874
-
1875
- var permission = (Wix.Permission)this.core.GetIndexedElement(row);
1876
-
1877
- if ("CreateFolder" == table)
1533
+ if (this.TryGetIndexedElement(table, out var xParent, id))
1534
{
1879
- var createFolderElements = (ArrayList)createFolders[id];
1880
-
1881
- if (null != createFolderElements)
1882
- {
1883
- foreach (Wix.CreateFolder createFolder in createFolderElements)
1884
- {
1885
- createFolder.AddChild(permission);
1886
- }
1887
- }
1888
- else
1889
- {
1890
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "LockPermissions", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1891
- }
1535
+ xParent.Add(xPermission);
1536
}
1537
else
1538
{
1895
- var parentElement = (Wix.IParentElement)this.core.GetIndexedElement(table, id);
1896
-
1897
- if (null != parentElement)
1898
- {
1899
- parentElement.AddChild(permission);
1900
- }
1901
- else
1902
- {
1903
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "LockPermissions", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1904
- }
1539
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, tableName, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1540
}
1541
}
1542
}
1543
}
1544
1545
+ /// <summary>
1546
+ /// Finalize the LockPermissions table.
1547
+ /// </summary>
1548
+ /// <param name="tables">The collection of all tables.</param>
1549
+ /// <remarks>
1550
+ /// Nests the Permission elements below their parent elements. There are no declared foreign
1551
+ /// keys for the parents of the LockPermissions table.
1552
+ /// </remarks>
1553
+ private void FinalizeLockPermissionsTable(TableIndexedCollection tables) => this.FinalizePermissionsTable(tables, "LockPermissions");
1554
+
1555
/// <summary>
1556
/// Finalize the MsiLockPermissionsEx table.
1557
/// </summary>
@@ -1915,164 +1560,58 @@ namespace WixToolset.Core.WindowsInstaller
1560
/// Nests the PermissionEx elements below their parent elements. There are no declared foreign
1561
/// keys for the parents of the MsiLockPermissionsEx table.
1562
/// </remarks>
1918
- private void FinalizeMsiLockPermissionsExTable(TableIndexedCollection tables)
1563
+ private void FinalizeMsiLockPermissionsExTable(TableIndexedCollection tables) => this.FinalizePermissionsTable(tables, "MsiLockPermissionsEx");
1564
+
1565
+ private static Dictionary<string, List<string>> IndexTable(Table table, int keyColumn, int? dataColumn)
1566
{
1920
- var createFolderTable = tables["CreateFolder"];
1921
- var msiLockPermissionsExTable = tables["MsiLockPermissionsEx"];
1567
+ if (table == null)
1568
+ {
1569
+ return new Dictionary<string, List<string>>();
1570
+ }
1571
1923
- var createFolders = new Hashtable();
1572
+ return table.Rows
1573
+ .ToLookup(row => row.FieldAsString(keyColumn), row => dataColumn.HasValue ? row.FieldAsString(dataColumn.Value) : null)
1574
+ .ToDictionary(lookup => lookup.Key, lookup => lookup.ToList());
1575
+ }
1576
1925
- // index the CreateFolder table because the foreign key to this table from the
1926
- // MsiLockPermissionsEx table is only part of the primary key of this table
1927
- if (null != createFolderTable)
1577
+ private static XElement FindComplianceDrive(XElement xSearch)
1578
+ {
1579
+ var xComplianceDrive = xSearch.Element(Names.ComplianceDriveElement);
1580
+ if (null == xComplianceDrive)
1581
{
1929
- foreach (var row in createFolderTable.Rows)
1930
- {
1931
- var createFolder = (Wix.CreateFolder)this.core.GetIndexedElement(row);
1932
- var directoryId = Convert.ToString(row[0]);
1933
-
1934
- if (!createFolders.Contains(directoryId))
1935
- {
1936
- createFolders.Add(directoryId, new ArrayList());
1937
- }
1938
- ((ArrayList)createFolders[directoryId]).Add(createFolder);
1939
- }
1582
+ xComplianceDrive = new XElement(Names.ComplianceDriveElement);
1583
+ xSearch.Add(xComplianceDrive);
1584
}
1585
1942
- if (null != msiLockPermissionsExTable)
1943
- {
1944
- foreach (var row in msiLockPermissionsExTable.Rows)
1945
- {
1946
- var id = Convert.ToString(row[1]);
1947
- var table = Convert.ToString(row[2]);
1586
+ return xComplianceDrive;
1587
+ }
1588
1949
- var permissionEx = (Wix.PermissionEx)this.core.GetIndexedElement(row);
1589
+ /// <summary>
1590
+ /// Finalize the search tables.
1591
+ /// </summary>
1592
+ /// <param name="tables">The collection of all tables.</param>
1593
+ /// <remarks>Does all the complex linking required for the search tables.</remarks>
1594
+ private void FinalizeSearchTables(TableIndexedCollection tables)
1595
+ {
1596
+ var appSearches = IndexTable(tables["AppSearch"], keyColumn: 1, dataColumn: 0);
1597
+ var ccpSearches = IndexTable(tables["CCPSearch"], keyColumn: 0, dataColumn: null);
1598
+ var drLocators = tables["DrLocator"]?.Rows.ToDictionary(row => this.GetIndexedElement(row), row => row);
1599
1951
- if ("CreateFolder" == table)
1952
- {
1953
- var createFolderElements = (ArrayList)createFolders[id];
1954
-
1955
- if (null != createFolderElements)
1956
- {
1957
- foreach (Wix.CreateFolder createFolder in createFolderElements)
1958
- {
1959
- createFolder.AddChild(permissionEx);
1960
- }
1961
- }
1962
- else
1963
- {
1964
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "MsiLockPermissionsEx", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1965
- }
1966
- }
1967
- else
1968
- {
1969
- var parentElement = (Wix.IParentElement)this.core.GetIndexedElement(table, id);
1970
-
1971
- if (null != parentElement)
1972
- {
1973
- parentElement.AddChild(permissionEx);
1974
- }
1975
- else
1976
- {
1977
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, "MsiLockPermissionsEx", row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "LockObject", id, table));
1978
- }
1979
- }
1980
- }
1981
- }
1982
- }
1983
-
1984
- /// <summary>
1985
- /// Finalize the search tables.
1986
- /// </summary>
1987
- /// <param name="tables">The collection of all tables.</param>
1988
- /// <remarks>Does all the complex linking required for the search tables.</remarks>
1989
- private void FinalizeSearchTables(TableIndexedCollection tables)
1990
- {
1991
- var appSearchTable = tables["AppSearch"];
1992
- var ccpSearchTable = tables["CCPSearch"];
1993
- var drLocatorTable = tables["DrLocator"];
1994
-
1995
- var appSearches = new Hashtable();
1996
- var ccpSearches = new Hashtable();
1997
- var drLocators = new Hashtable();
1998
- var locators = new Hashtable();
1999
- var usedSearchElements = new Hashtable();
2000
- var unusedSearchElements = new Dictionary<string, Wix.IParentElement>();
2001
-
2002
- Wix.ComplianceCheck complianceCheck = null;
2003
-
2004
- // index the AppSearch table by signatures
2005
- if (null != appSearchTable)
2006
- {
2007
- foreach (var row in appSearchTable.Rows)
2008
- {
2009
- var property = Convert.ToString(row[0]);
2010
- var signature = Convert.ToString(row[1]);
2011
-
2012
- if (!appSearches.Contains(signature))
2013
- {
2014
- appSearches.Add(signature, new StringCollection());
2015
- }
2016
-
2017
- ((StringCollection)appSearches[signature]).Add(property);
2018
- }
2019
- }
2020
-
2021
- // index the CCPSearch table by signatures
2022
- if (null != ccpSearchTable)
2023
- {
2024
- foreach (var row in ccpSearchTable.Rows)
2025
- {
2026
- var signature = Convert.ToString(row[0]);
2027
-
2028
- if (!ccpSearches.Contains(signature))
2029
- {
2030
- ccpSearches.Add(signature, new StringCollection());
2031
- }
2032
-
2033
- ((StringCollection)ccpSearches[signature]).Add(null);
2034
-
2035
- if (null == complianceCheck && !appSearches.Contains(signature))
2036
- {
2037
- complianceCheck = new Wix.ComplianceCheck();
2038
- this.core.RootElement.AddChild(complianceCheck);
2039
- }
2040
- }
2041
- }
2042
-
2043
- // index the directory searches by their search elements (to get back the original row)
2044
- if (null != drLocatorTable)
1600
+ var xComplianceCheck = new XElement(Names.ComplianceCheckElement);
1601
+ if (ccpSearches.Keys.Any(ccpSignature => !appSearches.ContainsKey(ccpSignature)))
1602
{
2046
- foreach (var row in drLocatorTable.Rows)
2047
- {
2048
- drLocators.Add(this.core.GetIndexedElement(row), row);
2049
- }
1603
+ this.RootElement.Add(xComplianceCheck);
1604
}
1605
1606
// index the locator tables by their signatures
2053
- var locatorTableNames = new string[] { "CompLocator", "RegLocator", "IniLocator", "DrLocator", "Signature" };
2054
- foreach (var locatorTableName in locatorTableNames)
2055
- {
2056
- var locatorTable = tables[locatorTableName];
2057
-
2058
- if (null != locatorTable)
2059
- {
2060
- foreach (var row in locatorTable.Rows)
2061
- {
2062
- var signature = Convert.ToString(row[0]);
2063
-
2064
- if (!locators.Contains(signature))
2065
- {
2066
- locators.Add(signature, new ArrayList());
2067
- }
2068
-
2069
- ((ArrayList)locators[signature]).Add(row);
2070
- }
2071
- }
2072
- }
1607
+ var locators =
1608
+ new[] { "CompLocator", "RegLocator", "IniLocator", "DrLocator", "Signature" }
1609
+ .SelectMany(table => tables[table]?.Rows ?? Enumerable.Empty<Row>())
1610
+ .ToLookup(row => row.FieldAsString(0), row => row)
1611
+ .ToDictionary(lookup => lookup.Key, lookup => lookup.ToList());
1612
1613
// move the DrLocator rows with a parent of CCP_DRIVE first to ensure they get FileSearch children (not FileSearchRef)
2075
- foreach (ArrayList locatorRows in locators.Values)
1614
+ foreach (var locatorRows in locators.Values)
1615
{
1616
var firstDrLocator = -1;
1617
@@ -2097,205 +1636,142 @@ namespace WixToolset.Core.WindowsInstaller
1636
}
1637
}
1638
2100
- foreach (string signature in locators.Keys)
1639
+ var xUsedSearches = new HashSet<XElement>();
1640
+ var xUnusedSearches = new Dictionary<string, XElement>();
1641
+
1642
+ foreach (var signature in locators.Keys)
1643
{
2102
- var locatorRows = (ArrayList)locators[signature];
2103
- var signatureSearchElements = new ArrayList();
1644
+ var locatorRows = locators[signature];
1645
+ var xSignatureSearches = new List<XElement>();
1646
2105
- foreach (Row locatorRow in locatorRows)
1647
+ foreach (var locatorRow in locatorRows)
1648
{
1649
var used = true;
2108
- var searchElement = this.core.GetIndexedElement(locatorRow);
1650
+ var xSearch = this.GetIndexedElement(locatorRow);
1651
2110
- if ("Signature" == locatorRow.TableDefinition.Name && 0 < signatureSearchElements.Count)
1652
+ if ("Signature" == locatorRow.TableDefinition.Name && 0 < xSignatureSearches.Count)
1653
{
2112
- foreach (Wix.IParentElement searchParentElement in signatureSearchElements)
1654
+ foreach (var xSearchParent in xSignatureSearches)
1655
{
2114
- if (!usedSearchElements.Contains(searchElement))
1656
+ if (!xUsedSearches.Contains(xSearch))
1657
{
2116
- searchParentElement.AddChild(searchElement);
2117
- usedSearchElements[searchElement] = null;
1658
+ xSearchParent.Add(xSearch);
1659
+ xUsedSearches.Add(xSearch);
1660
}
1661
else
1662
{
2121
- var fileSearchRef = new Wix.FileSearchRef();
1663
+ var xFileSearchRef = new XElement(Names.FileSearchRefElement,
1664
+ new XAttribute("Id", signature));
1665
2123
- fileSearchRef.Id = signature;
2124
-
2125
- searchParentElement.AddChild(fileSearchRef);
1666
+ xSearchParent.Add(xFileSearchRef);
1667
}
1668
}
1669
}
2129
- else if ("DrLocator" == locatorRow.TableDefinition.Name && null != locatorRow[1])
1670
+ else if ("DrLocator" == locatorRow.TableDefinition.Name && !locatorRow.IsColumnNull(1))
1671
{
2131
- var drSearchElement = (Wix.DirectorySearch)searchElement;
2132
- var parentSignature = Convert.ToString(locatorRow[1]);
1672
+ var parentSignature = locatorRow.FieldAsString(1);
1673
1674
if ("CCP_DRIVE" == parentSignature)
1675
{
2136
- if (appSearches.Contains(signature))
1676
+ if (appSearches.ContainsKey(signature)
1677
+ && appSearches.TryGetValue(signature, out var appSearchPropertyIds))
1678
{
2138
- var appSearchPropertyIds = (StringCollection)appSearches[signature];
2139
-
1679
foreach (var propertyId in appSearchPropertyIds)
1680
{
2142
- var property = this.EnsureProperty(propertyId);
2143
- Wix.ComplianceDrive complianceDrive = null;
2144
-
2145
- if (ccpSearches.Contains(signature))
2146
- {
2147
- property.ComplianceCheck = Wix.YesNoType.yes;
2148
- }
1681
+ var xProperty = this.EnsureProperty(propertyId);
1682
2150
- foreach (Wix.ISchemaElement element in property.Children)
1683
+ if (ccpSearches.ContainsKey(signature))
1684
{
2152
- complianceDrive = element as Wix.ComplianceDrive;
2153
- if (null != complianceDrive)
2154
- {
2155
- break;
2156
- }
1685
+ xProperty.SetAttributeValue("ComplianceCheck", "yes");
1686
}
1687
2159
- if (null == complianceDrive)
2160
- {
2161
- complianceDrive = new Wix.ComplianceDrive();
2162
- property.AddChild(complianceDrive);
2163
- }
1688
+ var xComplianceDrive = FindComplianceDrive(xProperty);
1689
2165
- if (!usedSearchElements.Contains(searchElement))
1690
+ if (!xUsedSearches.Contains(xSearch))
1691
{
2167
- complianceDrive.AddChild(searchElement);
2168
- usedSearchElements[searchElement] = null;
1692
+ xComplianceDrive.Add(xSearch);
1693
+ xUsedSearches.Add(xSearch);
1694
}
1695
else
1696
{
2172
- var directorySearchRef = new Wix.DirectorySearchRef();
2173
-
2174
- directorySearchRef.Id = signature;
2175
-
2176
- if (null != locatorRow[1])
2177
- {
2178
- directorySearchRef.Parent = Convert.ToString(locatorRow[1]);
2179
- }
2180
-
2181
- if (null != locatorRow[2])
2182
- {
2183
- directorySearchRef.Path = Convert.ToString(locatorRow[2]);
2184
- }
1697
+ var directorySearchRef = new XElement(Names.DirectorySearchRefElement,
1698
+ new XAttribute("Id", signature),
1699
+ XAttributeIfNotNull("Parent", locatorRow, 1),
1700
+ XAttributeIfNotNull("Path", locatorRow, 2));
1701
2186
- complianceDrive.AddChild(directorySearchRef);
2187
- signatureSearchElements.Add(directorySearchRef);
1702
+ xComplianceDrive.Add(directorySearchRef);
1703
+ xSignatureSearches.Add(directorySearchRef);
1704
}
1705
}
1706
}
2191
- else if (ccpSearches.Contains(signature))
1707
+ else if (ccpSearches.ContainsKey(signature))
1708
{
2193
- Wix.ComplianceDrive complianceDrive = null;
2194
-
2195
- foreach (Wix.ISchemaElement element in complianceCheck.Children)
2196
- {
2197
- complianceDrive = element as Wix.ComplianceDrive;
2198
- if (null != complianceDrive)
2199
- {
2200
- break;
2201
- }
2202
- }
2203
-
2204
- if (null == complianceDrive)
2205
- {
2206
- complianceDrive = new Wix.ComplianceDrive();
2207
- complianceCheck.AddChild(complianceDrive);
2208
- }
1709
+ var xComplianceDrive = FindComplianceDrive(xComplianceCheck);
1710
2210
- if (!usedSearchElements.Contains(searchElement))
1711
+ if (!xUsedSearches.Contains(xSearch))
1712
{
2212
- complianceDrive.AddChild(searchElement);
2213
- usedSearchElements[searchElement] = null;
1713
+ xComplianceDrive.Add(xSearch);
1714
+ xUsedSearches.Add(xSearch);
1715
}
1716
else
1717
{
2217
- var directorySearchRef = new Wix.DirectorySearchRef();
2218
-
2219
- directorySearchRef.Id = signature;
2220
-
2221
- if (null != locatorRow[1])
2222
- {
2223
- directorySearchRef.Parent = Convert.ToString(locatorRow[1]);
2224
- }
2225
-
2226
- if (null != locatorRow[2])
2227
- {
2228
- directorySearchRef.Path = Convert.ToString(locatorRow[2]);
2229
- }
1718
+ var directorySearchRef = new XElement(Names.DirectorySearchRefElement,
1719
+ new XAttribute("Id", signature),
1720
+ XAttributeIfNotNull("Parent", locatorRow, 1),
1721
+ XAttributeIfNotNull("Path", locatorRow, 2));
1722
2231
- complianceDrive.AddChild(directorySearchRef);
2232
- signatureSearchElements.Add(directorySearchRef);
1723
+ xComplianceDrive.Add(directorySearchRef);
1724
+ xSignatureSearches.Add(directorySearchRef);
1725
}
1726
}
1727
}
1728
else
1729
{
1730
var usedDrLocator = false;
2239
- var parentLocatorRows = (ArrayList)locators[parentSignature];
1731
2241
- if (null != parentLocatorRows)
1732
+ if (locators.TryGetValue(parentSignature, out var parentLocatorRows))
1733
{
2243
- foreach (Row parentLocatorRow in parentLocatorRows)
1734
+ foreach (var parentLocatorRow in parentLocatorRows)
1735
{
1736
if ("DrLocator" == parentLocatorRow.TableDefinition.Name)
1737
{
2247
- var parentSearchElement = (Wix.IParentElement)this.core.GetIndexedElement(parentLocatorRow);
1738
+ var xParentSearch = this.GetIndexedElement(parentLocatorRow);
1739
2249
- if (parentSearchElement.Children.GetEnumerator().MoveNext())
1740
+ if (xParentSearch.HasElements)
1741
{
2251
- var parentDrLocatorRow = (Row)drLocators[parentSearchElement];
2252
- var directorySeachRef = new Wix.DirectorySearchRef();
2253
-
2254
- directorySeachRef.Id = parentSignature;
2255
-
2256
- if (null != parentDrLocatorRow[1])
2257
- {
2258
- directorySeachRef.Parent = Convert.ToString(parentDrLocatorRow[1]);
2259
- }
2260
-
2261
- if (null != parentDrLocatorRow[2])
2262
- {
2263
- directorySeachRef.Path = Convert.ToString(parentDrLocatorRow[2]);
2264
- }
2265
-
2266
- parentSearchElement = directorySeachRef;
2267
- unusedSearchElements.Add(directorySeachRef.Id, directorySeachRef);
1742
+ var parentDrLocatorRow = drLocators[xParentSearch];
1743
+ var xDirectorySearchRef = new XElement(Names.DirectorySearchRefElement,
1744
+ new XAttribute("Id", parentSignature),
1745
+ XAttributeIfNotNull("Parent", parentDrLocatorRow, 1),
1746
+ XAttributeIfNotNull("Path", parentDrLocatorRow, 2));
1747
+
1748
+ xParentSearch = xDirectorySearchRef;
1749
+ xUnusedSearches.Add(parentSignature, xDirectorySearchRef);
1750
}
1751
2270
- if (!usedSearchElements.Contains(searchElement))
1752
+ if (!xUsedSearches.Contains(xSearch))
1753
{
2272
- parentSearchElement.AddChild(searchElement);
2273
- usedSearchElements[searchElement] = null;
1754
+ xParentSearch.Add(xSearch);
1755
+ xUsedSearches.Add(xSearch);
1756
usedDrLocator = true;
1757
}
1758
else
1759
{
2278
- var directorySearchRef = new Wix.DirectorySearchRef();
2279
-
2280
- directorySearchRef.Id = signature;
2281
-
2282
- directorySearchRef.Parent = parentSignature;
2283
-
2284
- if (null != locatorRow[2])
2285
- {
2286
- directorySearchRef.Path = Convert.ToString(locatorRow[2]);
2287
- }
1760
+ var xDirectorySearchRef = new XElement(Names.DirectorySearchRefElement,
1761
+ new XAttribute("Id", signature),
1762
+ new XAttribute("Parent", parentSignature),
1763
+ XAttributeIfNotNull("Path", locatorRow, 2));
1764
2289
- parentSearchElement.AddChild(searchElement);
1765
+ xParentSearch.Add(xSearch);
1766
usedDrLocator = true;
1767
}
1768
}
1769
else if ("RegLocator" == parentLocatorRow.TableDefinition.Name)
1770
{
2295
- var parentSearchElement = (Wix.IParentElement)this.core.GetIndexedElement(parentLocatorRow);
1771
+ var xParentSearch = this.GetIndexedElement(parentLocatorRow);
1772
2297
- parentSearchElement.AddChild(searchElement);
2298
- usedSearchElements[searchElement] = null;
1773
+ xParentSearch.Add(xSearch);
1774
+ xUsedSearches.Add(xSearch);
1775
usedDrLocator = true;
1776
}
1777
}
@@ -2303,7 +1779,7 @@ namespace WixToolset.Core.WindowsInstaller
1779
// keep track of unused DrLocator rows
1780
if (!usedDrLocator)
1781
{
2306
- unusedSearchElements.Add(drSearchElement.Id, drSearchElement);
1782
+ xUnusedSearches.Add(xSearch.Attribute("Id").Value, xSearch);
1783
}
1784
}
1785
else
@@ -2312,32 +1788,30 @@ namespace WixToolset.Core.WindowsInstaller
1788
}
1789
}
1790
}
2315
- else if (appSearches.Contains(signature))
1791
+ else if (appSearches.ContainsKey(signature)
1792
+ && appSearches.TryGetValue(signature, out var appSearchPropertyIds))
1793
{
2317
- var appSearchPropertyIds = (StringCollection)appSearches[signature];
2318
-
1794
foreach (var propertyId in appSearchPropertyIds)
1795
{
2321
- var property = this.EnsureProperty(propertyId);
1796
+ var xProperty = this.EnsureProperty(propertyId);
1797
2323
- if (ccpSearches.Contains(signature))
1798
+ if (ccpSearches.ContainsKey(signature))
1799
{
2325
- property.ComplianceCheck = Wix.YesNoType.yes;
1800
+ xProperty.SetAttributeValue("ComplianceCheck", "yes");
1801
}
1802
2328
- if (!usedSearchElements.Contains(searchElement))
1803
+ if (!xUsedSearches.Contains(xSearch))
1804
{
2330
- property.AddChild(searchElement);
2331
- usedSearchElements[searchElement] = null;
1805
+ xProperty.Add(xSearch);
1806
+ xUsedSearches.Add(xSearch);
1807
}
1808
else if ("RegLocator" == locatorRow.TableDefinition.Name)
1809
{
2335
- var registrySearchRef = new Wix.RegistrySearchRef();
2336
-
2337
- registrySearchRef.Id = signature;
1810
+ var xRegistrySearchRef = new XElement(Names.RegistrySearchRefElement,
1811
+ new XAttribute("Id", signature));
1812
2339
- property.AddChild(registrySearchRef);
2340
- signatureSearchElements.Add(registrySearchRef);
1813
+ xProperty.Add(xRegistrySearchRef);
1814
+ xSignatureSearches.Add(xRegistrySearchRef);
1815
}
1816
else
1817
{
@@ -2345,21 +1819,20 @@ namespace WixToolset.Core.WindowsInstaller
1819
}
1820
}
1821
}
2348
- else if (ccpSearches.Contains(signature))
1822
+ else if (ccpSearches.ContainsKey(signature))
1823
{
2350
- if (!usedSearchElements.Contains(searchElement))
1824
+ if (!xUsedSearches.Contains(xSearch))
1825
{
2352
- complianceCheck.AddChild(searchElement);
2353
- usedSearchElements[searchElement] = null;
1826
+ xComplianceCheck.Add(xSearch);
1827
+ xUsedSearches.Add(xSearch);
1828
}
1829
else if ("RegLocator" == locatorRow.TableDefinition.Name)
1830
{
2357
- var registrySearchRef = new Wix.RegistrySearchRef();
1831
+ var xRegistrySearchRef = new XElement(Names.RegistrySearchRefElement,
1832
+ new XAttribute("Id", signature));
1833
2359
- registrySearchRef.Id = signature;
2360
-
2361
- complianceCheck.AddChild(registrySearchRef);
2362
- signatureSearchElements.Add(registrySearchRef);
1834
+ xComplianceCheck.Add(xRegistrySearchRef);
1835
+ xSignatureSearches.Add(xRegistrySearchRef);
1836
}
1837
else
1838
{
@@ -2368,13 +1841,9 @@ namespace WixToolset.Core.WindowsInstaller
1841
}
1842
else
1843
{
2371
- if (searchElement is Wix.DirectorySearch directorySearch)
2372
- {
2373
- unusedSearchElements.Add(directorySearch.Id, directorySearch);
2374
- }
2375
- else if (searchElement is Wix.RegistrySearch registrySearch)
1844
+ if (xSearch.Name.LocalName == "DirectorySearch" || xSearch.Name.LocalName == "RegistrySearch")
1845
{
2377
- unusedSearchElements.Add(registrySearch.Id, registrySearch);
1846
+ xUnusedSearches.Add(xSearch.Attribute("Id").Value, xSearch);
1847
}
1848
else
1849
{
@@ -2386,51 +1855,44 @@ namespace WixToolset.Core.WindowsInstaller
1855
// keep track of the search elements for this signature so that nested searches go in the proper parents
1856
if (used)
1857
{
2389
- signatureSearchElements.Add(searchElement);
1858
+ xSignatureSearches.Add(xSearch);
1859
}
1860
}
1861
}
1862
1863
// Iterate through the unused elements through a sorted list of their ids so the output is deterministic.
2395
- var unusedSearchElementKeys = unusedSearchElements.Keys.ToList();
2396
- unusedSearchElementKeys.Sort();
2397
- foreach (var unusedSearchElementKey in unusedSearchElementKeys)
1864
+ foreach (var unusedSearch in xUnusedSearches.OrderBy(kvp => kvp.Key))
1865
{
2399
- var unusedSearchElement = unusedSearchElements[unusedSearchElementKey];
1866
var used = false;
1867
2402
- Wix.DirectorySearch leafDirectorySearch = null;
2403
- var parentElement = unusedSearchElement;
1868
+ XElement xLeafDirectorySearch = null;
1869
+ var xUnusedSearch = unusedSearch.Value;
1870
+ var xParent = xUnusedSearch;
1871
var updatedLeaf = true;
1872
while (updatedLeaf)
1873
{
1874
updatedLeaf = false;
2408
- foreach (var schemaElement in parentElement.Children)
1875
+
1876
+ var xDirectorySearch = xParent.Element(Names.DirectorySearchElement);
1877
+ if (xDirectorySearch != null)
1878
{
2410
- if (schemaElement is Wix.DirectorySearch directorySearch)
2411
- {
2412
- parentElement = leafDirectorySearch = directorySearch;
2413
- updatedLeaf = true;
2414
- break;
2415
- }
1879
+ xParent = xLeafDirectorySearch = xDirectorySearch;
1880
+ updatedLeaf = true;
1881
}
1882
}
1883
2419
- if (leafDirectorySearch != null)
1884
+ if (xLeafDirectorySearch != null)
1885
{
2421
- var appSearchProperties = (StringCollection)appSearches[leafDirectorySearch.Id];
2422
-
2423
- var unusedSearchSchemaElement = unusedSearchElement as Wix.ISchemaElement;
2424
- if (null != appSearchProperties)
1886
+ var leafDirectorySearchId = xLeafDirectorySearch.Attribute("Id").Value;
1887
+ if (appSearches.TryGetValue(leafDirectorySearchId, out var appSearchPropertyIds))
1888
{
2426
- var property = this.EnsureProperty(appSearchProperties[0]);
2427
-
2428
- property.AddChild(unusedSearchSchemaElement);
1889
+ var xProperty = this.EnsureProperty(appSearchPropertyIds[0]);
1890
+ xProperty.Add(xUnusedSearch);
1891
used = true;
1892
}
2431
- else if (ccpSearches.Contains(leafDirectorySearch.Id))
1893
+ else if (ccpSearches.ContainsKey(leafDirectorySearchId))
1894
{
2433
- complianceCheck.AddChild(unusedSearchSchemaElement);
1895
+ xComplianceCheck.Add(xUnusedSearch);
1896
used = true;
1897
}
1898
else
@@ -2464,18 +1926,19 @@ namespace WixToolset.Core.WindowsInstaller
1926
1927
foreach (var row in shortcutTable.Rows)
1928
{
2467
- var shortcut = (Wix.Shortcut)this.core.GetIndexedElement(row);
2468
- var target = Convert.ToString(row[4]);
2469
- var feature = this.core.GetIndexedElement("Feature", target);
2470
- if (feature == null)
1929
+ var xShortcut = this.GetIndexedElement(row);
1930
+
1931
+ var target = row.FieldAsString(4);
1932
+
1933
+ if (this.TryGetIndexedElement("Feature", out var _, target))
1934
{
2472
- // TODO: use this value to do a "more-correct" nesting under the indicated File or CreateDirectory element
2473
- shortcut.Target = target;
1935
+ xShortcut.SetAttributeValue("Advertise", "yes");
1936
+ this.SetPrimaryFeature(row, 4, 3);
1937
}
1938
else
1939
{
2477
- shortcut.Advertise = Wix.YesNoType.yes;
2478
- this.SetPrimaryFeature(row, 4, 3);
1940
+ // TODO: use this value to do a "more-correct" nesting under the indicated File or CreateDirectory element
1941
+ xShortcut.SetAttributeValue("Target", target);
1942
}
1943
}
1944
}
@@ -2520,12 +1983,12 @@ namespace WixToolset.Core.WindowsInstaller
1983
1984
actionSymbol.Action = action;
1985
2523
- if (null != row[1])
1986
+ if (!row.IsColumnNull(1))
1987
{
2525
- actionSymbol.Condition = Convert.ToString(row[1]);
1988
+ actionSymbol.Condition = row.FieldAsString(1);
1989
}
1990
2528
- actionSymbol.Sequence = Convert.ToInt32(row[2]);
1991
+ actionSymbol.Sequence = row.FieldAsInteger(2);
1992
1993
actionSymbol.SequenceTable = sequenceTable;
1994
@@ -2654,30 +2117,30 @@ namespace WixToolset.Core.WindowsInstaller
2117
2118
actionRow.Action = row.FieldAsString(0);
2119
2657
- if (null != row[1])
2120
+ if (!row.IsColumnNull(1))
2121
{
2659
- actionRow.Sequence = Convert.ToInt32(row[1]);
2122
+ actionRow.Sequence = row.FieldAsInteger(1);
2123
}
2124
2662
- if (null != row[2] && null != row[3])
2125
+ if (!row.IsColumnNull(2) && !row.IsColumnNull(3))
2126
{
2664
- switch (Convert.ToInt32(row[3]))
2127
+ switch (row.FieldAsInteger(3))
2128
{
2666
- case 0:
2667
- actionRow.Before = Convert.ToString(row[2]);
2668
- break;
2669
- case 1:
2670
- actionRow.After = Convert.ToString(row[2]);
2671
- break;
2672
- default:
2673
- this.Messaging.Write(WarningMessages.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3]));
2674
- break;
2129
+ case 0:
2130
+ actionRow.Before = row.FieldAsString(2);
2131
+ break;
2132
+ case 1:
2133
+ actionRow.After = row.FieldAsString(2);
2134
+ break;
2135
+ default:
2136
+ this.Messaging.Write(WarningMessages.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3]));
2137
+ break;
2138
}
2139
}
2140
2678
- if (null != row[4])
2141
+ if (!row.IsColumnNull(4))
2142
{
2680
- actionRow.Condition = Convert.ToString(row[4]);
2143
+ actionRow.Condition = row.FieldAsString(4);
2144
}
2145
2146
actionRow.SequenceTable = sequenceTable;
@@ -2707,7 +2170,6 @@ namespace WixToolset.Core.WindowsInstaller
2170
var upgradeTable = tables["Upgrade"];
2171
string downgradeErrorMessage = null;
2172
string disallowUpgradeErrorMessage = null;
2710
- var majorUpgrade = new Wix.MajorUpgrade();
2173
2174
// find the DowngradePreventedCondition launch condition message
2175
if (null != launchConditionTable && 0 < launchConditionTable.Rows.Count)
@@ -2727,65 +2189,63 @@ namespace WixToolset.Core.WindowsInstaller
2189
2190
if (null != upgradeTable && 0 < upgradeTable.Rows.Count)
2191
{
2730
- var hasMajorUpgrade = false;
2192
+ XElement xMajorUpgrade = null;
2193
2732
- foreach (var row in upgradeTable.Rows)
2194
+ foreach (UpgradeRow upgradeRow in upgradeTable.Rows)
2195
{
2734
- var upgradeRow = (UpgradeRow)row;
2735
-
2196
if (Common.UpgradeDetectedProperty == upgradeRow.ActionProperty)
2197
{
2738
- hasMajorUpgrade = true;
2198
var attr = upgradeRow.Attributes;
2199
var removeFeatures = upgradeRow.Remove;
2200
+ xMajorUpgrade = xMajorUpgrade ?? new XElement(Names.MajorUpgradeElement);
2201
2202
if (WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive == (attr & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive))
2203
{
2744
- majorUpgrade.AllowSameVersionUpgrades = Wix.YesNoType.yes;
2204
+ xMajorUpgrade.SetAttributeValue("AllowSameVersionUpgrades", "yes");
2205
}
2206
2207
if (WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures != (attr & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures))
2208
{
2749
- majorUpgrade.MigrateFeatures = Wix.YesNoType.no;
2209
+ xMajorUpgrade.SetAttributeValue("MigrateFeatures", "no");
2210
}
2211
2212
if (WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure == (attr & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure))
2213
{
2754
- majorUpgrade.IgnoreRemoveFailure = Wix.YesNoType.yes;
2214
+ xMajorUpgrade.SetAttributeValue("IgnoreRemoveFailure", "yes");
2215
}
2216
2217
if (!String.IsNullOrEmpty(removeFeatures))
2218
{
2759
- majorUpgrade.RemoveFeatures = removeFeatures;
2219
+ xMajorUpgrade.SetAttributeValue("RemoveFeatures", removeFeatures);
2220
}
2221
}
2222
else if (Common.DowngradeDetectedProperty == upgradeRow.ActionProperty)
2223
{
2764
- hasMajorUpgrade = true;
2765
- majorUpgrade.DowngradeErrorMessage = downgradeErrorMessage;
2224
+ xMajorUpgrade = xMajorUpgrade ?? new XElement(Names.MajorUpgradeElement);
2225
+ xMajorUpgrade.SetAttributeValue("DowngradeErrorMessage", downgradeErrorMessage);
2226
}
2227
}
2228
2769
- if (hasMajorUpgrade)
2229
+ if (xMajorUpgrade != null)
2230
{
2231
if (String.IsNullOrEmpty(downgradeErrorMessage))
2232
{
2773
- majorUpgrade.AllowDowngrades = Wix.YesNoType.yes;
2233
+ xMajorUpgrade.SetAttributeValue("AllowDowngrades", "yes");
2234
}
2235
2236
if (!String.IsNullOrEmpty(disallowUpgradeErrorMessage))
2237
{
2778
- majorUpgrade.Disallow = Wix.YesNoType.yes;
2779
- majorUpgrade.DisallowUpgradeErrorMessage = disallowUpgradeErrorMessage;
2238
+ xMajorUpgrade.SetAttributeValue("Disallow", "yes");
2239
+ xMajorUpgrade.SetAttributeValue("DisallowUpgradeErrorMessage", disallowUpgradeErrorMessage);
2240
}
2241
2242
var scheduledType = DetermineMajorUpgradeScheduling(tables);
2783
- if (Wix.MajorUpgrade.ScheduleType.afterInstallValidate != scheduledType)
2243
+ if (scheduledType != "afterInstallValidate")
2244
{
2785
- majorUpgrade.Schedule = scheduledType;
2245
+ xMajorUpgrade.SetAttributeValue("Schedule", scheduledType);
2246
}
2247
2788
- this.core.RootElement.AddChild(majorUpgrade);
2248
+ this.RootElement.Add(xMajorUpgrade);
2249
}
2250
}
2251
}
@@ -2801,43 +2261,25 @@ namespace WixToolset.Core.WindowsInstaller
2261
/// </remarks>
2262
private void FinalizeVerbTable(TableIndexedCollection tables)
2263
{
2804
- var extensionTable = tables["Extension"];
2805
- var verbTable = tables["Verb"];
2806
-
2807
- var extensionElements = new Hashtable();
2808
-
2809
- if (null != extensionTable)
2810
- {
2811
- foreach (var row in extensionTable.Rows)
2812
- {
2813
- var extension = (Wix.Extension)this.core.GetIndexedElement(row);
2814
-
2815
- if (!extensionElements.Contains(row[0]))
2816
- {
2817
- extensionElements.Add(row[0], new ArrayList());
2818
- }
2819
-
2820
- ((ArrayList)extensionElements[row[0]]).Add(extension);
2821
- }
2822
- }
2264
+ var xExtensions = this.IndexTableOneToMany(tables["Extension"]);
2265
2266
+ var verbTable = tables["Verb"];
2267
if (null != verbTable)
2268
{
2269
foreach (var row in verbTable.Rows)
2270
{
2828
- var verb = (Wix.Verb)this.core.GetIndexedElement(row);
2829
-
2830
- var extensionsArray = (ArrayList)extensionElements[row[0]];
2831
- if (null != extensionsArray)
2271
+ if (xExtensions.TryGetValue(row.FieldAsString(0), out var xVerbExtensions))
2272
{
2833
- foreach (Wix.Extension extension in extensionsArray)
2273
+ var xVerb = this.GetIndexedElement(row);
2274
+
2275
+ foreach (var xVerbExtension in xVerbExtensions)
2276
{
2835
- extension.AddChild(verb);
2277
+ xVerbExtension.Add(xVerb);
2278
}
2279
}
2280
else
2281
{
2840
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, verbTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Extension_", Convert.ToString(row[0]), "Extension"));
2282
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, verbTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Extension_", row.FieldAsString(0), "Extension"));
2283
}
2284
}
2285
}
@@ -2846,33 +2288,38 @@ namespace WixToolset.Core.WindowsInstaller
2288
/// <summary>
2289
/// Get the path to a file in the source image.
2290
/// </summary>
2849
- /// <param name="file">The file.</param>
2291
+ /// <param name="xFile">The file.</param>
2292
/// <returns>The path to the file in the source image.</returns>
2851
- private string GetSourcePath(Wix.File file)
2293
+ private string GetSourcePath(XElement xFile)
2294
{
2295
var sourcePath = new StringBuilder();
2296
2855
- var component = (Wix.Component)file.ParentElement;
2297
+ var component = xFile.Parent;
2298
2857
- for (var directory = (Wix.Directory)component.ParentElement; null != directory; directory = directory.ParentElement as Wix.Directory)
2299
+ for (var xDirectory = component.Parent; null != xDirectory && xDirectory.Name.LocalName == "Directory"; xDirectory = xDirectory.Parent)
2300
{
2301
string name;
2302
2861
- if (!this.shortNames && null != directory.SourceName)
2303
+ var dirSourceName = xDirectory.Attribute("SourceName")?.Value;
2304
+ var dirShortSourceName = xDirectory.Attribute("ShortSourceName")?.Value;
2305
+ var dirShortName = xDirectory.Attribute("ShortName")?.Value;
2306
+ var dirName = xDirectory.Attribute("Name")?.Value;
2307
+
2308
+ if (!this.ShortNames && null != dirSourceName)
2309
{
2863
- name = directory.SourceName;
2310
+ name = dirSourceName;
2311
}
2865
- else if (null != directory.ShortSourceName)
2312
+ else if (null != dirShortSourceName)
2313
{
2867
- name = directory.ShortSourceName;
2314
+ name = dirShortSourceName;
2315
}
2869
- else if (!this.shortNames || null == directory.ShortName)
2316
+ else if (!this.ShortNames || null == dirShortName)
2317
{
2871
- name = directory.Name;
2318
+ name = dirName;
2319
}
2320
else
2321
{
2875
- name = directory.ShortName;
2322
+ name = dirShortName;
2323
}
2324
2325
if (0 == sourcePath.Length)
@@ -2895,11 +2342,11 @@ namespace WixToolset.Core.WindowsInstaller
2342
/// <param name="tableName">The name of the table to resolve.</param>
2343
/// <param name="unsortedTableNames">The unsorted table names.</param>
2344
/// <param name="sortedTableNames">The sorted table names.</param>
2898
- private void ResolveTableDependencies(string tableName, SortedList unsortedTableNames, StringCollection sortedTableNames)
2345
+ private void ResolveTableDependencies(string tableName, List<string> unsortedTableNames, HashSet<string> sortedTableNames)
2346
{
2347
unsortedTableNames.Remove(tableName);
2348
2902
- foreach (var columnDefinition in this.tableDefinitions[tableName].Columns)
2349
+ foreach (var columnDefinition in this.TableDefinitions[tableName].Columns)
2350
{
2351
// no dependency to resolve because this column doesn't reference another table
2352
if (null == columnDefinition.KeyTable)
@@ -2917,7 +2364,7 @@ namespace WixToolset.Core.WindowsInstaller
2364
{
2365
continue; // dependent table has already been sorted
2366
}
2920
- else if (!this.tableDefinitions.Contains(keyTable))
2367
+ else if (!this.TableDefinitions.Contains(keyTable))
2368
{
2369
this.Messaging.Write(ErrorMessages.MissingTableDefinition(keyTable));
2370
}
@@ -2941,24 +2388,18 @@ namespace WixToolset.Core.WindowsInstaller
2388
/// Get the names of the tables to process in the order they should be processed, according to their dependencies.
2389
/// </summary>
2390
/// <returns>A StringCollection containing the ordered table names.</returns>
2944
- private StringCollection GetSortedTableNames()
2391
+ private HashSet<string> GetOrderedTableNames()
2392
{
2946
- var sortedTableNames = new StringCollection();
2947
- var unsortedTableNames = new SortedList();
2948
-
2949
- // index the table names
2950
- foreach (var tableDefinition in this.tableDefinitions)
2951
- {
2952
- unsortedTableNames.Add(tableDefinition.Name, tableDefinition.Name);
2953
- }
2393
+ var orderedTableNames = new HashSet<string>();
2394
+ var unsortedTableNames = new List<string>(this.TableDefinitions.Select(t => t.Name));
2395
2396
// resolve the dependencies for each table
2397
while (0 < unsortedTableNames.Count)
2398
{
2958
- this.ResolveTableDependencies(Convert.ToString(unsortedTableNames.GetByIndex(0)), unsortedTableNames, sortedTableNames);
2399
+ this.ResolveTableDependencies(unsortedTableNames[0], unsortedTableNames, orderedTableNames);
2400
}
2401
2961
- return sortedTableNames;
2402
+ return orderedTableNames;
2403
}
2404
2405
/// <summary>
@@ -2968,26 +2409,17 @@ namespace WixToolset.Core.WindowsInstaller
2409
private void InitializeDecompile(TableIndexedCollection tables, int codepage)
2410
{
2411
// reset all the state information
2971
- this.compressed = false;
2972
- this.patchTargetFiles.Clear();
2973
- this.sequenceElements.Clear();
2974
- this.shortNames = false;
2412
+ this.Compressed = false;
2413
+ this.ShortNames = false;
2414
+
2415
+ this.Singletons.Clear();
2416
+ this.IndexedElements.Clear();
2417
+ this.PatchTargetFiles.Clear();
2418
2419
// set the codepage if its not neutral (0)
2420
if (0 != codepage)
2421
{
2979
- switch (this.OutputType)
2980
- {
2981
- case OutputType.Module:
2982
- ((Wix.Module)this.core.RootElement).Codepage = codepage.ToString(CultureInfo.InvariantCulture);
2983
- break;
2984
- case OutputType.PatchCreation:
2985
- ((Wix.PatchCreation)this.core.RootElement).Codepage = codepage.ToString(CultureInfo.InvariantCulture);
2986
- break;
2987
- case OutputType.Product:
2988
- ((Wix.Product)this.core.RootElement).Codepage = codepage.ToString(CultureInfo.InvariantCulture);
2989
- break;
2990
- }
2422
+ this.RootElement.SetAttributeValue("Codepage", codepage);
2423
}
2424
2425
// index the rows from the extension libraries
@@ -3011,15 +2443,15 @@ namespace WixToolset.Core.WindowsInstaller
2443
// the Actions table needs to be handled specially
2444
if ("WixAction" == table.Name)
2445
{
3014
- primaryKey = Convert.ToString(row[1]);
2446
+ primaryKey = row.FieldAsString(1);
2447
2448
if (OutputType.Module == this.outputType)
2449
{
3018
- tableName = String.Concat("Module", Convert.ToString(row[0]));
2450
+ tableName = String.Concat("Module", row.FieldAsString(0));
2451
}
2452
else
2453
{
3022
- tableName = Convert.ToString(row[0]);
2454
+ tableName = row.FieldAsString(0);
2455
}
2456
}
2457
else
@@ -3077,9 +2509,8 @@ namespace WixToolset.Core.WindowsInstaller
2509
/// <param name="output">The output being decompiled.</param>
2510
private void DecompileTables(WindowsInstallerData output)
2511
{
3080
- var sortedTableNames = this.GetSortedTableNames();
3081
-
3082
- foreach (var tableName in sortedTableNames)
2512
+ var orderedTableNames = this.GetOrderedTableNames();
2513
+ foreach (var tableName in orderedTableNames)
2514
{
2515
var table = output.Tables[tableName];
2516
@@ -3094,328 +2525,326 @@ namespace WixToolset.Core.WindowsInstaller
2525
// empty tables may be kept with EnsureTable if the user set the proper option
2526
if (0 == table.Rows.Count && this.SuppressDroppingEmptyTables)
2527
{
3097
- var ensureTable = new Wix.EnsureTable();
3098
- ensureTable.Id = table.Name;
3099
- this.core.RootElement.AddChild(ensureTable);
2528
+ this.RootElement.Add(new XElement(Names.EnsureTableElement, new XAttribute("Id", table.Name)));
2529
}
2530
2531
switch (table.Name)
2532
{
3104
- case "_SummaryInformation":
3105
- this.Decompile_SummaryInformationTable(table);
3106
- break;
3107
- case "AdminExecuteSequence":
3108
- case "AdminUISequence":
3109
- case "AdvtExecuteSequence":
3110
- case "InstallExecuteSequence":
3111
- case "InstallUISequence":
3112
- case "ModuleAdminExecuteSequence":
3113
- case "ModuleAdminUISequence":
3114
- case "ModuleAdvtExecuteSequence":
3115
- case "ModuleInstallExecuteSequence":
3116
- case "ModuleInstallUISequence":
3117
- // handled in FinalizeSequenceTables
3118
- break;
3119
- case "ActionText":
3120
- this.DecompileActionTextTable(table);
3121
- break;
3122
- case "AdvtUISequence":
3123
- this.Messaging.Write(WarningMessages.DeprecatedTable(table.Name));
3124
- break;
3125
- case "AppId":
3126
- this.DecompileAppIdTable(table);
3127
- break;
3128
- case "AppSearch":
3129
- // handled in FinalizeSearchTables
3130
- break;
3131
- case "BBControl":
3132
- this.DecompileBBControlTable(table);
3133
- break;
3134
- case "Billboard":
3135
- this.DecompileBillboardTable(table);
3136
- break;
3137
- case "Binary":
3138
- this.DecompileBinaryTable(table);
3139
- break;
3140
- case "BindImage":
3141
- this.DecompileBindImageTable(table);
3142
- break;
3143
- case "CCPSearch":
3144
- // handled in FinalizeSearchTables
3145
- break;
3146
- case "CheckBox":
3147
- // handled in FinalizeCheckBoxTable
3148
- break;
3149
- case "Class":
3150
- this.DecompileClassTable(table);
3151
- break;
3152
- case "ComboBox":
3153
- this.DecompileComboBoxTable(table);
3154
- break;
3155
- case "Control":
3156
- this.DecompileControlTable(table);
3157
- break;
3158
- case "ControlCondition":
3159
- this.DecompileControlConditionTable(table);
3160
- break;
3161
- case "ControlEvent":
3162
- this.DecompileControlEventTable(table);
3163
- break;
3164
- case "CreateFolder":
3165
- this.DecompileCreateFolderTable(table);
3166
- break;
3167
- case "CustomAction":
3168
- this.DecompileCustomActionTable(table);
3169
- break;
3170
- case "CompLocator":
3171
- this.DecompileCompLocatorTable(table);
3172
- break;
3173
- case "Complus":
3174
- this.DecompileComplusTable(table);
3175
- break;
3176
- case "Component":
3177
- this.DecompileComponentTable(table);
3178
- break;
3179
- case "Condition":
3180
- this.DecompileConditionTable(table);
3181
- break;
3182
- case "Dialog":
3183
- this.DecompileDialogTable(table);
3184
- break;
3185
- case "Directory":
3186
- this.DecompileDirectoryTable(table);
3187
- break;
3188
- case "DrLocator":
3189
- this.DecompileDrLocatorTable(table);
3190
- break;
3191
- case "DuplicateFile":
3192
- this.DecompileDuplicateFileTable(table);
3193
- break;
3194
- case "Environment":
3195
- this.DecompileEnvironmentTable(table);
3196
- break;
3197
- case "Error":
3198
- this.DecompileErrorTable(table);
3199
- break;
3200
- case "EventMapping":
3201
- this.DecompileEventMappingTable(table);
3202
- break;
3203
- case "Extension":
3204
- this.DecompileExtensionTable(table);
3205
- break;
3206
- case "ExternalFiles":
3207
- this.DecompileExternalFilesTable(table);
3208
- break;
3209
- case "FamilyFileRanges":
3210
- // handled in FinalizeFamilyFileRangesTable
3211
- break;
3212
- case "Feature":
3213
- this.DecompileFeatureTable(table);
3214
- break;
3215
- case "FeatureComponents":
3216
- this.DecompileFeatureComponentsTable(table);
3217
- break;
3218
- case "File":
3219
- this.DecompileFileTable(table);
3220
- break;
3221
- case "FileSFPCatalog":
3222
- this.DecompileFileSFPCatalogTable(table);
3223
- break;
3224
- case "Font":
3225
- this.DecompileFontTable(table);
3226
- break;
3227
- case "Icon":
3228
- this.DecompileIconTable(table);
3229
- break;
3230
- case "ImageFamilies":
3231
- this.DecompileImageFamiliesTable(table);
3232
- break;
3233
- case "IniFile":
3234
- this.DecompileIniFileTable(table);
3235
- break;
3236
- case "IniLocator":
3237
- this.DecompileIniLocatorTable(table);
3238
- break;
3239
- case "IsolatedComponent":
3240
- this.DecompileIsolatedComponentTable(table);
3241
- break;
3242
- case "LaunchCondition":
3243
- this.DecompileLaunchConditionTable(table);
3244
- break;
3245
- case "ListBox":
3246
- this.DecompileListBoxTable(table);
3247
- break;
3248
- case "ListView":
3249
- this.DecompileListViewTable(table);
3250
- break;
3251
- case "LockPermissions":
3252
- this.DecompileLockPermissionsTable(table);
3253
- break;
3254
- case "Media":
3255
- this.DecompileMediaTable(table);
3256
- break;
3257
- case "MIME":
3258
- this.DecompileMIMETable(table);
3259
- break;
3260
- case "ModuleAdvtUISequence":
3261
- this.Messaging.Write(WarningMessages.DeprecatedTable(table.Name));
3262
- break;
3263
- case "ModuleComponents":
3264
- // handled by DecompileComponentTable (since the ModuleComponents table
3265
- // rows are created by nesting components under the Module element)
3266
- break;
3267
- case "ModuleConfiguration":
3268
- this.DecompileModuleConfigurationTable(table);
3269
- break;
3270
- case "ModuleDependency":
3271
- this.DecompileModuleDependencyTable(table);
3272
- break;
3273
- case "ModuleExclusion":
3274
- this.DecompileModuleExclusionTable(table);
3275
- break;
3276
- case "ModuleIgnoreTable":
3277
- this.DecompileModuleIgnoreTableTable(table);
3278
- break;
3279
- case "ModuleSignature":
3280
- this.DecompileModuleSignatureTable(table);
3281
- break;
3282
- case "ModuleSubstitution":
3283
- this.DecompileModuleSubstitutionTable(table);
3284
- break;
3285
- case "MoveFile":
3286
- this.DecompileMoveFileTable(table);
3287
- break;
3288
- case "MsiAssembly":
3289
- // handled in FinalizeFileTable
3290
- break;
3291
- case "MsiDigitalCertificate":
3292
- this.DecompileMsiDigitalCertificateTable(table);
3293
- break;
3294
- case "MsiDigitalSignature":
3295
- this.DecompileMsiDigitalSignatureTable(table);
3296
- break;
3297
- case "MsiEmbeddedChainer":
3298
- this.DecompileMsiEmbeddedChainerTable(table);
3299
- break;
3300
- case "MsiEmbeddedUI":
3301
- this.DecompileMsiEmbeddedUITable(table);
3302
- break;
3303
- case "MsiLockPermissionsEx":
3304
- this.DecompileMsiLockPermissionsExTable(table);
3305
- break;
3306
- case "MsiPackageCertificate":
3307
- this.DecompileMsiPackageCertificateTable(table);
3308
- break;
3309
- case "MsiPatchCertificate":
3310
- this.DecompileMsiPatchCertificateTable(table);
3311
- break;
3312
- case "MsiShortcutProperty":
3313
- this.DecompileMsiShortcutPropertyTable(table);
3314
- break;
3315
- case "ODBCAttribute":
3316
- this.DecompileODBCAttributeTable(table);
3317
- break;
3318
- case "ODBCDataSource":
3319
- this.DecompileODBCDataSourceTable(table);
3320
- break;
3321
- case "ODBCDriver":
3322
- this.DecompileODBCDriverTable(table);
3323
- break;
3324
- case "ODBCSourceAttribute":
3325
- this.DecompileODBCSourceAttributeTable(table);
3326
- break;
3327
- case "ODBCTranslator":
3328
- this.DecompileODBCTranslatorTable(table);
3329
- break;
3330
- case "PatchMetadata":
3331
- this.DecompilePatchMetadataTable(table);
3332
- break;
3333
- case "PatchSequence":
3334
- this.DecompilePatchSequenceTable(table);
3335
- break;
3336
- case "ProgId":
3337
- this.DecompileProgIdTable(table);
3338
- break;
3339
- case "Properties":
3340
- this.DecompilePropertiesTable(table);
3341
- break;
3342
- case "Property":
3343
- this.DecompilePropertyTable(table);
3344
- break;
3345
- case "PublishComponent":
3346
- this.DecompilePublishComponentTable(table);
3347
- break;
3348
- case "RadioButton":
3349
- this.DecompileRadioButtonTable(table);
3350
- break;
3351
- case "Registry":
3352
- this.DecompileRegistryTable(table);
3353
- break;
3354
- case "RegLocator":
3355
- this.DecompileRegLocatorTable(table);
3356
- break;
3357
- case "RemoveFile":
3358
- this.DecompileRemoveFileTable(table);
3359
- break;
3360
- case "RemoveIniFile":
3361
- this.DecompileRemoveIniFileTable(table);
3362
- break;
3363
- case "RemoveRegistry":
3364
- this.DecompileRemoveRegistryTable(table);
3365
- break;
3366
- case "ReserveCost":
3367
- this.DecompileReserveCostTable(table);
3368
- break;
3369
- case "SelfReg":
3370
- this.DecompileSelfRegTable(table);
3371
- break;
3372
- case "ServiceControl":
3373
- this.DecompileServiceControlTable(table);
3374
- break;
3375
- case "ServiceInstall":
3376
- this.DecompileServiceInstallTable(table);
3377
- break;
3378
- case "SFPCatalog":
3379
- this.DecompileSFPCatalogTable(table);
3380
- break;
3381
- case "Shortcut":
3382
- this.DecompileShortcutTable(table);
3383
- break;
3384
- case "Signature":
3385
- this.DecompileSignatureTable(table);
3386
- break;
3387
- case "TargetFiles_OptionalData":
3388
- this.DecompileTargetFiles_OptionalDataTable(table);
3389
- break;
3390
- case "TargetImages":
3391
- this.DecompileTargetImagesTable(table);
3392
- break;
3393
- case "TextStyle":
3394
- this.DecompileTextStyleTable(table);
3395
- break;
3396
- case "TypeLib":
3397
- this.DecompileTypeLibTable(table);
3398
- break;
3399
- case "Upgrade":
3400
- this.DecompileUpgradeTable(table);
3401
- break;
3402
- case "UpgradedFiles_OptionalData":
3403
- this.DecompileUpgradedFiles_OptionalDataTable(table);
3404
- break;
3405
- case "UpgradedFilesToIgnore":
3406
- this.DecompileUpgradedFilesToIgnoreTable(table);
3407
- break;
3408
- case "UpgradedImages":
3409
- this.DecompileUpgradedImagesTable(table);
3410
- break;
3411
- case "UIText":
3412
- this.DecompileUITextTable(table);
3413
- break;
3414
- case "Verb":
3415
- this.DecompileVerbTable(table);
3416
- break;
2533
+ case "_SummaryInformation":
2534
+ this.Decompile_SummaryInformationTable(table);
2535
+ break;
2536
+ case "AdminExecuteSequence":
2537
+ case "AdminUISequence":
2538
+ case "AdvtExecuteSequence":
2539
+ case "InstallExecuteSequence":
2540
+ case "InstallUISequence":
2541
+ case "ModuleAdminExecuteSequence":
2542
+ case "ModuleAdminUISequence":
2543
+ case "ModuleAdvtExecuteSequence":
2544
+ case "ModuleInstallExecuteSequence":
2545
+ case "ModuleInstallUISequence":
2546
+ // handled in FinalizeSequenceTables
2547
+ break;
2548
+ case "ActionText":
2549
+ this.DecompileActionTextTable(table);
2550
+ break;
2551
+ case "AdvtUISequence":
2552
+ this.Messaging.Write(WarningMessages.DeprecatedTable(table.Name));
2553
+ break;
2554
+ case "AppId":
2555
+ this.DecompileAppIdTable(table);
2556
+ break;
2557
+ case "AppSearch":
2558
+ // handled in FinalizeSearchTables
2559
+ break;
2560
+ case "BBControl":
2561
+ this.DecompileBBControlTable(table);
2562
+ break;
2563
+ case "Billboard":
2564
+ this.DecompileBillboardTable(table);
2565
+ break;
2566
+ case "Binary":
2567
+ this.DecompileBinaryTable(table);
2568
+ break;
2569
+ case "BindImage":
2570
+ this.DecompileBindImageTable(table);
2571
+ break;
2572
+ case "CCPSearch":
2573
+ // handled in FinalizeSearchTables
2574
+ break;
2575
+ case "CheckBox":
2576
+ // handled in FinalizeCheckBoxTable
2577
+ break;
2578
+ case "Class":
2579
+ this.DecompileClassTable(table);
2580
+ break;
2581
+ case "ComboBox":
2582
+ this.DecompileComboBoxTable(table);
2583
+ break;
2584
+ case "Control":
2585
+ this.DecompileControlTable(table);
2586
+ break;
2587
+ case "ControlCondition":
2588
+ this.DecompileControlConditionTable(table);
2589
+ break;
2590
+ case "ControlEvent":
2591
+ this.DecompileControlEventTable(table);
2592
+ break;
2593
+ case "CreateFolder":
2594
+ this.DecompileCreateFolderTable(table);
2595
+ break;
2596
+ case "CustomAction":
2597
+ this.DecompileCustomActionTable(table);
2598
+ break;
2599
+ case "CompLocator":
2600
+ this.DecompileCompLocatorTable(table);
2601
+ break;
2602
+ case "Complus":
2603
+ this.DecompileComplusTable(table);
2604
+ break;
2605
+ case "Component":
2606
+ this.DecompileComponentTable(table);
2607
+ break;
2608
+ case "Condition":
2609
+ this.DecompileConditionTable(table);
2610
+ break;
2611
+ case "Dialog":
2612
+ this.DecompileDialogTable(table);
2613
+ break;
2614
+ case "Directory":
2615
+ this.DecompileDirectoryTable(table);
2616
+ break;
2617
+ case "DrLocator":
2618
+ this.DecompileDrLocatorTable(table);
2619
+ break;
2620
+ case "DuplicateFile":
2621
+ this.DecompileDuplicateFileTable(table);
2622
+ break;
2623
+ case "Environment":
2624
+ this.DecompileEnvironmentTable(table);
2625
+ break;
2626
+ case "Error":
2627
+ this.DecompileErrorTable(table);
2628
+ break;
2629
+ case "EventMapping":
2630
+ this.DecompileEventMappingTable(table);
2631
+ break;
2632
+ case "Extension":
2633
+ this.DecompileExtensionTable(table);
2634
+ break;
2635
+ case "ExternalFiles":
2636
+ this.DecompileExternalFilesTable(table);
2637
+ break;
2638
+ case "FamilyFileRanges":
2639
+ // handled in FinalizeFamilyFileRangesTable
2640
+ break;
2641
+ case "Feature":
2642
+ this.DecompileFeatureTable(table);
2643
+ break;
2644
+ case "FeatureComponents":
2645
+ this.DecompileFeatureComponentsTable(table);
2646
+ break;
2647
+ case "File":
2648
+ this.DecompileFileTable(table);
2649
+ break;
2650
+ case "FileSFPCatalog":
2651
+ this.DecompileFileSFPCatalogTable(table);
2652
+ break;
2653
+ case "Font":
2654
+ this.DecompileFontTable(table);
2655
+ break;
2656
+ case "Icon":
2657
+ this.DecompileIconTable(table);
2658
+ break;
2659
+ case "ImageFamilies":
2660
+ this.DecompileImageFamiliesTable(table);
2661
+ break;
2662
+ case "IniFile":
2663
+ this.DecompileIniFileTable(table);
2664
+ break;
2665
+ case "IniLocator":
2666
+ this.DecompileIniLocatorTable(table);
2667
+ break;
2668
+ case "IsolatedComponent":
2669
+ this.DecompileIsolatedComponentTable(table);
2670
+ break;
2671
+ case "LaunchCondition":
2672
+ this.DecompileLaunchConditionTable(table);
2673
+ break;
2674
+ case "ListBox":
2675
+ this.DecompileListBoxTable(table);
2676
+ break;
2677
+ case "ListView":
2678
+ this.DecompileListViewTable(table);
2679
+ break;
2680
+ case "LockPermissions":
2681
+ this.DecompileLockPermissionsTable(table);
2682
+ break;
2683
+ case "Media":
2684
+ this.DecompileMediaTable(table);
2685
+ break;
2686
+ case "MIME":
2687
+ this.DecompileMIMETable(table);
2688
+ break;
2689
+ case "ModuleAdvtUISequence":
2690
+ this.Messaging.Write(WarningMessages.DeprecatedTable(table.Name));
2691
+ break;
2692
+ case "ModuleComponents":
2693
+ // handled by DecompileComponentTable (since the ModuleComponents table
2694
+ // rows are created by nesting components under the Module element)
2695
+ break;
2696
+ case "ModuleConfiguration":
2697
+ this.DecompileModuleConfigurationTable(table);
2698
+ break;
2699
+ case "ModuleDependency":
2700
+ this.DecompileModuleDependencyTable(table);
2701
+ break;
2702
+ case "ModuleExclusion":
2703
+ this.DecompileModuleExclusionTable(table);
2704
+ break;
2705
+ case "ModuleIgnoreTable":
2706
+ this.DecompileModuleIgnoreTableTable(table);
2707
+ break;
2708
+ case "ModuleSignature":
2709
+ this.DecompileModuleSignatureTable(table);
2710
+ break;
2711
+ case "ModuleSubstitution":
2712
+ this.DecompileModuleSubstitutionTable(table);
2713
+ break;
2714
+ case "MoveFile":
2715
+ this.DecompileMoveFileTable(table);
2716
+ break;
2717
+ case "MsiAssembly":
2718
+ // handled in FinalizeFileTable
2719
+ break;
2720
+ case "MsiDigitalCertificate":
2721
+ this.DecompileMsiDigitalCertificateTable(table);
2722
+ break;
2723
+ case "MsiDigitalSignature":
2724
+ this.DecompileMsiDigitalSignatureTable(table);
2725
+ break;
2726
+ case "MsiEmbeddedChainer":
2727
+ this.DecompileMsiEmbeddedChainerTable(table);
2728
+ break;
2729
+ case "MsiEmbeddedUI":
2730
+ this.DecompileMsiEmbeddedUITable(table);
2731
+ break;
2732
+ case "MsiLockPermissionsEx":
2733
+ this.DecompileMsiLockPermissionsExTable(table);
2734
+ break;
2735
+ case "MsiPackageCertificate":
2736
+ this.DecompileMsiPackageCertificateTable(table);
2737
+ break;
2738
+ case "MsiPatchCertificate":
2739
+ this.DecompileMsiPatchCertificateTable(table);
2740
+ break;
2741
+ case "MsiShortcutProperty":
2742
+ this.DecompileMsiShortcutPropertyTable(table);
2743
+ break;
2744
+ case "ODBCAttribute":
2745
+ this.DecompileODBCAttributeTable(table);
2746
+ break;
2747
+ case "ODBCDataSource":
2748
+ this.DecompileODBCDataSourceTable(table);
2749
+ break;
2750
+ case "ODBCDriver":
2751
+ this.DecompileODBCDriverTable(table);
2752
+ break;
2753
+ case "ODBCSourceAttribute":
2754
+ this.DecompileODBCSourceAttributeTable(table);
2755
+ break;
2756
+ case "ODBCTranslator":
2757
+ this.DecompileODBCTranslatorTable(table);
2758
+ break;
2759
+ case "PatchMetadata":
2760
+ this.DecompilePatchMetadataTable(table);
2761
+ break;
2762
+ case "PatchSequence":
2763
+ this.DecompilePatchSequenceTable(table);
2764
+ break;
2765
+ case "ProgId":
2766
+ this.DecompileProgIdTable(table);
2767
+ break;
2768
+ case "Properties":
2769
+ this.DecompilePropertiesTable(table);
2770
+ break;
2771
+ case "Property":
2772
+ this.DecompilePropertyTable(table);
2773
+ break;
2774
+ case "PublishComponent":
2775
+ this.DecompilePublishComponentTable(table);
2776
+ break;
2777
+ case "RadioButton":
2778
+ this.DecompileRadioButtonTable(table);
2779
+ break;
2780
+ case "Registry":
2781
+ this.DecompileRegistryTable(table);
2782
+ break;
2783
+ case "RegLocator":
2784
+ this.DecompileRegLocatorTable(table);
2785
+ break;
2786
+ case "RemoveFile":
2787
+ this.DecompileRemoveFileTable(table);
2788
+ break;
2789
+ case "RemoveIniFile":
2790
+ this.DecompileRemoveIniFileTable(table);
2791
+ break;
2792
+ case "RemoveRegistry":
2793
+ this.DecompileRemoveRegistryTable(table);
2794
+ break;
2795
+ case "ReserveCost":
2796
+ this.DecompileReserveCostTable(table);
2797
+ break;
2798
+ case "SelfReg":
2799
+ this.DecompileSelfRegTable(table);
2800
+ break;
2801
+ case "ServiceControl":
2802
+ this.DecompileServiceControlTable(table);
2803
+ break;
2804
+ case "ServiceInstall":
2805
+ this.DecompileServiceInstallTable(table);
2806
+ break;
2807
+ case "SFPCatalog":
2808
+ this.DecompileSFPCatalogTable(table);
2809
+ break;
2810
+ case "Shortcut":
2811
+ this.DecompileShortcutTable(table);
2812
+ break;
2813
+ case "Signature":
2814
+ this.DecompileSignatureTable(table);
2815
+ break;
2816
+ case "TargetFiles_OptionalData":
2817
+ this.DecompileTargetFiles_OptionalDataTable(table);
2818
+ break;
2819
+ case "TargetImages":
2820
+ this.DecompileTargetImagesTable(table);
2821
+ break;
2822
+ case "TextStyle":
2823
+ this.DecompileTextStyleTable(table);
2824
+ break;
2825
+ case "TypeLib":
2826
+ this.DecompileTypeLibTable(table);
2827
+ break;
2828
+ case "Upgrade":
2829
+ this.DecompileUpgradeTable(table);
2830
+ break;
2831
+ case "UpgradedFiles_OptionalData":
2832
+ this.DecompileUpgradedFiles_OptionalDataTable(table);
2833
+ break;
2834
+ case "UpgradedFilesToIgnore":
2835
+ this.DecompileUpgradedFilesToIgnoreTable(table);
2836
+ break;
2837
+ case "UpgradedImages":
2838
+ this.DecompileUpgradedImagesTable(table);
2839
+ break;
2840
+ case "UIText":
2841
+ this.DecompileUITextTable(table);
2842
+ break;
2843
+ case "Verb":
2844
+ this.DecompileVerbTable(table);
2845
+ break;
2846
3418
- default:
2847
+ default:
2848
#if TODO_DECOMPILER_EXTENSIONS
2849
if (this.ExtensionsByTableName.TryGetValue(table.Name, out var extension)
2850
{
@@ -3423,11 +2852,11 @@ namespace WixToolset.Core.WindowsInstaller
2852
}
2853
else
2854
#endif
3426
- if (!this.SuppressCustomTables)
3427
- {
3428
- this.DecompileCustomTable(table);
3429
- }
3430
- break;
2855
+ if (!this.SuppressCustomTables)
2856
+ {
2857
+ this.DecompileCustomTable(table);
2858
+ }
2859
+ break;
2860
}
2861
}
2862
}
@@ -3442,87 +2871,87 @@ namespace WixToolset.Core.WindowsInstaller
2871
{
2872
switch (tableName)
2873
{
3445
- case "ActionText":
3446
- case "BBControl":
3447
- case "Billboard":
3448
- case "CheckBox":
3449
- case "Control":
3450
- case "ControlCondition":
3451
- case "ControlEvent":
3452
- case "Dialog":
3453
- case "Error":
3454
- case "EventMapping":
3455
- case "RadioButton":
3456
- case "TextStyle":
3457
- case "UIText":
3458
- return !this.SuppressUI;
3459
- case "ModuleAdminExecuteSequence":
3460
- case "ModuleAdminUISequence":
3461
- case "ModuleAdvtExecuteSequence":
3462
- case "ModuleAdvtUISequence":
3463
- case "ModuleComponents":
3464
- case "ModuleConfiguration":
3465
- case "ModuleDependency":
3466
- case "ModuleIgnoreTable":
3467
- case "ModuleInstallExecuteSequence":
3468
- case "ModuleInstallUISequence":
3469
- case "ModuleExclusion":
3470
- case "ModuleSignature":
3471
- case "ModuleSubstitution":
3472
- if (OutputType.Module != output.Type)
3473
- {
3474
- this.Messaging.Write(WarningMessages.SkippingMergeModuleTable(output.SourceLineNumbers, tableName));
3475
- return false;
3476
- }
3477
- else
3478
- {
3479
- return true;
3480
- }
3481
- case "ExternalFiles":
3482
- case "FamilyFileRanges":
3483
- case "ImageFamilies":
3484
- case "PatchMetadata":
3485
- case "PatchSequence":
3486
- case "Properties":
3487
- case "TargetFiles_OptionalData":
3488
- case "TargetImages":
3489
- case "UpgradedFiles_OptionalData":
3490
- case "UpgradedFilesToIgnore":
3491
- case "UpgradedImages":
3492
- if (OutputType.PatchCreation != output.Type)
3493
- {
3494
- this.Messaging.Write(WarningMessages.SkippingPatchCreationTable(output.SourceLineNumbers, tableName));
2874
+ case "ActionText":
2875
+ case "BBControl":
2876
+ case "Billboard":
2877
+ case "CheckBox":
2878
+ case "Control":
2879
+ case "ControlCondition":
2880
+ case "ControlEvent":
2881
+ case "Dialog":
2882
+ case "Error":
2883
+ case "EventMapping":
2884
+ case "RadioButton":
2885
+ case "TextStyle":
2886
+ case "UIText":
2887
+ return !this.SuppressUI;
2888
+ case "ModuleAdminExecuteSequence":
2889
+ case "ModuleAdminUISequence":
2890
+ case "ModuleAdvtExecuteSequence":
2891
+ case "ModuleAdvtUISequence":
2892
+ case "ModuleComponents":
2893
+ case "ModuleConfiguration":
2894
+ case "ModuleDependency":
2895
+ case "ModuleIgnoreTable":
2896
+ case "ModuleInstallExecuteSequence":
2897
+ case "ModuleInstallUISequence":
2898
+ case "ModuleExclusion":
2899
+ case "ModuleSignature":
2900
+ case "ModuleSubstitution":
2901
+ if (OutputType.Module != output.Type)
2902
+ {
2903
+ this.Messaging.Write(WarningMessages.SkippingMergeModuleTable(output.SourceLineNumbers, tableName));
2904
+ return false;
2905
+ }
2906
+ else
2907
+ {
2908
+ return true;
2909
+ }
2910
+ case "ExternalFiles":
2911
+ case "FamilyFileRanges":
2912
+ case "ImageFamilies":
2913
+ case "PatchMetadata":
2914
+ case "PatchSequence":
2915
+ case "Properties":
2916
+ case "TargetFiles_OptionalData":
2917
+ case "TargetImages":
2918
+ case "UpgradedFiles_OptionalData":
2919
+ case "UpgradedFilesToIgnore":
2920
+ case "UpgradedImages":
2921
+ if (OutputType.PatchCreation != output.Type)
2922
+ {
2923
+ this.Messaging.Write(WarningMessages.SkippingPatchCreationTable(output.SourceLineNumbers, tableName));
2924
+ return false;
2925
+ }
2926
+ else
2927
+ {
2928
+ return true;
2929
+ }
2930
+ case "MsiPatchHeaders":
2931
+ case "MsiPatchMetadata":
2932
+ case "MsiPatchOldAssemblyName":
2933
+ case "MsiPatchOldAssemblyFile":
2934
+ case "MsiPatchSequence":
2935
+ case "Patch":
2936
+ case "PatchPackage":
2937
+ this.Messaging.Write(WarningMessages.PatchTable(output.SourceLineNumbers, tableName));
2938
return false;
3496
- }
3497
- else
3498
- {
2939
+ case "_SummaryInformation":
2940
return true;
3500
- }
3501
- case "MsiPatchHeaders":
3502
- case "MsiPatchMetadata":
3503
- case "MsiPatchOldAssemblyName":
3504
- case "MsiPatchOldAssemblyFile":
3505
- case "MsiPatchSequence":
3506
- case "Patch":
3507
- case "PatchPackage":
3508
- this.Messaging.Write(WarningMessages.PatchTable(output.SourceLineNumbers, tableName));
3509
- return false;
3510
- case "_SummaryInformation":
3511
- return true;
3512
- case "_Validation":
3513
- case "MsiAssemblyName":
3514
- case "MsiFileHash":
3515
- return false;
3516
- default: // all other tables are allowed in any output except for a patch creation package
3517
- if (OutputType.PatchCreation == output.Type)
3518
- {
3519
- this.Messaging.Write(WarningMessages.IllegalPatchCreationTable(output.SourceLineNumbers, tableName));
2941
+ case "_Validation":
2942
+ case "MsiAssemblyName":
2943
+ case "MsiFileHash":
2944
return false;
3521
- }
3522
- else
3523
- {
3524
- return true;
3525
- }
2945
+ default: // all other tables are allowed in any output except for a patch creation package
2946
+ if (OutputType.PatchCreation == output.Type)
2947
+ {
2948
+ this.Messaging.Write(WarningMessages.IllegalPatchCreationTable(output.SourceLineNumbers, tableName));
2949
+ return false;
2950
+ }
2951
+ else
2952
+ {
2953
+ return true;
2954
+ }
2955
}
2956
}
2957
@@ -3534,200 +2963,177 @@ namespace WixToolset.Core.WindowsInstaller
2963
{
2964
if (OutputType.Module == this.OutputType || OutputType.Product == this.OutputType)
2965
{
3537
- var package = new Wix.Package();
2966
+ var xPackage = new XElement(Names.PackageElement);
2967
2968
foreach (var row in table.Rows)
2969
{
3541
- var value = Convert.ToString(row[1]);
2970
+ var value = row.FieldAsString(1);
2971
3543
- if (null != value && 0 < value.Length)
2972
+ if (!String.IsNullOrEmpty(value))
2973
{
3545
- switch (Convert.ToInt32(row[0]))
2974
+ switch (row.FieldAsInteger(0))
2975
{
3547
- case 1:
3548
- if ("1252" != value)
3549
- {
3550
- package.SummaryCodepage = value;
3551
- }
3552
- break;
3553
- case 3:
3554
- package.Description = value;
3555
- break;
3556
- case 4:
3557
- package.Manufacturer = value;
3558
- break;
3559
- case 5:
3560
- if ("Installer" != value)
3561
- {
3562
- package.Keywords = value;
3563
- }
3564
- break;
3565
- case 6:
3566
- if (!value.StartsWith("This installer database contains the logic and data required to install "))
3567
- {
3568
- package.Comments = value;
3569
- }
3570
- break;
3571
- case 7:
3572
- var template = value.Split(';');
3573
- if (0 < template.Length && 0 < template[template.Length - 1].Length)
3574
- {
3575
- package.Languages = template[template.Length - 1];
3576
- }
3577
-
3578
- if (1 < template.Length && null != template[0] && 0 < template[0].Length)
3579
- {
3580
- switch (template[0])
2976
+ case 1:
2977
+ if ("1252" != value)
2978
{
3582
- case "Intel":
3583
- package.Platform = WixToolset.Data.Serialize.Package.PlatformType.x86;
3584
- break;
3585
- case "Intel64":
3586
- package.Platform = WixToolset.Data.Serialize.Package.PlatformType.ia64;
3587
- break;
3588
- case "x64":
3589
- package.Platform = WixToolset.Data.Serialize.Package.PlatformType.x64;
3590
- break;
2979
+ xPackage.SetAttributeValue("SummaryCodepage", value);
2980
+ }
2981
+ break;
2982
+ case 3:
2983
+ xPackage.SetAttributeValue("Description", value);
2984
+ break;
2985
+ case 4:
2986
+ xPackage.SetAttributeValue("Manufacturer", value);
2987
+ break;
2988
+ case 5:
2989
+ if ("Installer" != value)
2990
+ {
2991
+ xPackage.SetAttributeValue("Keywords", value);
2992
+ }
2993
+ break;
2994
+ case 6:
2995
+ if (!value.StartsWith("This installer database contains the logic and data required to install "))
2996
+ {
2997
+ xPackage.SetAttributeValue("Comments", value);
2998
+ }
2999
+ break;
3000
+ case 7:
3001
+ var template = value.Split(';');
3002
+ if (0 < template.Length && 0 < template[template.Length - 1].Length)
3003
+ {
3004
+ xPackage.SetAttributeValue("Languages", template[template.Length - 1]);
3005
}
3592
- }
3593
- break;
3594
- case 9:
3595
- if (OutputType.Module == this.OutputType)
3596
- {
3597
- this.modularizationGuid = value;
3598
- package.Id = value;
3599
- }
3600
- break;
3601
- case 14:
3602
- package.InstallerVersion = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
3603
- break;
3604
- case 15:
3605
- var wordCount = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
3606
- if (0x1 == (wordCount & 0x1))
3607
- {
3608
- this.shortNames = true;
3609
- package.ShortNames = Wix.YesNoType.yes;
3610
- }
3006
3612
- if (0x2 == (wordCount & 0x2))
3613
- {
3614
- this.compressed = true;
3007
+ if (1 < template.Length && null != template[0] && 0 < template[0].Length)
3008
+ {
3009
+ switch (template[0])
3010
+ {
3011
+ case "Intel":
3012
+ xPackage.SetAttributeValue("Platform", "x86");
3013
+ break;
3014
+ case "Intel64":
3015
+ xPackage.SetAttributeValue("Platform", "ia64");
3016
+ break;
3017
+ case "x64":
3018
+ xPackage.SetAttributeValue("Platform", "x64");
3019
+ break;
3020
+ case "Arm":
3021
+ xPackage.SetAttributeValue("Platform", "arm");
3022
+ break;
3023
+ case "Arm64":
3024
+ xPackage.SetAttributeValue("Platform", "arm64");
3025
+ break;
3026
+ }
3027
+ }
3028
+ break;
3029
+ case 9:
3030
+ if (OutputType.Module == this.OutputType)
3031
+ {
3032
+ this.ModularizationGuid = value;
3033
+ xPackage.SetAttributeValue("Id", value);
3034
+ }
3035
+ break;
3036
+ case 14:
3037
+ xPackage.SetAttributeValue("InstallerVersion", row.FieldAsInteger(1));
3038
+ break;
3039
+ case 15:
3040
+ var wordCount = row.FieldAsInteger(1);
3041
+ if (0x1 == (wordCount & 0x1))
3042
+ {
3043
+ this.ShortNames = true;
3044
+ xPackage.SetAttributeValue("ShortNames", "yes");
3045
+ }
3046
3616
- if (OutputType.Product == this.OutputType)
3047
+ if (0x2 == (wordCount & 0x2))
3048
{
3618
- package.Compressed = Wix.YesNoType.yes;
3049
+ this.Compressed = true;
3050
+
3051
+ if (OutputType.Product == this.OutputType)
3052
+ {
3053
+ xPackage.SetAttributeValue("Compressed", "yes");
3054
+ }
3055
}
3620
- }
3056
3622
- if (0x4 == (wordCount & 0x4))
3623
- {
3624
- package.AdminImage = Wix.YesNoType.yes;
3625
- }
3057
+ if (0x4 == (wordCount & 0x4))
3058
+ {
3059
+ xPackage.SetAttributeValue("AdminImage", "yes");
3060
+ }
3061
3627
- if (0x8 == (wordCount & 0x8))
3628
- {
3629
- package.InstallPrivileges = Wix.Package.InstallPrivilegesType.limited;
3630
- }
3062
+ if (0x8 == (wordCount & 0x8))
3063
+ {
3064
+ xPackage.SetAttributeValue("InstallPrivileges", "limited");
3065
+ }
3066
3632
- break;
3633
- case 19:
3634
- var security = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
3635
- switch (security)
3636
- {
3637
- case 0:
3638
- package.ReadOnly = Wix.YesNoDefaultType.no;
3067
break;
3640
- case 4:
3641
- package.ReadOnly = Wix.YesNoDefaultType.yes;
3068
+ case 19:
3069
+ var security = row.FieldAsInteger(1);
3070
+ switch (security)
3071
+ {
3072
+ case 0:
3073
+ xPackage.SetAttributeValue("ReadOnly", "no");
3074
+ break;
3075
+ case 4:
3076
+ xPackage.SetAttributeValue("ReadOnly", "yes");
3077
+ break;
3078
+ }
3079
break;
3643
- }
3644
- break;
3080
}
3081
}
3082
}
3083
3649
- this.core.RootElement.AddChild(package);
3084
+ this.RootElement.Add(xPackage);
3085
}
3086
else
3087
{
3653
- var patchInformation = new Wix.PatchInformation();
3088
+ var xPatchInformation = new XElement(Names.PatchInformationElement);
3089
3090
foreach (var row in table.Rows)
3091
{
3657
- var propertyId = Convert.ToInt32(row[0]);
3658
- var value = Convert.ToString(row[1]);
3092
+ var propertyId = row.FieldAsInteger(0);
3093
+ var value = row.FieldAsString(1);
3094
3660
- if (null != row[1] && 0 < value.Length)
3095
+ if (!String.IsNullOrEmpty(value))
3096
{
3097
switch (propertyId)
3098
{
3664
- case 1:
3665
- if ("1252" != value)
3666
- {
3667
- patchInformation.SummaryCodepage = value;
3668
- }
3669
- break;
3670
- case 3:
3671
- patchInformation.Description = value;
3672
- break;
3673
- case 4:
3674
- patchInformation.Manufacturer = value;
3675
- break;
3676
- case 5:
3677
- if ("Installer,Patching,PCP,Database" != value)
3678
- {
3679
- patchInformation.Keywords = value;
3680
- }
3681
- break;
3682
- case 6:
3683
- patchInformation.Comments = value;
3684
- break;
3685
- case 7:
3686
- var template = value.Split(';');
3687
- if (0 < template.Length && 0 < template[template.Length - 1].Length)
3688
- {
3689
- patchInformation.Languages = template[template.Length - 1];
3690
- }
3691
-
3692
- if (1 < template.Length && null != template[0] && 0 < template[0].Length)
3693
- {
3694
- patchInformation.Platforms = template[0];
3695
- }
3696
- break;
3697
- case 15:
3698
- var wordCount = Convert.ToInt32(value, CultureInfo.InvariantCulture);
3699
- if (0x1 == (wordCount & 0x1))
3700
- {
3701
- patchInformation.ShortNames = Wix.YesNoType.yes;
3702
- }
3703
-
3704
- if (0x2 == (wordCount & 0x2))
3705
- {
3706
- patchInformation.Compressed = Wix.YesNoType.yes;
3707
- }
3708
-
3709
- if (0x4 == (wordCount & 0x4))
3710
- {
3711
- patchInformation.AdminImage = Wix.YesNoType.yes;
3712
- }
3713
- break;
3714
- case 19:
3715
- var security = Convert.ToInt32(value, CultureInfo.InvariantCulture);
3716
- switch (security)
3717
- {
3718
- case 0:
3719
- patchInformation.ReadOnly = Wix.YesNoDefaultType.no;
3099
+ case 1:
3100
+ if ("1252" != value)
3101
+ {
3102
+ xPatchInformation.SetAttributeValue("SummaryCodepage", value);
3103
+ }
3104
+ break;
3105
+ case 3:
3106
+ xPatchInformation.SetAttributeValue("Description", value);
3107
break;
3108
case 4:
3722
- patchInformation.ReadOnly = Wix.YesNoDefaultType.yes;
3109
+ xPatchInformation.SetAttributeValue("Manufacturer", value);
3110
+ break;
3111
+ case 5:
3112
+ if ("Installer,Patching,PCP,Database" != value)
3113
+ {
3114
+ xPatchInformation.SetAttributeValue("Keywords", value);
3115
+ }
3116
+ break;
3117
+ case 6:
3118
+ xPatchInformation.SetAttributeValue("Comments", value);
3119
+ break;
3120
+ case 19:
3121
+ var security = Convert.ToInt32(value, CultureInfo.InvariantCulture);
3122
+ switch (security)
3123
+ {
3124
+ case 0:
3125
+ xPatchInformation.SetAttributeValue("ReadOnly", "no");
3126
+ break;
3127
+ case 4:
3128
+ xPatchInformation.SetAttributeValue("ReadOnly", "yes");
3129
+ break;
3130
+ }
3131
break;
3724
- }
3725
- break;
3132
}
3133
}
3134
}
3135
3730
- this.core.RootElement.AddChild(patchInformation);
3136
+ this.RootElement.Add(xPatchInformation);
3137
}
3138
}
3139
@@ -3739,21 +3145,12 @@ namespace WixToolset.Core.WindowsInstaller
3145
{
3146
foreach (var row in table.Rows)
3147
{
3742
- var progressText = new Wix.ProgressText();
3148
+ var progressText = new XElement(Names.ProgressTextElement,
3149
+ new XAttribute("Action", row.FieldAsString(0)),
3150
+ row.IsColumnNull(1) ? null : new XAttribute("Content", row.FieldAsString(1)),
3151
+ row.IsColumnNull(2) ? null : new XAttribute("Template", row.FieldAsString(2)));
3152
3744
- progressText.Action = Convert.ToString(row[0]);
3745
-
3746
- if (null != row[1])
3747
- {
3748
- progressText.Content = Convert.ToString(row[1]);
3749
- }
3750
-
3751
- if (null != row[2])
3752
- {
3753
- progressText.Template = Convert.ToString(row[2]);
3754
- }
3755
-
3756
- this.core.UIElement.AddChild(progressText);
3153
+ this.UIElement.Add(progressText);
3154
}
3155
}
3156
@@ -3765,44 +3162,18 @@ namespace WixToolset.Core.WindowsInstaller
3162
{
3163
foreach (var row in table.Rows)
3164
{
3768
- var appId = new Wix.AppId();
3769
-
3770
- appId.Advertise = Wix.YesNoType.yes;
3771
-
3772
- appId.Id = Convert.ToString(row[0]);
3773
-
3774
- if (null != row[1])
3775
- {
3776
- appId.RemoteServerName = Convert.ToString(row[1]);
3777
- }
3778
-
3779
- if (null != row[2])
3780
- {
3781
- appId.LocalService = Convert.ToString(row[2]);
3782
- }
3165
+ var appId = new XElement(Names.AppIdElement,
3166
+ new XAttribute("Advertise", "yes"),
3167
+ new XAttribute("Id", row.FieldAsString(0)),
3168
+ row.IsColumnNull(1) ? null : new XAttribute("RemoteServerName", row.FieldAsString(1)),
3169
+ row.IsColumnNull(2) ? null : new XAttribute("LocalService", row.FieldAsString(2)),
3170
+ row.IsColumnNull(3) ? null : new XAttribute("ServiceParameters", row.FieldAsString(3)),
3171
+ row.IsColumnNull(4) ? null : new XAttribute("DllSurrogate", row.FieldAsString(4)),
3172
+ row.IsColumnNull(5) || row.FieldAsInteger(5) != 1 ? null : new XAttribute("ActivateAtStorage", "yes"),
3173
+ row.IsColumnNull(6) || row.FieldAsInteger(6) != 1 ? null : new XAttribute("RunAsInteractiveUser", "yes"));
3174
3784
- if (null != row[3])
3785
- {
3786
- appId.ServiceParameters = Convert.ToString(row[3]);
3787
- }
3788
-
3789
- if (null != row[4])
3790
- {
3791
- appId.DllSurrogate = Convert.ToString(row[4]);
3792
- }
3793
-
3794
- if (null != row[5] && Int32.Equals(row[5], 1))
3795
- {
3796
- appId.ActivateAtStorage = Wix.YesNoType.yes;
3797
- }
3798
-
3799
- if (null != row[6] && Int32.Equals(row[6], 1))
3800
- {
3801
- appId.RunAsInteractiveUser = Wix.YesNoType.yes;
3802
- }
3803
-
3804
- this.core.RootElement.AddChild(appId);
3805
- this.core.IndexElement(row, appId);
3175
+ this.RootElement.Add(appId);
3176
+ this.IndexElement(row, appId);
3177
}
3178
}
3179
@@ -3814,34 +3185,23 @@ namespace WixToolset.Core.WindowsInstaller
3185
{
3186
foreach (BBControlRow bbControlRow in table.Rows)
3187
{
3817
- var control = new Wix.Control();
3818
-
3819
- control.Id = bbControlRow.BBControl;
3820
-
3821
- control.Type = bbControlRow.Type;
3822
-
3823
- control.X = bbControlRow.X;
3824
-
3825
- control.Y = bbControlRow.Y;
3826
-
3827
- control.Width = bbControlRow.Width;
3828
-
3829
- control.Height = bbControlRow.Height;
3188
+ var xControl = new XElement(Names.ControlElement,
3189
+ new XAttribute("Id", bbControlRow.BBControl),
3190
+ new XAttribute("Type", bbControlRow.Type),
3191
+ new XAttribute("X", bbControlRow.X),
3192
+ new XAttribute("Y", bbControlRow.Y),
3193
+ new XAttribute("Width", bbControlRow.Width),
3194
+ new XAttribute("Height", bbControlRow.Height),
3195
+ null == bbControlRow.Text ? null : new XAttribute("Text", bbControlRow.Text));
3196
3197
if (null != bbControlRow[7])
3198
{
3833
- SetControlAttributes(bbControlRow.Attributes, control);
3199
+ SetControlAttributes(bbControlRow.Attributes, xControl);
3200
}
3201
3836
- if (null != bbControlRow.Text)
3202
+ if (this.TryGetIndexedElement("Billboard", out var xBillboard, bbControlRow.Billboard))
3203
{
3838
- control.Text = bbControlRow.Text;
3839
- }
3840
-
3841
- var billboard = (Wix.Billboard)this.core.GetIndexedElement("Billboard", bbControlRow.Billboard);
3842
- if (null != billboard)
3843
- {
3844
- billboard.AddChild(control);
3204
+ xBillboard.Add(xControl);
3205
}
3206
else
3207
{
@@ -3856,37 +3216,34 @@ namespace WixToolset.Core.WindowsInstaller
3216
/// <param name="table">The table to decompile.</param>
3217
private void DecompileBillboardTable(Table table)
3218
{
3859
- var billboardActions = new Hashtable();
3860
- var billboards = new SortedList();
3219
+ var billboards = new SortedList<string, Row>();
3220
3221
foreach (var row in table.Rows)
3863
- {
3864
- var billboard = new Wix.Billboard();
3865
-
3866
- billboard.Id = Convert.ToString(row[0]);
3867
-
3868
- billboard.Feature = Convert.ToString(row[1]);
3222
+ {
3223
+ var xBillboard = new XElement(Names.BillboardElement,
3224
+ new XAttribute("Id", row.FieldAsString(0)),
3225
+ new XAttribute("Feature", row.FieldAsString(1)));
3226
3870
- this.core.IndexElement(row, billboard);
3227
+ this.IndexElement(row, xBillboard);
3228
billboards.Add(String.Format(CultureInfo.InvariantCulture, "{0}|{1:0000000000}", row[0], row[3]), row);
3229
}
3230
3874
- foreach (Row row in billboards.Values)
3231
+ var billboardActions = new Dictionary<string, XElement>();
3232
+
3233
+ foreach (var row in billboards.Values)
3234
{
3876
- var billboard = (Wix.Billboard)this.core.GetIndexedElement(row);
3877
- var billboardAction = (Wix.BillboardAction)billboardActions[row[2]];
3235
+ var xBillboard = this.GetIndexedElement(row);
3236
3879
- if (null == billboardAction)
3237
+ if (!billboardActions.TryGetValue(row.FieldAsString(2), out var xBillboardAction))
3238
{
3881
- billboardAction = new Wix.BillboardAction();
3239
+ xBillboardAction = new XElement(Names.BillboardActionElement,
3240
+ new XAttribute("Id", row.FieldAsString(2)));
3241
3883
- billboardAction.Id = Convert.ToString(row[2]);
3884
-
3885
- this.core.UIElement.AddChild(billboardAction);
3886
- billboardActions.Add(row[2], billboardAction);
3242
+ this.UIElement.Add(xBillboardAction);
3243
+ billboardActions.Add(row.FieldAsString(2), xBillboardAction);
3244
}
3245
3889
- billboardAction.AddChild(billboard);
3246
+ xBillboardAction.Add(xBillboard);
3247
}
3248
}
3249
@@ -3898,13 +3255,11 @@ namespace WixToolset.Core.WindowsInstaller
3255
{
3256
foreach (var row in table.Rows)
3257
{
3901
- var binary = new Wix.Binary();
3902
-
3903
- binary.Id = Convert.ToString(row[0]);
3258
+ var xBinary = new XElement(Names.BinaryElement,
3259
+ new XAttribute("Id", row.FieldAsString(0)),
3260
+ new XAttribute("SourceFile", row.FieldAsString(1)));
3261
3905
- binary.SourceFile = Convert.ToString(row[1]);
3906
-
3907
- this.core.RootElement.AddChild(binary);
3262
+ this.RootElement.Add(xBinary);
3263
}
3264
}
3265
@@ -3916,15 +3271,13 @@ namespace WixToolset.Core.WindowsInstaller
3271
{
3272
foreach (var row in table.Rows)
3273
{
3919
- var file = (Wix.File)this.core.GetIndexedElement("File", Convert.ToString(row[0]));
3920
-
3921
- if (null != file)
3274
+ if (this.TryGetIndexedElement("File", out var xFile, row.FieldAsString(0)))
3275
{
3923
- file.BindPath = Convert.ToString(row[1]);
3276
+ xFile.SetAttributeValue("BindPath", row.FieldAsString(1));
3277
}
3278
else
3279
{
3927
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File_", Convert.ToString(row[0]), "File"));
3280
+ this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "File_", row.FieldAsString(0), "File"));
3281
}
3282
}
3283
}
@@ -3937,46 +3290,20 @@ namespace WixToolset.Core.WindowsInstaller
3290
{
3291
foreach (var row in table.Rows)
3292
{
3940
- var wixClass = new Wix.Class();
3941
-
3942
- wixClass.Advertise = Wix.YesNoType.yes;
3943
-
3944
- wixClass.Id = Convert.ToString(row[0]);
3945
-
3946
- switch (Convert.ToString(row[1]))
3947
- {
3948
- case "LocalServer":
3949
- wixClass.Context = Wix.Class.ContextType.LocalServer;
3950
- break;
3951
- case "LocalServer32":
3952
- wixClass.Context = Wix.Class.ContextType.LocalServer32;
3953
- break;
3954
- case "InprocServer":
3955
- wixClass.Context = Wix.Class.ContextType.InprocServer;
3956
- break;
3957
- case "InprocServer32":
3958
- wixClass.Context = Wix.Class.ContextType.InprocServer32;
3959
- break;
3960
- default:
3961
- this.Messaging.Write(WarningMessages.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[1].Column.Name, row[1]));
3962
- break;
3963
- }
3964
-
3965
- // ProgId children are handled in FinalizeProgIdTable
3966
-
3967
- if (null != row[4])
3968
- {
3969
- wixClass.Description = Convert.ToString(row[4]);
3970
- }
3971
-
3972
- if (null != row[5])
3973
- {
3974
- wixClass.AppId = Convert.ToString(row[5]);
3975
- }
3293
+ var xClass = new XElement(Names.ClassElement,
3294
+ new XAttribute("Id", row.FieldAsString(0)),
3295
+ new XAttribute("Advertise", "yes"),
3296
+ new XAttribute("Context", row.FieldAsString(1)),
3297
+ row.IsColumnNull(4) ? null : new XAttribute("Description", row.FieldAsString(4)),
3298
+ row.IsColumnNull(5) ? null : new XAttribute("AppId", row.FieldAsString(5)),
3299
+ row.IsColumnNull(7) ? null : new XAttribute("Icon", row.FieldAsString(7)),
3300
+ row.IsColumnNull(8) ? null : new XAttribute("IconIndex", row.FieldAsString(8)),
3301
+ row.IsColumnNull(9) ? null : new XAttribute("Handler", row.FieldAsString(9)),
3302
+ row.IsColumnNull(10) ? null : new XAttribute("Argument", row.FieldAsString(10)));
3303
3977
- if (null != row[6])
3304
+ if (!row.IsColumnNull(6))
3305
{
3979
- var fileTypeMaskStrings = (Convert.ToString(row[6])).Split(';');
3306
+ var fileTypeMaskStrings = row.FieldAsString(6).Split(';');
3307
3308
try
3309
{
@@ -3986,15 +3313,12 @@ namespace WixToolset.Core.WindowsInstaller
3313
3314
if (4 == fileTypeMaskParts.Length)
3315
{
3989
- var fileTypeMask = new Wix.FileTypeMask();
3316
+ var xFileTypeMask = new XElement(Names.FileTypeMaskElement,
3317
+ new XAttribute("Offset", Convert.ToInt32(fileTypeMaskParts[0], CultureInfo.InvariantCulture)),
3318
+ new XAttribute("Mask", fileTypeMaskParts[2]),
3319
+ new XAttribute("Value", fileTypeMaskParts[3]));
3320
3991
- fileTypeMask.Offset = Convert.ToInt32(fileTypeMaskParts[0], CultureInfo.InvariantCulture);
3992
-
3993
- fileTypeMask.Mask = fileTypeMaskParts[2];
3994
-
3995
- fileTypeMask.Value = fileTypeMaskParts[3];
3996
-
3997
- wixClass.AddChild(fileTypeMask);
3321
+ xClass.Add(xFileTypeMask);
3322
}
3323
else
3324
{
@@ -4012,31 +3336,11 @@ namespace WixToolset.Core.WindowsInstaller
3336
}
3337
}
3338
4015
- if (null != row[7])
4016
- {
4017
- wixClass.Icon = Convert.ToString(row[7]);
4018
- }
4019
-
4020
- if (null != row[8])
4021
- {
4022
- wixClass.IconIndex = Convert.ToInt32(row[8]);
4023
- }
4024
-
4025
- if (null != row[9])
4026
- {
4027
- wixClass.Handler = Convert.ToString(row[9]);
4028
- }
4029
-
4030
- if (null != row[10])
3339
+ if (!row.IsColumnNull(12))
3340
{
4032
- wixClass.Argument = Convert.ToString(row[10]);
4033
- }
4034
-
4035
- if (null != row[12])
4036
- {
4037
- if (1 == Convert.ToInt32(row[12]))
3341
+ if (1 == row.FieldAsInteger(12))
3342
{
4039
- wixClass.RelativePath = Wix.YesNoType.yes;
3343
+ xClass.SetAttributeValue("RelativePath", "yes");
3344
}
3345
else
3346
{
@@ -4044,17 +3348,8 @@ namespace WixToolset.Core.WindowsInstaller
3348
}
3349
}
3350
4047
- var component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[2]));
4048
- if (null != component)
4049
- {
4050
- component.AddChild(wixClass);
4051
- }
4052
- else
4053
- {
4054
- this.Messaging.Write(WarningMessages.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[2]), "Component"));
4055
- }
4056
-
4057
- this.core.IndexElement(row, wixClass);
3351
+ this.AddChildToParent("Component", xClass, row, 2);
3352
+ this.IndexElement(row, xClass);
3353
}
3354
}
3355
@@ -4064,36 +3359,27 @@ namespace WixToolset.Core.WindowsInstaller
3359
/// <param name="table">The table to decompile.</param>
3360
private void DecompileComboBoxTable(Table table)
3361
{
4067
- Wix.ComboBox comboBox = null;
4068
- var comboBoxRows = new SortedList();
4069
-
3362
// sort the combo boxes by their property and order
4071
- foreach (var row in table.Rows)
4072
- {
4073
- comboBoxRows.Add(String.Concat("{0}|{1:0000000000}", row[0], row[1]), row);
4074
- }
3363
+ var comboBoxRows = table.Rows.Select(row => row).OrderBy(row => String.Format("{0}|{1:0000000000}", row.FieldAsString(0), row.FieldAsInteger(1)));
3364
4076
- foreach (Row row in comboBoxRows.Values)
3365
+ XElement xComboBox = null;
3366
+ string property = null;
3367
+ foreach (var row in comboBoxRows)
3368
{
4078
- if (null == comboBox || Convert.ToString(row[0]) != comboBox.Property)
3369
+ if (null == xComboBox || row.FieldAsString(0) != property)
3370
{
4080
- comboBox = new Wix.ComboBox();
4081
-
4082
- comboBox.Property = Convert.ToString(row[0]);
4083
-
4084
- this.core.UIElement.AddChild(comboBox);
4085
- }
3371
+ property = row.FieldAsString(0);
3372
4087
- var listItem = new Wix.ListItem();
3373
+ xComboBox = new XElement(Names.ComboBoxElement,
3374
+ new XAttribute("Property", property));
3375
4089
- listItem.Value = Convert.ToString(row[2]);
4090
-
4091
- if (null != row[3])
4092
- {
4093
- listItem.Text = Convert.ToString(row[3]);
3376
+ this.UIElement.Add(xComboBox);
3377
}
3378
4096
- comboBox.AddChild(listItem);
3379
+ var xListItem = new XElement(Names.ListItemElement,
3380
+ new XAttribute("Value", row.FieldAsString(2)),
3381
+ row.IsColumnNull(3) ? null : new XAttribute("Text", row.FieldAsString(3)));
3382
+ xComboBox.Add(xListItem);
3383
}
3384
}
3385
@@ -4105,80 +3391,75 @@ namespace WixToolset.Core.WindowsInstaller
3391
{
3392
foreach (ControlRow controlRow in table.Rows)
3393
{
4108
- var control = new Wix.Control();
4109
-
4110
- control.Id = controlRow.Control;
4111
-
4112
- control.Type = controlRow.Type;
3394
+ var xControl = new XElement(Names.ControlElement,
3395
+ new XAttribute("Id", controlRow.Control),
3396
+ new XAttribute("Type", controlRow.Type),
3397
+ new XAttribute("X", controlRow.X),
3398
+ new XAttribute("Y", controlRow.Y),
3399
+ new XAttribute("Width", controlRow.Width),
3400
+ new XAttribute("Height", controlRow.Height),
3401
+ new XAttribute("Text", controlRow.Text));
3402
4114
- control.X = controlRow.X;
4115
-
4116
- control.Y = controlRow.Y;
4117
-
4118
- control.Width = controlRow.Width;
4119
-
4120
- control.Height = controlRow.Height;
4121
-
4122
- if (null != controlRow[7])
3403
+ if (!controlRow.IsColumnNull(7))
3404
{
3405
string[] specialAttributes;
3406
3407
// sets various common attributes like Disabled, Indirect, Integer, ...
4127
- SetControlAttributes(controlRow.Attributes, control);
3408
+ SetControlAttributes(controlRow.Attributes, xControl);
This file is too large to show in full.
src/WixToolset.Core.WindowsInstaller/Decompile/DecompilerCore.cs
deleted
-110
@@ -1,110 +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
4
-{
5
- using System;
6
- using System.Collections;
7
- using WixToolset.Data.WindowsInstaller;
8
- using WixToolset.Extensibility;
9
- using Wix = WixToolset.Data.Serialize;
10
-
11
- /// <summary>
12
- /// The base of the decompiler. Holds some variables used by the decompiler and extensions,
13
- /// as well as some utility methods.
14
- /// </summary>
15
- internal class DecompilerCore
16
- {
17
- private readonly Hashtable elements;
18
- private Wix.UI uiElement;
19
-
20
- /// <summary>
21
- /// Instantiate a new decompiler core.
22
- /// </summary>
23
- /// <param name="rootElement">The root element of the decompiled database.</param>
24
- /// <param name="messageHandler">The message handler.</param>
25
- internal DecompilerCore(Wix.IParentElement rootElement)
26
- {
27
- this.elements = new Hashtable();
28
- this.RootElement = rootElement;
29
- }
30
-
31
- /// <summary>
32
- /// Gets the root element of the decompiled output.
33
- /// </summary>
34
- /// <value>The root element of the decompiled output.</value>
35
- public Wix.IParentElement RootElement { get; }
36
-
37
- /// <summary>
38
- /// Gets the UI element.
39
- /// </summary>
40
- /// <value>The UI element.</value>
41
- public Wix.UI UIElement
42
- {
43
- get
44
- {
45
- if (null == this.uiElement)
46
- {
47
- this.uiElement = new Wix.UI();
48
- this.RootElement.AddChild(this.uiElement);
49
- }
50
-
51
- return this.uiElement;
52
- }
53
- }
54
-
55
- /// <summary>
56
- /// Verifies if a filename is a valid short filename.
57
- /// </summary>
58
- /// <param name="filename">Filename to verify.</param>
59
- /// <param name="allowWildcards">true if wildcards are allowed in the filename.</param>
60
- /// <returns>True if the filename is a valid short filename</returns>
61
- public virtual bool IsValidShortFilename(string filename, bool allowWildcards)
62
- {
63
- return false;
64
- }
65
-
66
- /// <summary>
67
- /// Convert an Int32 into a DateTime.
68
- /// </summary>
69
- /// <param name="value">The Int32 value.</param>
70
- /// <returns>The DateTime.</returns>
71
- public DateTime ConvertIntegerToDateTime(int value)
72
- {
73
- var date = value / 65536;
74
- var time = value % 65536;
75
-
76
- return new DateTime(1980 + (date / 512), (date % 512) / 32, date % 32, time / 2048, (time % 2048) / 32, (time % 32) * 2);
77
- }
78
-
79
- /// <summary>
80
- /// Gets the element corresponding to the row it came from.
81
- /// </summary>
82
- /// <param name="row">The row corresponding to the element.</param>
83
- /// <returns>The indexed element.</returns>
84
- public Wix.ISchemaElement GetIndexedElement(Row row)
85
- {
86
- return this.GetIndexedElement(row.TableDefinition.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter));
87
- }
88
-
89
- /// <summary>
90
- /// Gets the element corresponding to the primary key of the given table.
91
- /// </summary>
92
- /// <param name="table">The table corresponding to the element.</param>
93
- /// <param name="primaryKey">The primary key corresponding to the element.</param>
94
- /// <returns>The indexed element.</returns>
95
- public Wix.ISchemaElement GetIndexedElement(string table, params string[] primaryKey)
96
- {
97
- return (Wix.ISchemaElement)this.elements[String.Concat(table, ':', String.Join(DecompilerConstants.PrimaryKeyDelimiterString, primaryKey))];
98
- }
99
-
100
- /// <summary>
101
- /// Index an element by its corresponding row.
102
- /// </summary>
103
- /// <param name="row">The row corresponding to the element.</param>
104
- /// <param name="element">The element to index.</param>
105
- public void IndexElement(Row row, Wix.ISchemaElement element)
106
- {
107
- this.elements.Add(String.Concat(row.TableDefinition.Name, ':', row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter)), element);
108
- }
109
- }
110
-}
src/WixToolset.Core.WindowsInstaller/Decompile/Names.cs
new
+158
@@ -0,0 +1,158 @@
1
+namespace WixToolset.Core.WindowsInstaller.Decompile
2
+{
3
+ using System.Xml.Linq;
4
+
5
+ internal static class Names
6
+ {
7
+ public static readonly XNamespace WxsNamespace = "http://wixtoolset.org/schemas/v4/wxs";
8
+
9
+ public static readonly XName WixElement = WxsNamespace + "Wix";
10
+
11
+ public static readonly XName ProductElement = WxsNamespace + "Product";
12
+ public static readonly XName ModuleElement = WxsNamespace + "Module";
13
+ public static readonly XName PatchCreationElement = WxsNamespace + "PatchCreation";
14
+
15
+ public static readonly XName CustomElement = WxsNamespace + "Custom";
16
+
17
+ public static readonly XName AdminExecuteSequenceElement = WxsNamespace + "AdminExecuteSequence";
18
+ public static readonly XName AdminUISequenceElement = WxsNamespace + "AdminUISequence";
19
+ public static readonly XName AdvertiseExecuteSequenceElement = WxsNamespace + "AdvertiseExecuteSequence";
20
+ public static readonly XName InstallExecuteSequenceElement = WxsNamespace + "InstallExecuteSequence";
21
+ public static readonly XName InstallUISequenceElement = WxsNamespace + "InstallUISequence";
22
+
23
+ public static readonly XName AppSearchElement = WxsNamespace + "AppSearch";
24
+
25
+ public static readonly XName PropertyElement = WxsNamespace + "Property";
26
+
27
+ public static readonly XName ProtectRangeElement = WxsNamespace + "ProtectRange";
28
+ public static readonly XName ProtectFileElement = WxsNamespace + "ProtectFile";
29
+
30
+ public static readonly XName FileElement = WxsNamespace + "File";
31
+
32
+ public static readonly XName EnsureTableElement = WxsNamespace + "EnsureTable";
33
+ public static readonly XName PackageElement = WxsNamespace + "Package";
34
+ public static readonly XName PatchInformationElement = WxsNamespace + "PatchInformation";
35
+
36
+ public static readonly XName ProgressTextElement = WxsNamespace + "ProgressText";
37
+ public static readonly XName UIElement = WxsNamespace + "UI";
38
+
39
+ public static readonly XName AppIdElement = WxsNamespace + "AppId";
40
+
41
+ public static readonly XName ControlElement = WxsNamespace + "Control";
42
+
43
+ public static readonly XName BillboardElement = WxsNamespace + "Billboard";
44
+ public static readonly XName BillboardActionElement = WxsNamespace + "BillboardAction";
45
+
46
+ public static readonly XName BinaryElement = WxsNamespace + "Binary";
47
+
48
+ public static readonly XName ClassElement = WxsNamespace + "Class";
49
+
50
+ public static readonly XName FileTypeMaskElement = WxsNamespace + "FileTypeMask";
51
+
52
+ public static readonly XName ComboBoxElement = WxsNamespace + "ComboBox";
53
+
54
+ public static readonly XName ListItemElement = WxsNamespace + "ListItem";
55
+
56
+ public static readonly XName ConditionElement = WxsNamespace + "Condition";
57
+ public static readonly XName PublishElement = WxsNamespace + "Publish";
58
+ public static readonly XName CustomTableElement = WxsNamespace + "CustomTable";
59
+ public static readonly XName ColumnElement = WxsNamespace + "Column";
60
+ public static readonly XName RowElement = WxsNamespace + "Row";
61
+ public static readonly XName DataElement = WxsNamespace + "Data";
62
+ public static readonly XName CreateFolderElement = WxsNamespace + "CreateFolder";
63
+
64
+ public static readonly XName CustomActionElement = WxsNamespace + "CustomAction";
65
+
66
+ public static readonly XName ComponentSearchElement = WxsNamespace + "ComponentSearch";
67
+ public static readonly XName ComponentElement = WxsNamespace + "Component";
68
+
69
+ public static readonly XName LevelElement = WxsNamespace + "Level";
70
+ public static readonly XName DialogElement = WxsNamespace + "Dialog";
71
+ public static readonly XName DirectoryElement = WxsNamespace + "Directory";
72
+ public static readonly XName DirectorySearchElement = WxsNamespace + "DirectorySearch";
73
+ public static readonly XName CopyFileElement = WxsNamespace + "CopyFile";
74
+ public static readonly XName EnvironmentElement = WxsNamespace + "Environment";
75
+ public static readonly XName ErrorElement = WxsNamespace + "Error";
76
+ public static readonly XName SubscribeElement = WxsNamespace + "Subscribe";
77
+ public static readonly XName ExtensionElement = WxsNamespace + "Extension";
78
+ public static readonly XName ExternalFileElement = WxsNamespace + "ExternalFile";
79
+ public static readonly XName SymbolPathElement = WxsNamespace + "SymbolPath";
80
+ public static readonly XName IgnoreRangeElement = WxsNamespace + "IgnoreRange";
81
+
82
+ public static readonly XName FeatureElement = WxsNamespace + "Feature";
83
+ public static readonly XName ComponentRefElement = WxsNamespace + "ComponentRef";
84
+ public static readonly XName SFPFileElement = WxsNamespace + "SFPFile";
85
+ public static readonly XName IconElement = WxsNamespace + "Icon";
86
+ public static readonly XName FamilyElement = WxsNamespace + "Family";
87
+ public static readonly XName IniFileElement = WxsNamespace + "IniFile";
88
+ public static readonly XName IniFileSearchElement = WxsNamespace + "IniFileSearch";
89
+ public static readonly XName IsolateComponentElement = WxsNamespace + "IsolateComponent";
90
+ public static readonly XName LaunchElement = WxsNamespace + "Launch";
91
+ public static readonly XName ListBoxElement = WxsNamespace + "ListBox";
92
+ public static readonly XName ListViewElement = WxsNamespace + "ListView";
93
+ public static readonly XName PermissionElement = WxsNamespace + "Permission";
94
+ public static readonly XName MediaElement = WxsNamespace + "Media";
95
+ public static readonly XName MIMEElement = WxsNamespace + "MIME";
96
+ public static readonly XName ConfigurationElement = WxsNamespace + "Configuration";
97
+ public static readonly XName DependencyElement = WxsNamespace + "Dependency";
98
+ public static readonly XName ExclusionElement = WxsNamespace + "Exclusion";
99
+ public static readonly XName IgnoreTableElement = WxsNamespace + "IgnoreTable";
100
+ public static readonly XName SubstitutionElement = WxsNamespace + "Substitution";
101
+ public static readonly XName DigitalCertificateElement = WxsNamespace + "DigitalCertificate";
102
+ public static readonly XName DigitalSignatureElement = WxsNamespace + "DigitalSignature";
103
+ public static readonly XName EmbeddedChainerElement = WxsNamespace + "EmbeddedChainer";
104
+ public static readonly XName EmbeddedUIElement = WxsNamespace + "EmbeddedUI";
105
+ public static readonly XName EmbeddedUIResourceElement = WxsNamespace + "EmbeddedUIResource";
106
+ public static readonly XName PermissionExElement = WxsNamespace + "PermissionEx";
107
+ public static readonly XName PackageCertificatesElement = WxsNamespace + "PackageCertificates";
108
+ public static readonly XName PatchCertificatesElement = WxsNamespace + "PatchCertificates";
109
+ public static readonly XName ShortcutPropertyElement = WxsNamespace + "ShortcutProperty";
110
+ public static readonly XName ODBCDataSourceElement = WxsNamespace + "ODBCDataSource";
111
+ public static readonly XName ODBCDriverElement = WxsNamespace + "ODBCDriver";
112
+ public static readonly XName ODBCTranslatorElement = WxsNamespace + "ODBCTranslator";
113
+ public static readonly XName PatchMetadataElement = WxsNamespace + "PatchMetadata";
114
+ public static readonly XName OptimizeCustomActionsElement = WxsNamespace + "OptimizeCustomActions";
115
+ public static readonly XName CustomPropertyElement = WxsNamespace + "CustomProperty";
116
+ public static readonly XName PatchSequenceElement = WxsNamespace + "PatchSequence";
117
+ public static readonly XName ProgIdElement = WxsNamespace + "ProgId";
118
+ public static readonly XName ReplacePatchElement = WxsNamespace + "ReplacePatch";
119
+ public static readonly XName TargetProductCodeElement = WxsNamespace + "TargetProductCode";
120
+ public static readonly XName PatchPropertyElement = WxsNamespace + "PatchProperty";
121
+ public static readonly XName CategoryElement = WxsNamespace + "Category";
122
+ public static readonly XName RadioButtonElement = WxsNamespace + "RadioButton";
123
+ public static readonly XName RadioButtonGroupElement = WxsNamespace + "RadioButtonGroup";
124
+ public static readonly XName RegistryKeyElement = WxsNamespace + "RegistryKey";
125
+ public static readonly XName RegistryValueElement = WxsNamespace + "RegistryValue";
126
+ public static readonly XName MultiStringElement = WxsNamespace + "MultiString";
127
+ public static readonly XName RegistrySearchElement = WxsNamespace + "RegistrySearch";
128
+ public static readonly XName RemoveFolderElement = WxsNamespace + "RemoveFolder";
129
+ public static readonly XName RemoveFileElement = WxsNamespace + "RemoveFile";
130
+ public static readonly XName RemoveRegistryKeyElement = WxsNamespace + "RemoveRegistryKey";
131
+ public static readonly XName RemoveRegistryValueElement = WxsNamespace + "RemoveRegistryValue";
132
+ public static readonly XName ReserveCostElement = WxsNamespace + "ReserveCost";
133
+ public static readonly XName ServiceControlElement = WxsNamespace + "ServiceControl";
134
+ public static readonly XName ServiceArgumentElement = WxsNamespace + "ServiceArgument";
135
+ public static readonly XName ServiceInstallElement = WxsNamespace + "ServiceInstall";
136
+ public static readonly XName ServiceDependencyElement = WxsNamespace + "ServiceDependency";
137
+ public static readonly XName SFPCatalogElement = WxsNamespace + "SFPCatalog";
138
+ public static readonly XName ShortcutElement = WxsNamespace + "Shortcut";
139
+ public static readonly XName FileSearchElement = WxsNamespace + "FileSearch";
140
+ public static readonly XName TargetFileElement = WxsNamespace + "TargetFile";
141
+ public static readonly XName TargetImageElement = WxsNamespace + "TargetImage";
142
+ public static readonly XName TextStyleElement = WxsNamespace + "TextStyle";
143
+ public static readonly XName TypeLibElement = WxsNamespace + "TypeLib";
144
+ public static readonly XName UpgradeElement = WxsNamespace + "Upgrade";
145
+ public static readonly XName UpgradeVersionElement = WxsNamespace + "UpgradeVersion";
146
+ public static readonly XName UpgradeFileElement = WxsNamespace + "UpgradeFile";
147
+ public static readonly XName UpgradeImageElement = WxsNamespace + "UpgradeImage";
148
+ public static readonly XName UITextElement = WxsNamespace + "UIText";
149
+ public static readonly XName VerbElement = WxsNamespace + "Verb";
150
+ public static readonly XName ComplianceCheckElement = WxsNamespace + "ComplianceCheck";
151
+ public static readonly XName FileSearchRefElement = WxsNamespace + "FileSearchRef";
152
+ public static readonly XName ComplianceDriveElement = WxsNamespace + "ComplianceDrive";
153
+ public static readonly XName DirectorySearchRefElement = WxsNamespace + "DirectorySearchRef";
154
+ public static readonly XName RegistrySearchRefElement = WxsNamespace + "RegistrySearchRef";
155
+ public static readonly XName MajorUpgradeElement = WxsNamespace + "MajorUpgrade";
156
+ //public static readonly XName Element = WxsNamespace + "";
157
+ }
158
+}
src/WixToolset.Core.WindowsInstaller/Melter.cs
-1
@@ -12,7 +12,6 @@ namespace WixToolset
12
using System.Text;
13
using System.Text.RegularExpressions;
14
using WixToolset.Data;
15
- using Wix = WixToolset.Data.Serialize;
15
16
/// <summary>
17
/// Converts a wixout representation of an MSM database into a ComponentGroup the form of WiX source.
src/WixToolset.Core/CommandLine/DecompileCommand.cs
+1
-1
@@ -33,7 +33,7 @@ namespace WixToolset.Core.CommandLine
33
34
public Task<int> ExecuteAsync(CancellationToken _)
35
{
36
- if (this.commandLine.ShowHelp)
36
+ if (this.commandLine.ShowHelp || String.IsNullOrEmpty(this.commandLine.DecompileFilePath))
37
{
38
Console.WriteLine("TODO: Show decompile command help");
39
return Task.FromResult(-1);
src/WixToolset.Core/Compiler.cs
+3
-3
@@ -3331,7 +3331,7 @@ namespace WixToolset.Core
3331
break;
3332
}
3333
break;
3334
- case "ScriptFile":
3334
+ case "ScriptSourceFile":
3335
scriptFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
3336
break;
3337
case "SuppressModularization":
@@ -3387,7 +3387,7 @@ namespace WixToolset.Core
3387
{
3388
if (String.IsNullOrEmpty(scriptFile))
3389
{
3390
- this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ScriptFile", "Script"));
3390
+ this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ScriptSourceFile", "Script"));
3391
}
3392
}
3393
else if (CustomActionTargetType.VBScript == targetType) // non-inline vbscript
@@ -3426,7 +3426,7 @@ namespace WixToolset.Core
3426
3427
if (!inlineScript && !String.IsNullOrEmpty(scriptFile))
3428
{
3429
- this.Core.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, node.Name.LocalName, "ScriptFile", "Script"));
3429
+ this.Core.Write(ErrorMessages.IllegalAttributeWithoutOtherAttributes(sourceLineNumbers, node.Name.LocalName, "ScriptSourceFile", "Script"));
3430
}
3431
3432
if (win64 && CustomActionTargetType.VBScript != targetType && CustomActionTargetType.JScript != targetType)
src/test/WixToolsetTest.CoreIntegration/CustomTableFixture.cs
+2
-13
@@ -3,6 +3,7 @@
3
namespace WixToolsetTest.CoreIntegration
4
{
5
using System.IO;
6
+ using System.Xml.Linq;
7
using WixBuildTools.TestSupport;
8
using WixToolset.Core.TestPackage;
9
using Xunit;
@@ -224,20 +225,8 @@ namespace WixToolsetTest.CoreIntegration
225
226
result.AssertSuccess();
227
227
- CompareLineByLine(expectedFile, decompiledWxsPath);
228
+ WixAssert.CompareXml(expectedFile, decompiledWxsPath);
229
}
230
}
230
-
231
- private static void CompareLineByLine(string expectedFile, string actualFile)
232
- {
233
- var expectedLines = File.ReadAllLines(expectedFile);
234
- var actualLines = File.ReadAllLines(actualFile);
235
- for (var i = 0; i < expectedLines.Length; ++i)
236
- {
237
- Assert.True(actualLines.Length > i, $"{i}: Expected file longer than actual file");
238
- Assert.Equal($"{i}: {expectedLines[i]}", $"{i}: {actualLines[i]}");
239
- }
240
- Assert.True(expectedLines.Length == actualLines.Length, "Actual file longer than expected file");
241
- }
231
}
232
}
src/test/WixToolsetTest.CoreIntegration/DecompileFixture.cs
+16
-124
@@ -6,14 +6,14 @@ namespace WixToolsetTest.CoreIntegration
6
using System.Xml.Linq;
7
using WixBuildTools.TestSupport;
8
using WixToolset.Core.TestPackage;
9
+ using WixToolset.Extensibility.Services;
10
using Xunit;
11
12
public class DecompileFixture
13
{
13
- [Fact]
14
- public void CanDecompileSingleFileCompressed()
14
+ private static void DecompileAndCompare(string sourceFolder, string msiName, string expectedWxsName)
15
{
16
- var folder = TestData.Get(@"TestData\DecompileSingleFileCompressed");
16
+ var folder = TestData.Get(sourceFolder);
17
18
using (var fs = new DisposableFileSystem())
19
{
@@ -23,75 +23,33 @@ namespace WixToolsetTest.CoreIntegration
23
var result = WixRunner.Execute(new[]
24
{
25
"decompile",
26
- Path.Combine(folder, "example.msi"),
26
+ Path.Combine(folder, msiName),
27
"-intermediateFolder", intermediateFolder,
28
"-o", outputPath
29
});
30
31
result.AssertSuccess();
32
33
- var actual = File.ReadAllText(outputPath);
34
- var actualFormatted = XDocument.Parse(actual, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
35
- var expected = XDocument.Load(Path.Combine(folder, "Expected.wxs"), LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
36
-
37
- Assert.Equal(expected, actualFormatted);
33
+ WixAssert.CompareXml(Path.Combine(folder, expectedWxsName), outputPath);
34
}
35
}
36
37
[Fact]
42
- public void CanDecompile64BitSingleFileCompressed()
38
+ public void CanDecompileSingleFileCompressed()
39
{
44
- var folder = TestData.Get(@"TestData\DecompileSingleFileCompressed64");
45
-
46
- using (var fs = new DisposableFileSystem())
47
- {
48
- var intermediateFolder = fs.GetFolder();
49
- var outputPath = Path.Combine(intermediateFolder, @"Actual.wxs");
50
-
51
- var result = WixRunner.Execute(new[]
52
- {
53
- "decompile",
54
- Path.Combine(folder, "example.msi"),
55
- "-intermediateFolder", intermediateFolder,
56
- "-o", outputPath
57
- });
58
-
59
- result.AssertSuccess();
60
-
61
- var actual = File.ReadAllText(outputPath);
62
- var actualFormatted = XDocument.Parse(actual, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
63
- var expected = XDocument.Load(Path.Combine(folder, "Expected.wxs"), LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
40
+ DecompileAndCompare(@"TestData\DecompileSingleFileCompressed", "example.msi", "Expected.wxs");
41
+ }
42
65
- Assert.Equal(expected, actualFormatted);
66
- }
43
+ [Fact]
44
+ public void CanDecompile64BitSingleFileCompressed()
45
+ {
46
+ DecompileAndCompare(@"TestData\DecompileSingleFileCompressed64", "example.msi", "Expected.wxs");
47
}
48
49
[Fact]
50
public void CanDecompileNestedDirSearchUnderRegSearch()
51
{
72
- var folder = TestData.Get(@"TestData\AppSearch");
73
-
74
- using (var fs = new DisposableFileSystem())
75
- {
76
- var intermediateFolder = fs.GetFolder();
77
- var outputPath = Path.Combine(intermediateFolder, @"Actual.wxs");
78
-
79
- var result = WixRunner.Execute(new[]
80
- {
81
- "decompile",
82
- Path.Combine(folder, "NestedDirSearchUnderRegSearch.msi"),
83
- "-intermediateFolder", intermediateFolder,
84
- "-o", outputPath
85
- });
86
-
87
- result.AssertSuccess();
88
-
89
- var actual = File.ReadAllText(outputPath);
90
- var actualFormatted = XDocument.Parse(actual, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
91
- var expected = XDocument.Load(Path.Combine(folder, "DecompiledNestedDirSearchUnderRegSearch.wxs"), LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
92
-
93
- Assert.Equal(expected, actualFormatted);
94
- }
52
+ DecompileAndCompare(@"TestData\AppSearch", "NestedDirSearchUnderRegSearch.msi", "DecompiledNestedDirSearchUnderRegSearch.wxs");
53
}
54
55
[Fact]
@@ -100,85 +58,19 @@ namespace WixToolsetTest.CoreIntegration
58
// The input MSI was not created using standard methods, it is an example of a real world database that needs to be decompiled.
59
// The Class/@Feature_ column has length of 32, the File/@Attributes has length of 2,
60
// and numerous foreign key relationships are missing.
103
- var folder = TestData.Get(@"TestData\Class");
104
-
105
- using (var fs = new DisposableFileSystem())
106
- {
107
- var intermediateFolder = fs.GetFolder();
108
- var outputPath = Path.Combine(intermediateFolder, @"Actual.wxs");
109
-
110
- var result = WixRunner.Execute(new[]
111
- {
112
- "decompile",
113
- Path.Combine(folder, "OldClassTableDef.msi"),
114
- "-intermediateFolder", intermediateFolder,
115
- "-o", outputPath
116
- });
117
-
118
- result.AssertSuccess();
119
-
120
- var actual = File.ReadAllText(outputPath);
121
- var actualFormatted = XDocument.Parse(actual, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
122
- var expected = XDocument.Load(Path.Combine(folder, "DecompiledOldClassTableDef.wxs"), LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
123
-
124
- Assert.Equal(expected, actualFormatted);
125
- }
61
+ DecompileAndCompare(@"TestData\Class", "OldClassTableDef.msi", "DecompiledOldClassTableDef.wxs");
62
}
63
64
[Fact]
65
public void CanDecompileSequenceTables()
66
{
131
- var folder = TestData.Get(@"TestData\SequenceTables");
132
-
133
- using (var fs = new DisposableFileSystem())
134
- {
135
- var intermediateFolder = fs.GetFolder();
136
- var outputPath = Path.Combine(intermediateFolder, @"Actual.wxs");
137
-
138
- var result = WixRunner.Execute(new[]
139
- {
140
- "decompile",
141
- Path.Combine(folder, "SequenceTables.msi"),
142
- "-intermediateFolder", intermediateFolder,
143
- "-o", outputPath
144
- });
145
-
146
- result.AssertSuccess();
147
-
148
- var actual = File.ReadAllText(outputPath);
149
- var actualFormatted = XDocument.Parse(actual, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
150
- var expected = XDocument.Load(Path.Combine(folder, "DecompiledSequenceTables.wxs"), LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
151
-
152
- Assert.Equal(expected, actualFormatted);
153
- }
67
+ DecompileAndCompare(@"TestData\SequenceTables", "SequenceTables.msi", "DecompiledSequenceTables.wxs");
68
}
69
70
[Fact]
71
public void CanDecompileShortcuts()
72
{
159
- var folder = TestData.Get(@"TestData\Shortcut");
160
-
161
- using (var fs = new DisposableFileSystem())
162
- {
163
- var intermediateFolder = fs.GetFolder();
164
- var outputPath = Path.Combine(intermediateFolder, @"Actual.wxs");
165
-
166
- var result = WixRunner.Execute(new[]
167
- {
168
- "decompile",
169
- Path.Combine(folder, "shortcuts.msi"),
170
- "-intermediateFolder", intermediateFolder,
171
- "-o", outputPath
172
- });
173
-
174
- result.AssertSuccess();
175
-
176
- var actual = File.ReadAllText(outputPath);
177
- var actualFormatted = XDocument.Parse(actual, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
178
- var expected = XDocument.Load(Path.Combine(folder, "DecompiledShortcuts.wxs"), LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo).ToString();
179
-
180
- Assert.Equal(expected, actualFormatted);
181
- }
73
+ DecompileAndCompare(@"TestData\Shortcut", "shortcuts.msi", "DecompiledShortcuts.wxs");
74
}
75
}
76
}
src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable-Expected.wxs
+4
-4
@@ -6,12 +6,12 @@
6
<Column Id="Column1" PrimaryKey="yes" Type="string" Width="0" Category="text" Description="The first custom column." />
7
<Column Id="Component_" Type="string" Width="72" KeyTable="Component" KeyColumn="1" Description="The custom table's Component reference" />
8
<Row>
9
- <Data Column="Column1">Row1</Data>
10
- <Data Column="Component_">test.txt</Data>
9
+ <Data Column="Column1" Value="Row1" />
10
+ <Data Column="Component_" Value="test.txt" />
11
</Row>
12
<Row>
13
- <Data Column="Column1">Row2</Data>
14
- <Data Column="Component_">test.txt</Data>
13
+ <Data Column="Column1" Value="Row2" />
14
+ <Data Column="Component_" Value="test.txt" />
15
</Row>
16
</CustomTable>
17
<Directory Id="TARGETDIR" Name="SourceDir">