@joebigelow / wix / commits / 816bfd18

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" />