aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs3
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs296
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs12
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/ProcessDependencyReferencesCommand.cs2
-rw-r--r--src/WixToolset.Core/Compiler.cs4
-rw-r--r--src/WixToolset.Core/Compiler_Package.cs2
-rw-r--r--src/WixToolset.Core/Linker.cs435
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs2
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs4
9 files changed, 338 insertions, 422 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index 7a64b777..292f1572 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -192,6 +192,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
192 command.Execute(); 192 command.Execute();
193 } 193 }
194 194
195 if (section.Type == SectionType.Product || section.Type == SectionType.Module)
195 { 196 {
196 var command = new AddRequiredStandardDirectories(section, platform); 197 var command = new AddRequiredStandardDirectories(section, platform);
197 command.Execute(); 198 command.Execute();
@@ -329,7 +330,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
329 330
330 if (dependencyRefs.Any()) 331 if (dependencyRefs.Any())
331 { 332 {
332 var command = new ProcessDependencyReferencesCommand(this.WindowsInstallerBackendHelper, section, dependencyRefs); 333 var command = new ProcessDependencyReferencesCommand(section, dependencyRefs);
333 command.Execute(); 334 command.Execute();
334 } 335 }
335 } 336 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs
index dc60a9ac..9ec26964 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs
@@ -25,6 +25,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
25 this.TableDefinitions = tableDefinitions; 25 this.TableDefinitions = tableDefinitions;
26 this.BackendExtensions = backendExtensions; 26 this.BackendExtensions = backendExtensions;
27 this.BackendHelper = backendHelper; 27 this.BackendHelper = backendHelper;
28 this.GeneratedShortNames = new Dictionary<string, List<FileSymbol>>();
28 } 29 }
29 30
30 private IEnumerable<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; } 31 private IEnumerable<IWindowsInstallerBackendBinderExtension> BackendExtensions { get; }
@@ -37,6 +38,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
37 38
38 private IntermediateSection Section { get; } 39 private IntermediateSection Section { get; }
39 40
41 private Dictionary<string, List<FileSymbol>> GeneratedShortNames { get; }
42
40 public WindowsInstallerData Data { get; private set; } 43 public WindowsInstallerData Data { get; private set; }
41 44
42 public WindowsInstallerData Execute() 45 public WindowsInstallerData Execute()
@@ -136,6 +139,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
136 139
137 case SymbolDefinitionType.ModuleConfiguration: 140 case SymbolDefinitionType.ModuleConfiguration:
138 this.AddModuleConfigurationSymbol((ModuleConfigurationSymbol)symbol); 141 this.AddModuleConfigurationSymbol((ModuleConfigurationSymbol)symbol);
142 this.EnsureModuleIgnoredTable(symbol, "ModuleConfiguration");
143 break;
144
145 case SymbolDefinitionType.ModuleSubstitution:
146 this.EnsureModuleIgnoredTable(symbol, "ModuleSubstitution");
139 break; 147 break;
140 148
141 case SymbolDefinitionType.MsiEmbeddedUI: 149 case SymbolDefinitionType.MsiEmbeddedUI:
@@ -262,6 +270,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
262 } 270 }
263 271
264 this.AddIndexedCellSymbols(cellsByTableAndRowId); 272 this.AddIndexedCellSymbols(cellsByTableAndRowId);
273 this.EnsureRequiredTables();
274 this.ReportGeneratedShortFileNameConflicts();
275 this.ReportIllegalTables();
276 this.ReportMismatchedModularizations();
277 this.ReportWindowsInstallerDataInconsistencies();
265 } 278 }
266 279
267 private void AddAssemblySymbol(AssemblySymbol symbol) 280 private void AddAssemblySymbol(AssemblySymbol symbol)
@@ -426,6 +439,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
426 row[2] = symbol.Source; 439 row[2] = symbol.Source;
427 row[3] = symbol.Target; 440 row[3] = symbol.Target;
428 row[4] = symbol.PatchUninstall ? (int?)WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall : null; 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 }
429 } 451 }
430 452
431 private void AddDialogSymbol(DialogSymbol symbol) 453 private void AddDialogSymbol(DialogSymbol symbol)
@@ -483,6 +505,38 @@ namespace WixToolset.Core.WindowsInstaller.Bind
483 row[0] = symbol.Id.Id; 505 row[0] = symbol.Id.Id;
484 row[1] = symbol.ParentDirectoryRef; 506 row[1] = symbol.ParentDirectoryRef;
485 row[2] = defaultDir; 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 }
486 } 540 }
487 541
488 private void AddDuplicateFileSymbol(DuplicateFileSymbol symbol) 542 private void AddDuplicateFileSymbol(DuplicateFileSymbol symbol)
@@ -570,6 +624,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
570 if (null == symbol.ShortName && null != name && !Common.IsValidShortFilename(name, false)) 624 if (null == symbol.ShortName && null != name && !Common.IsValidShortFilename(name, false))
571 { 625 {
572 symbol.ShortName = CreateShortName(name, true, false, "File", symbol.DirectoryRef); 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);
573 } 635 }
574 636
575 var row = (FileRow)this.CreateRow(symbol, "File"); 637 var row = (FileRow)this.CreateRow(symbol, "File");
@@ -612,7 +674,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
612 var tableName = (IniFileActionType.AddLine == symbol.Action || IniFileActionType.AddTag == symbol.Action || IniFileActionType.CreateLine == symbol.Action) ? "IniFile" : "RemoveIniFile"; 674 var tableName = (IniFileActionType.AddLine == symbol.Action || IniFileActionType.AddTag == symbol.Action || IniFileActionType.CreateLine == symbol.Action) ? "IniFile" : "RemoveIniFile";
613 675
614 var name = symbol.FileName; 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))
616 { 678 {
617 symbol.ShortFileName = CreateShortName(name, true, false, "IniFile", symbol.ComponentRef); 679 symbol.ShortFileName = CreateShortName(name, true, false, "IniFile", symbol.ComponentRef);
618 } 680 }
@@ -1168,6 +1230,238 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1168 private bool AddSymbolDefaultly(IntermediateSymbol symbol) => 1230 private bool AddSymbolDefaultly(IntermediateSymbol symbol) =>
1169 this.BackendHelper.TryAddSymbolToMatchingTableDefinitions(this.Section, symbol, this.Data, this.TableDefinitions); 1231 this.BackendHelper.TryAddSymbolToMatchingTableDefinitions(this.Section, symbol, this.Data, this.TableDefinitions);
1170 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
1171 private static OutputType SectionTypeToOutputType(SectionType type) 1465 private static OutputType SectionTypeToOutputType(SectionType type)
1172 { 1466 {
1173 switch (type) 1467 switch (type)
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs
index e96dfd91..67515154 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/OptimizeFileFacadesOrderCommand.cs
@@ -36,7 +36,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
36 { 36 {
37 var canonicalComponentTargetPaths = this.ComponentTargetPaths(); 37 var canonicalComponentTargetPaths = this.ComponentTargetPaths();
38 38
39 this.FileFacades.Sort(new FileFacadeOptimizer(canonicalComponentTargetPaths)); 39 this.FileFacades.Sort(new FileFacadeOptimizer(canonicalComponentTargetPaths, this.Section.Type == SectionType.Module));
40 40
41 return this.FileFacades; 41 return this.FileFacades;
42 } 42 }
@@ -71,17 +71,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
71 71
72 private class FileFacadeOptimizer : IComparer<FileFacade> 72 private class FileFacadeOptimizer : IComparer<FileFacade>
73 { 73 {
74 public FileFacadeOptimizer(Dictionary<string, string> componentTargetPaths) 74 public FileFacadeOptimizer(Dictionary<string, string> componentTargetPaths, bool optimizingMergeModule)
75 { 75 {
76 this.ComponentTargetPaths = componentTargetPaths; 76 this.ComponentTargetPaths = componentTargetPaths;
77 this.OptimizingMergeModule = optimizingMergeModule;
77 } 78 }
78 79
79 private Dictionary<string, string> ComponentTargetPaths { get; } 80 private Dictionary<string, string> ComponentTargetPaths { get; }
80 81
82 private bool OptimizingMergeModule { get; }
83
81 public int Compare(FileFacade x, FileFacade y) 84 public int Compare(FileFacade x, FileFacade y)
82 { 85 {
83 // First group files by DiskId. 86 // First group files by DiskId but ignore if processing a Merge Module
84 var compare = x.DiskId.CompareTo(y.DiskId); 87 // because Merge Modules don't have separate disks.
88 var compare = this.OptimizingMergeModule ? 0 : x.DiskId.CompareTo(y.DiskId);
85 89
86 if (compare != 0) 90 if (compare != 0)
87 { 91 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessDependencyReferencesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessDependencyReferencesCommand.cs
index 0ae7ca73..7a7c2649 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessDependencyReferencesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessDependencyReferencesCommand.cs
@@ -17,7 +17,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
17 private const string DependencyRegistryRoot = @"Software\Classes\Installer\Dependencies\"; 17 private const string DependencyRegistryRoot = @"Software\Classes\Installer\Dependencies\";
18 private const string RegistryDependents = "Dependents"; 18 private const string RegistryDependents = "Dependents";
19 19
20 public ProcessDependencyReferencesCommand(IWindowsInstallerBackendHelper backendHelper, IntermediateSection section, IEnumerable<WixDependencyRefSymbol> dependencyRefSymbols) 20 public ProcessDependencyReferencesCommand(IntermediateSection section, IEnumerable<WixDependencyRefSymbol> dependencyRefSymbols)
21 { 21 {
22 this.Section = section; 22 this.Section = section;
23 this.DependencyRefSymbols = dependencyRefSymbols; 23 this.DependencyRefSymbols = dependencyRefSymbols;
diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs
index 8aa82d47..f311a5f6 100644
--- a/src/WixToolset.Core/Compiler.cs
+++ b/src/WixToolset.Core/Compiler.cs
@@ -7178,7 +7178,7 @@ namespace WixToolset.Core
7178 cabinet = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 7178 cabinet = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
7179 break; 7179 break;
7180 case "CompressionLevel": 7180 case "CompressionLevel":
7181 compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, node, attrib); 7181 compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, attrib);
7182 break; 7182 break;
7183 case "DiskPrompt": 7183 case "DiskPrompt":
7184 diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 7184 diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
@@ -7381,7 +7381,7 @@ namespace WixToolset.Core
7381 } 7381 }
7382 break; 7382 break;
7383 case "CompressionLevel": 7383 case "CompressionLevel":
7384 compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, node, attrib); 7384 compressionLevel = this.ParseCompressionLevel(sourceLineNumbers, attrib);
7385 break; 7385 break;
7386 case "DiskPrompt": 7386 case "DiskPrompt":
7387 diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 7387 diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
diff --git a/src/WixToolset.Core/Compiler_Package.cs b/src/WixToolset.Core/Compiler_Package.cs
index 2cc77a60..03ba1c40 100644
--- a/src/WixToolset.Core/Compiler_Package.cs
+++ b/src/WixToolset.Core/Compiler_Package.cs
@@ -4950,7 +4950,7 @@ namespace WixToolset.Core
4950 } 4950 }
4951 } 4951 }
4952 4952
4953 private CompressionLevel? ParseCompressionLevel(SourceLineNumber sourceLineNumbers, XElement node, XAttribute attribute) 4953 private CompressionLevel? ParseCompressionLevel(SourceLineNumber sourceLineNumbers, XAttribute attribute)
4954 { 4954 {
4955 var compressionLevel = this.Core.GetAttributeValue(sourceLineNumbers, attribute); 4955 var compressionLevel = this.Core.GetAttributeValue(sourceLineNumbers, attribute);
4956 switch (compressionLevel) 4956 switch (compressionLevel)
diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs
index 41e0db7d..3281cbd0 100644
--- a/src/WixToolset.Core/Linker.cs
+++ b/src/WixToolset.Core/Linker.cs
@@ -93,52 +93,12 @@ namespace WixToolset.Core
93 } 93 }
94 } 94 }
95 95
96#if MOVE_TO_BACKEND
97 bool containsModuleSubstitution = false;
98 bool containsModuleConfiguration = false;
99#endif
100
101 //this.activeOutput = null; 96 //this.activeOutput = null;
102 97
103#if MOVE_TO_BACKEND
104 StringCollection generatedShortFileNameIdentifiers = new StringCollection();
105 Hashtable generatedShortFileNames = new Hashtable();
106#endif
107
108 var multipleFeatureComponents = new Hashtable(); 98 var multipleFeatureComponents = new Hashtable();
109 99
110 var wixVariables = new Dictionary<string, WixVariableSymbol>(); 100 var wixVariables = new Dictionary<string, WixVariableSymbol>();
111 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
142 // First find the entry section and while processing all sections load all the symbols from all of the sections. 102 // First find the entry section and while processing all sections load all the symbols from all of the sections.
143 var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, sections, this.Context.ExpectedOutputType); 103 var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, sections, this.Context.ExpectedOutputType);
144 find.Execute(); 104 find.Execute();
@@ -211,7 +171,8 @@ namespace WixToolset.Core
211 // resolve the feature to feature connects 171 // resolve the feature to feature connects
212 this.ResolveFeatureToFeatureConnects(featuresToFeatures, find.SymbolsByName); 172 this.ResolveFeatureToFeatureConnects(featuresToFeatures, find.SymbolsByName);
213 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.
215 var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type, find.EntrySection.Codepage); 176 var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type, find.EntrySection.Codepage);
216 177
217 var sectionCount = 0; 178 var sectionCount = 0;
@@ -245,54 +206,6 @@ namespace WixToolset.Core
245 } 206 }
246 break; 207 break;
247 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
296 case SymbolDefinitionType.Extension: 209 case SymbolDefinitionType.Extension:
297 if (SectionType.Product == resolvedSection.Type) 210 if (SectionType.Product == resolvedSection.Type)
298 { 211 {
@@ -300,16 +213,6 @@ namespace WixToolset.Core
300 } 213 }
301 break; 214 break;
302 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
313 case SymbolDefinitionType.Assembly: 216 case SymbolDefinitionType.Assembly:
314 if (SectionType.Product == resolvedSection.Type) 217 if (SectionType.Product == resolvedSection.Type)
315 { 218 {
@@ -338,26 +241,6 @@ namespace WixToolset.Core
338 } 241 }
339 break; 242 break;
340 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
361 case SymbolDefinitionType.WixMerge: 244 case SymbolDefinitionType.WixMerge:
362 if (SectionType.Product == resolvedSection.Type) 245 if (SectionType.Product == resolvedSection.Type)
363 { 246 {
@@ -374,30 +257,9 @@ namespace WixToolset.Core
374 break; 257 break;
375 258
376 case SymbolDefinitionType.WixVariable: 259 case SymbolDefinitionType.WixVariable:
377 // check for colliding values and collect the wix variable rows 260 this.AddWixVariable(wixVariables, (WixVariableSymbol)symbol);
378 { 261 copySymbol = false; // Do not copy the symbol, it will be added later after all overriding has been handled.
379 var wixVariableSymbol = (WixVariableSymbol)symbol; 262 break;
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;
401 } 263 }
402 264
403 if (copySymbol) 265 if (copySymbol)
@@ -407,7 +269,7 @@ namespace WixToolset.Core
407 } 269 }
408 } 270 }
409 271
410 // copy the module to feature connections into the output 272 // Copy the module to feature connections into the output.
411 foreach (ConnectToFeature connectToFeature in modulesToFeatures) 273 foreach (ConnectToFeature connectToFeature in modulesToFeatures)
412 { 274 {
413 foreach (var feature in connectToFeature.ConnectFeatures) 275 foreach (var feature in connectToFeature.ConnectFeatures)
@@ -420,136 +282,23 @@ namespace WixToolset.Core
420 } 282 }
421 } 283 }
422 284
423#if MOVE_TO_BACKEND 285 // Correct the section Id in FeatureComponents table.
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
467 if (this.sectionIdOnRows) 286 if (this.sectionIdOnRows)
468 { 287 {
469 //var componentSectionIds = new Dictionary<string, string>(); 288#if TODO_DO_SYMBOLS_NEED_SECTIONIDS
470 289 var componentSectionIds = resolvedSection.Symbols.OfType<ComponentSymbol>().ToDictionary(c => c.Id.Id, c => c.SectionId);
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];
517 290
518 // create lists of conflicting generated short file names 291 foreach (var featureComponentSymbol in resolvedSection.Symbols.OfType<FeatureComponentsSymbol>())
519 if (!generatedShortFileNames.Contains(shortFileName))
520 { 292 {
521 generatedShortFileNames.Add(shortFileName, new ArrayList()); 293 if (componentSectionIds.TryGetValue(featureComponentSymbol.ComponentRef, out var componentSectionId))
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++)
540 { 294 {
541 FileRow fileRow = (FileRow)fileRows[i]; 295 featureComponentSymbol.SectionId = componentSectionId;
542
543 if (null != fileRow.SourceLineNumbers)
544 {
545 this.Messaging.Write(WixWarnings.GeneratedShortFileNameConflict2(fileRow.SourceLineNumbers));
546 }
547 } 296 }
548 } 297 }
549 }
550#endif 298#endif
299 }
551 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.
553 foreach (var symbol in wixVariables.Values) 302 foreach (var symbol in wixVariables.Values)
554 { 303 {
555 resolvedSection.AddSymbol(symbol); 304 resolvedSection.AddSymbol(symbol);
@@ -567,10 +316,6 @@ namespace WixToolset.Core
567 var localizationsByCulture = collate.Execute(); 316 var localizationsByCulture = collate.Execute();
568 317
569 intermediate = new Intermediate(resolvedSection.Id, Data.IntermediateLevels.Linked, new[] { resolvedSection }, localizationsByCulture); 318 intermediate = new Intermediate(resolvedSection.Id, Data.IntermediateLevels.Linked, new[] { resolvedSection }, localizationsByCulture);
570
571#if MOVE_TO_BACKEND
572 this.CheckOutputConsistency(output);
573#endif
574 } 319 }
575 finally 320 finally
576 { 321 {
@@ -583,159 +328,31 @@ namespace WixToolset.Core
583 return this.Messaging.EncounteredError ? null : intermediate; 328 return this.Messaging.EncounteredError ? null : intermediate;
584 } 329 }
585 330
586#if MOVE_TO_BACKEND
587 /// <summary> 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.
589 /// </summary> 333 /// </summary>
590 /// <param name="output">The output to check.</param> 334 /// <param name="wixVariables">Collection of WixVariableSymbols by id.</param>
591 private void CheckForIllegalTables(Output output) 335 /// <param name="symbol">WixVariableSymbol to add, if not overridden.</param>
336 private void AddWixVariable(Dictionary<string, WixVariableSymbol> wixVariables, WixVariableSymbol symbol)
592 { 337 {
593 foreach (Table table in output.Tables) 338 var id = symbol.Id.Id;
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
680 339
681#if MOVE_TO_BACKEND 340 if (wixVariables.TryGetValue(id, out var collidingSymbol))
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)
692 { 341 {
693 foreach (Row row in summaryInformationTable.Rows) 342 if (collidingSymbol.Overridable && !symbol.Overridable)
694 { 343 {
695 if (14 == (int)row[0]) 344 wixVariables[id] = symbol;
696 {
697 outputInstallerVersion = Convert.ToInt32(row[1], CultureInfo.InvariantCulture);
698 break;
699 }
700 } 345 }
701 } 346 else if (!symbol.Overridable || (collidingSymbol.Overridable && symbol.Overridable))
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)
714 { 347 {
715 foreach (Row row in isolatedComponentTable.Rows) 348 this.Messaging.Write(ErrorMessages.WixVariableCollision(symbol.SourceLineNumbers, id));
716 {
717 this.Messaging.Write(WixWarnings.TableIncompatibleWithInstallerVersion(row.SourceLineNumbers, "IsolatedComponent", outputInstallerVersion));
718 }
719 } 349 }
720 } 350 }
721 351 else
722 // check for the presence of tables/rows/columns that require MSI 4.0 or later
723 if (400 > outputInstallerVersion)
724 { 352 {
725 Table shortcutTable = output.Tables["Shortcut"]; 353 wixVariables.Add(id, symbol);
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 }
736 } 354 }
737 } 355 }
738#endif
739 356
740 /// <summary> 357 /// <summary>
741 /// Load the standard action and directory symbols. 358 /// Load the standard action and directory symbols.
diff --git a/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs b/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
index 8c3487f0..2af47034 100644
--- a/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
+++ b/src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
@@ -1022,7 +1022,7 @@ namespace WixToolsetTest.CoreIntegration
1022 Assert.Empty(section.Symbols.OfType<FileSymbol>()); 1022 Assert.Empty(section.Symbols.OfType<FileSymbol>());
1023 1023
1024 var data = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb")); 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 1026
1027 var results = Query.QueryDatabase(msiPath, new[] { "File" }); 1027 var results = Query.QueryDatabase(msiPath, new[] { "File" });
1028 WixAssert.CompareLineByLine(new[] 1028 WixAssert.CompareLineByLine(new[]
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs
index 7f4a43e5..d32e808c 100644
--- a/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs
+++ b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs
@@ -7,7 +7,7 @@
7 7
8 <CustomTable Id="CustomTable1"> 8 <CustomTable Id="CustomTable1">
9 <Column Id="Column1" Type="string" PrimaryKey="yes" Category="text" Modularize="column" Description="The first custom column." /> 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> 11 <Row>
12 <Data Column="Column1" Value="Row1" /> 12 <Data Column="Column1" Value="Row1" />
13 <Data Column="Component_" Value="test.txt" /> 13 <Data Column="Component_" Value="test.txt" />
@@ -20,7 +20,7 @@
20 20
21 <CustomTable Id="CustomTable2" Unreal="yes"> 21 <CustomTable Id="CustomTable2" Unreal="yes">
22 <Column Id="ColumnA" Type="string" PrimaryKey="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> 24 <Row>
25 <Data Column="ColumnA" Value="RowA" /> 25 <Data Column="ColumnA" Value="RowA" />
26 <Data Column="Component_" Value="test.txt" /> 26 <Data Column="Component_" Value="test.txt" />