Complete MOVE_TO_BACKEND code migration
Fixes wixtoolset/issues#6212
Rob Mensching committed
Mar 3, 2021 at 10:37 UTC
816bfd180f132a9b07aaa573f5ac0f5948195764
9 files changed
+338
-422
src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+2
-1
@@ -192,6 +192,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
192
command.Execute();
193
}
194
195
+ if (section.Type == SectionType.Product || section.Type == SectionType.Module)
196
{
197
var command = new AddRequiredStandardDirectories(section, platform);
198
command.Execute();
@@ -329,7 +330,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
330
331
if (dependencyRefs.Any())
332
{
332
- var command = new ProcessDependencyReferencesCommand(this.WindowsInstallerBackendHelper, section, dependencyRefs);
333
+ var command = new ProcessDependencyReferencesCommand(section, dependencyRefs);
334
command.Execute();
335
}
336
}
src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs
+295
-1
@@ -25,6 +25,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
25
this.TableDefinitions = tableDefinitions;
26
this.BackendExtensions = backendExtensions;
27
this.BackendHelper = backendHelper;
28
+ this.GeneratedShortNames = new Dictionary<string, List<FileSymbol>>();
29
}
30
31
private IEnumerable<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; }
@@ -37,6 +38,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
38
39
private IntermediateSection Section { get; }
40
41
+ private Dictionary<string, List<FileSymbol>> GeneratedShortNames { get; }
42
+
43
public WindowsInstallerData Data { get; private set; }
44
45
public WindowsInstallerData Execute()
@@ -136,6 +139,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
139
140
case SymbolDefinitionType.ModuleConfiguration:
141
this.AddModuleConfigurationSymbol((ModuleConfigurationSymbol)symbol);
142
+ this.EnsureModuleIgnoredTable(symbol, "ModuleConfiguration");
143
+ break;
144
+
145
+ case SymbolDefinitionType.ModuleSubstitution:
146
+ this.EnsureModuleIgnoredTable(symbol, "ModuleSubstitution");
147
break;
148
149
case SymbolDefinitionType.MsiEmbeddedUI:
@@ -262,6 +270,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
270
}
271
272
this.AddIndexedCellSymbols(cellsByTableAndRowId);
273
+ this.EnsureRequiredTables();
274
+ this.ReportGeneratedShortFileNameConflicts();
275
+ this.ReportIllegalTables();
276
+ this.ReportMismatchedModularizations();
277
+ this.ReportWindowsInstallerDataInconsistencies();
278
}
279
280
private void AddAssemblySymbol(AssemblySymbol symbol)
@@ -426,6 +439,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
439
row[2] = symbol.Source;
440
row[3] = symbol.Target;
441
row[4] = symbol.PatchUninstall ? (int?)WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall : null;
442
+
443
+ if (OutputType.Module == this.Data.Type)
444
+ {
445
+ this.Data.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]);
446
+ this.Data.EnsureTable(this.TableDefinitions["AdminUISequence"]);
447
+ this.Data.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]);
448
+ this.Data.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]);
449
+ this.Data.EnsureTable(this.TableDefinitions["InstallUISequence"]);
450
+ }
451
}
452
453
private void AddDialogSymbol(DialogSymbol symbol)
@@ -483,6 +505,38 @@ namespace WixToolset.Core.WindowsInstaller.Bind
505
row[0] = symbol.Id.Id;
506
row[1] = symbol.ParentDirectoryRef;
507
row[2] = defaultDir;
508
+
509
+ if (OutputType.Module == this.Data.Type)
510
+ {
511
+ var directoryId = symbol.Id.Id;
512
+
513
+ if (WindowsInstallerStandard.IsStandardDirectory(directoryId))
514
+ {
515
+ // If the directory table contains references to standard windows folders
516
+ // mergemod.dll will add customactions to set the MSM directory to
517
+ // the same directory as the standard windows folder and will add references to
518
+ // custom action to all the standard sequence tables. A problem will occur
519
+ // if the MSI does not have these tables as mergemod.dll does not add these
520
+ // tables to the MSI if absent. This code adds the tables in case mergemod.dll
521
+ // needs them.
522
+ this.Data.EnsureTable(this.TableDefinitions["CustomAction"]);
523
+ this.Data.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]);
524
+ this.Data.EnsureTable(this.TableDefinitions["AdminUISequence"]);
525
+ this.Data.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]);
526
+ this.Data.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]);
527
+ this.Data.EnsureTable(this.TableDefinitions["InstallUISequence"]);
528
+ }
529
+ else
530
+ {
531
+ foreach (var standardDirectory in WindowsInstallerStandard.StandardDirectories())
532
+ {
533
+ if (directoryId.StartsWith(standardDirectory.Id.Id, StringComparison.Ordinal))
534
+ {
535
+ this.Messaging.Write(WarningMessages.StandardDirectoryConflictInMergeModule(symbol.SourceLineNumbers, directoryId, standardDirectory.Id.Id));
536
+ }
537
+ }
538
+ }
539
+ }
540
}
541
542
private void AddDuplicateFileSymbol(DuplicateFileSymbol symbol)
@@ -570,6 +624,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
624
if (null == symbol.ShortName && null != name && !Common.IsValidShortFilename(name, false))
625
{
626
symbol.ShortName = CreateShortName(name, true, false, "File", symbol.DirectoryRef);
627
+
628
+ if (!this.GeneratedShortNames.TryGetValue(symbol.ShortName, out var potentialConflicts))
629
+ {
630
+ potentialConflicts = new List<FileSymbol>();
631
+ this.GeneratedShortNames.Add(symbol.ShortName, potentialConflicts);
632
+ }
633
+
634
+ potentialConflicts.Add(symbol);
635
}
636
637
var row = (FileRow)this.CreateRow(symbol, "File");
@@ -612,7 +674,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
674
var tableName = (IniFileActionType.AddLine == symbol.Action || IniFileActionType.AddTag == symbol.Action || IniFileActionType.CreateLine == symbol.Action) ? "IniFile" : "RemoveIniFile";
675
676
var name = symbol.FileName;
615
- if (null == symbol.ShortFileName && null != name && !Common.IsValidShortFilename(name, false))
677
+ if (null == symbol.ShortFileName && null != name && !Common.IsValidShortFilename(name, false))
678
{
679
symbol.ShortFileName = CreateShortName(name, true, false, "IniFile", symbol.ComponentRef);
680
}
@@ -1168,6 +1230,238 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1230
private bool AddSymbolDefaultly(IntermediateSymbol symbol) =>
1231
this.BackendHelper.TryAddSymbolToMatchingTableDefinitions(this.Section, symbol, this.Data, this.TableDefinitions);
1232
1233
+ private void EnsureModuleIgnoredTable(IntermediateSymbol symbol, string ignoredTable)
1234
+ {
1235
+ var tableDefinition = this.TableDefinitions["ModuleIgnoreTable"];
1236
+ var table = this.Data.EnsureTable(tableDefinition);
1237
+ if (!table.Rows.Any(r => r.FieldAsString(0) == ignoredTable))
1238
+ {
1239
+ var row = this.CreateRow(symbol, tableDefinition);
1240
+ row[0] = ignoredTable;
1241
+ }
1242
+ }
1243
+
1244
+ private void EnsureRequiredTables()
1245
+ {
1246
+ // check for missing table and add them or display an error as appropriate
1247
+ switch (this.Data.Type)
1248
+ {
1249
+ case OutputType.Module:
1250
+ this.Data.EnsureTable(this.TableDefinitions["Component"]);
1251
+ this.Data.EnsureTable(this.TableDefinitions["Directory"]);
1252
+ this.Data.EnsureTable(this.TableDefinitions["FeatureComponents"]);
1253
+ this.Data.EnsureTable(this.TableDefinitions["File"]);
1254
+ this.Data.EnsureTable(this.TableDefinitions["ModuleComponents"]);
1255
+ this.Data.EnsureTable(this.TableDefinitions["ModuleSignature"]);
1256
+ break;
1257
+
1258
+ case OutputType.PatchCreation:
1259
+ var imageFamiliesCount = this.Data.Tables["ImageFamilies"]?.Rows.Count ?? 0;
1260
+ var targetImagesCount = this.Data.Tables["TargetImages"]?.Rows.Count ?? 0;
1261
+ var upgradedImagesCount = this.Data.Tables["UpgradedImages"]?.Rows.Count ?? 0;
1262
+
1263
+ if (imageFamiliesCount < 1)
1264
+ {
1265
+ this.Messaging.Write(ErrorMessages.ExpectedRowInPatchCreationPackage("ImageFamilies"));
1266
+ }
1267
+
1268
+ if (targetImagesCount < 1)
1269
+ {
1270
+ this.Messaging.Write(ErrorMessages.ExpectedRowInPatchCreationPackage("TargetImages"));
1271
+ }
1272
+
1273
+ if (upgradedImagesCount < 1)
1274
+ {
1275
+ this.Messaging.Write(ErrorMessages.ExpectedRowInPatchCreationPackage("UpgradedImages"));
1276
+ }
1277
+
1278
+ this.Data.EnsureTable(this.TableDefinitions["Properties"]);
1279
+ break;
1280
+
1281
+ case OutputType.Product:
1282
+ this.Data.EnsureTable(this.TableDefinitions["File"]);
1283
+ this.Data.EnsureTable(this.TableDefinitions["Media"]);
1284
+ break;
1285
+ }
1286
+ }
1287
+
1288
+ private void ReportGeneratedShortFileNameConflicts()
1289
+ {
1290
+ foreach (var conflicts in this.GeneratedShortNames.Values.Where(l => l.Count > 1))
1291
+ {
1292
+ this.Messaging.Write(WarningMessages.GeneratedShortFileNameConflict(conflicts[0].SourceLineNumbers, conflicts[0].ShortName));
1293
+ for (var i = 1; i < conflicts.Count; ++i)
1294
+ {
1295
+ this.Messaging.Write(WarningMessages.GeneratedShortFileNameConflict2(conflicts[i].SourceLineNumbers));
1296
+ }
1297
+ }
1298
+ }
1299
+
1300
+ private void ReportIllegalTables()
1301
+ {
1302
+ foreach (var table in this.Data.Tables)
1303
+ {
1304
+ switch (this.Data.Type)
1305
+ {
1306
+ case OutputType.Module:
1307
+ if ("BBControl" == table.Name ||
1308
+ "Billboard" == table.Name ||
1309
+ "CCPSearch" == table.Name ||
1310
+ "Feature" == table.Name ||
1311
+ "LaunchCondition" == table.Name ||
1312
+ "Media" == table.Name ||
1313
+ "Patch" == table.Name ||
1314
+ "Upgrade" == table.Name ||
1315
+ "WixMerge" == table.Name)
1316
+ {
1317
+ foreach (Row row in table.Rows)
1318
+ {
1319
+ this.Messaging.Write(ErrorMessages.UnexpectedTableInMergeModule(row.SourceLineNumbers, table.Name));
1320
+ }
1321
+ }
1322
+ else if ("Error" == table.Name)
1323
+ {
1324
+ foreach (var row in table.Rows)
1325
+ {
1326
+ this.Messaging.Write(WarningMessages.DangerousTableInMergeModule(row.SourceLineNumbers, table.Name));
1327
+ }
1328
+ }
1329
+ break;
1330
+
1331
+ case OutputType.PatchCreation:
1332
+ if (!table.Definition.Unreal &&
1333
+ "_SummaryInformation" != table.Name &&
1334
+ "ExternalFiles" != table.Name &&
1335
+ "FamilyFileRanges" != table.Name &&
1336
+ "ImageFamilies" != table.Name &&
1337
+ "PatchMetadata" != table.Name &&
1338
+ "PatchSequence" != table.Name &&
1339
+ "Properties" != table.Name &&
1340
+ "TargetFiles_OptionalData" != table.Name &&
1341
+ "TargetImages" != table.Name &&
1342
+ "UpgradedFiles_OptionalData" != table.Name &&
1343
+ "UpgradedFilesToIgnore" != table.Name &&
1344
+ "UpgradedImages" != table.Name)
1345
+ {
1346
+ foreach (var row in table.Rows)
1347
+ {
1348
+ this.Messaging.Write(ErrorMessages.UnexpectedTableInPatchCreationPackage(row.SourceLineNumbers, table.Name));
1349
+ }
1350
+ }
1351
+ break;
1352
+
1353
+ case OutputType.Patch:
1354
+ if (!table.Definition.Unreal &&
1355
+ "_SummaryInformation" != table.Name &&
1356
+ "Media" != table.Name &&
1357
+ "MsiFileHash" != table.Name &&
1358
+ "MsiPatchMetadata" != table.Name &&
1359
+ "MsiPatchSequence" != table.Name)
1360
+ {
1361
+ foreach (var row in table.Rows)
1362
+ {
1363
+ this.Messaging.Write(ErrorMessages.UnexpectedTableInPatch(row.SourceLineNumbers, table.Name));
1364
+ }
1365
+ }
1366
+ break;
1367
+
1368
+ case OutputType.Product:
1369
+ if ("ModuleAdminExecuteSequence" == table.Name ||
1370
+ "ModuleAdminUISequence" == table.Name ||
1371
+ "ModuleAdvtExecuteSequence" == table.Name ||
1372
+ "ModuleAdvtUISequence" == table.Name ||
1373
+ "ModuleComponents" == table.Name ||
1374
+ "ModuleConfiguration" == table.Name ||
1375
+ "ModuleDependency" == table.Name ||
1376
+ "ModuleExclusion" == table.Name ||
1377
+ "ModuleIgnoreTable" == table.Name ||
1378
+ "ModuleInstallExecuteSequence" == table.Name ||
1379
+ "ModuleInstallUISequence" == table.Name ||
1380
+ "ModuleSignature" == table.Name ||
1381
+ "ModuleSubstitution" == table.Name)
1382
+ {
1383
+ foreach (var row in table.Rows)
1384
+ {
1385
+ this.Messaging.Write(WarningMessages.UnexpectedTableInProduct(row.SourceLineNumbers, table.Name));
1386
+ }
1387
+ }
1388
+ break;
1389
+ }
1390
+ }
1391
+ }
1392
+
1393
+ private void ReportMismatchedModularizations()
1394
+ {
1395
+ // verify that modularization types match for foreign key relationships
1396
+ foreach (var tableDefinition in this.TableDefinitions)
1397
+ {
1398
+ foreach (var columnDefinition in tableDefinition.Columns)
1399
+ {
1400
+ if (null != columnDefinition.KeyTable && 0 > columnDefinition.KeyTable.IndexOf(';') && columnDefinition.KeyColumn.HasValue)
1401
+ {
1402
+ if (this.TableDefinitions.TryGet(columnDefinition.KeyTable, out var keyTableDefinition))
1403
+ {
1404
+ var keyColumnIndex = columnDefinition.KeyColumn ?? -1;
1405
+
1406
+ if (keyColumnIndex <= 0 || keyColumnIndex > keyTableDefinition.Columns.Length)
1407
+ {
1408
+ this.Messaging.Write(ErrorMessages.InvalidKeyColumn(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, keyColumnIndex));
1409
+ }
1410
+ else if (keyTableDefinition.Columns[keyColumnIndex - 1].ModularizeType != columnDefinition.ModularizeType && ColumnModularizeType.CompanionFile != columnDefinition.ModularizeType)
1411
+ {
1412
+ this.Messaging.Write(ErrorMessages.CollidingModularizationTypes(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, keyColumnIndex, columnDefinition.ModularizeType.ToString(), keyTableDefinition.Columns[keyColumnIndex - 1].ModularizeType.ToString()));
1413
+ }
1414
+ }
1415
+ // else - ignore missing table definitions as that error is caught in other places
1416
+ }
1417
+ }
1418
+ }
1419
+ }
1420
+
1421
+ private void ReportWindowsInstallerDataInconsistencies()
1422
+ {
1423
+ // Get the output's minimum installer version
1424
+ var outputInstallerVersion = Int32.MaxValue;
1425
+
1426
+ if (this.Data.Tables.TryGetTable("_SummaryInformation", out var summaryInformationTable))
1427
+ {
1428
+ outputInstallerVersion = summaryInformationTable.Rows.FirstOrDefault(r => 14 == r.FieldAsInteger(0))?.FieldAsInteger(1) ?? Int32.MaxValue;
1429
+ }
1430
+
1431
+ // Ensure the Error table exists if output is marked for MSI 1.0 or below (see ICE40).
1432
+ if (outputInstallerVersion <= 100 && OutputType.Product == this.Data.Type)
1433
+ {
1434
+ this.Data.EnsureTable(this.TableDefinitions["Error"]);
1435
+ }
1436
+
1437
+ // Check for the presence of tables/rows/columns that require MSI 1.1 or later.
1438
+ if (outputInstallerVersion < 110)
1439
+ {
1440
+ if (this.Data.Tables.TryGetTable("IsolatedComponent", out var isolatedComponentTable))
1441
+ {
1442
+ foreach (var row in isolatedComponentTable.Rows)
1443
+ {
1444
+ this.Messaging.Write(WarningMessages.TableIncompatibleWithInstallerVersion(row.SourceLineNumbers, "IsolatedComponent", outputInstallerVersion));
1445
+ }
1446
+ }
1447
+ }
1448
+
1449
+ // Check for the presence of tables/rows/columns that require MSI 4.0 or later
1450
+ if (outputInstallerVersion < 400)
1451
+ {
1452
+ if (this.Data.Tables.TryGetTable("Shortcut", out var shortcutTable))
1453
+ {
1454
+ foreach (var row in shortcutTable.Rows)
1455
+ {
1456
+ if (null != row[12] || null != row[13] || null != row[14] || null != row[15])
1457
+ {
1458
+ this.Messaging.Write(WarningMessages.ColumnsIncompatibleWithInstallerVersion(row.SourceLineNumbers, "Shortcut", outputInstallerVersion));
1459
+ }
1460
+ }
1461
+ }
1462
+ }
1463
+ }
1464
+
1465
private static OutputType SectionTypeToOutputType(SectionType type)
1466
{
1467
switch (type)
src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs
+8
-4
@@ -36,7 +36,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
36
{
37
var canonicalComponentTargetPaths = this.ComponentTargetPaths();
38
39
- this.FileFacades.Sort(new FileFacadeOptimizer(canonicalComponentTargetPaths));
39
+ this.FileFacades.Sort(new FileFacadeOptimizer(canonicalComponentTargetPaths, this.Section.Type == SectionType.Module));
40
41
return this.FileFacades;
42
}
@@ -71,17 +71,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
71
72
private class FileFacadeOptimizer : IComparer<FileFacade>
73
{
74
- public FileFacadeOptimizer(Dictionary<string, string> componentTargetPaths)
74
+ public FileFacadeOptimizer(Dictionary<string, string> componentTargetPaths, bool optimizingMergeModule)
75
{
76
this.ComponentTargetPaths = componentTargetPaths;
77
+ this.OptimizingMergeModule = optimizingMergeModule;
78
}
79
80
private Dictionary<string, string> ComponentTargetPaths { get; }
81
82
+ private bool OptimizingMergeModule { get; }
83
+
84
public int Compare(FileFacade x, FileFacade y)
85
{
83
- // First group files by DiskId.
84
- var compare = x.DiskId.CompareTo(y.DiskId);
86
+ // First group files by DiskId but ignore if processing a Merge Module
87
+ // because Merge Modules don't have separate disks.
88
+ var compare = this.OptimizingMergeModule ? 0 : x.DiskId.CompareTo(y.DiskId);
89
90
if (compare != 0)
91
{
src/WixToolset.Core.WindowsInstaller/Bind/ProcessDependencyReferencesCommand.cs
+1
-1
@@ -17,7 +17,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
17
private const string DependencyRegistryRoot = @"Software\Classes\Installer\Dependencies\";
18
private const string RegistryDependents = "Dependents";
19
20
- public ProcessDependencyReferencesCommand(IWindowsInstallerBackendHelper backendHelper, IntermediateSection section, IEnumerable<WixDependencyRefSymbol> dependencyRefSymbols)
20
+ public ProcessDependencyReferencesCommand(IntermediateSection section, IEnumerable<WixDependencyRefSymbol> dependencyRefSymbols)
21
{
22
this.Section = section;
23
this.DependencyRefSymbols = dependencyRefSymbols;
src/WixToolset.Core/Compiler.cs
+2
-2
@@ -7178,7 +7178,7 @@ namespace WixToolset.Core
7178
cabinet = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
7179
break;
7180
case "CompressionLevel":
7181
- compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, node, attrib);
7181
+ compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, attrib);
7182
break;
7183
case "DiskPrompt":
7184
diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
@@ -7381,7 +7381,7 @@ namespace WixToolset.Core
7381
}
7382
break;
7383
case "CompressionLevel":
7384
- compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, node, attrib);
7384
+ compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, attrib);
7385
break;
7386
case "DiskPrompt":
7387
diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
src/WixToolset.Core/Compiler_Package.cs
+1
-1
@@ -4950,7 +4950,7 @@ namespace WixToolset.Core
4950
}
4951
}
4952
4953
- private CompressionLevel? ParseCompressionLevel(SourceLineNumber sourceLineNumbers, XElement node, XAttribute attribute)
4953
+ private CompressionLevel? ParseCompressionLevel(SourceLineNumber sourceLineNumbers, XAttribute attribute)
4954
{
4955
var compressionLevel = this.Core.GetAttributeValue(sourceLineNumbers, attribute);
4956
switch (compressionLevel)
src/WixToolset.Core/Linker.cs
+26
-409
@@ -93,52 +93,12 @@ namespace WixToolset.Core
93
}
94
}
95
96
-#if MOVE_TO_BACKEND
97
- bool containsModuleSubstitution = false;
98
- bool containsModuleConfiguration = false;
99
-#endif
100
-
96
//this.activeOutput = null;
97
103
-#if MOVE_TO_BACKEND
104
- StringCollection generatedShortFileNameIdentifiers = new StringCollection();
105
- Hashtable generatedShortFileNames = new Hashtable();
106
-#endif
107
-
98
var multipleFeatureComponents = new Hashtable();
99
100
var wixVariables = new Dictionary<string, WixVariableSymbol>();
101
112
-#if MOVE_TO_BACKEND
113
- // verify that modularization types match for foreign key relationships
114
- foreach (TableDefinition tableDefinition in this.tableDefinitions)
115
- {
116
- foreach (ColumnDefinition columnDefinition in tableDefinition.Columns)
117
- {
118
- if (null != columnDefinition.KeyTable && 0 > columnDefinition.KeyTable.IndexOf(';') && columnDefinition.IsKeyColumnSet)
119
- {
120
- try
121
- {
122
- TableDefinition keyTableDefinition = this.tableDefinitions[columnDefinition.KeyTable];
123
-
124
- if (0 >= columnDefinition.KeyColumn || keyTableDefinition.Columns.Count < columnDefinition.KeyColumn)
125
- {
126
- this.Messaging.Write(WixErrors.InvalidKeyColumn(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn));
127
- }
128
- else if (keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType != columnDefinition.ModularizeType && ColumnModularizeType.CompanionFile != columnDefinition.ModularizeType)
129
- {
130
- this.Messaging.Write(WixErrors.CollidingModularizationTypes(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn, columnDefinition.ModularizeType.ToString(), keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType.ToString()));
131
- }
132
- }
133
- catch (WixMissingTableDefinitionException)
134
- {
135
- // ignore missing table definitions - this error is caught in other places
136
- }
137
- }
138
- }
139
- }
140
-#endif
141
-
102
// First find the entry section and while processing all sections load all the symbols from all of the sections.
103
var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, sections, this.Context.ExpectedOutputType);
104
find.Execute();
@@ -211,7 +171,8 @@ namespace WixToolset.Core
171
// resolve the feature to feature connects
172
this.ResolveFeatureToFeatureConnects(featuresToFeatures, find.SymbolsByName);
173
214
- // Create the section to hold the linked content.
174
+ // Create a new section to hold the linked content. Start with the entry section's
175
+ // metadata.
176
var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type, find.EntrySection.Codepage);
177
178
var sectionCount = 0;
@@ -245,54 +206,6 @@ namespace WixToolset.Core
206
}
207
break;
208
248
-#if MOVE_TO_BACKEND
249
- case "CustomAction":
250
- if (OutputType.Module == this.activeOutput.Type)
251
- {
252
- this.activeOutput.EnsureTable(this.tableDefinitions["AdminExecuteSequence"]);
253
- this.activeOutput.EnsureTable(this.tableDefinitions["AdminUISequence"]);
254
- this.activeOutput.EnsureTable(this.tableDefinitions["AdvtExecuteSequence"]);
255
- this.activeOutput.EnsureTable(this.tableDefinitions["InstallExecuteSequence"]);
256
- this.activeOutput.EnsureTable(this.tableDefinitions["InstallUISequence"]);
257
- }
258
- break;
259
-
260
- case "Directory":
261
- foreach (Row row in table.Rows)
262
- {
263
- if (OutputType.Module == this.activeOutput.Type)
264
- {
265
- string directory = row[0].ToString();
266
- if (WindowsInstallerStandard.IsStandardDirectory(directory))
267
- {
268
- // if the directory table contains references to standard windows folders
269
- // mergemod.dll will add customactions to set the MSM directory to
270
- // the same directory as the standard windows folder and will add references to
271
- // custom action to all the standard sequence tables. A problem will occur
272
- // if the MSI does not have these tables as mergemod.dll does not add these
273
- // tables to the MSI if absent. This code adds the tables in case mergemod.dll
274
- // needs them.
275
- this.activeOutput.EnsureTable(this.tableDefinitions["CustomAction"]);
276
- this.activeOutput.EnsureTable(this.tableDefinitions["AdminExecuteSequence"]);
277
- this.activeOutput.EnsureTable(this.tableDefinitions["AdminUISequence"]);
278
- this.activeOutput.EnsureTable(this.tableDefinitions["AdvtExecuteSequence"]);
279
- this.activeOutput.EnsureTable(this.tableDefinitions["InstallExecuteSequence"]);
280
- this.activeOutput.EnsureTable(this.tableDefinitions["InstallUISequence"]);
281
- }
282
- else
283
- {
284
- foreach (string standardDirectory in WindowsInstallerStandard.GetStandardDirectories())
285
- {
286
- if (directory.StartsWith(standardDirectory, StringComparison.Ordinal))
287
- {
288
- this.Messaging.Write(WixWarnings.StandardDirectoryConflictInMergeModule(row.SourceLineNumbers, directory, standardDirectory));
289
- }
290
- }
291
- }
292
- }
293
- }
294
- break;
295
-#endif
209
case SymbolDefinitionType.Extension:
210
if (SectionType.Product == resolvedSection.Type)
211
{
@@ -300,16 +213,6 @@ namespace WixToolset.Core
213
}
214
break;
215
303
-#if MOVE_TO_BACKEND
304
- case SymbolDefinitionType.ModuleSubstitution:
305
- containsModuleSubstitution = true;
306
- break;
307
-
308
- case SymbolDefinitionType.ModuleConfiguration:
309
- containsModuleConfiguration = true;
310
- break;
311
-#endif
312
-
216
case SymbolDefinitionType.Assembly:
217
if (SectionType.Product == resolvedSection.Type)
218
{
@@ -338,26 +241,6 @@ namespace WixToolset.Core
241
}
242
break;
243
341
-#if MOVE_TO_BACKEND
342
- case "WixFile":
343
- foreach (Row row in table.Rows)
344
- {
345
- // DiskId is not valid when creating a module, so set it to
346
- // 0 for all files to ensure proper sorting in the binder
347
- if (SectionType.Module == entrySection.Type)
348
- {
349
- row[5] = 0;
350
- }
351
-
352
- // if the short file name was generated, check for collisions
353
- if (0x1 == (int)row[9])
354
- {
355
- generatedShortFileNameIdentifiers.Add((string)row[0]);
356
- }
357
- }
358
- break;
359
-#endif
360
-
244
case SymbolDefinitionType.WixMerge:
245
if (SectionType.Product == resolvedSection.Type)
246
{
@@ -374,30 +257,9 @@ namespace WixToolset.Core
257
break;
258
259
case SymbolDefinitionType.WixVariable:
377
- // check for colliding values and collect the wix variable rows
378
- {
379
- var wixVariableSymbol = (WixVariableSymbol)symbol;
380
- var id = wixVariableSymbol.Id.Id;
381
-
382
- if (wixVariables.TryGetValue(id, out var collidingSymbol))
383
- {
384
- if (collidingSymbol.Overridable && !wixVariableSymbol.Overridable)
385
- {
386
- wixVariables[id] = wixVariableSymbol;
387
- }
388
- else if (!wixVariableSymbol.Overridable || (collidingSymbol.Overridable && wixVariableSymbol.Overridable))
389
- {
390
- this.Messaging.Write(ErrorMessages.WixVariableCollision(wixVariableSymbol.SourceLineNumbers, id));
391
- }
392
- }
393
- else
394
- {
395
- wixVariables.Add(id, wixVariableSymbol);
396
- }
397
- }
398
-
399
- copySymbol = false;
400
- break;
260
+ this.AddWixVariable(wixVariables, (WixVariableSymbol)symbol);
261
+ copySymbol = false; // Do not copy the symbol, it will be added later after all overriding has been handled.
262
+ break;
263
}
264
265
if (copySymbol)
@@ -407,7 +269,7 @@ namespace WixToolset.Core
269
}
270
}
271
410
- // copy the module to feature connections into the output
272
+ // Copy the module to feature connections into the output.
273
foreach (ConnectToFeature connectToFeature in modulesToFeatures)
274
{
275
foreach (var feature in connectToFeature.ConnectFeatures)
@@ -420,136 +282,23 @@ namespace WixToolset.Core
282
}
283
}
284
423
-#if MOVE_TO_BACKEND
424
- // check for missing table and add them or display an error as appropriate
425
- switch (this.activeOutput.Type)
426
- {
427
- case OutputType.Module:
428
- this.activeOutput.EnsureTable(this.tableDefinitions["Component"]);
429
- this.activeOutput.EnsureTable(this.tableDefinitions["Directory"]);
430
- this.activeOutput.EnsureTable(this.tableDefinitions["FeatureComponents"]);
431
- this.activeOutput.EnsureTable(this.tableDefinitions["File"]);
432
- this.activeOutput.EnsureTable(this.tableDefinitions["ModuleComponents"]);
433
- this.activeOutput.EnsureTable(this.tableDefinitions["ModuleSignature"]);
434
- break;
435
- case OutputType.PatchCreation:
436
- Table imageFamiliesTable = this.activeOutput.Tables["ImageFamilies"];
437
- Table targetImagesTable = this.activeOutput.Tables["TargetImages"];
438
- Table upgradedImagesTable = this.activeOutput.Tables["UpgradedImages"];
439
-
440
- if (null == imageFamiliesTable || 1 > imageFamiliesTable.Rows.Count)
441
- {
442
- this.Messaging.Write(WixErrors.ExpectedRowInPatchCreationPackage("ImageFamilies"));
443
- }
444
-
445
- if (null == targetImagesTable || 1 > targetImagesTable.Rows.Count)
446
- {
447
- this.Messaging.Write(WixErrors.ExpectedRowInPatchCreationPackage("TargetImages"));
448
- }
449
-
450
- if (null == upgradedImagesTable || 1 > upgradedImagesTable.Rows.Count)
451
- {
452
- this.Messaging.Write(WixErrors.ExpectedRowInPatchCreationPackage("UpgradedImages"));
453
- }
454
-
455
- this.activeOutput.EnsureTable(this.tableDefinitions["Properties"]);
456
- break;
457
- case OutputType.Product:
458
- this.activeOutput.EnsureTable(this.tableDefinitions["File"]);
459
- this.activeOutput.EnsureTable(this.tableDefinitions["Media"]);
460
- break;
461
- }
462
-
463
- this.CheckForIllegalTables(this.activeOutput);
464
-#endif
465
-
466
- //correct the section Id in FeatureComponents table
285
+ // Correct the section Id in FeatureComponents table.
286
if (this.sectionIdOnRows)
287
{
469
- //var componentSectionIds = new Dictionary<string, string>();
470
-
471
- //foreach (var componentSymbol in entrySection.Symbols.OfType<ComponentSymbol>())
472
- //{
473
- // componentSectionIds.Add(componentSymbol.Id.Id, componentSymbol.SectionId);
474
- //}
475
-
476
- //foreach (var featureComponentSymbol in entrySection.Symbols.OfType<FeatureComponentsSymbol>())
477
- //{
478
- // if (componentSectionIds.TryGetValue(featureComponentSymbol.Component_, out var componentSectionId))
479
- // {
480
- // featureComponentSymbol.SectionId = componentSectionId;
481
- // }
482
- //}
483
- }
484
-
485
-#if MOVE_TO_BACKEND
486
- // add the ModuleSubstitution table to the ModuleIgnoreTable
487
- if (containsModuleSubstitution)
488
- {
489
- Table moduleIgnoreTableTable = this.activeOutput.EnsureTable(this.tableDefinitions["ModuleIgnoreTable"]);
490
-
491
- Row moduleIgnoreTableRow = moduleIgnoreTableTable.CreateRow(null);
492
- moduleIgnoreTableRow[0] = "ModuleSubstitution";
493
- }
494
-
495
- // add the ModuleConfiguration table to the ModuleIgnoreTable
496
- if (containsModuleConfiguration)
497
- {
498
- Table moduleIgnoreTableTable = this.activeOutput.EnsureTable(this.tableDefinitions["ModuleIgnoreTable"]);
499
-
500
- Row moduleIgnoreTableRow = moduleIgnoreTableTable.CreateRow(null);
501
- moduleIgnoreTableRow[0] = "ModuleConfiguration";
502
- }
503
-#endif
504
-
505
-#if MOVE_TO_BACKEND
506
- // index all the file rows
507
- Table fileTable = this.activeOutput.Tables["File"];
508
- RowDictionary<FileRow> indexedFileRows = (null == fileTable) ? new RowDictionary<FileRow>() : new RowDictionary<FileRow>(fileTable);
509
-
510
- // flag all the generated short file name collisions
511
- foreach (string fileId in generatedShortFileNameIdentifiers)
512
- {
513
- FileRow fileRow = indexedFileRows[fileId];
514
-
515
- string[] names = fileRow.FileName.Split('|');
516
- string shortFileName = names[0];
288
+#if TODO_DO_SYMBOLS_NEED_SECTIONIDS
289
+ var componentSectionIds = resolvedSection.Symbols.OfType<ComponentSymbol>().ToDictionary(c => c.Id.Id, c => c.SectionId);
290
518
- // create lists of conflicting generated short file names
519
- if (!generatedShortFileNames.Contains(shortFileName))
291
+ foreach (var featureComponentSymbol in resolvedSection.Symbols.OfType<FeatureComponentsSymbol>())
292
{
521
- generatedShortFileNames.Add(shortFileName, new ArrayList());
522
- }
523
- ((ArrayList)generatedShortFileNames[shortFileName]).Add(fileRow);
524
- }
525
-
526
- // check for generated short file name collisions
527
- foreach (DictionaryEntry entry in generatedShortFileNames)
528
- {
529
- string shortFileName = (string)entry.Key;
530
- ArrayList fileRows = (ArrayList)entry.Value;
531
-
532
- if (1 < fileRows.Count)
533
- {
534
- // sort the rows by DiskId
535
- fileRows.Sort();
536
-
537
- this.Messaging.Write(WixWarnings.GeneratedShortFileNameConflict(((FileRow)fileRows[0]).SourceLineNumbers, shortFileName));
538
-
539
- for (int i = 1; i < fileRows.Count; i++)
293
+ if (componentSectionIds.TryGetValue(featureComponentSymbol.ComponentRef, out var componentSectionId))
294
{
541
- FileRow fileRow = (FileRow)fileRows[i];
542
-
543
- if (null != fileRow.SourceLineNumbers)
544
- {
545
- this.Messaging.Write(WixWarnings.GeneratedShortFileNameConflict2(fileRow.SourceLineNumbers));
546
- }
295
+ featureComponentSymbol.SectionId = componentSectionId;
296
}
297
}
549
- }
298
#endif
299
+ }
300
552
- // copy the wix variable rows to the output after all overriding has been accounted for.
301
+ // Copy the wix variable rows to the output now that all overriding has been accounted for.
302
foreach (var symbol in wixVariables.Values)
303
{
304
resolvedSection.AddSymbol(symbol);
@@ -567,10 +316,6 @@ namespace WixToolset.Core
316
var localizationsByCulture = collate.Execute();
317
318
intermediate = new Intermediate(resolvedSection.Id, Data.IntermediateLevels.Linked, new[] { resolvedSection }, localizationsByCulture);
570
-
571
-#if MOVE_TO_BACKEND
572
- this.CheckOutputConsistency(output);
573
-#endif
319
}
320
finally
321
{
@@ -583,159 +328,31 @@ namespace WixToolset.Core
328
return this.Messaging.EncounteredError ? null : intermediate;
329
}
330
586
-#if MOVE_TO_BACKEND
331
/// <summary>
588
- /// Checks for any tables in the output which are not allowed in the output type.
332
+ /// Check for colliding values and collect the wix variable rows.
333
/// </summary>
590
- /// <param name="output">The output to check.</param>
591
- private void CheckForIllegalTables(Output output)
334
+ /// <param name="wixVariables">Collection of WixVariableSymbols by id.</param>
335
+ /// <param name="symbol">WixVariableSymbol to add, if not overridden.</param>
336
+ private void AddWixVariable(Dictionary<string, WixVariableSymbol> wixVariables, WixVariableSymbol symbol)
337
{
593
- foreach (Table table in output.Tables)
594
- {
595
- switch (output.Type)
596
- {
597
- case OutputType.Module:
598
- if ("BBControl" == table.Name ||
599
- "Billboard" == table.Name ||
600
- "CCPSearch" == table.Name ||
601
- "Feature" == table.Name ||
602
- "LaunchCondition" == table.Name ||
603
- "Media" == table.Name ||
604
- "Patch" == table.Name ||
605
- "Upgrade" == table.Name ||
606
- "WixMerge" == table.Name)
607
- {
608
- foreach (Row row in table.Rows)
609
- {
610
- this.Messaging.Write(WixErrors.UnexpectedTableInMergeModule(row.SourceLineNumbers, table.Name));
611
- }
612
- }
613
- else if ("Error" == table.Name)
614
- {
615
- foreach (Row row in table.Rows)
616
- {
617
- this.Messaging.Write(WixWarnings.DangerousTableInMergeModule(row.SourceLineNumbers, table.Name));
618
- }
619
- }
620
- break;
621
- case OutputType.PatchCreation:
622
- if (!table.Definition.Unreal &&
623
- "_SummaryInformation" != table.Name &&
624
- "ExternalFiles" != table.Name &&
625
- "FamilyFileRanges" != table.Name &&
626
- "ImageFamilies" != table.Name &&
627
- "PatchMetadata" != table.Name &&
628
- "PatchSequence" != table.Name &&
629
- "Properties" != table.Name &&
630
- "TargetFiles_OptionalData" != table.Name &&
631
- "TargetImages" != table.Name &&
632
- "UpgradedFiles_OptionalData" != table.Name &&
633
- "UpgradedFilesToIgnore" != table.Name &&
634
- "UpgradedImages" != table.Name)
635
- {
636
- foreach (Row row in table.Rows)
637
- {
638
- this.Messaging.Write(WixErrors.UnexpectedTableInPatchCreationPackage(row.SourceLineNumbers, table.Name));
639
- }
640
- }
641
- break;
642
- case OutputType.Patch:
643
- if (!table.Definition.Unreal &&
644
- "_SummaryInformation" != table.Name &&
645
- "Media" != table.Name &&
646
- "MsiPatchMetadata" != table.Name &&
647
- "MsiPatchSequence" != table.Name)
648
- {
649
- foreach (Row row in table.Rows)
650
- {
651
- this.Messaging.Write(WixErrors.UnexpectedTableInPatch(row.SourceLineNumbers, table.Name));
652
- }
653
- }
654
- break;
655
- case OutputType.Product:
656
- if ("ModuleAdminExecuteSequence" == table.Name ||
657
- "ModuleAdminUISequence" == table.Name ||
658
- "ModuleAdvtExecuteSequence" == table.Name ||
659
- "ModuleAdvtUISequence" == table.Name ||
660
- "ModuleComponents" == table.Name ||
661
- "ModuleConfiguration" == table.Name ||
662
- "ModuleDependency" == table.Name ||
663
- "ModuleExclusion" == table.Name ||
664
- "ModuleIgnoreTable" == table.Name ||
665
- "ModuleInstallExecuteSequence" == table.Name ||
666
- "ModuleInstallUISequence" == table.Name ||
667
- "ModuleSignature" == table.Name ||
668
- "ModuleSubstitution" == table.Name)
669
- {
670
- foreach (Row row in table.Rows)
671
- {
672
- this.Messaging.Write(WixWarnings.UnexpectedTableInProduct(row.SourceLineNumbers, table.Name));
673
- }
674
- }
675
- break;
676
- }
677
- }
678
- }
679
-#endif
338
+ var id = symbol.Id.Id;
339
681
-#if MOVE_TO_BACKEND
682
- /// <summary>
683
- /// Performs various consistency checks on the output.
684
- /// </summary>
685
- /// <param name="output">Output containing instance transform definitions.</param>
686
- private void CheckOutputConsistency(Output output)
687
- {
688
- // Get the output's minimum installer version
689
- int outputInstallerVersion = int.MinValue;
690
- Table summaryInformationTable = output.Tables["_SummaryInformation"];
691
- if (null != summaryInformationTable)
340
+ if (wixVariables.TryGetValue(id, out var collidingSymbol))
341
{
693
- foreach (Row row in summaryInformationTable.Rows)
342
+ if (collidingSymbol.Overridable && !symbol.Overridable)
343
{
695
- if (14 == (int)row[0])
696
- {
697
- outputInstallerVersion = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
698
- break;
699
- }
344
+ wixVariables[id] = symbol;
345
}
701
- }
702
-
703
- // ensure the Error table exists if output is marked for MSI 1.0 or below (see ICE40)
704
- if (100 >= outputInstallerVersion && OutputType.Product == output.Type)
705
- {
706
- output.EnsureTable(this.tableDefinitions["Error"]);
707
- }
708
-
709
- // check for the presence of tables/rows/columns that require MSI 1.1 or later
710
- if (110 > outputInstallerVersion)
711
- {
712
- Table isolatedComponentTable = output.Tables["IsolatedComponent"];
713
- if (null != isolatedComponentTable)
346
+ else if (!symbol.Overridable || (collidingSymbol.Overridable && symbol.Overridable))
347
{
715
- foreach (Row row in isolatedComponentTable.Rows)
716
- {
717
- this.Messaging.Write(WixWarnings.TableIncompatibleWithInstallerVersion(row.SourceLineNumbers, "IsolatedComponent", outputInstallerVersion));
718
- }
348
+ this.Messaging.Write(ErrorMessages.WixVariableCollision(symbol.SourceLineNumbers, id));
349
}
350
}
721
-
722
- // check for the presence of tables/rows/columns that require MSI 4.0 or later
723
- if (400 > outputInstallerVersion)
351
+ else
352
{
725
- Table shortcutTable = output.Tables["Shortcut"];
726
- if (null != shortcutTable)
727
- {
728
- foreach (Row row in shortcutTable.Rows)
729
- {
730
- if (null != row[12] || null != row[13] || null != row[14] || null != row[15])
731
- {
732
- this.Messaging.Write(WixWarnings.ColumnsIncompatibleWithInstallerVersion(row.SourceLineNumbers, "Shortcut", outputInstallerVersion));
733
- }
734
- }
735
- }
353
+ wixVariables.Add(id, symbol);
354
}
355
}
738
-#endif
356
357
/// <summary>
358
/// Load the standard action and directory symbols.
src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
+1
-1
@@ -1022,7 +1022,7 @@ namespace WixToolsetTest.CoreIntegration
1022
Assert.Empty(section.Symbols.OfType<FileSymbol>());
1023
1024
var data = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
1025
- Assert.Null(data.Tables["File"]);
1025
+ Assert.Empty(data.Tables["File"].Rows);
1026
1027
var results = Query.QueryDatabase(msiPath, new[] { "File" });
1028
WixAssert.CompareLineByLine(new[]
src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs
+2
-2
@@ -7,7 +7,7 @@
7
8
<CustomTable Id="CustomTable1">
9
<Column Id="Column1" Type="string" PrimaryKey="yes" Category="text" Modularize="column" Description="The first custom column." />
10
- <Column Id="Component_" Type="string" Width="72" KeyTable="Component" KeyColumn="1" Description="The custom table's Component reference" />
10
+ <Column Id="Component_" Type="string" Width="72" KeyTable="Component" KeyColumn="1" Description="The custom table's Component reference" Modularize="column" />
11
<Row>
12
<Data Column="Column1" Value="Row1" />
13
<Data Column="Component_" Value="test.txt" />
@@ -20,7 +20,7 @@
20
21
<CustomTable Id="CustomTable2" Unreal="yes">
22
<Column Id="ColumnA" Type="string" PrimaryKey="yes" />
23
- <Column Id="Component_" Type="string" Width="72" KeyTable="Component" KeyColumn="1" />
23
+ <Column Id="Component_" Type="string" Width="72" KeyTable="Component" KeyColumn="1" Modularize="column" />
24
<Row>
25
<Data Column="ColumnA" Value="RowA" />
26
<Data Column="Component_" Value="test.txt" />