aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2019-10-23 12:53:27 -0700
committerRob Mensching <rob@firegiant.com>2019-10-23 12:57:55 -0700
commit752301ba571020717862d2232e3fad585de6a39a (patch)
treea97ceeb6b762af2dd18d0d561dadeaceda3bf387
parent11355d03334e300886512411d4649536a5ee65e3 (diff)
downloadwix-752301ba571020717862d2232e3fad585de6a39a.tar.gz
wix-752301ba571020717862d2232e3fad585de6a39a.tar.bz2
wix-752301ba571020717862d2232e3fad585de6a39a.zip
Fix custom tables, small fixes in linker and update latest Data
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs34
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs119
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs213
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs2
-rw-r--r--src/WixToolset.Core/Common.cs2
-rw-r--r--src/WixToolset.Core/Compiler.cs6
-rw-r--r--src/WixToolset.Core/Librarian.cs37
-rw-r--r--src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs16
-rw-r--r--src/WixToolset.Core/Link/ResolveReferencesCommand.cs11
-rw-r--r--src/WixToolset.Core/Linker.cs459
-rw-r--r--src/test/Example.Extension/Data/example.wirbin398 -> 588 bytes
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs2
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/WixiplFixture.cs2
13 files changed, 427 insertions, 476 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index 53451752..411f64bf 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -32,8 +32,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
32 32
33 this.PathResolver = this.ServiceProvider.GetService<IPathResolver>(); 33 this.PathResolver = this.ServiceProvider.GetService<IPathResolver>();
34 34
35 this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
36
37 this.CabbingThreadCount = context.CabbingThreadCount; 35 this.CabbingThreadCount = context.CabbingThreadCount;
38 this.CabCachePath = context.CabCachePath; 36 this.CabCachePath = context.CabCachePath;
39 this.Codepage = context.Codepage; 37 this.Codepage = context.Codepage;
@@ -86,8 +84,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
86 84
87 private bool SuppressLayout { get; } 85 private bool SuppressLayout { get; }
88 86
89 private TableDefinitionCollection TableDefinitions { get; }
90
91 private string IntermediateFolder { get; } 87 private string IntermediateFolder { get; }
92 88
93 private Validator Validator { get; } 89 private Validator Validator { get; }
@@ -111,6 +107,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
111 // If there are any fields to resolve later, create the cache to populate during bind. 107 // If there are any fields to resolve later, create the cache to populate during bind.
112 var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null; 108 var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null;
113 109
110 TableDefinitionCollection tableDefinitions;
111 {
112 var command = new LoadTableDefinitionsCommand(section);
113 command.Execute();
114
115 tableDefinitions = command.TableDefinitions;
116 }
117
114 // Process the summary information table before the other tables. 118 // Process the summary information table before the other tables.
115 bool compressed; 119 bool compressed;
116 bool longNames; 120 bool longNames;
@@ -231,7 +235,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
231 command.FileFacades = fileFacades; 235 command.FileFacades = fileFacades;
232 command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); 236 command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule);
233 command.OverwriteHash = true; 237 command.OverwriteHash = true;
234 command.TableDefinitions = this.TableDefinitions; 238 command.TableDefinitions = tableDefinitions;
235 command.VariableCache = variableCache; 239 command.VariableCache = variableCache;
236 command.Execute(); 240 command.Execute();
237 } 241 }
@@ -308,7 +312,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
308 // Time to create the output object. Try to put as much above here as possible, updating the IR is better. 312 // Time to create the output object. Try to put as much above here as possible, updating the IR is better.
309 Output output; 313 Output output;
310 { 314 {
311 var command = new CreateOutputFromIRCommand(section, this.TableDefinitions, this.BackendExtensions); 315 var command = new CreateOutputFromIRCommand(this.Messaging, section, tableDefinitions, this.BackendExtensions);
312 command.Execute(); 316 command.Execute();
313 317
314 output = command.Output; 318 output = command.Output;
@@ -402,7 +406,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
402 command.Compressed = compressed; 406 command.Compressed = compressed;
403 command.FileRowsByCabinet = filesByCabinetMedia; 407 command.FileRowsByCabinet = filesByCabinetMedia;
404 command.ResolveMedia = this.ResolveMedia; 408 command.ResolveMedia = this.ResolveMedia;
405 command.TableDefinitions = this.TableDefinitions; 409 command.TableDefinitions = tableDefinitions;
406 command.TempFilesLocation = this.IntermediateFolder; 410 command.TempFilesLocation = this.IntermediateFolder;
407 command.Execute(); 411 command.Execute();
408 412
@@ -429,11 +433,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
429 // Generate database file. 433 // Generate database file.
430 this.Messaging.Write(VerboseMessages.GeneratingDatabase()); 434 this.Messaging.Write(VerboseMessages.GeneratingDatabase());
431 435
432 var trackMsi = this.BackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final); 436 {
433 trackedFiles.Add(trackMsi); 437 var trackMsi = this.BackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final);
438 trackedFiles.Add(trackMsi);
434 439
435 var temporaryFiles = this.GenerateDatabase(output, trackMsi.Path, false, false); 440 var temporaryFiles = this.GenerateDatabase(output, tableDefinitions, trackMsi.Path, false, false);
436 trackedFiles.AddRange(temporaryFiles); 441 trackedFiles.AddRange(temporaryFiles);
442 }
437 443
438 // Stop processing if an error previously occurred. 444 // Stop processing if an error previously occurred.
439 if (this.Messaging.EncounteredError) 445 if (this.Messaging.EncounteredError)
@@ -456,7 +462,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
456 462
457 if (null == sequenceTable) 463 if (null == sequenceTable)
458 { 464 {
459 sequenceTable = output.EnsureTable(this.TableDefinitions[sequenceTableName]); 465 sequenceTable = output.EnsureTable(tableDefinitions[sequenceTableName]);
460 } 466 }
461 467
462 if (0 == sequenceTable.Rows.Count) 468 if (0 == sequenceTable.Rows.Count)
@@ -911,7 +917,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
911 /// <param name="databaseFile">The database file to create.</param> 917 /// <param name="databaseFile">The database file to create.</param>
912 /// <param name="keepAddedColumns">Whether to keep columns added in a transform.</param> 918 /// <param name="keepAddedColumns">Whether to keep columns added in a transform.</param>
913 /// <param name="useSubdirectory">Whether to use a subdirectory based on the <paramref name="databaseFile"/> file name for intermediate files.</param> 919 /// <param name="useSubdirectory">Whether to use a subdirectory based on the <paramref name="databaseFile"/> file name for intermediate files.</param>
914 private IEnumerable<ITrackedFile> GenerateDatabase(Output output, string databaseFile, bool keepAddedColumns, bool useSubdirectory) 920 private IEnumerable<ITrackedFile> GenerateDatabase(Output output, TableDefinitionCollection tableDefinitions, string databaseFile, bool keepAddedColumns, bool useSubdirectory)
915 { 921 {
916 var command = new GenerateDatabaseCommand(); 922 var command = new GenerateDatabaseCommand();
917 command.BackendHelper = this.BackendHelper; 923 command.BackendHelper = this.BackendHelper;
@@ -921,7 +927,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
921 command.KeepAddedColumns = keepAddedColumns; 927 command.KeepAddedColumns = keepAddedColumns;
922 command.UseSubDirectory = useSubdirectory; 928 command.UseSubDirectory = useSubdirectory;
923 command.SuppressAddingValidationRows = this.SuppressAddingValidationRows; 929 command.SuppressAddingValidationRows = this.SuppressAddingValidationRows;
924 command.TableDefinitions = this.TableDefinitions; 930 command.TableDefinitions = tableDefinitions;
925 command.IntermediateFolder = this.IntermediateFolder; 931 command.IntermediateFolder = this.IntermediateFolder;
926 command.Codepage = this.Codepage; 932 command.Codepage = this.Codepage;
927 command.Execute(); 933 command.Execute();
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
index ebb494c0..17cac83a 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
@@ -11,14 +11,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind
11 using WixToolset.Data.WindowsInstaller; 11 using WixToolset.Data.WindowsInstaller;
12 using WixToolset.Data.WindowsInstaller.Rows; 12 using WixToolset.Data.WindowsInstaller.Rows;
13 using WixToolset.Extensibility; 13 using WixToolset.Extensibility;
14 using WixToolset.Extensibility.Services;
14 15
15 internal class CreateOutputFromIRCommand 16 internal class CreateOutputFromIRCommand
16 { 17 {
17 private const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB 18 private const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
18 private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB) 19 private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
19 20
20 public CreateOutputFromIRCommand(IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions) 21 private static readonly char[] ColonCharacter = new[] { ':' };
22
23 public CreateOutputFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions)
21 { 24 {
25 this.Messaging = messaging;
22 this.Section = section; 26 this.Section = section;
23 this.TableDefinitions = tableDefinitions; 27 this.TableDefinitions = tableDefinitions;
24 this.BackendExtensions = backendExtensions; 28 this.BackendExtensions = backendExtensions;
@@ -26,6 +30,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
26 30
27 private IEnumerable<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; } 31 private IEnumerable<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; }
28 32
33 private IMessaging Messaging { get; }
34
29 private TableDefinitionCollection TableDefinitions { get; } 35 private TableDefinitionCollection TableDefinitions { get; }
30 36
31 private IntermediateSection Section { get; } 37 private IntermediateSection Section { get; }
@@ -49,6 +55,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
49 { 55 {
50 switch (tuple.Definition.Type) 56 switch (tuple.Definition.Type)
51 { 57 {
58 case TupleDefinitionType.AppSearch:
59 this.AddTupleDefaultly(tuple, output);
60 output.EnsureTable(this.TableDefinitions["Signature"]);
61 break;
62
52 case TupleDefinitionType.Binary: 63 case TupleDefinitionType.Binary:
53 this.AddTupleDefaultly(tuple, output, idIsPrimaryKey: true); 64 this.AddTupleDefaultly(tuple, output, idIsPrimaryKey: true);
54 break; 65 break;
@@ -133,6 +144,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
133 this.AddMoveFileTuple((MoveFileTuple)tuple, output); 144 this.AddMoveFileTuple((MoveFileTuple)tuple, output);
134 break; 145 break;
135 146
147 case TupleDefinitionType.ProgId:
148 this.AddTupleDefaultly(tuple, output);
149 output.EnsureTable(this.TableDefinitions["Extension"]);
150 break;
151
136 case TupleDefinitionType.Property: 152 case TupleDefinitionType.Property:
137 this.AddPropertyTuple((PropertyTuple)tuple, output); 153 this.AddPropertyTuple((PropertyTuple)tuple, output);
138 break; 154 break;
@@ -197,6 +213,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
197 this.AddTupleFromExtension(tuple, output); 213 this.AddTupleFromExtension(tuple, output);
198 break; 214 break;
199 215
216 case TupleDefinitionType.WixCustomRow:
217 this.AddWixCustomRowTuple((WixCustomRowTuple)tuple, output);
218 break;
219
220 case TupleDefinitionType.WixEnsureTable:
221 this.AddWixEnsureTableTuple((WixEnsureTableTuple)tuple, output);
222 break;
223
200 // ignored. 224 // ignored.
201 case TupleDefinitionType.WixFile: 225 case TupleDefinitionType.WixFile:
202 case TupleDefinitionType.WixComponentGroup: 226 case TupleDefinitionType.WixComponentGroup:
@@ -204,6 +228,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
204 case TupleDefinitionType.WixFeatureGroup: 228 case TupleDefinitionType.WixFeatureGroup:
205 break; 229 break;
206 230
231 // Already processed.
232 case TupleDefinitionType.WixCustomTable:
233 break;
234
207 default: 235 default:
208 this.AddTupleDefaultly(tuple, output); 236 this.AddTupleDefaultly(tuple, output);
209 break; 237 break;
@@ -382,6 +410,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
382 row[7] = tuple.FirstControlRef; 410 row[7] = tuple.FirstControlRef;
383 row[8] = tuple.DefaultControlRef; 411 row[8] = tuple.DefaultControlRef;
384 row[9] = tuple.CancelControlRef; 412 row[9] = tuple.CancelControlRef;
413
414 output.EnsureTable(this.TableDefinitions["ListBox"]);
385 } 415 }
386 416
387 private void AddDirectoryTuple(DirectoryTuple tuple, Output output) 417 private void AddDirectoryTuple(DirectoryTuple tuple, Output output)
@@ -929,6 +959,93 @@ namespace WixToolset.Core.WindowsInstaller.Bind
929 row[2] = tuple.Sequence; 959 row[2] = tuple.Sequence;
930 } 960 }
931 } 961 }
962
963 private void AddWixCustomRowTuple(WixCustomRowTuple tuple, Output output)
964 {
965 var customTableDefinition = this.TableDefinitions[tuple.Table];
966
967 if (customTableDefinition.Unreal)
968 {
969
970 return;
971 }
972
973 var customTable = output.EnsureTable(customTableDefinition);
974 var customRow = customTable.CreateRow(tuple.SourceLineNumbers);
975
976#if TODO // SectionId seems like a good thing to preserve.
977 customRow.SectionId = tuple.SectionId;
978#endif
979
980 var data = tuple.FieldDataSeparated;
981
982 for (var i = 0; i < data.Length; ++i)
983 {
984 var foundColumn = false;
985 var item = data[i].Split(ColonCharacter, 2);
986
987 for (var j = 0; j < customRow.Fields.Length; ++j)
988 {
989 if (customRow.Fields[j].Column.Name == item[0])
990 {
991 if (0 < item[1].Length)
992 {
993 if (ColumnType.Number == customRow.Fields[j].Column.Type)
994 {
995 try
996 {
997 customRow.Fields[j].Data = Convert.ToInt32(item[1], CultureInfo.InvariantCulture);
998 }
999 catch (FormatException)
1000 {
1001 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(tuple.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1]));
1002 }
1003 catch (OverflowException)
1004 {
1005 this.Messaging.Write(ErrorMessages.IllegalIntegerValue(tuple.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1]));
1006 }
1007 }
1008 else if (ColumnCategory.Identifier == customRow.Fields[j].Column.Category)
1009 {
1010 if (Common.IsIdentifier(item[1]) || Common.IsValidBinderVariable(item[1]) || ColumnCategory.Formatted == customRow.Fields[j].Column.Category)
1011 {
1012 customRow.Fields[j].Data = item[1];
1013 }
1014 else
1015 {
1016 this.Messaging.Write(ErrorMessages.IllegalIdentifier(tuple.SourceLineNumbers, "Data", item[1]));
1017 }
1018 }
1019 else
1020 {
1021 customRow.Fields[j].Data = item[1];
1022 }
1023 }
1024 foundColumn = true;
1025 break;
1026 }
1027 }
1028
1029 if (!foundColumn)
1030 {
1031 this.Messaging.Write(ErrorMessages.UnexpectedCustomTableColumn(tuple.SourceLineNumbers, item[0]));
1032 }
1033 }
1034
1035 for (var i = 0; i < customTableDefinition.Columns.Length; ++i)
1036 {
1037 if (!customTableDefinition.Columns[i].Nullable && (null == customRow.Fields[i].Data || 0 == customRow.Fields[i].Data.ToString().Length))
1038 {
1039 this.Messaging.Write(ErrorMessages.NoDataForColumn(tuple.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name));
1040 }
1041 }
1042 }
1043
1044 private void AddWixEnsureTableTuple(WixEnsureTableTuple tuple, Output output)
1045 {
1046 var tableDefinition = this.TableDefinitions[tuple.Table];
1047 output.EnsureTable(tableDefinition);
1048 }
932 1049
933 private void AddWixMediaTemplateTuple(WixMediaTemplateTuple tuple, Output output) 1050 private void AddWixMediaTemplateTuple(WixMediaTemplateTuple tuple, Output output)
934 { 1051 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs
new file mode 100644
index 00000000..05f865fa
--- /dev/null
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs
@@ -0,0 +1,213 @@
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
3namespace WixToolset.Core.WindowsInstaller.Bind
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.Linq;
9 using WixToolset.Data;
10 using WixToolset.Data.Tuples;
11 using WixToolset.Data.WindowsInstaller;
12
13 internal class LoadTableDefinitionsCommand
14 {
15 public LoadTableDefinitionsCommand(IntermediateSection section) => this.Section = section;
16
17 public TableDefinitionCollection TableDefinitions { get; private set; }
18
19 private IntermediateSection Section { get; }
20
21 public TableDefinitionCollection Execute()
22 {
23 var tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandardInternal.GetTableDefinitions());
24
25 foreach (var tuple in this.Section.Tuples.OfType<WixCustomTableTuple>())
26 {
27 var customTableDefinition = this.CreateCustomTable(tuple);
28 tableDefinitions.Add(customTableDefinition);
29 }
30
31 this.TableDefinitions = tableDefinitions;
32 return this.TableDefinitions;
33 }
34
35 private TableDefinition CreateCustomTable(WixCustomTableTuple row)
36 {
37 var columnNames = row.ColumnNames.Split('\t');
38 var columnTypes = row.ColumnTypes.Split('\t');
39 var primaryKeys = row.PrimaryKeys.Split('\t');
40 var minValues = row.MinValues?.Split('\t');
41 var maxValues = row.MaxValues?.Split('\t');
42 var keyTables = row.KeyTables?.Split('\t');
43 var keyColumns = row.KeyColumns?.Split('\t');
44 var categories = row.Categories?.Split('\t');
45 var sets = row.Sets?.Split('\t');
46 var descriptions = row.Descriptions?.Split('\t');
47 var modularizations = row.Modularizations?.Split('\t');
48
49 var currentPrimaryKey = 0;
50
51 var columns = new List<ColumnDefinition>(columnNames.Length);
52 for (var i = 0; i < columnNames.Length; ++i)
53 {
54 var name = columnNames[i];
55 var type = ColumnType.Unknown;
56
57 if (columnTypes[i].StartsWith("s", StringComparison.OrdinalIgnoreCase))
58 {
59 type = ColumnType.String;
60 }
61 else if (columnTypes[i].StartsWith("l", StringComparison.OrdinalIgnoreCase))
62 {
63 type = ColumnType.Localized;
64 }
65 else if (columnTypes[i].StartsWith("i", StringComparison.OrdinalIgnoreCase))
66 {
67 type = ColumnType.Number;
68 }
69 else if (columnTypes[i].StartsWith("v", StringComparison.OrdinalIgnoreCase))
70 {
71 type = ColumnType.Object;
72 }
73
74 var nullable = columnTypes[i].Substring(0, 1) == columnTypes[i].Substring(0, 1).ToUpperInvariant();
75 var length = Convert.ToInt32(columnTypes[i].Substring(1), CultureInfo.InvariantCulture);
76
77 var primaryKey = false;
78 if (currentPrimaryKey < primaryKeys.Length && primaryKeys[currentPrimaryKey] == columnNames[i])
79 {
80 primaryKey = true;
81 currentPrimaryKey++;
82 }
83
84 var minValue = String.IsNullOrEmpty(minValues?[i]) ? (int?)null : Convert.ToInt32(minValues[i], CultureInfo.InvariantCulture);
85 var maxValue = String.IsNullOrEmpty(maxValues?[i]) ? (int?)null : Convert.ToInt32(maxValues[i], CultureInfo.InvariantCulture);
86 var keyColumn = String.IsNullOrEmpty(keyColumns?[i]) ? (int?)null : Convert.ToInt32(keyColumns[i], CultureInfo.InvariantCulture);
87
88 var category = ColumnCategory.Unknown;
89 if (null != categories && null != categories[i] && 0 < categories[i].Length)
90 {
91 switch (categories[i])
92 {
93 case "Text":
94 category = ColumnCategory.Text;
95 break;
96 case "UpperCase":
97 category = ColumnCategory.UpperCase;
98 break;
99 case "LowerCase":
100 category = ColumnCategory.LowerCase;
101 break;
102 case "Integer":
103 category = ColumnCategory.Integer;
104 break;
105 case "DoubleInteger":
106 category = ColumnCategory.DoubleInteger;
107 break;
108 case "TimeDate":
109 category = ColumnCategory.TimeDate;
110 break;
111 case "Identifier":
112 category = ColumnCategory.Identifier;
113 break;
114 case "Property":
115 category = ColumnCategory.Property;
116 break;
117 case "Filename":
118 category = ColumnCategory.Filename;
119 break;
120 case "WildCardFilename":
121 category = ColumnCategory.WildCardFilename;
122 break;
123 case "Path":
124 category = ColumnCategory.Path;
125 break;
126 case "Paths":
127 category = ColumnCategory.Paths;
128 break;
129 case "AnyPath":
130 category = ColumnCategory.AnyPath;
131 break;
132 case "DefaultDir":
133 category = ColumnCategory.DefaultDir;
134 break;
135 case "RegPath":
136 category = ColumnCategory.RegPath;
137 break;
138 case "Formatted":
139 category = ColumnCategory.Formatted;
140 break;
141 case "FormattedSddl":
142 category = ColumnCategory.FormattedSDDLText;
143 break;
144 case "Template":
145 category = ColumnCategory.Template;
146 break;
147 case "Condition":
148 category = ColumnCategory.Condition;
149 break;
150 case "Guid":
151 category = ColumnCategory.Guid;
152 break;
153 case "Version":
154 category = ColumnCategory.Version;
155 break;
156 case "Language":
157 category = ColumnCategory.Language;
158 break;
159 case "Binary":
160 category = ColumnCategory.Binary;
161 break;
162 case "CustomSource":
163 category = ColumnCategory.CustomSource;
164 break;
165 case "Cabinet":
166 category = ColumnCategory.Cabinet;
167 break;
168 case "Shortcut":
169 category = ColumnCategory.Shortcut;
170 break;
171 default:
172 break;
173 }
174 }
175
176 var keyTable = keyTables?[i];
177 var setValue = sets?[i];
178 var description = descriptions?[i];
179 var modString = modularizations?[i];
180 var modularization = ColumnModularizeType.None;
181
182 switch (modString)
183 {
184 case null:
185 case "None":
186 modularization = ColumnModularizeType.None;
187 break;
188 case "Column":
189 modularization = ColumnModularizeType.Column;
190 break;
191 case "Property":
192 modularization = ColumnModularizeType.Property;
193 break;
194 case "Condition":
195 modularization = ColumnModularizeType.Condition;
196 break;
197 case "CompanionFile":
198 modularization = ColumnModularizeType.CompanionFile;
199 break;
200 case "SemicolonDelimited":
201 modularization = ColumnModularizeType.SemicolonDelimited;
202 break;
203 }
204
205 var columnDefinition = new ColumnDefinition(name, type, length, primaryKey, nullable, category, minValue, maxValue, keyTable, keyColumn, setValue, description, modularization, ColumnType.Localized == type, true);
206 columns.Add(columnDefinition);
207 }
208
209 var customTable = new TableDefinition(row.Id.Id, columns/*, unreal: bootstrapperApplicationData, bootstrapperApplicationData*/);
210 return customTable;
211 }
212 }
213}
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
index e671f6a1..0699199b 100644
--- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
@@ -271,7 +271,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
271 } 271 }
272 } 272 }
273 273
274 var tableDefinition = new TableDefinition(tableName, columns, false, false); 274 var tableDefinition = new TableDefinition(tableName, columns, false);
275 275
276 // use our table definitions if core properties are the same; this allows us to take advantage 276 // use our table definitions if core properties are the same; this allows us to take advantage
277 // of wix concepts like localizable columns which current code assumes 277 // of wix concepts like localizable columns which current code assumes
diff --git a/src/WixToolset.Core/Common.cs b/src/WixToolset.Core/Common.cs
index 610bfcaa..e6f30e0c 100644
--- a/src/WixToolset.Core/Common.cs
+++ b/src/WixToolset.Core/Common.cs
@@ -104,8 +104,6 @@ namespace WixToolset.Core
104 104
105 public static readonly Regex WixVariableRegex = new Regex(@"(\!|\$)\((?<namespace>loc|wix|bind|bindpath)\.(?<fullname>(?<name>[_A-Za-z][0-9A-Za-z_]+)(\.(?<scope>[_A-Za-z][0-9A-Za-z_\.]*))?)(\=(?<value>.+?))?\)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture); 105 public static readonly Regex WixVariableRegex = new Regex(@"(\!|\$)\((?<namespace>loc|wix|bind|bindpath)\.(?<fullname>(?<name>[_A-Za-z][0-9A-Za-z_]+)(\.(?<scope>[_A-Za-z][0-9A-Za-z_\.]*))?)(\=(?<value>.+?))?\)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture);
106 106
107 internal const char CustomRowFieldSeparator = '\x85';
108
109 private static readonly Regex PropertySearch = new Regex(@"\[[#$!]?[a-zA-Z_][a-zA-Z0-9_\.]*]", RegexOptions.Singleline); 107 private static readonly Regex PropertySearch = new Regex(@"\[[#$!]?[a-zA-Z_][a-zA-Z0-9_\.]*]", RegexOptions.Singleline);
110 private static readonly Regex AddPrefix = new Regex(@"^[^a-zA-Z_]", RegexOptions.Compiled); 108 private static readonly Regex AddPrefix = new Regex(@"^[^a-zA-Z_]", RegexOptions.Compiled);
111 private static readonly Regex LegalIdentifierCharacters = new Regex(@"^[_A-Za-z][0-9A-Za-z_\.]*$", RegexOptions.Compiled); 109 private static readonly Regex LegalIdentifierCharacters = new Regex(@"^[_A-Za-z][0-9A-Za-z_\.]*$", RegexOptions.Compiled);
diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs
index 480e8758..974f3188 100644
--- a/src/WixToolset.Core/Compiler.cs
+++ b/src/WixToolset.Core/Compiler.cs
@@ -3750,7 +3750,7 @@ namespace WixToolset.Core
3750 case "Id": 3750 case "Id":
3751 tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); 3751 tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
3752 break; 3752 break;
3753 case "BootstrapperApplicationData": 3753 case "Unreal":
3754 bootstrapperApplicationData = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 3754 bootstrapperApplicationData = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
3755 break; 3755 break;
3756 default: 3756 default:
@@ -3951,7 +3951,7 @@ namespace WixToolset.Core
3951 this.Core.Write(ErrorMessages.ExpectedAttribute(dataSourceLineNumbers, data.Name.LocalName, "Column")); 3951 this.Core.Write(ErrorMessages.ExpectedAttribute(dataSourceLineNumbers, data.Name.LocalName, "Column"));
3952 } 3952 }
3953 3953
3954 dataValue = String.Concat(dataValue, null == dataValue ? String.Empty : Common.CustomRowFieldSeparator.ToString(), columnName, ":", Common.GetInnerText(data)); 3954 dataValue = String.Concat(dataValue, null == dataValue ? String.Empty : WixCustomRowTuple.FieldSeparator.ToString(), columnName, ":", Common.GetInnerText(data));
3955 break; 3955 break;
3956 } 3956 }
3957 } 3957 }
@@ -4001,7 +4001,7 @@ namespace WixToolset.Core
4001 Sets = sets, 4001 Sets = sets,
4002 Descriptions = descriptions, 4002 Descriptions = descriptions,
4003 Modularizations = modularizations, 4003 Modularizations = modularizations,
4004 BootstrapperApplicationData = bootstrapperApplicationData 4004 Unreal = bootstrapperApplicationData
4005 }; 4005 };
4006 4006
4007 this.Core.AddTuple(tuple); 4007 this.Core.AddTuple(tuple);
diff --git a/src/WixToolset.Core/Librarian.cs b/src/WixToolset.Core/Librarian.cs
index a3bdc170..81d3a0ed 100644
--- a/src/WixToolset.Core/Librarian.cs
+++ b/src/WixToolset.Core/Librarian.cs
@@ -30,7 +30,6 @@ namespace WixToolset.Core
30 /// <summary> 30 /// <summary>
31 /// Create a library by combining several intermediates (objects). 31 /// Create a library by combining several intermediates (objects).
32 /// </summary> 32 /// </summary>
33 /// <param name="sections">The sections to combine into a library.</param>
34 /// <returns>Returns the new library.</returns> 33 /// <returns>Returns the new library.</returns>
35 public Intermediate Combine(ILibraryContext context) 34 public Intermediate Combine(ILibraryContext context)
36 { 35 {
@@ -79,26 +78,6 @@ namespace WixToolset.Core
79 return this.Messaging.EncounteredError ? null : library; 78 return this.Messaging.EncounteredError ? null : library;
80 } 79 }
81 80
82 /// <summary>
83 /// Validate that a library contains one entry section and no duplicate symbols.
84 /// </summary>
85 /// <param name="library">Library to validate.</param>
86 private void Validate(Intermediate library)
87 {
88 var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, library.Sections);
89 find.Execute();
90
91 // TODO: Consider bringing this sort of verification back.
92 // foreach (Section section in library.Sections)
93 // {
94 // ResolveReferencesCommand resolve = new ResolveReferencesCommand(find.EntrySection, find.Symbols);
95 // resolve.Execute();
96 //
97 // ReportDuplicateResolvedSymbolErrorsCommand reportDupes = new ReportDuplicateResolvedSymbolErrorsCommand(find.SymbolsWithDuplicates, resolve.ResolvedSections);
98 // reportDupes.Execute();
99 // }
100 }
101
102 private List<string> ResolveFilePathsToEmbed(ILibraryContext context, IEnumerable<IntermediateSection> sections) 81 private List<string> ResolveFilePathsToEmbed(ILibraryContext context, IEnumerable<IntermediateSection> sections)
103 { 82 {
104 var embedFilePaths = new List<string>(); 83 var embedFilePaths = new List<string>();
@@ -140,5 +119,21 @@ namespace WixToolset.Core
140 119
141 return embedFilePaths; 120 return embedFilePaths;
142 } 121 }
122
123 private void Validate(Intermediate library)
124 {
125 var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, library.Sections, OutputType.Library);
126 find.Execute();
127
128 // TODO: Consider bringing this sort of verification back.
129 // foreach (Section section in library.Sections)
130 // {
131 // ResolveReferencesCommand resolve = new ResolveReferencesCommand(find.EntrySection, find.Symbols);
132 // resolve.Execute();
133 //
134 // ReportDuplicateResolvedSymbolErrorsCommand reportDupes = new ReportDuplicateResolvedSymbolErrorsCommand(find.SymbolsWithDuplicates, resolve.ResolvedSections);
135 // reportDupes.Execute();
136 // }
137 }
143 } 138 }
144} 139}
diff --git a/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs b/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs
index daf3e878..b9890a3b 100644
--- a/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs
+++ b/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs
@@ -10,20 +10,18 @@ namespace WixToolset.Core.Link
10 10
11 internal class FindEntrySectionAndLoadSymbolsCommand 11 internal class FindEntrySectionAndLoadSymbolsCommand
12 { 12 {
13 public FindEntrySectionAndLoadSymbolsCommand(IMessaging messaging, IEnumerable<IntermediateSection> sections) 13 public FindEntrySectionAndLoadSymbolsCommand(IMessaging messaging, IEnumerable<IntermediateSection> sections, OutputType expectedOutpuType)
14 { 14 {
15 this.Messaging = messaging; 15 this.Messaging = messaging;
16 this.Sections = sections; 16 this.Sections = sections;
17 this.ExpectedOutputType = expectedOutpuType;
17 } 18 }
18 19
19 private IMessaging Messaging { get; } 20 private IMessaging Messaging { get; }
20 21
21 private IEnumerable<IntermediateSection> Sections { get; } 22 private IEnumerable<IntermediateSection> Sections { get; }
22 23
23 /// <summary> 24 private OutputType ExpectedOutputType { get; }
24 /// Sets the expected entry output type, based on output file extension provided to the linker.
25 /// </summary>
26 public OutputType ExpectedOutputType { private get; set; }
27 25
28 /// <summary> 26 /// <summary>
29 /// Gets the located entry section after the command is executed. 27 /// Gets the located entry section after the command is executed.
@@ -42,8 +40,8 @@ namespace WixToolset.Core.Link
42 40
43 public void Execute() 41 public void Execute()
44 { 42 {
45 Dictionary<string, Symbol> symbols = new Dictionary<string, Symbol>(); 43 var symbols = new Dictionary<string, Symbol>();
46 HashSet<Symbol> possibleConflicts = new HashSet<Symbol>(); 44 var possibleConflicts = new HashSet<Symbol>();
47 45
48 if (!Enum.TryParse(this.ExpectedOutputType.ToString(), out SectionType expectedEntrySectionType)) 46 if (!Enum.TryParse(this.ExpectedOutputType.ToString(), out SectionType expectedEntrySectionType))
49 { 47 {
@@ -74,9 +72,9 @@ namespace WixToolset.Core.Link
74 } 72 }
75 73
76 // Load all the symbols from the section's tables that create symbols. 74 // Load all the symbols from the section's tables that create symbols.
77 foreach (var row in section.Tuples.Where(t => t.Id != null)) 75 foreach (var tuple in section.Tuples.Where(t => t.Id != null))
78 { 76 {
79 var symbol = new Symbol(section, row); 77 var symbol = new Symbol(section, tuple);
80 78
81 if (!symbols.TryGetValue(symbol.Name, out var existingSymbol)) 79 if (!symbols.TryGetValue(symbol.Name, out var existingSymbol))
82 { 80 {
diff --git a/src/WixToolset.Core/Link/ResolveReferencesCommand.cs b/src/WixToolset.Core/Link/ResolveReferencesCommand.cs
index ed11095f..6dcd36d3 100644
--- a/src/WixToolset.Core/Link/ResolveReferencesCommand.cs
+++ b/src/WixToolset.Core/Link/ResolveReferencesCommand.cs
@@ -14,8 +14,8 @@ namespace WixToolset.Core.Link
14 /// </summary> 14 /// </summary>
15 internal class ResolveReferencesCommand 15 internal class ResolveReferencesCommand
16 { 16 {
17 private IntermediateSection entrySection; 17 private readonly IntermediateSection entrySection;
18 private IDictionary<string, Symbol> symbols; 18 private readonly IDictionary<string, Symbol> symbols;
19 private HashSet<Symbol> referencedSymbols; 19 private HashSet<Symbol> referencedSymbols;
20 private HashSet<IntermediateSection> resolvedSections; 20 private HashSet<IntermediateSection> resolvedSections;
21 21
@@ -24,13 +24,14 @@ namespace WixToolset.Core.Link
24 this.Messaging = messaging; 24 this.Messaging = messaging;
25 this.entrySection = entrySection; 25 this.entrySection = entrySection;
26 this.symbols = symbols; 26 this.symbols = symbols;
27 this.BuildingMergeModule = (SectionType.Module == entrySection.Type);
27 } 28 }
28 29
29 public bool BuildingMergeModule { private get; set; } 30 public IEnumerable<Symbol> ReferencedSymbols => this.referencedSymbols;
30 31
31 public IEnumerable<Symbol> ReferencedSymbols { get { return this.referencedSymbols; } } 32 public IEnumerable<IntermediateSection> ResolvedSections => this.resolvedSections;
32 33
33 public IEnumerable<IntermediateSection> ResolvedSections { get { return this.resolvedSections; } } 34 private bool BuildingMergeModule { get; }
34 35
35 private IMessaging Messaging { get; } 36 private IMessaging Messaging { get; }
36 37
diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs
index 9526ac95..81696840 100644
--- a/src/WixToolset.Core/Linker.cs
+++ b/src/WixToolset.Core/Linker.cs
@@ -20,7 +20,6 @@ namespace WixToolset.Core
20 /// </summary> 20 /// </summary>
21 internal class Linker : ILinker 21 internal class Linker : ILinker
22 { 22 {
23 private static readonly char[] ColonCharacter = new[] { ':' };
24 private static readonly string EmptyGuid = Guid.Empty.ToString("B"); 23 private static readonly string EmptyGuid = Guid.Empty.ToString("B");
25 24
26 private readonly bool sectionIdOnRows; 25 private readonly bool sectionIdOnRows;
@@ -56,9 +55,7 @@ namespace WixToolset.Core
56 /// <summary> 55 /// <summary>
57 /// Links a collection of sections into an output. 56 /// Links a collection of sections into an output.
58 /// </summary> 57 /// </summary>
59 /// <param name="inputs">The collection of sections to link together.</param> 58 /// <returns>Output intermediate from the linking.</returns>
60 /// <param name="expectedOutputType">Expected output type, based on output file extension provided to the linker.</param>
61 /// <returns>Output object from the linking.</returns>
62 public Intermediate Link(ILinkContext context) 59 public Intermediate Link(ILinkContext context)
63 { 60 {
64 this.Context = context; 61 this.Context = context;
@@ -97,9 +94,6 @@ namespace WixToolset.Core
97 94
98 //this.activeOutput = null; 95 //this.activeOutput = null;
99 96
100 //TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection();
101 //IntermediateTuple customRows = new List<IntermediateTuple>();
102
103#if MOVE_TO_BACKEND 97#if MOVE_TO_BACKEND
104 StringCollection generatedShortFileNameIdentifiers = new StringCollection(); 98 StringCollection generatedShortFileNameIdentifiers = new StringCollection();
105 Hashtable generatedShortFileNames = new Hashtable(); 99 Hashtable generatedShortFileNames = new Hashtable();
@@ -123,11 +117,11 @@ namespace WixToolset.Core
123 117
124 if (0 >= columnDefinition.KeyColumn || keyTableDefinition.Columns.Count < columnDefinition.KeyColumn) 118 if (0 >= columnDefinition.KeyColumn || keyTableDefinition.Columns.Count < columnDefinition.KeyColumn)
125 { 119 {
126 this.OnMessage(WixErrors.InvalidKeyColumn(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn)); 120 this.Messaging.Write(WixErrors.InvalidKeyColumn(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn));
127 } 121 }
128 else if (keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType != columnDefinition.ModularizeType && ColumnModularizeType.CompanionFile != columnDefinition.ModularizeType) 122 else if (keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType != columnDefinition.ModularizeType && ColumnModularizeType.CompanionFile != columnDefinition.ModularizeType)
129 { 123 {
130 this.OnMessage(WixErrors.CollidingModularizationTypes(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn, columnDefinition.ModularizeType.ToString(), keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType.ToString())); 124 this.Messaging.Write(WixErrors.CollidingModularizationTypes(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn, columnDefinition.ModularizeType.ToString(), keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType.ToString()));
131 } 125 }
132 } 126 }
133 catch (WixMissingTableDefinitionException) 127 catch (WixMissingTableDefinitionException)
@@ -141,8 +135,7 @@ namespace WixToolset.Core
141 135
142 // First find the entry section and while processing all sections load all the symbols from all of the sections. 136 // First find the entry section and while processing all sections load all the symbols from all of the sections.
143 // sections.FindEntrySectionAndLoadSymbols(false, this, expectedOutputType, out entrySection, out allSymbols); 137 // sections.FindEntrySectionAndLoadSymbols(false, this, expectedOutputType, out entrySection, out allSymbols);
144 var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, sections); 138 var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, sections, this.Context.ExpectedOutputType);
145 find.ExpectedOutputType = this.Context.ExpectedOutputType;
146 find.Execute(); 139 find.Execute();
147 140
148 // Must have found the entry section by now. 141 // Must have found the entry section by now.
@@ -157,7 +150,6 @@ namespace WixToolset.Core
157 // Resolve the symbol references to find the set of sections we care about for linking. 150 // Resolve the symbol references to find the set of sections we care about for linking.
158 // Of course, we start with the entry section (that's how it got its name after all). 151 // Of course, we start with the entry section (that's how it got its name after all).
159 var resolve = new ResolveReferencesCommand(this.Messaging, find.EntrySection, find.Symbols); 152 var resolve = new ResolveReferencesCommand(this.Messaging, find.EntrySection, find.Symbols);
160 resolve.BuildingMergeModule = (SectionType.Module == find.EntrySection.Type);
161 153
162 resolve.Execute(); 154 resolve.Execute();
163 155
@@ -197,7 +189,7 @@ namespace WixToolset.Core
197 { 189 {
198 if (!referencedComponents.Contains(symbol.Name)) 190 if (!referencedComponents.Contains(symbol.Name))
199 { 191 {
200 this.OnMessage(ErrorMessages.OrphanedComponent(symbol.Row.SourceLineNumbers, symbol.Row.Id.Id)); 192 this.Messaging.Write(ErrorMessages.OrphanedComponent(symbol.Row.SourceLineNumbers, symbol.Row.Id.Id));
201 } 193 }
202 } 194 }
203 195
@@ -238,12 +230,6 @@ namespace WixToolset.Core
238 // handle special tables 230 // handle special tables
239 switch (tuple.Definition.Type) 231 switch (tuple.Definition.Type)
240 { 232 {
241#if MOVE_TO_BACKEND
242 case "AppSearch":
243 this.activeOutput.EnsureTable(this.tableDefinitions["Signature"]);
244 break;
245#endif
246
247 case TupleDefinitionType.Class: 233 case TupleDefinitionType.Class:
248 if (SectionType.Product == resolvedSection.Type) 234 if (SectionType.Product == resolvedSection.Type)
249 { 235 {
@@ -263,10 +249,6 @@ namespace WixToolset.Core
263 } 249 }
264 break; 250 break;
265 251
266 case "Dialog":
267 this.activeOutput.EnsureTable(this.tableDefinitions["ListBox"]);
268 break;
269
270 case "Directory": 252 case "Directory":
271 foreach (Row row in table.Rows) 253 foreach (Row row in table.Rows)
272 { 254 {
@@ -295,7 +277,7 @@ namespace WixToolset.Core
295 { 277 {
296 if (directory.StartsWith(standardDirectory, StringComparison.Ordinal)) 278 if (directory.StartsWith(standardDirectory, StringComparison.Ordinal))
297 { 279 {
298 this.OnMessage(WixWarnings.StandardDirectoryConflictInMergeModule(row.SourceLineNumbers, directory, standardDirectory)); 280 this.Messaging.Write(WixWarnings.StandardDirectoryConflictInMergeModule(row.SourceLineNumbers, directory, standardDirectory));
299 } 281 }
300 } 282 }
301 } 283 }
@@ -327,26 +309,6 @@ namespace WixToolset.Core
327 } 309 }
328 break; 310 break;
329 311
330#if MOVE_TO_BACKEND
331 case "ProgId":
332 // the Extension table is required with a ProgId table
333 this.activeOutput.EnsureTable(this.tableDefinitions["Extension"]);
334 break;
335
336 case "Property":
337 // Remove property rows with no value. These are properties associated with
338 // AppSearch but without a default value.
339 for (int i = 0; i < table.Rows.Count; i++)
340 {
341 if (null == table.Rows[i][1])
342 {
343 table.Rows.RemoveAt(i);
344 i--;
345 }
346 }
347 break;
348#endif
349
350 case TupleDefinitionType.PublishComponent: 312 case TupleDefinitionType.PublishComponent:
351 if (SectionType.Product == resolvedSection.Type) 313 if (SectionType.Product == resolvedSection.Type)
352 { 314 {
@@ -368,27 +330,10 @@ namespace WixToolset.Core
368 } 330 }
369 break; 331 break;
370 332
371#if SOLVE_CUSTOM_TABLE
372 case "WixCustomTable":
373 this.LinkCustomTable(table, customTableDefinitions);
374 copyTuple = false; // we've created table definitions from these rows, no need to process them any longer
375 break;
376
377 case "WixCustomRow":
378 foreach (Row row in table.Rows)
379 {
380 row.SectionId = (this.sectionIdOnRows ? sectionId : null);
381 customRows.Add(row);
382 }
383 copyTuple = false;
384 break;
385#endif
386
387 case TupleDefinitionType.WixEnsureTable: 333 case TupleDefinitionType.WixEnsureTable:
388 ensureTableRows.Add(tuple); 334 ensureTableRows.Add(tuple);
389 break; 335 break;
390 336
391
392#if MOVE_TO_BACKEND 337#if MOVE_TO_BACKEND
393 case "WixFile": 338 case "WixFile":
394 foreach (Row row in table.Rows) 339 foreach (Row row in table.Rows)
@@ -427,23 +372,23 @@ namespace WixToolset.Core
427 case TupleDefinitionType.WixVariable: 372 case TupleDefinitionType.WixVariable:
428 // check for colliding values and collect the wix variable rows 373 // check for colliding values and collect the wix variable rows
429 { 374 {
430 var row = (WixVariableTuple)tuple; 375 var wixVariableTuple = (WixVariableTuple)tuple;
431 var id = row.Id.Id; 376 var id = wixVariableTuple.Id.Id;
432 377
433 if (wixVariables.TryGetValue(id, out var collidingRow)) 378 if (wixVariables.TryGetValue(id, out var collidingTuple))
434 { 379 {
435 if (collidingRow.Overridable && !row.Overridable) 380 if (collidingTuple.Overridable && !wixVariableTuple.Overridable)
436 { 381 {
437 wixVariables[id] = row; 382 wixVariables[id] = wixVariableTuple;
438 } 383 }
439 else if (!row.Overridable || (collidingRow.Overridable && row.Overridable)) 384 else if (!wixVariableTuple.Overridable || (collidingTuple.Overridable && wixVariableTuple.Overridable))
440 { 385 {
441 this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, id)); 386 this.Messaging.Write(ErrorMessages.WixVariableCollision(wixVariableTuple.SourceLineNumbers, id));
442 } 387 }
443 } 388 }
444 else 389 else
445 { 390 {
446 wixVariables.Add(id, row); 391 wixVariables.Add(id, wixVariableTuple);
447 } 392 }
448 } 393 }
449 394
@@ -463,36 +408,15 @@ namespace WixToolset.Core
463 { 408 {
464 foreach (var feature in connectToFeature.ConnectFeatures) 409 foreach (var feature in connectToFeature.ConnectFeatures)
465 { 410 {
466 var row = new WixFeatureModulesTuple(); 411 var row = new WixFeatureModulesTuple
467 row.FeatureRef = feature;
468 row.WixMergeRef = connectToFeature.ChildId;
469
470 resolvedSection.Tuples.Add(row);
471 }
472 }
473
474#if MOVE_TO_BACKEND
475 // ensure the creation of tables that need to exist
476 if (0 < ensureTableRows.Count)
477 {
478 foreach (Row row in ensureTableRows)
479 {
480 string tableId = (string)row[0];
481 TableDefinition tableDef = null;
482
483 try
484 { 412 {
485 tableDef = this.tableDefinitions[tableId]; 413 FeatureRef = feature,
486 } 414 WixMergeRef = connectToFeature.ChildId
487 catch (WixMissingTableDefinitionException) 415 };
488 {
489 tableDef = customTableDefinitions[tableId];
490 }
491 416
492 this.activeOutput.EnsureTable(tableDef); 417 resolvedSection.Tuples.Add(row);
493 } 418 }
494 } 419 }
495#endif
496 420
497#if MOVE_TO_BACKEND 421#if MOVE_TO_BACKEND
498 // check for missing table and add them or display an error as appropriate 422 // check for missing table and add them or display an error as appropriate
@@ -513,17 +437,17 @@ namespace WixToolset.Core
513 437
514 if (null == imageFamiliesTable || 1 > imageFamiliesTable.Rows.Count) 438 if (null == imageFamiliesTable || 1 > imageFamiliesTable.Rows.Count)
515 { 439 {
516 this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("ImageFamilies")); 440 this.Messaging.Write(WixErrors.ExpectedRowInPatchCreationPackage("ImageFamilies"));
517 } 441 }
518 442
519 if (null == targetImagesTable || 1 > targetImagesTable.Rows.Count) 443 if (null == targetImagesTable || 1 > targetImagesTable.Rows.Count)
520 { 444 {
521 this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("TargetImages")); 445 this.Messaging.Write(WixErrors.ExpectedRowInPatchCreationPackage("TargetImages"));
522 } 446 }
523 447
524 if (null == upgradedImagesTable || 1 > upgradedImagesTable.Rows.Count) 448 if (null == upgradedImagesTable || 1 > upgradedImagesTable.Rows.Count)
525 { 449 {
526 this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("UpgradedImages")); 450 this.Messaging.Write(WixErrors.ExpectedRowInPatchCreationPackage("UpgradedImages"));
527 } 451 }
528 452
529 this.activeOutput.EnsureTable(this.tableDefinitions["Properties"]); 453 this.activeOutput.EnsureTable(this.tableDefinitions["Properties"]);
@@ -537,81 +461,6 @@ namespace WixToolset.Core
537 this.CheckForIllegalTables(this.activeOutput); 461 this.CheckForIllegalTables(this.activeOutput);
538#endif 462#endif
539 463
540#if SOLVE_CUSTOM_TABLE
541 // add the custom row data
542 foreach (Row row in customRows)
543 {
544 TableDefinition customTableDefinition = (TableDefinition)customTableDefinitions[row[0].ToString()];
545 Table customTable = this.activeOutput.EnsureTable(customTableDefinition);
546 Row customRow = customTable.CreateRow(row.SourceLineNumbers);
547
548 customRow.SectionId = row.SectionId;
549
550 string[] data = row[1].ToString().Split(Common.CustomRowFieldSeparator);
551
552 for (int i = 0; i < data.Length; ++i)
553 {
554 bool foundColumn = false;
555 string[] item = data[i].Split(colonCharacter, 2);
556
557 for (int j = 0; j < customRow.Fields.Length; ++j)
558 {
559 if (customRow.Fields[j].Column.Name == item[0])
560 {
561 if (0 < item[1].Length)
562 {
563 if (ColumnType.Number == customRow.Fields[j].Column.Type)
564 {
565 try
566 {
567 customRow.Fields[j].Data = Convert.ToInt32(item[1], CultureInfo.InvariantCulture);
568 }
569 catch (FormatException)
570 {
571 this.OnMessage(WixErrors.IllegalIntegerValue(row.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1]));
572 }
573 catch (OverflowException)
574 {
575 this.OnMessage(WixErrors.IllegalIntegerValue(row.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1]));
576 }
577 }
578 else if (ColumnCategory.Identifier == customRow.Fields[j].Column.Category)
579 {
580 if (Common.IsIdentifier(item[1]) || Common.IsValidBinderVariable(item[1]) || ColumnCategory.Formatted == customRow.Fields[j].Column.Category)
581 {
582 customRow.Fields[j].Data = item[1];
583 }
584 else
585 {
586 this.OnMessage(WixErrors.IllegalIdentifier(row.SourceLineNumbers, "Data", item[1]));
587 }
588 }
589 else
590 {
591 customRow.Fields[j].Data = item[1];
592 }
593 }
594 foundColumn = true;
595 break;
596 }
597 }
598
599 if (!foundColumn)
600 {
601 this.OnMessage(WixErrors.UnexpectedCustomTableColumn(row.SourceLineNumbers, item[0]));
602 }
603 }
604
605 for (int i = 0; i < customTableDefinition.Columns.Count; ++i)
606 {
607 if (!customTableDefinition.Columns[i].Nullable && (null == customRow.Fields[i].Data || 0 == customRow.Fields[i].Data.ToString().Length))
608 {
609 this.OnMessage(WixErrors.NoDataForColumn(row.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name));
610 }
611 }
612 }
613#endif
614
615 //correct the section Id in FeatureComponents table 464 //correct the section Id in FeatureComponents table
616 if (this.sectionIdOnRows) 465 if (this.sectionIdOnRows)
617 { 466 {
@@ -683,7 +532,7 @@ namespace WixToolset.Core
683 // sort the rows by DiskId 532 // sort the rows by DiskId
684 fileRows.Sort(); 533 fileRows.Sort();
685 534
686 this.OnMessage(WixWarnings.GeneratedShortFileNameConflict(((FileRow)fileRows[0]).SourceLineNumbers, shortFileName)); 535 this.Messaging.Write(WixWarnings.GeneratedShortFileNameConflict(((FileRow)fileRows[0]).SourceLineNumbers, shortFileName));
687 536
688 for (int i = 1; i < fileRows.Count; i++) 537 for (int i = 1; i < fileRows.Count; i++)
689 { 538 {
@@ -691,7 +540,7 @@ namespace WixToolset.Core
691 540
692 if (null != fileRow.SourceLineNumbers) 541 if (null != fileRow.SourceLineNumbers)
693 { 542 {
694 this.OnMessage(WixWarnings.GeneratedShortFileNameConflict2(fileRow.SourceLineNumbers)); 543 this.Messaging.Write(WixWarnings.GeneratedShortFileNameConflict2(fileRow.SourceLineNumbers));
695 } 544 }
696 } 545 }
697 } 546 }
@@ -732,223 +581,6 @@ namespace WixToolset.Core
732 return this.Messaging.EncounteredError ? null : intermediate; 581 return this.Messaging.EncounteredError ? null : intermediate;
733 } 582 }
734 583
735#if SOLVE_CUSTOM_TABLE
736 /// <summary>
737 /// Links the definition of a custom table.
738 /// </summary>
739 /// <param name="table">The table to link.</param>
740 /// <param name="customTableDefinitions">Receives the linked definition of the custom table.</param>
741 private void LinkCustomTable(Table table, TableDefinitionCollection customTableDefinitions)
742 {
743 foreach (Row row in table.Rows)
744 {
745 bool bootstrapperApplicationData = (null != row[13] && 1 == (int)row[13]);
746
747 if (null == row[4])
748 {
749 this.OnMessage(WixErrors.ExpectedAttribute(row.SourceLineNumbers, "CustomTable/Column", "PrimaryKey"));
750 }
751
752 string[] columnNames = row[2].ToString().Split('\t');
753 string[] columnTypes = row[3].ToString().Split('\t');
754 string[] primaryKeys = row[4].ToString().Split('\t');
755 string[] minValues = row[5] == null ? null : row[5].ToString().Split('\t');
756 string[] maxValues = row[6] == null ? null : row[6].ToString().Split('\t');
757 string[] keyTables = row[7] == null ? null : row[7].ToString().Split('\t');
758 string[] keyColumns = row[8] == null ? null : row[8].ToString().Split('\t');
759 string[] categories = row[9] == null ? null : row[9].ToString().Split('\t');
760 string[] sets = row[10] == null ? null : row[10].ToString().Split('\t');
761 string[] descriptions = row[11] == null ? null : row[11].ToString().Split('\t');
762 string[] modularizations = row[12] == null ? null : row[12].ToString().Split('\t');
763
764 int currentPrimaryKey = 0;
765
766 List<ColumnDefinition> columns = new List<ColumnDefinition>(columnNames.Length);
767 for (int i = 0; i < columnNames.Length; ++i)
768 {
769 string name = columnNames[i];
770 ColumnType type = ColumnType.Unknown;
771
772 if (columnTypes[i].StartsWith("s", StringComparison.OrdinalIgnoreCase))
773 {
774 type = ColumnType.String;
775 }
776 else if (columnTypes[i].StartsWith("l", StringComparison.OrdinalIgnoreCase))
777 {
778 type = ColumnType.Localized;
779 }
780 else if (columnTypes[i].StartsWith("i", StringComparison.OrdinalIgnoreCase))
781 {
782 type = ColumnType.Number;
783 }
784 else if (columnTypes[i].StartsWith("v", StringComparison.OrdinalIgnoreCase))
785 {
786 type = ColumnType.Object;
787 }
788 else
789 {
790 throw new WixException(WixErrors.UnknownCustomTableColumnType(row.SourceLineNumbers, columnTypes[i]));
791 }
792
793 bool nullable = columnTypes[i].Substring(0, 1) == columnTypes[i].Substring(0, 1).ToUpper(CultureInfo.InvariantCulture);
794 int length = Convert.ToInt32(columnTypes[i].Substring(1), CultureInfo.InvariantCulture);
795
796 bool primaryKey = false;
797 if (currentPrimaryKey < primaryKeys.Length && primaryKeys[currentPrimaryKey] == columnNames[i])
798 {
799 primaryKey = true;
800 currentPrimaryKey++;
801 }
802
803 bool minValSet = null != minValues && null != minValues[i] && 0 < minValues[i].Length;
804 int minValue = 0;
805 if (minValSet)
806 {
807 minValue = Convert.ToInt32(minValues[i], CultureInfo.InvariantCulture);
808 }
809
810 bool maxValSet = null != maxValues && null != maxValues[i] && 0 < maxValues[i].Length;
811 int maxValue = 0;
812 if (maxValSet)
813 {
814 maxValue = Convert.ToInt32(maxValues[i], CultureInfo.InvariantCulture);
815 }
816
817 bool keyColumnSet = null != keyColumns && null != keyColumns[i] && 0 < keyColumns[i].Length;
818 int keyColumn = 0;
819 if (keyColumnSet)
820 {
821 keyColumn = Convert.ToInt32(keyColumns[i], CultureInfo.InvariantCulture);
822 }
823
824 ColumnCategory category = ColumnCategory.Unknown;
825 if (null != categories && null != categories[i] && 0 < categories[i].Length)
826 {
827 switch (categories[i])
828 {
829 case "Text":
830 category = ColumnCategory.Text;
831 break;
832 case "UpperCase":
833 category = ColumnCategory.UpperCase;
834 break;
835 case "LowerCase":
836 category = ColumnCategory.LowerCase;
837 break;
838 case "Integer":
839 category = ColumnCategory.Integer;
840 break;
841 case "DoubleInteger":
842 category = ColumnCategory.DoubleInteger;
843 break;
844 case "TimeDate":
845 category = ColumnCategory.TimeDate;
846 break;
847 case "Identifier":
848 category = ColumnCategory.Identifier;
849 break;
850 case "Property":
851 category = ColumnCategory.Property;
852 break;
853 case "Filename":
854 category = ColumnCategory.Filename;
855 break;
856 case "WildCardFilename":
857 category = ColumnCategory.WildCardFilename;
858 break;
859 case "Path":
860 category = ColumnCategory.Path;
861 break;
862 case "Paths":
863 category = ColumnCategory.Paths;
864 break;
865 case "AnyPath":
866 category = ColumnCategory.AnyPath;
867 break;
868 case "DefaultDir":
869 category = ColumnCategory.DefaultDir;
870 break;
871 case "RegPath":
872 category = ColumnCategory.RegPath;
873 break;
874 case "Formatted":
875 category = ColumnCategory.Formatted;
876 break;
877 case "FormattedSddl":
878 category = ColumnCategory.FormattedSDDLText;
879 break;
880 case "Template":
881 category = ColumnCategory.Template;
882 break;
883 case "Condition":
884 category = ColumnCategory.Condition;
885 break;
886 case "Guid":
887 category = ColumnCategory.Guid;
888 break;
889 case "Version":
890 category = ColumnCategory.Version;
891 break;
892 case "Language":
893 category = ColumnCategory.Language;
894 break;
895 case "Binary":
896 category = ColumnCategory.Binary;
897 break;
898 case "CustomSource":
899 category = ColumnCategory.CustomSource;
900 break;
901 case "Cabinet":
902 category = ColumnCategory.Cabinet;
903 break;
904 case "Shortcut":
905 category = ColumnCategory.Shortcut;
906 break;
907 default:
908 break;
909 }
910 }
911
912 string keyTable = keyTables != null ? keyTables[i] : null;
913 string setValue = sets != null ? sets[i] : null;
914 string description = descriptions != null ? descriptions[i] : null;
915 string modString = modularizations != null ? modularizations[i] : null;
916 ColumnModularizeType modularization = ColumnModularizeType.None;
917 if (modString != null)
918 {
919 switch (modString)
920 {
921 case "None":
922 modularization = ColumnModularizeType.None;
923 break;
924 case "Column":
925 modularization = ColumnModularizeType.Column;
926 break;
927 case "Property":
928 modularization = ColumnModularizeType.Property;
929 break;
930 case "Condition":
931 modularization = ColumnModularizeType.Condition;
932 break;
933 case "CompanionFile":
934 modularization = ColumnModularizeType.CompanionFile;
935 break;
936 case "SemicolonDelimited":
937 modularization = ColumnModularizeType.SemicolonDelimited;
938 break;
939 }
940 }
941
942 ColumnDefinition columnDefinition = new ColumnDefinition(name, type, length, primaryKey, nullable, modularization, ColumnType.Localized == type, minValSet, minValue, maxValSet, maxValue, keyTable, keyColumnSet, keyColumn, category, setValue, description, true, true);
943 columns.Add(columnDefinition);
944 }
945
946 TableDefinition customTable = new TableDefinition((string)row[0], columns, false, bootstrapperApplicationData, bootstrapperApplicationData);
947 customTableDefinitions.Add(customTable);
948 }
949 }
950#endif
951
952#if MOVE_TO_BACKEND 584#if MOVE_TO_BACKEND
953 /// <summary> 585 /// <summary>
954 /// Checks for any tables in the output which are not allowed in the output type. 586 /// Checks for any tables in the output which are not allowed in the output type.
@@ -973,14 +605,14 @@ namespace WixToolset.Core
973 { 605 {
974 foreach (Row row in table.Rows) 606 foreach (Row row in table.Rows)
975 { 607 {
976 this.OnMessage(WixErrors.UnexpectedTableInMergeModule(row.SourceLineNumbers, table.Name)); 608 this.Messaging.Write(WixErrors.UnexpectedTableInMergeModule(row.SourceLineNumbers, table.Name));
977 } 609 }
978 } 610 }
979 else if ("Error" == table.Name) 611 else if ("Error" == table.Name)
980 { 612 {
981 foreach (Row row in table.Rows) 613 foreach (Row row in table.Rows)
982 { 614 {
983 this.OnMessage(WixWarnings.DangerousTableInMergeModule(row.SourceLineNumbers, table.Name)); 615 this.Messaging.Write(WixWarnings.DangerousTableInMergeModule(row.SourceLineNumbers, table.Name));
984 } 616 }
985 } 617 }
986 break; 618 break;
@@ -1001,7 +633,7 @@ namespace WixToolset.Core
1001 { 633 {
1002 foreach (Row row in table.Rows) 634 foreach (Row row in table.Rows)
1003 { 635 {
1004 this.OnMessage(WixErrors.UnexpectedTableInPatchCreationPackage(row.SourceLineNumbers, table.Name)); 636 this.Messaging.Write(WixErrors.UnexpectedTableInPatchCreationPackage(row.SourceLineNumbers, table.Name));
1005 } 637 }
1006 } 638 }
1007 break; 639 break;
@@ -1014,7 +646,7 @@ namespace WixToolset.Core
1014 { 646 {
1015 foreach (Row row in table.Rows) 647 foreach (Row row in table.Rows)
1016 { 648 {
1017 this.OnMessage(WixErrors.UnexpectedTableInPatch(row.SourceLineNumbers, table.Name)); 649 this.Messaging.Write(WixErrors.UnexpectedTableInPatch(row.SourceLineNumbers, table.Name));
1018 } 650 }
1019 } 651 }
1020 break; 652 break;
@@ -1035,7 +667,7 @@ namespace WixToolset.Core
1035 { 667 {
1036 foreach (Row row in table.Rows) 668 foreach (Row row in table.Rows)
1037 { 669 {
1038 this.OnMessage(WixWarnings.UnexpectedTableInProduct(row.SourceLineNumbers, table.Name)); 670 this.Messaging.Write(WixWarnings.UnexpectedTableInProduct(row.SourceLineNumbers, table.Name));
1039 } 671 }
1040 } 672 }
1041 break; 673 break;
@@ -1080,7 +712,7 @@ namespace WixToolset.Core
1080 { 712 {
1081 foreach (Row row in isolatedComponentTable.Rows) 713 foreach (Row row in isolatedComponentTable.Rows)
1082 { 714 {
1083 this.OnMessage(WixWarnings.TableIncompatibleWithInstallerVersion(row.SourceLineNumbers, "IsolatedComponent", outputInstallerVersion)); 715 this.Messaging.Write(WixWarnings.TableIncompatibleWithInstallerVersion(row.SourceLineNumbers, "IsolatedComponent", outputInstallerVersion));
1084 } 716 }
1085 } 717 }
1086 } 718 }
@@ -1095,7 +727,7 @@ namespace WixToolset.Core
1095 { 727 {
1096 if (null != row[12] || null != row[13] || null != row[14] || null != row[15]) 728 if (null != row[12] || null != row[13] || null != row[14] || null != row[15])
1097 { 729 {
1098 this.OnMessage(WixWarnings.ColumnsIncompatibleWithInstallerVersion(row.SourceLineNumbers, "Shortcut", outputInstallerVersion)); 730 this.Messaging.Write(WixWarnings.ColumnsIncompatibleWithInstallerVersion(row.SourceLineNumbers, "Shortcut", outputInstallerVersion));
1099 } 731 }
1100 } 732 }
1101 } 733 }
@@ -1104,15 +736,6 @@ namespace WixToolset.Core
1104#endif 736#endif
1105 737
1106 /// <summary> 738 /// <summary>
1107 /// Sends a message to the message delegate if there is one.
1108 /// </summary>
1109 /// <param name="message">Message event arguments.</param>
1110 public void OnMessage(Message message)
1111 {
1112 this.Messaging.Write(message);
1113 }
1114
1115 /// <summary>
1116 /// Load the standard action symbols. 739 /// Load the standard action symbols.
1117 /// </summary> 740 /// </summary>
1118 /// <param name="symbols">Collection of symbols.</param> 741 /// <param name="symbols">Collection of symbols.</param>
@@ -1165,7 +788,7 @@ namespace WixToolset.Core
1165 { 788 {
1166 if (connection.IsExplicitPrimaryFeature) 789 if (connection.IsExplicitPrimaryFeature)
1167 { 790 {
1168 this.OnMessage(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), connection.PrimaryFeature ?? resolvedSection.Id)); 791 this.Messaging.Write(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), connection.PrimaryFeature ?? resolvedSection.Id));
1169 continue; 792 continue;
1170 } 793 }
1171 else 794 else
@@ -1197,7 +820,7 @@ namespace WixToolset.Core
1197 connection = featuresToFeatures[wixComplexReferenceRow.Child]; 820 connection = featuresToFeatures[wixComplexReferenceRow.Child];
1198 if (null != connection) 821 if (null != connection)
1199 { 822 {
1200 this.OnMessage(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id))); 823 this.Messaging.Write(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id)));
1201 continue; 824 continue;
1202 } 825 }
1203 826
@@ -1214,7 +837,7 @@ namespace WixToolset.Core
1214 { 837 {
1215 if (connection.IsExplicitPrimaryFeature) 838 if (connection.IsExplicitPrimaryFeature)
1216 { 839 {
1217 this.OnMessage(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id))); 840 this.Messaging.Write(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id)));
1218 continue; 841 continue;
1219 } 842 }
1220 else 843 else
@@ -1241,7 +864,7 @@ namespace WixToolset.Core
1241 case ComplexReferenceChildType.Component: 864 case ComplexReferenceChildType.Component:
1242 if (componentsToModules.ContainsKey(wixComplexReferenceRow.Child)) 865 if (componentsToModules.ContainsKey(wixComplexReferenceRow.Child))
1243 { 866 {
1244 this.OnMessage(ErrorMessages.ComponentReferencedTwice(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.Child)); 867 this.Messaging.Write(ErrorMessages.ComponentReferencedTwice(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.Child));
1245 continue; 868 continue;
1246 } 869 }
1247 else 870 else
@@ -1285,7 +908,7 @@ namespace WixToolset.Core
1285 connection = featuresToFeatures[wixComplexReferenceRow.Child]; 908 connection = featuresToFeatures[wixComplexReferenceRow.Child];
1286 if (null != connection) 909 if (null != connection)
1287 { 910 {
1288 this.OnMessage(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id))); 911 this.Messaging.Write(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id)));
1289 continue; 912 continue;
1290 } 913 }
1291 914
@@ -1470,7 +1093,7 @@ namespace WixToolset.Core
1470 // way up to present the loop as a directed graph. 1093 // way up to present the loop as a directed graph.
1471 var loop = String.Join(" -> ", loopDetector); 1094 var loop = String.Join(" -> ", loopDetector);
1472 1095
1473 this.OnMessage(ErrorMessages.ReferenceLoopDetected(wixComplexReferenceRow?.SourceLineNumbers, loop)); 1096 this.Messaging.Write(ErrorMessages.ReferenceLoopDetected(wixComplexReferenceRow?.SourceLineNumbers, loop));
1474 1097
1475 // Cleanup the parentGroupsNeedingProcessing and the loopDetector just like the 1098 // Cleanup the parentGroupsNeedingProcessing and the loopDetector just like the
1476 // exit of this method does at the end because we are exiting early. 1099 // exit of this method does at the end because we are exiting early.
@@ -1712,11 +1335,11 @@ namespace WixToolset.Core
1712 // display an error for the component or merge module as approrpriate 1335 // display an error for the component or merge module as approrpriate
1713 if (null != multipleFeatureComponents) 1336 if (null != multipleFeatureComponents)
1714 { 1337 {
1715 this.OnMessage(ErrorMessages.ComponentExpectedFeature(row.SourceLineNumbers, connectionId, row.Definition.Name, row.Id.Id)); 1338 this.Messaging.Write(ErrorMessages.ComponentExpectedFeature(row.SourceLineNumbers, connectionId, row.Definition.Name, row.Id.Id));
1716 } 1339 }
1717 else 1340 else
1718 { 1341 {
1719 this.OnMessage(ErrorMessages.MergeModuleExpectedFeature(row.SourceLineNumbers, connectionId)); 1342 this.Messaging.Write(ErrorMessages.MergeModuleExpectedFeature(row.SourceLineNumbers, connectionId));
1720 } 1343 }
1721 } 1344 }
1722 else 1345 else
@@ -1731,7 +1354,7 @@ namespace WixToolset.Core
1731 { 1354 {
1732 if (!multipleFeatureComponents.Contains(connectionId)) 1355 if (!multipleFeatureComponents.Contains(connectionId))
1733 { 1356 {
1734 this.OnMessage(WarningMessages.ImplicitComponentPrimaryFeature(connectionId)); 1357 this.Messaging.Write(WarningMessages.ImplicitComponentPrimaryFeature(connectionId));
1735 1358
1736 // remember this component so only one warning is generated for it 1359 // remember this component so only one warning is generated for it
1737 multipleFeatureComponents[connectionId] = null; 1360 multipleFeatureComponents[connectionId] = null;
@@ -1739,7 +1362,7 @@ namespace WixToolset.Core
1739 } 1362 }
1740 else 1363 else
1741 { 1364 {
1742 this.OnMessage(WarningMessages.ImplicitMergeModulePrimaryFeature(connectionId)); 1365 this.Messaging.Write(WarningMessages.ImplicitMergeModulePrimaryFeature(connectionId));
1743 } 1366 }
1744 } 1367 }
1745 1368
diff --git a/src/test/Example.Extension/Data/example.wir b/src/test/Example.Extension/Data/example.wir
index ba8ccbbe..8e32f901 100644
--- a/src/test/Example.Extension/Data/example.wir
+++ b/src/test/Example.Extension/Data/example.wir
Binary files differ
diff --git a/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs b/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
index 8535f69c..6ebdb993 100644
--- a/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
+++ b/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
@@ -252,7 +252,7 @@ namespace WixToolsetTest.CoreIntegration
252 } 252 }
253 } 253 }
254 254
255 [Fact(Skip = "Test demonstrates failure")] 255 [Fact]
256 public void PopulatesCustomTable1() 256 public void PopulatesCustomTable1()
257 { 257 {
258 var folder = TestData.Get(@"TestData"); 258 var folder = TestData.Get(@"TestData");
diff --git a/src/test/WixToolsetTest.CoreIntegration/WixiplFixture.cs b/src/test/WixToolsetTest.CoreIntegration/WixiplFixture.cs
index dd730501..668c273a 100644
--- a/src/test/WixToolsetTest.CoreIntegration/WixiplFixture.cs
+++ b/src/test/WixToolsetTest.CoreIntegration/WixiplFixture.cs
@@ -91,7 +91,7 @@ namespace WixToolsetTest.CoreIntegration
91 } 91 }
92 } 92 }
93 93
94 [Fact(Skip = "Test demonstrates failure")] 94 [Fact]
95 public void CanBuildMsiUsingExtensionLibrary() 95 public void CanBuildMsiUsingExtensionLibrary()
96 { 96 {
97 var folder = TestData.Get(@"TestData\Wixipl"); 97 var folder = TestData.Get(@"TestData\Wixipl");