diff options
Diffstat (limited to 'src')
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" /> |
