From 9f8cb5374481b6c8a06eb2739858332350f72666 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Sat, 11 Nov 2017 01:45:59 -0800 Subject: Additional IR updates --- .../Bind/AssignMediaCommand.cs | 187 +++--- .../Bind/BindDatabaseCommand.cs | 739 +++++++-------------- .../Bind/BindSummaryInfoCommand.cs | 178 ++--- .../Bind/BindTransformCommand.cs | 2 +- .../Bind/CabinetBuilder.cs | 2 +- .../Bind/CabinetWorkItem.cs | 3 +- .../Bind/CalculateComponentGuids.cs | 174 +++++ .../Bind/ConfigurationCallback.cs | 2 +- .../Bind/CopyTransformDataCommand.cs | 7 +- .../Bind/CreateCabinetsCommand.cs | 24 +- .../Bind/CreateDeltaPatchesCommand.cs | 44 +- .../Bind/CreateOutputFromIRCommand.cs | 230 +++++++ .../Bind/CreateSpecialPropertiesCommand.cs | 87 +-- .../Bind/ExtractMergeModuleFilesCommand.cs | 51 +- .../Bind/GenerateDatabaseCommand.cs | 2 +- .../Bind/GetFileFacadesCommand.cs | 61 +- .../Bind/MergeModulesCommand.cs | 32 +- .../Bind/ProcessUncompressedFilesCommand.cs | 36 +- .../Bind/SequenceActionsCommand.cs | 671 +++++++++++++++++++ .../Bind/UpdateControlTextCommand.cs | 2 +- .../Bind/UpdateFileFacadesCommand.cs | 112 ++-- .../Bind/UpdateMediaSequencesCommand.cs | 126 ++++ .../Inscribe/InscribeMsiPackageCommand.cs | 2 +- src/WixToolset.Core.WindowsInstaller/MstBackend.cs | 1 - src/WixToolset.Core.WindowsInstaller/Patch.cs | 2 +- .../Unbind/UnbindDatabaseCommand.cs | 2 +- .../Unbind/UnbindTranformCommand.cs | 7 +- .../Bind/ExtractEmbeddedFilesCommand.cs | 15 +- .../Bind/ResolveDelayedFieldsCommand.cs | 78 +-- src/WixToolset.Core/Bind/ResolvedDirectory.cs | 18 +- src/WixToolset.Core/Binder.cs | 8 +- src/WixToolset.Core/Compiler.cs | 8 +- src/WixToolset.Core/Linker.cs | 670 +------------------ src/WixToolset.Core/WindowsInstallerStandard.cs | 260 -------- src/WixToolset.Core/WixStrings.Designer.cs | 4 +- .../Data/tables.xml | 2 +- .../RowDictionary.cs | 3 +- .../Rows/SymbolPathType.cs | 17 - .../Rows/WixActionRow.cs | 52 +- .../Rows/WixActionRowCollection.cs | 1 + .../Rows/WixDeltaPatchSymbolPathsRow.cs | 2 + .../TableDefinitionCollection.cs | 11 + .../WindowsInstallerStandard.cs | 442 ------------ .../WindowsInstallerStandardInternal.cs | 59 ++ .../ProgramFixture.cs | 7 +- 45 files changed, 2001 insertions(+), 2442 deletions(-) create mode 100644 src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs create mode 100644 src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs create mode 100644 src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs create mode 100644 src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs delete mode 100644 src/WixToolset.Core/WindowsInstallerStandard.cs delete mode 100644 src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs delete mode 100644 src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs create mode 100644 src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs (limited to 'src') diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs index 74e2cdb5..f426b96d 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs @@ -1,43 +1,44 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; using System.Globalization; + using System.Linq; using WixToolset.Core.Bind; using WixToolset.Data; using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; /// /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows. /// - public class AssignMediaCommand + internal class AssignMediaCommand { - public AssignMediaCommand() + public AssignMediaCommand(IntermediateSection section) { this.CabinetNameTemplate = "Cab{0}.cab"; + this.Section = section; } - public Output Output { private get; set; } + private IntermediateSection Section { get; } + + public IEnumerable FileFacades { private get; set; } public bool FilesCompressed { private get; set; } public string CabinetNameTemplate { private get; set; } - public IEnumerable FileFacades { private get; set; } - - public TableDefinitionCollection TableDefinitions { private get; set; } - /// /// Gets cabinets with their file rows. /// - public Dictionary> FileFacadesByCabinetMedia { get; private set; } + public Dictionary> FileFacadesByCabinetMedia { get; private set; } /// /// Get media rows. /// - public RowDictionary MediaRows { get; private set; } + public Dictionary MediaRows { get; private set; } /// /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no. @@ -47,42 +48,41 @@ namespace WixToolset.Core.WindowsInstaller.Databases public void Execute() { - Dictionary> filesByCabinetMedia = new Dictionary>(); + var filesByCabinetMedia = new Dictionary>(); - RowDictionary mediaRows = new RowDictionary(); + var mediaRows = new Dictionary(); List uncompressedFiles = new List(); - MediaRow mergeModuleMediaRow = null; - Table mediaTable = this.Output.Tables["Media"]; - Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"]; + var mediaTable = this.Section.Tuples.OfType().ToList(); + var mediaTemplateTable = this.Section.Tuples.OfType().ToList(); // If both tables are authored, it is an error. - if ((mediaTemplateTable != null && mediaTemplateTable.Rows.Count > 0) && (mediaTable != null && mediaTable.Rows.Count > 1)) + if ((mediaTemplateTable != null && mediaTemplateTable.Count > 0) && (mediaTable != null && mediaTable.Count > 1)) { throw new WixException(WixErrors.MediaTableCollision(null)); } // When building merge module, all the files go to "#MergeModule.CABinet". - if (OutputType.Module == this.Output.Type) + if (SectionType.Module == this.Section.Type) { - Table mergeModuleMediaTable = new Table(this.TableDefinitions["Media"]); - mergeModuleMediaRow = (MediaRow)mergeModuleMediaTable.CreateRow(null); + var mergeModuleMediaRow = new MediaTuple(); mergeModuleMediaRow.Cabinet = "#MergeModule.CABinet"; - filesByCabinetMedia.Add(mergeModuleMediaRow, new List()); - } + this.Section.Tuples.Add(mergeModuleMediaRow); - if (OutputType.Module == this.Output.Type || null == mediaTemplateTable) + filesByCabinetMedia.Add(mergeModuleMediaRow, new List(this.FileFacades)); + } + else if (null == mediaTemplateTable) { - this.ManuallyAssignFiles(mediaTable, mergeModuleMediaRow, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); + this.ManuallyAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); } else { this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); } - this.FileFacadesByCabinetMedia = new Dictionary>(); + this.FileFacadesByCabinetMedia = new Dictionary>(); foreach (var mediaRowWithFiles in filesByCabinetMedia) { @@ -98,7 +98,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// Assign files to cabinets based on MediaTemplate authoring. /// /// FileRowCollection - private void AutoAssignFiles(Table mediaTable, IEnumerable fileFacades, Dictionary> filesByCabinetMedia, RowDictionary mediaRows, List uncompressedFiles) + private void AutoAssignFiles(List mediaTable, IEnumerable fileFacades, Dictionary> filesByCabinetMedia, Dictionary mediaRows, List uncompressedFiles) { const int MaxCabIndex = 999; @@ -107,13 +107,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases int maxPreCabSizeInMB = 0; int currentCabIndex = 0; - MediaRow currentMediaRow = null; + MediaTuple currentMediaRow = null; - Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"]; + var mediaTemplateTable = this.Section.Tuples.OfType(); + + // Remove all previous media tuples since they will be replaced with + // media template. + foreach (var mediaTuple in mediaTable) + { + this.Section.Tuples.Remove(mediaTuple); + } // Auto assign files to cabinets based on maximum uncompressed media size - mediaTable.Rows.Clear(); - WixMediaTemplateRow mediaTemplateRow = (WixMediaTemplateRow)mediaTemplateTable.Rows[0]; + var mediaTemplateRow = mediaTemplateTable.Single(); if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) { @@ -149,9 +155,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases { // When building a product, if the current file is not to be compressed or if // the package set not to be compressed, don't cab it. - if (OutputType.Product == this.Output.Type && - (!facade.File.Compressed.Value || - (!facade.File.Compressed.HasValue && !this.FilesCompressed))) + if (SectionType.Product == this.Section.Type && + ((facade.File.Compressed.HasValue && !facade.File.Compressed.Value) || + (!facade.File.Compressed.HasValue && !this.FilesCompressed))) { uncompressedFiles.Add(facade); continue; @@ -172,8 +178,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases if (currentPreCabSize > maxPreCabSizeInBytes) { // Overflow due to current file - currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex); - mediaRows.Add(currentMediaRow); + currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); + mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); filesByCabinetMedia.Add(currentMediaRow, new List()); List cabinetFileRows = filesByCabinetMedia[currentMediaRow]; @@ -188,8 +194,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases if (currentMediaRow == null) { // Create new cab and MediaRow - currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex); - mediaRows.Add(currentMediaRow); + currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); + mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); filesByCabinetMedia.Add(currentMediaRow, new List()); } @@ -201,11 +207,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases } // If there are uncompressed files and no MediaRow, create a default one. - if (uncompressedFiles.Count > 0 && mediaTable.Rows.Count == 0) + if (uncompressedFiles.Count > 0 && !this.Section.Tuples.OfType().Any()) { - MediaRow defaultMediaRow = (MediaRow)mediaTable.CreateRow(null); + var defaultMediaRow = new MediaTuple(null, new Identifier(1, AccessModifier.Private)); defaultMediaRow.DiskId = 1; - mediaRows.Add(defaultMediaRow); + + mediaRows.Add(1, defaultMediaRow); + this.Section.Tuples.Add(defaultMediaRow); } } @@ -213,79 +221,65 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// Assign files to cabinets based on Media authoring. /// /// - /// /// - private void ManuallyAssignFiles(Table mediaTable, MediaRow mergeModuleMediaRow, IEnumerable fileFacades, Dictionary> filesByCabinetMedia, RowDictionary mediaRows, List uncompressedFiles) + private void ManuallyAssignFiles(List mediaTable, IEnumerable fileFacades, Dictionary> filesByCabinetMedia, Dictionary mediaRows, List uncompressedFiles) { - if (OutputType.Module != this.Output.Type) + if (mediaTable.Any()) { - if (null != mediaTable) + var cabinetMediaRows = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var mediaRow in mediaTable) { - Dictionary cabinetMediaRows = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - foreach (MediaRow mediaRow in mediaTable.Rows) + // If the Media row has a cabinet, make sure it is unique across all Media rows. + if (!String.IsNullOrEmpty(mediaRow.Cabinet)) { - // If the Media row has a cabinet, make sure it is unique across all Media rows. - if (!String.IsNullOrEmpty(mediaRow.Cabinet)) + if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out var existingRow)) { - MediaRow existingRow; - if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out existingRow)) - { - Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); - Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); - } - else - { - cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); - } + Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); + Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); + } + else + { + cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); } - - mediaRows.Add(mediaRow); } + + mediaRows.Add(mediaRow.DiskId, mediaRow); } + } - foreach (MediaRow mediaRow in mediaRows.Values) + foreach (var mediaRow in mediaRows.Values) + { + if (null != mediaRow.Cabinet) { - if (null != mediaRow.Cabinet) - { - filesByCabinetMedia.Add(mediaRow, new List()); - } + filesByCabinetMedia.Add(mediaRow, new List()); } } foreach (FileFacade facade in fileFacades) { - if (OutputType.Module == this.Output.Type) + if (!mediaRows.TryGetValue(facade.WixFile.DiskId, out var mediaRow)) { - filesByCabinetMedia[mergeModuleMediaRow].Add(facade); + Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); + continue; } - else - { - MediaRow mediaRow; - if (!mediaRows.TryGetValue(facade.WixFile.DiskId.ToString(CultureInfo.InvariantCulture), out mediaRow)) - { - Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); - continue; - } - // When building a product, if the current file is not to be compressed or if - // the package set not to be compressed, don't cab it. - if (OutputType.Product == this.Output.Type && - (!facade.File.Compressed.Value || - (!facade.File.Compressed.HasValue && !this.FilesCompressed))) + // When building a product, if the current file is not to be compressed or if + // the package set not to be compressed, don't cab it. + if (SectionType.Product == this.Section.Type && + (!facade.File.Compressed.Value || + (!facade.File.Compressed.HasValue && !this.FilesCompressed))) + { + uncompressedFiles.Add(facade); + } + else // file is marked compressed. + { + if (filesByCabinetMedia.TryGetValue(mediaRow, out var cabinetFiles)) { - uncompressedFiles.Add(facade); + cabinetFiles.Add(facade); } - else // file is marked compressed. + else { - List cabinetFiles; - if (filesByCabinetMedia.TryGetValue(mediaRow, out cabinetFiles)) - { - cabinetFiles.Add(facade); - } - else - { - Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); - } + Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); } } } @@ -297,17 +291,20 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// /// /// - private MediaRow AddMediaRow(WixMediaTemplateRow mediaTemplateRow, Table mediaTable, int cabIndex) + private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateRow, int cabIndex) { - MediaRow currentMediaRow = (MediaRow)mediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers); + var currentMediaRow = new MediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); currentMediaRow.DiskId = cabIndex; currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex); - Table wixMediaTable = this.Output.EnsureTable(this.TableDefinitions["WixMedia"]); - WixMediaRow row = (WixMediaRow)wixMediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers); - row.DiskId = cabIndex; + this.Section.Tuples.Add(currentMediaRow); + + var row = new WixMediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); + row.DiskId_ = cabIndex; row.CompressionLevel = mediaTemplateRow.CompressionLevel; + this.Section.Tuples.Add(row); + return currentMediaRow; } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index 5a61b63c..30a19a4b 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs @@ -3,21 +3,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind { using System; - using System.Collections; using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; using System.IO; using System.Linq; - using WixToolset.Bind; using WixToolset.Core.Bind; - using WixToolset.Core.WindowsInstaller.Databases; using WixToolset.Data; using WixToolset.Data.Bind; - using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; using WixToolset.Extensibility; using WixToolset.Extensibility.Services; - using WixToolset.Msi; /// /// Binds a databse. @@ -25,11 +19,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind internal class BindDatabaseCommand { // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. - private static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); + internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); public BindDatabaseCommand(IBindContext context, Validator validator) { - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); this.BindPaths = context.BindPaths; this.CabbingThreadCount = context.CabbingThreadCount; @@ -73,8 +67,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind private Intermediate Intermediate { get; } - private Output Output { get; } - private string OutputPath { get; } private bool SuppressAddingValidationRows { get; } @@ -95,22 +87,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind public void Execute() { - this.Intermediate.Save(this.OutputPath); -#if FINISH - List fileTransfers = new List(); + var section = this.Intermediate.Sections.Single(); - HashSet suppressedTableNames = new HashSet(); + var fileTransfers = new List(); - // If there are any fields to resolve later, create the cache to populate during bind. - IDictionary variableCache = null; - if (this.DelayedFields.Any()) - { - variableCache = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - } + var suppressedTableNames = new HashSet(); - this.LocalizeUI(this.Output.Tables); + // If there are any fields to resolve later, create the cache to populate during bind. + var variableCache = this.DelayedFields.Any() ? new Dictionary(StringComparer.InvariantCultureIgnoreCase) : null; - this.Output = CreateOutputFromIR(this.Intermediate); + this.LocalizeUI(section); // Process the summary information table before the other tables. bool compressed; @@ -118,8 +104,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind int installerVersion; string modularizationGuid; { - BindSummaryInfoCommand command = new BindSummaryInfoCommand(); - command.Output = this.Output; + var command = new BindSummaryInfoCommand(section); command.Execute(); compressed = command.Compressed; @@ -128,42 +113,61 @@ namespace WixToolset.Core.WindowsInstaller.Bind modularizationGuid = command.ModularizationGuid; } - // Stop processing if an error previously occurred. - if (Messaging.Instance.EncounteredError) - { - return; - } - - // Modularize identifiers and add tables with real streams to the import tables. - if (OutputType.Module == this.Output.Type) + // Add binder variables for all properties. + if (SectionType.Product == section.Type || variableCache != null) { - // Gather all the suppress modularization identifiers - HashSet suppressModularizationIdentifiers = null; - Table wixSuppressModularizationTable = this.Output.Tables["WixSuppressModularization"]; - if (null != wixSuppressModularizationTable) + foreach (var propertyRow in section.Tuples.OfType()) { - suppressModularizationIdentifiers = new HashSet(wixSuppressModularizationTable.Rows.Select(row => (string)row[0])); - } + // Set the ProductCode if it is to be generated. + if ("ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) + { + propertyRow.Value = Common.GenerateGuid(); - foreach (Table table in this.Output.Tables) - { - table.Modularize(modularizationGuid, suppressModularizationIdentifiers); +#if TODO_FIX_INSTANCE_TRANSFORM + // Update the target ProductCode in any instance transforms. + foreach (SubStorage subStorage in this.Output.SubStorages) + { + Output subStorageOutput = subStorage.Data; + if (OutputType.Transform != subStorageOutput.Type) + { + continue; + } + + Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; + foreach (Row row in instanceSummaryInformationTable.Rows) + { + if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) + { + row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); + break; + } + } + } +#endif + } + + // Add the property name and value to the variableCache. + if (variableCache != null) + { + var key = String.Concat("property.", propertyRow.Property); + variableCache[key] = propertyRow.Value; + } } } - // This must occur after all variables and source paths have been resolved and after modularization. - List fileFacades; + // Sequence all the actions. { - GetFileFacadesCommand command = new GetFileFacadesCommand(); - command.FileTable = this.Output.Tables["File"]; - command.WixFileTable = this.Output.Tables["WixFile"]; - command.WixDeltaPatchFileTable = this.Output.Tables["WixDeltaPatchFile"]; - command.WixDeltaPatchSymbolPathsTable = this.Output.Tables["WixDeltaPatchSymbolPaths"]; + var command = new SequenceActionsCommand(section); + command.Messaging = Messaging.Instance; command.Execute(); + } - fileFacades = command.FileFacades; + { + var command = new CreateSpecialPropertiesCommand(section); + command.Execute(); } +#if TODO_FINISH_PATCH ////if (OutputType.Patch == this.Output.Type) ////{ //// foreach (SubStorage substorage in this.Output.SubStorages) @@ -183,87 +187,72 @@ namespace WixToolset.Core.WindowsInstaller.Bind //// this.MergeUnrealTables(transform.Tables); //// } ////} - - { - CreateSpecialPropertiesCommand command = new CreateSpecialPropertiesCommand(); - command.PropertyTable = this.Output.Tables["Property"]; - command.WixPropertyTable = this.Output.Tables["WixProperty"]; - command.Execute(); - } +#endif if (Messaging.Instance.EncounteredError) { return; } - // Add binder variables for all properties. - Table propertyTable = this.Output.Tables["Property"]; - if (null != propertyTable) + Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); + + // This must occur after all variables and source paths have been resolved. + List fileFacades; { - foreach (PropertyRow propertyRow in propertyTable.Rows) - { - // Set the ProductCode if it is to be generated. - if (OutputType.Product == this.Output.Type && "ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) - { - propertyRow.Value = Common.GenerateGuid(); + var command = new GetFileFacadesCommand(section); + command.Execute(); - // Update the target ProductCode in any instance transforms. - foreach (SubStorage subStorage in this.Output.SubStorages) - { - Output subStorageOutput = subStorage.Data; - if (OutputType.Transform != subStorageOutput.Type) - { - continue; - } + fileFacades = command.FileFacades; + } - Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; - foreach (Row row in instanceSummaryInformationTable.Rows) - { - if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) - { - row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); - break; - } - } - } - } + // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules). + { + var command = new ExtractEmbeddedFilesCommand(this.ExpectedEmbeddedFiles); + command.Execute(); + } - // Add the property name and value to the variableCache. - if (null != variableCache) - { - string key = String.Concat("property.", Common.Demodularize(this.Output.Type, modularizationGuid, propertyRow.Property)); - variableCache[key] = propertyRow.Value; - } - } + // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table). + { + var command = new UpdateFileFacadesCommand(section); + command.FileFacades = fileFacades; + command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); + command.OverwriteHash = true; + command.TableDefinitions = this.TableDefinitions; + command.VariableCache = variableCache; + command.Execute(); } - // Extract files that come from cabinet files (this does not extract files from merge modules). + // Now that the variable cache is populated, resolve any delayed fields. + if (this.DelayedFields.Any()) { - ExtractEmbeddedFilesCommand command = new ExtractEmbeddedFilesCommand(); - command.FilesWithEmbeddedFiles = this.ExpectedEmbeddedFiles; + var command = new ResolveDelayedFieldsCommand(this.DelayedFields, variableCache); command.Execute(); } - if (OutputType.Product == this.Output.Type) + // Set generated component guids. + { + var command = new CalculateComponentGuids(section); + command.Execute(); + } + + if (SectionType.Product == section.Type) { // Retrieve files and their information from merge modules. - Table wixMergeTable = this.Output.Tables["WixMerge"]; + var wixMergeTuples = section.Tuples.OfType().ToList(); - if (null != wixMergeTable) + if (wixMergeTuples.Any()) { - ExtractMergeModuleFilesCommand command = new ExtractMergeModuleFilesCommand(); + var command = new ExtractMergeModuleFilesCommand(section, wixMergeTuples); command.FileFacades = fileFacades; - command.FileTable = this.Output.Tables["File"]; - command.WixFileTable = this.Output.Tables["WixFile"]; - command.WixMergeTable = wixMergeTable; command.OutputInstallerVersion = installerVersion; command.SuppressLayout = this.SuppressLayout; - command.TempFilesLocation = this.IntermediateFolder; + command.IntermediateFolder = this.IntermediateFolder; command.Execute(); fileFacades.AddRange(command.MergeModulesFileFacades); } } +#if TODO_FINISH_PATCH else if (OutputType.Patch == this.Output.Type) { // Merge transform data into the output object. @@ -271,6 +260,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind fileFacades.AddRange(filesFromTransform); } +#endif // stop processing if an error previously occurred if (Messaging.Instance.EncounteredError) @@ -278,51 +268,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind return; } - Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); - - // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table). - { - UpdateFileFacadesCommand command = new UpdateFileFacadesCommand(); - command.FileFacades = fileFacades; - command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); - command.ModularizationGuid = modularizationGuid; - command.Output = this.Output; - command.OverwriteHash = true; - command.TableDefinitions = this.TableDefinitions; - command.VariableCache = variableCache; - command.Execute(); - } - - // Set generated component guids. - this.SetComponentGuids(this.Output); - +#if TODO_FIX_INSTANCE_TRANSFORM // With the Component Guids set now we can create instance transforms. this.CreateInstanceTransforms(this.Output); - - this.ValidateComponentGuids(this.Output); - - this.UpdateControlText(this.Output); - - if (this.DelayedFields.Any()) - { - ResolveDelayedFieldsCommand command = new ResolveDelayedFieldsCommand(); - command.OutputType = this.Output.Type; - command.DelayedFields = this.DelayedFields; - command.ModularizationGuid = null; - command.VariableCache = variableCache; - command.Execute(); - } +#endif // Assign files to media. - RowDictionary assignedMediaRows; - Dictionary> filesByCabinetMedia; + Dictionary assignedMediaRows; + Dictionary> filesByCabinetMedia; IEnumerable uncompressedFiles; { - AssignMediaCommand command = new AssignMediaCommand(); - command.FilesCompressed = compressed; + var command = new AssignMediaCommand(section); command.FileFacades = fileFacades; - command.Output = this.Output; - command.TableDefinitions = this.TableDefinitions; + command.FilesCompressed = compressed; command.Execute(); assignedMediaRows = command.MediaRows; @@ -330,15 +288,40 @@ namespace WixToolset.Core.WindowsInstaller.Bind uncompressedFiles = command.UncompressedFileFacades; } - // Update file sequence. - this.UpdateMediaSequences(this.Output.Type, fileFacades, assignedMediaRows); - // stop processing if an error previously occurred if (Messaging.Instance.EncounteredError) { return; } + // Try to put as much above here as possible, updating the IR is better. + Output output; + { + var command = new CreateOutputFromIRCommand(section, this.TableDefinitions); + command.Execute(); + + output = command.Output; + } + + // Update file sequence. + { + var command = new UpdateMediaSequencesCommand(output, fileFacades, assignedMediaRows); + command.Execute(); + } + + // Modularize identifiers and add tables with real streams to the import tables. + if (OutputType.Module == output.Type) + { + // Gather all the suppress modularization identifiers + var suppressModularizationIdentifiers = new HashSet(section.Tuples.OfType().Select(s => s.WixSuppressModularization)); + + foreach (var table in output.Tables) + { + table.Modularize(modularizationGuid, suppressModularizationIdentifiers); + } + } + +#if TODO_FINISH_UPDATE // Extended binder extensions can be called now that fields are resolved. { Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]); @@ -372,27 +355,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind command.Execute(); } } +#endif - // stop processing if an error previously occurred + // Stop processing if an error previously occurred. if (Messaging.Instance.EncounteredError) { return; } + // Ensure the intermediate folder is created since delta patches will be + // created there. Directory.CreateDirectory(this.IntermediateFolder); - if (OutputType.Patch == this.Output.Type && this.DeltaBinaryPatch) + if (SectionType.Patch == section.Type && this.DeltaBinaryPatch) { - CreateDeltaPatchesCommand command = new CreateDeltaPatchesCommand(); - command.FileFacades = fileFacades; - command.WixPatchIdTable = this.Output.Tables["WixPatchId"]; - command.TempFilesLocation = this.IntermediateFolder; + var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Tuples.OfType().FirstOrDefault()); command.Execute(); } // create cabinet files and process uncompressed files string layoutDirectory = Path.GetDirectoryName(this.OutputPath); - if (!this.SuppressLayout || OutputType.Module == this.Output.Type) + if (!this.SuppressLayout || OutputType.Module == output.Type) { Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles()); @@ -400,7 +383,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind command.CabbingThreadCount = this.CabbingThreadCount; command.CabCachePath = this.CabCachePath; command.DefaultCompressionLevel = this.DefaultCompressionLevel; - command.Output = this.Output; + command.Output = output; command.BackendExtensions = this.BackendExtensions; command.LayoutDirectory = layoutDirectory; command.Compressed = compressed; @@ -408,39 +391,35 @@ namespace WixToolset.Core.WindowsInstaller.Bind command.ResolveMedia = this.ResolveMedia; command.TableDefinitions = this.TableDefinitions; command.TempFilesLocation = this.IntermediateFolder; - command.WixMediaTable = this.Output.Tables["WixMedia"]; + command.WixMediaTable = output.Tables["WixMedia"]; command.Execute(); fileTransfers.AddRange(command.FileTransfers); } +#if TODO_FINISH_PATCH if (OutputType.Patch == this.Output.Type) { // copy output data back into the transforms this.CopyToTransformData(this.Output); } +#endif - // stop processing if an error previously occurred - if (Messaging.Instance.EncounteredError) - { - return; - } - - // add back suppressed tables which must be present prior to merging in modules - if (OutputType.Product == this.Output.Type) + // Add back suppressed tables which must be present prior to merging in modules. + if (OutputType.Product == output.Type) { - Table wixMergeTable = this.Output.Tables["WixMerge"]; + Table wixMergeTable = output.Tables["WixMerge"]; if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count) { foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable))) { string sequenceTableName = sequence.ToString(); - Table sequenceTable = this.Output.Tables[sequenceTableName]; + Table sequenceTable = output.Tables[sequenceTableName]; if (null == sequenceTable) { - sequenceTable = this.Output.EnsureTable(this.TableDefinitions[sequenceTableName]); + sequenceTable = output.EnsureTable(this.TableDefinitions[sequenceTableName]); } if (0 == sequenceTable.Rows.Count) @@ -456,67 +435,59 @@ namespace WixToolset.Core.WindowsInstaller.Bind // extension.PostBind(this.Context); //} - // generate database file + this.ValidateComponentGuids(output); + + // stop processing if an error previously occurred + if (Messaging.Instance.EncounteredError) + { + return; + } + + // Generate database file. Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase()); string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); - this.GenerateDatabase(this.Output, tempDatabaseFile, false, false); + this.GenerateDatabase(output, tempDatabaseFile, false, false); - FileTransfer transfer; - if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, this.Output.Type.ToString(), null, out transfer)) // note where this database needs to move in the future + if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, output.Type.ToString(), null, out var transfer)) // note where this database needs to move in the future { transfer.Built = true; fileTransfers.Add(transfer); } - // stop processing if an error previously occurred + // Stop processing if an error previously occurred. if (Messaging.Instance.EncounteredError) { return; } - // Output the output to a file + // Output the output to a file. Pdb pdb = new Pdb(); - pdb.Output = this.Output; + pdb.Output = output; if (!String.IsNullOrEmpty(this.PdbFile)) { pdb.Save(this.PdbFile); } // Merge modules. - if (OutputType.Product == this.Output.Type) + if (OutputType.Product == output.Type) { Messaging.Instance.OnMessage(WixVerboses.MergingModules()); - MergeModulesCommand command = new MergeModulesCommand(); + var command = new MergeModulesCommand(); command.FileFacades = fileFacades; - command.Output = this.Output; + command.Output = output; command.OutputPath = tempDatabaseFile; command.SuppressedTableNames = suppressedTableNames; command.Execute(); - - // stop processing if an error previously occurred - if (Messaging.Instance.EncounteredError) - { - return; - } } - // inspect the MSI prior to running ICEs - //InspectorCore inspectorCore = new InspectorCore(); - //foreach (InspectorExtension inspectorExtension in this.InspectorExtensions) - //{ - // inspectorExtension.Core = inspectorCore; - // inspectorExtension.InspectDatabase(tempDatabaseFile, pdb); - - // inspectorExtension.Core = null; // reset. - //} - if (Messaging.Instance.EncounteredError) { return; } - // validate the output if there is an MSI validator +#if TODO_FINISH_VALIDATION + // Validate the output if there is an MSI validator. if (null != this.Validator) { Stopwatch stopwatch = Stopwatch.StartNew(); @@ -537,19 +508,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind return; } } +#endif // Process uncompressed files. if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) { - var command = new ProcessUncompressedFilesCommand(); + var command = new ProcessUncompressedFilesCommand(section); command.Compressed = compressed; command.FileFacades = uncompressedFiles; command.LayoutDirectory = layoutDirectory; command.LongNamesInImage = longNames; - command.MediaRows = assignedMediaRows; command.ResolveMedia = this.ResolveMedia; command.DatabasePath = tempDatabaseFile; - command.WixMediaTable = this.Output.Tables["WixMedia"]; command.Execute(); fileTransfers.AddRange(command.FileTransfers); @@ -557,94 +527,92 @@ namespace WixToolset.Core.WindowsInstaller.Bind this.FileTransfers = fileTransfers; this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList(); + + // TODO: Eventually this gets removed + var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths); + intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir")); } /// /// Localize dialogs and controls. /// /// The tables to localize. - private void LocalizeUI(TableIndexedCollection tables) + private void LocalizeUI(IntermediateSection section) { - Table dialogTable = tables["Dialog"]; - if (null != dialogTable) + foreach (var row in section.Tuples.OfType()) { - foreach (Row row in dialogTable.Rows) - { - string dialog = (string)row[0]; + string dialog = row.Dialog; - if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) + if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) + { + if (CompilerConstants.IntegerNotSet != localizedControl.X) { - if (CompilerConstants.IntegerNotSet != localizedControl.X) - { - row[1] = localizedControl.X; - } + row.HCentering = localizedControl.X; + } - if (CompilerConstants.IntegerNotSet != localizedControl.Y) - { - row[2] = localizedControl.Y; - } + if (CompilerConstants.IntegerNotSet != localizedControl.Y) + { + row.VCentering = localizedControl.Y; + } - if (CompilerConstants.IntegerNotSet != localizedControl.Width) - { - row[3] = localizedControl.Width; - } + if (CompilerConstants.IntegerNotSet != localizedControl.Width) + { + row.Width = localizedControl.Width; + } - if (CompilerConstants.IntegerNotSet != localizedControl.Height) - { - row[4] = localizedControl.Height; - } + if (CompilerConstants.IntegerNotSet != localizedControl.Height) + { + row.Height = localizedControl.Height; + } - row[5] = (int)row[5] | localizedControl.Attributes; + row.Attributes = row.Attributes | localizedControl.Attributes; - if (!String.IsNullOrEmpty(localizedControl.Text)) - { - row[6] = localizedControl.Text; - } + if (!String.IsNullOrEmpty(localizedControl.Text)) + { + row.Title = localizedControl.Text; } } } - Table controlTable = tables["Control"]; - if (null != controlTable) + + foreach (var row in section.Tuples.OfType()) { - foreach (Row row in controlTable.Rows) - { - string dialog = (string)row[0]; - string control = (string)row[1]; + string dialog = row.Dialog_; + string control = row.Control; - if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) + if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) + { + if (CompilerConstants.IntegerNotSet != localizedControl.X) { - if (CompilerConstants.IntegerNotSet != localizedControl.X) - { - row[3] = localizedControl.X.ToString(); - } + row.X = localizedControl.X; + } - if (CompilerConstants.IntegerNotSet != localizedControl.Y) - { - row[4] = localizedControl.Y.ToString(); - } + if (CompilerConstants.IntegerNotSet != localizedControl.Y) + { + row.Y = localizedControl.Y; + } - if (CompilerConstants.IntegerNotSet != localizedControl.Width) - { - row[5] = localizedControl.Width.ToString(); - } + if (CompilerConstants.IntegerNotSet != localizedControl.Width) + { + row.Width = localizedControl.Width; + } - if (CompilerConstants.IntegerNotSet != localizedControl.Height) - { - row[6] = localizedControl.Height.ToString(); - } + if (CompilerConstants.IntegerNotSet != localizedControl.Height) + { + row.Height = localizedControl.Height; + } - row[7] = (int)row[7] | localizedControl.Attributes; + row.Attributes = row.Attributes | localizedControl.Attributes; - if (!String.IsNullOrEmpty(localizedControl.Text)) - { - row[9] = localizedControl.Text; - } + if (!String.IsNullOrEmpty(localizedControl.Text)) + { + row.Text = localizedControl.Text; } } } } +#if TODO_FINISH_PATCH /// /// Copy file data between transform substorages and the patch output object /// @@ -674,269 +642,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind command.TableDefinitions = this.TableDefinitions; command.Execute(); } +#endif - private void UpdateMediaSequences(OutputType outputType, IEnumerable fileFacades, RowDictionary mediaRows) - { - // Calculate sequence numbers and media disk id layout for all file media information objects. - if (OutputType.Module == outputType) - { - int lastSequence = 0; - foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI. - { - facade.File.Sequence = ++lastSequence; - } - } - else - { - int lastSequence = 0; - MediaRow mediaRow = null; - Dictionary> patchGroups = new Dictionary>(); - - // sequence the non-patch-added files - foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI. - { - if (null == mediaRow) - { - mediaRow = mediaRows.Get(facade.WixFile.DiskId); - if (OutputType.Patch == outputType) - { - // patch Media cannot start at zero - lastSequence = mediaRow.LastSequence; - } - } - else if (mediaRow.DiskId != facade.WixFile.DiskId) - { - mediaRow.LastSequence = lastSequence; - mediaRow = mediaRows.Get(facade.WixFile.DiskId); - } - - if (0 < facade.WixFile.PatchGroup) - { - List patchGroup = patchGroups[facade.WixFile.PatchGroup]; - - if (null == patchGroup) - { - patchGroup = new List(); - patchGroups.Add(facade.WixFile.PatchGroup, patchGroup); - } - - patchGroup.Add(facade); - } - else - { - facade.File.Sequence = ++lastSequence; - } - } - - if (null != mediaRow) - { - mediaRow.LastSequence = lastSequence; - mediaRow = null; - } - - // sequence the patch-added files - foreach (List patchGroup in patchGroups.Values) - { - foreach (FileFacade facade in patchGroup) - { - if (null == mediaRow) - { - mediaRow = mediaRows.Get(facade.WixFile.DiskId); - } - else if (mediaRow.DiskId != facade.WixFile.DiskId) - { - mediaRow.LastSequence = lastSequence; - mediaRow = mediaRows.Get(facade.WixFile.DiskId); - } - - facade.File.Sequence = ++lastSequence; - } - } - - if (null != mediaRow) - { - mediaRow.LastSequence = lastSequence; - } - } - } - - /// - /// Set the guids for components with generatable guids. - /// - /// Internal representation of the database to operate on. - private void SetComponentGuids(Output output) - { - Table componentTable = output.Tables["Component"]; - if (null != componentTable) - { - Hashtable registryKeyRows = null; - Hashtable directories = null; - Hashtable componentIdGenSeeds = null; - Dictionary> fileRows = null; - - // find components with generatable guids - foreach (ComponentRow componentRow in componentTable.Rows) - { - // component guid will be generated - if ("*" == componentRow.Guid) - { - if (null == componentRow.KeyPath || componentRow.IsOdbcDataSourceKeyPath) - { - Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers)); - } - else if (componentRow.IsRegistryKeyPath) - { - if (null == registryKeyRows) - { - Table registryTable = output.Tables["Registry"]; - - registryKeyRows = new Hashtable(registryTable.Rows.Count); - - foreach (Row registryRow in registryTable.Rows) - { - registryKeyRows.Add((string)registryRow[0], registryRow); - } - } - - Row foundRow = registryKeyRows[componentRow.KeyPath] as Row; - - string bitness = componentRow.Is64Bit ? "64" : String.Empty; - if (null != foundRow) - { - string regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]); - componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant(); - } - } - else // must be a File KeyPath - { - // if the directory table hasn't been loaded into an indexed hash - // of directory ids to target names do that now. - if (null == directories) - { - Table directoryTable = output.Tables["Directory"]; - - int numDirectoryTableRows = (null != directoryTable) ? directoryTable.Rows.Count : 0; - - directories = new Hashtable(numDirectoryTableRows); - - // get the target paths for all directories - if (null != directoryTable) - { - foreach (Row row in directoryTable.Rows) - { - // if the directory Id already exists, we will skip it here since - // checking for duplicate primary keys is done later when importing tables - // into database - if (directories.ContainsKey(row[0])) - { - continue; - } - - string targetName = Common.GetName((string)row[2], false, true); - directories.Add(row[0], new ResolvedDirectory((string)row[1], targetName)); - } - } - } - - // if the component id generation seeds have not been indexed - // from the WixDirectory table do that now. - if (null == componentIdGenSeeds) - { - Table wixDirectoryTable = output.Tables["WixDirectory"]; - - int numWixDirectoryRows = (null != wixDirectoryTable) ? wixDirectoryTable.Rows.Count : 0; - - componentIdGenSeeds = new Hashtable(numWixDirectoryRows); - - // if there are any WixDirectory rows, build up the Component Guid - // generation seeds indexed by Directory/@Id. - if (null != wixDirectoryTable) - { - foreach (Row row in wixDirectoryTable.Rows) - { - componentIdGenSeeds.Add(row[0], (string)row[1]); - } - } - } - - // if the file rows have not been indexed by File.Component yet - // then do that now - if (null == fileRows) - { - Table fileTable = output.Tables["File"]; - - int numFileRows = (null != fileTable) ? fileTable.Rows.Count : 0; - - fileRows = new Dictionary>(numFileRows); - - if (null != fileTable) - { - foreach (FileRow file in fileTable.Rows) - { - List files; - if (!fileRows.TryGetValue(file.Component, out files)) - { - files = new List(); - fileRows.Add(file.Component, files); - } - - files.Add(file); - } - } - } - - // validate component meets all the conditions to have a generated guid - List currentComponentFiles = fileRows[componentRow.Component]; - int numFilesInComponent = currentComponentFiles.Count; - string path = null; - - foreach (FileRow fileRow in currentComponentFiles) - { - if (fileRow.File == componentRow.KeyPath) - { - // calculate the key file's canonical target path - string directoryPath = Binder.GetDirectoryPath(directories, componentIdGenSeeds, componentRow.Directory, true); - string fileName = Common.GetName(fileRow.FileName, false, true).ToLower(CultureInfo.InvariantCulture); - path = Path.Combine(directoryPath, fileName); - - // find paths that are not canonicalized - if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) || - path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) || - path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) || - path.StartsWith("TARGETDIR", StringComparison.Ordinal) || - path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) || - path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal)) - { - Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component, path)); - } - - // if component has more than one file, the key path must be versioned - if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version)) - { - Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers)); - } - } - else - { - // not a key path, so it must be an unversioned file if component has more than one file - if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version)) - { - Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers)); - } - } - } - - // if the rules were followed, reward with a generated guid - if (!Messaging.Instance.EncounteredError) - { - componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant(); - } - } - } - } - } - } +#if TODO_FIX_INSTANCE_TRANSFORM /// /// Creates instance transform substorages in the output. /// @@ -1171,6 +880,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind } } } +#endif /// /// Validate that there are no duplicate GUIDs in the output. @@ -1186,7 +896,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind { Dictionary componentGuidConditions = new Dictionary(componentTable.Rows.Count); - foreach (ComponentRow row in componentTable.Rows) + foreach (Data.Rows.ComponentRow row in componentTable.Rows) { // we don't care about unmanaged components and if there's a * GUID remaining, // there's already an error that prevented it from being replaced with a real GUID. @@ -1221,7 +931,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind /// Internal representation of the msi database to operate upon. private void UpdateControlText(Output output) { - UpdateControlTextCommand command = new UpdateControlTextCommand(); + var command = new UpdateControlTextCommand(); command.BBControlTable = output.Tables["BBControl"]; command.WixBBControlTable = output.Tables["WixBBControl"]; command.ControlTable = output.Tables["Control"]; @@ -1229,7 +939,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind command.Execute(); } - private string ResolveMedia(MediaRow mediaRow, string mediaLayoutDirectory, string layoutDirectory) + private string ResolveMedia(MediaTuple mediaRow, string mediaLayoutDirectory, string layoutDirectory) { string layout = null; @@ -1282,7 +992,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind command.TempFilesLocation = this.IntermediateFolder; command.Codepage = this.Codepage; command.Execute(); -#endif } } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs index 5471792d..c9286a38 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs @@ -1,20 +1,24 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Globalization; + using System.Linq; using WixToolset.Data; + using WixToolset.Data.Tuples; /// /// Binds the summary information table of a database. /// internal class BindSummaryInfoCommand { - /// - /// The output to bind. - /// - public Output Output { private get; set; } + public BindSummaryInfoCommand(IntermediateSection section) + { + this.Section = section; + } + + private IntermediateSection Section { get; } /// /// Returns a flag indicating if files are compressed by default. @@ -40,95 +44,97 @@ namespace WixToolset.Core.WindowsInstaller.Databases this.InstallerVersion = 0; this.ModularizationGuid = null; - Table summaryInformationTable = this.Output.Tables["_SummaryInformation"]; + bool foundCreateDataTime = false; + bool foundLastSaveDataTime = false; + bool foundCreatingApplication = false; + string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); - if (null != summaryInformationTable) + foreach (var summaryInformationRow in this.Section.Tuples.OfType<_SummaryInformationTuple>()) { - bool foundCreateDataTime = false; - bool foundLastSaveDataTime = false; - bool foundCreatingApplication = false; - string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); - - foreach (Row summaryInformationRow in summaryInformationTable.Rows) + switch (summaryInformationRow.PropertyId) { - switch (summaryInformationRow.FieldAsInteger(0)) - { - case 1: // PID_CODEPAGE + case 1: // PID_CODEPAGE // make sure the code page is an int and not a web name or null - string codepage = summaryInformationRow.FieldAsString(1); - - if (null == codepage) - { - codepage = "0"; - } - else - { - summaryInformationRow[1] = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); - } - break; - case 9: // PID_REVNUMBER - string packageCode = (string)summaryInformationRow[1]; - - if (OutputType.Module == this.Output.Type) - { - this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_'); - } - else if ("*" == packageCode) - { - // set the revision number (package/patch code) if it should be automatically generated - summaryInformationRow[1] = Common.GenerateGuid(); - } - break; - case 12: // PID_CREATE_DTM - foundCreateDataTime = true; - break; - case 13: // PID_LASTSAVE_DTM - foundLastSaveDataTime = true; - break; - case 14: - this.InstallerVersion = summaryInformationRow.FieldAsInteger(1); - break; - case 15: // PID_WORDCOUNT - if (OutputType.Patch == this.Output.Type) - { - this.LongNames = true; - this.Compressed = true; - } - else - { - this.LongNames = (0 == (summaryInformationRow.FieldAsInteger(1) & 1)); - this.Compressed = (2 == (summaryInformationRow.FieldAsInteger(1) & 2)); - } - break; - case 18: // PID_APPNAME - foundCreatingApplication = true; - break; - } - } + var codepage = summaryInformationRow.Value; - // add a summary information row for the create time/date property if its not already set - if (!foundCreateDataTime) - { - Row createTimeDateRow = summaryInformationTable.CreateRow(null); - createTimeDateRow[0] = 12; - createTimeDateRow[1] = now; - } + if (String.IsNullOrEmpty(codepage)) + { + codepage = "0"; + } + else + { + summaryInformationRow.Value = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); + } + break; + case 9: // PID_REVNUMBER + var packageCode = summaryInformationRow.Value; - // add a summary information row for the last save time/date property if its not already set - if (!foundLastSaveDataTime) - { - Row lastSaveTimeDateRow = summaryInformationTable.CreateRow(null); - lastSaveTimeDateRow[0] = 13; - lastSaveTimeDateRow[1] = now; + if (SectionType.Module == this.Section.Type) + { + this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_'); + } + else if ("*" == packageCode) + { + // set the revision number (package/patch code) if it should be automatically generated + summaryInformationRow.Value = Common.GenerateGuid(); + } + break; + case 12: // PID_CREATE_DTM + foundCreateDataTime = true; + break; + case 13: // PID_LASTSAVE_DTM + foundLastSaveDataTime = true; + break; + case 14: + this.InstallerVersion = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); + break; + case 15: // PID_WORDCOUNT + if (SectionType.Patch == this.Section.Type) + { + this.LongNames = true; + this.Compressed = true; + } + else + { + var attributes = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); + this.LongNames = (0 == (attributes & 1)); + this.Compressed = (2 == (attributes & 2)); + } + break; + case 18: // PID_APPNAME + foundCreatingApplication = true; + break; } + } - // add a summary information row for the creating application property if its not already set - if (!foundCreatingApplication) - { - Row creatingApplicationRow = summaryInformationTable.CreateRow(null); - creatingApplicationRow[0] = 18; - creatingApplicationRow[1] = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString()); - } + // add a summary information row for the create time/date property if its not already set + if (!foundCreateDataTime) + { + var createTimeDateRow = new _SummaryInformationTuple(null, new Identifier(12, AccessModifier.Private)); + createTimeDateRow.PropertyId = 12; + createTimeDateRow.Value = now; + + this.Section.Tuples.Add(createTimeDateRow); + } + + // add a summary information row for the last save time/date property if its not already set + if (!foundLastSaveDataTime) + { + var lastSaveTimeDateRow = new _SummaryInformationTuple(null, new Identifier(13, AccessModifier.Private)); + lastSaveTimeDateRow.PropertyId = 13; + lastSaveTimeDateRow.Value = now; + + this.Section.Tuples.Add(lastSaveTimeDateRow); + } + + // add a summary information row for the creating application property if its not already set + if (!foundCreatingApplication) + { + var creatingApplicationRow = new _SummaryInformationTuple(null, new Identifier(18, AccessModifier.Private)); + creatingApplicationRow.PropertyId = 18; + creatingApplicationRow.Value = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString()); + + this.Section.Tuples.Add(creatingApplicationRow); } } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs index 425d1f9c..b4027834 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs index b2cc76fc..c25a497e 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections; diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs index dcafcd36..405b840b 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs @@ -1,11 +1,10 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System.Collections.Generic; using WixToolset.Core.Bind; using WixToolset.Data; - using WixToolset.Data.Rows; /// /// A cabinet builder work item. diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs new file mode 100644 index 00000000..0c0aea1f --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs @@ -0,0 +1,174 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core.WindowsInstaller.Bind +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using WixToolset.Bind; + using WixToolset.Core.Native; + using WixToolset.Data; + using WixToolset.Data.Tuples; + + /// + /// Set the guids for components with generatable guids. + /// + internal class CalculateComponentGuids + { + public CalculateComponentGuids(IntermediateSection section) + { + this.Section = section; + } + + private IntermediateSection Section { get; } + + public void Execute() + { + Dictionary registryKeyRows = null; + Dictionary targetPathsByDirectoryId = null; + Dictionary componentIdGenSeeds = null; + Dictionary> filesByComponentId = null; + + // Find components with generatable guids. + foreach (var componentRow in this.Section.Tuples.OfType()) + { + // Skip components that do not specify generate guid. + if (componentRow.ComponentId != "*") + { + continue; + } + + var odbcDataSourceKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesODBCDataSource) != 0; + + if (String.IsNullOrEmpty(componentRow.KeyPath) || odbcDataSourceKeyPath) + { + Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers)); + continue; + } + + var registryKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesRegistryKeyPath) != 0; + + if (registryKeyPath) + { + if (registryKeyRows is null) + { + registryKeyRows = this.Section.Tuples.OfType().ToDictionary(t => t.Registry); + } + + if (registryKeyRows.TryGetValue(componentRow.KeyPath, out var foundRow)) + { + var is64Bit = (componentRow.Attributes & MsiInterop.MsidbComponentAttributes64bit) != 0; + var bitness = is64Bit ? "64" : String.Empty; + var regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]); + componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant(); + } + } + else // must be a File KeyPath. + { + // If the directory table hasn't been loaded into an indexed hash + // of directory ids to target names do that now. + if (targetPathsByDirectoryId is null) + { + var directories = this.Section.Tuples.OfType().ToList(); + + targetPathsByDirectoryId = new Dictionary(directories.Count); + + // Get the target paths for all directories. + foreach (var row in directories) + { + // If the directory Id already exists, we will skip it here since + // checking for duplicate primary keys is done later when importing tables + // into database + if (targetPathsByDirectoryId.ContainsKey(row.Directory)) + { + continue; + } + + var targetName = Common.GetName(row.DefaultDir, false, true); + targetPathsByDirectoryId.Add(row.Directory, new ResolvedDirectory(row.Directory_Parent, targetName)); + } + } + + // If the component id generation seeds have not been indexed + // from the WixDirectory table do that now. + if (componentIdGenSeeds is null) + { + // If there are any WixDirectory rows, build up the Component Guid + // generation seeds indexed by Directory/@Id. + componentIdGenSeeds = this.Section.Tuples.OfType() + .Where(t => !String.IsNullOrEmpty(t.ComponentGuidGenerationSeed)) + .ToDictionary(t => t.Directory_, t => t.ComponentGuidGenerationSeed); + } + + // if the file rows have not been indexed by File.Component yet + // then do that now + if (filesByComponentId is null) + { + var files = this.Section.Tuples.OfType().ToList(); + + filesByComponentId = new Dictionary>(files.Count); + + foreach (var file in files) + { + if (!filesByComponentId.TryGetValue(file.Component_, out var componentFiles)) + { + componentFiles = new List(); + filesByComponentId.Add(file.Component_, componentFiles); + } + + componentFiles.Add(file); + } + } + + // validate component meets all the conditions to have a generated guid + var currentComponentFiles = filesByComponentId[componentRow.Component]; + var numFilesInComponent = currentComponentFiles.Count; + string path = null; + + foreach (var fileRow in currentComponentFiles) + { + if (fileRow.File == componentRow.KeyPath) + { + // calculate the key file's canonical target path + string directoryPath = Binder.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentRow.Directory_, true); + string fileName = Common.GetName(fileRow.LongFileName, false, true).ToLowerInvariant(); + path = Path.Combine(directoryPath, fileName); + + // find paths that are not canonicalized + if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) || + path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) || + path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) || + path.StartsWith("TARGETDIR", StringComparison.Ordinal) || + path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) || + path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal)) + { + Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component_, path)); + } + + // if component has more than one file, the key path must be versioned + if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version)) + { + Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers)); + } + } + else + { + // not a key path, so it must be an unversioned file if component has more than one file + if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version)) + { + Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers)); + } + } + } + + // if the rules were followed, reward with a generated guid + if (!Messaging.Instance.EncounteredError) + { + componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant(); + } + } + } + } + } +} diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs index d4d3799f..9a8e2bba 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections; diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs index 6388a352..0dcddb99 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; @@ -10,6 +10,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases using WixToolset.Extensibility; using WixToolset.Core.Native; using WixToolset.Core.Bind; + using WixToolset.Data.Tuples; internal class CopyTransformDataCommand { @@ -29,7 +30,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases List allFileRows = this.CopyOutFileRows ? new List() : null; -#if false // TODO: Fix this patching related code to work correctly with FileFacades. +#if REVISIT_FOR_PATCHING // TODO: Fix this patching related code to work correctly with FileFacades. bool copyToPatch = (allFileRows != null); bool copyFromPatch = !copyToPatch; @@ -454,7 +455,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases } Row patchAction = iesTable.CreateRow(null); - WixActionRow wixPatchAction = WindowsInstallerStandard.GetStandardActions()[table, "PatchFiles"]; + WixActionRow wixPatchAction = WindowsInstallerStandardInternal.GetStandardActionRows()[table, "PatchFiles"]; int sequence = wixPatchAction.Sequence; // Test for default sequence value's appropriateness if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence)) diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs index 02015744..b5a436c5 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; @@ -10,10 +10,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases using System.Runtime.InteropServices; using System.Threading; using WixToolset.Core.Bind; - using WixToolset.Core.WindowsInstaller.Bind; using WixToolset.Data; using WixToolset.Data.Bind; using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; using WixToolset.Extensibility; /// @@ -60,9 +60,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases public bool Compressed { private get; set; } - public Dictionary> FileRowsByCabinet { private get; set; } + public Dictionary> FileRowsByCabinet { private get; set; } - public Func ResolveMedia { private get; set; } + public Func ResolveMedia { private get; set; } public TableDefinitionCollection TableDefinitions { private get; set; } @@ -77,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// The uncompressed file rows. public void Execute() { - RowDictionary wixMediaRows = new RowDictionary(this.WixMediaTable); + var wixMediaRows = new RowDictionary(this.WixMediaTable); this.lastCabinetAddedToMediaTable = new Dictionary(); @@ -87,22 +87,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); // Supply Compile MediaTemplate Attributes to Cabinet Builder - int MaximumCabinetSizeForLargeFileSplitting; - int MaximumUncompressedMediaSize; - this.GetMediaTemplateAttributes(out MaximumCabinetSizeForLargeFileSplitting, out MaximumUncompressedMediaSize); + this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize); cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting; cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize; foreach (var entry in this.FileRowsByCabinet) { - MediaRow mediaRow = entry.Key; + var mediaRow = entry.Key; IEnumerable files = entry.Value; CompressionLevel compressionLevel = this.DefaultCompressionLevel; - WixMediaRow wixMediaRow = null; string mediaLayoutFolder = null; - if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) + if (wixMediaRows.TryGetValue(mediaRow.Id.Id, out var wixMediaRow)) { mediaLayoutFolder = wixMediaRow.Layout; @@ -185,7 +182,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// Collection of files in this cabinet. /// Array of files to be transfered. /// created CabinetWorkItem object - private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaRow mediaRow, CompressionLevel compressionLevel, IEnumerable fileFacades, List fileTransfers) + private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaTuple mediaRow, CompressionLevel compressionLevel, IEnumerable fileFacades, List fileTransfers) { CabinetWorkItem cabinetWorkItem = null; string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); @@ -254,8 +251,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases else { string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); - FileTransfer transfer; - if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out transfer)) + if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out var transfer)) { transfer.Built = true; fileTransfers.Add(transfer); diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs index 42a69310..7c7b07cc 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; @@ -9,49 +9,40 @@ namespace WixToolset.Core.WindowsInstaller.Databases using WixToolset.Core.Bind; using WixToolset.Data; using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; /// /// Creates delta patches and updates the appropriate rows to point to the newly generated patches. /// internal class CreateDeltaPatchesCommand { - public IEnumerable FileFacades { private get; set; } + public CreateDeltaPatchesCommand(List fileFacades, string intermediateFolder, WixPatchIdTuple wixPatchId) + { + this.FileFacades = fileFacades; + this.IntermediateFolder = intermediateFolder; + this.WixPatchId = wixPatchId; + } - public Table WixPatchIdTable { private get; set; } + private IEnumerable FileFacades { get; } - public string TempFilesLocation { private get; set; } + private WixPatchIdTuple WixPatchId { get; } + + private string IntermediateFolder { get; } public void Execute() { -#if REVISIT_FOR_PATCHING - bool optimizePatchSizeForLargeFiles = false; - PatchSymbolFlagsType apiPatchingSymbolFlags = 0; - - if (null != this.WixPatchIdTable) - { - Row row = this.WixPatchIdTable.Rows[0]; - if (null != row) - { - if (null != row[2]) - { - optimizePatchSizeForLargeFiles = (1 == Convert.ToUInt32(row[2], CultureInfo.InvariantCulture)); - } - - if (null != row[3]) - { - apiPatchingSymbolFlags = (PatchSymbolFlagsType)Convert.ToUInt32(row[3], CultureInfo.InvariantCulture); - } - } - } + var optimizePatchSizeForLargeFiles = this.WixPatchId?.OptimizePatchSizeForLargeFiles ?? false; + var apiPatchingSymbolFlags = (PatchSymbolFlagsType)(this.WixPatchId?.ApiPatchingSymbolFlags ?? 0); +#if REVISIT_FOR_PATCHING foreach (FileFacade facade in this.FileFacades) { if (RowOperation.Modify == facade.File.Operation && 0 != (facade.WixFile.PatchAttributes & PatchAttributeType.IncludeWholeFile)) { string deltaBase = String.Concat("delta_", facade.File.File); - string deltaFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".dpf")); - string headerFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".phd")); + string deltaFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".dpf")); + string headerFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".phd")); bool retainRangeWarning = false; @@ -84,6 +75,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases } } #endif + throw new NotImplementedException(); } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs new file mode 100644 index 00000000..85b3b25a --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs @@ -0,0 +1,230 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core.WindowsInstaller.Bind +{ + using System; + using System.Linq; + using WixToolset.Core.Native; + using WixToolset.Data; + using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; + + internal class CreateOutputFromIRCommand + { + public CreateOutputFromIRCommand(IntermediateSection section, TableDefinitionCollection tableDefinitions) + { + this.Section = section; + this.TableDefinitions = tableDefinitions; + } + + private TableDefinitionCollection TableDefinitions { get; } + + private IntermediateSection Section { get; } + + public Output Output { get; private set; } + + public void Execute() + { + var output = new Output(this.Section.Tuples.First().SourceLineNumbers); + output.Codepage = this.Section.Codepage; + output.Type = SectionTypeToOutputType(this.Section.Type); + + this.AddSectionToOutput(this.Section, output); + + this.Output = output; + } + + private void AddSectionToOutput(IntermediateSection section, Output output) + { + foreach (var tuple in section.Tuples) + { + switch (tuple.Definition.Type) + { + case TupleDefinitionType.File: + this.AddFileTuple((FileTuple)tuple, output); + break; + + case TupleDefinitionType.WixAction: + this.AddWixActionTuple((WixActionTuple)tuple, output); + break; + + default: + this.AddTupleDefaultly(tuple, output); + break; + } + } + } + + private void AddFileTuple(FileTuple tuple, Output output) + { + var table = output.EnsureTable(this.TableDefinitions["File"]); + var row = (FileRow)table.CreateRow(tuple.SourceLineNumbers); + row.File = tuple.File; + row.Component = tuple.Component_; + row.FileName = GetMsiFilenameValue(tuple.ShortFileName, tuple.LongFileName); + row.FileSize = tuple.FileSize; + row.Version = tuple.Version; + row.Language = tuple.Language; + + var attributes = tuple.Checksum ? MsiInterop.MsidbFileAttributesChecksum : 0; + attributes |= (tuple.Compressed.HasValue && tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesCompressed : 0; + attributes |= (tuple.Compressed.HasValue && !tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesNoncompressed : 0; + attributes |= tuple.Hidden ? MsiInterop.MsidbFileAttributesHidden : 0; + attributes |= tuple.ReadOnly ? MsiInterop.MsidbFileAttributesReadOnly : 0; + attributes |= tuple.System ? MsiInterop.MsidbFileAttributesSystem : 0; + attributes |= tuple.Vital ? MsiInterop.MsidbFileAttributesVital : 0; + row.Attributes = attributes; + } + + private void AddWixActionTuple(WixActionTuple actionRow, Output output) + { + // Get the table definition for the action (and ensure the proper table exists for a module). + TableDefinition sequenceTableDefinition = null; + switch (actionRow.SequenceTable) + { + case SequenceTable.AdminExecuteSequence: + if (OutputType.Module == output.Type) + { + output.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]); + sequenceTableDefinition = this.TableDefinitions["ModuleAdminExecuteSequence"]; + } + else + { + sequenceTableDefinition = this.TableDefinitions["AdminExecuteSequence"]; + } + break; + case SequenceTable.AdminUISequence: + if (OutputType.Module == output.Type) + { + output.EnsureTable(this.TableDefinitions["AdminUISequence"]); + sequenceTableDefinition = this.TableDefinitions["ModuleAdminUISequence"]; + } + else + { + sequenceTableDefinition = this.TableDefinitions["AdminUISequence"]; + } + break; + case SequenceTable.AdvtExecuteSequence: + if (OutputType.Module == output.Type) + { + output.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]); + sequenceTableDefinition = this.TableDefinitions["ModuleAdvtExecuteSequence"]; + } + else + { + sequenceTableDefinition = this.TableDefinitions["AdvtExecuteSequence"]; + } + break; + case SequenceTable.InstallExecuteSequence: + if (OutputType.Module == output.Type) + { + output.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]); + sequenceTableDefinition = this.TableDefinitions["ModuleInstallExecuteSequence"]; + } + else + { + sequenceTableDefinition = this.TableDefinitions["InstallExecuteSequence"]; + } + break; + case SequenceTable.InstallUISequence: + if (OutputType.Module == output.Type) + { + output.EnsureTable(this.TableDefinitions["InstallUISequence"]); + sequenceTableDefinition = this.TableDefinitions["ModuleInstallUISequence"]; + } + else + { + sequenceTableDefinition = this.TableDefinitions["InstallUISequence"]; + } + break; + } + + // create the action sequence row in the output + var sequenceTable = output.EnsureTable(sequenceTableDefinition); + var row = sequenceTable.CreateRow(actionRow.SourceLineNumbers); + + if (SectionType.Module == this.Section.Type) + { + row[0] = actionRow.Action; + if (0 != actionRow.Sequence) + { + row[1] = actionRow.Sequence; + } + else + { + bool after = (null == actionRow.Before); + row[2] = after ? actionRow.After : actionRow.Before; + row[3] = after ? 1 : 0; + } + row[4] = actionRow.Condition; + } + else + { + row[0] = actionRow.Action; + row[1] = actionRow.Condition; + row[2] = actionRow.Sequence; + } + } + + private void AddTupleDefaultly(IntermediateTuple tuple, Output output) + { + if (!this.TableDefinitions.TryGet(tuple.Definition.Name, out var tableDefinition)) + { + return; + } + + var table = output.EnsureTable(tableDefinition); + var row = table.CreateRow(tuple.SourceLineNumbers); + for (var i = 0; i < tuple.Fields.Length; ++i) + { + if (i < tableDefinition.Columns.Count) + { + var column = tableDefinition.Columns[i]; + + switch (column.Type) + { + case ColumnType.Number: + row[i] = tuple.AsNumber(i); + break; + + default: + row[i] = tuple.AsString(i); + break; + } + } + } + } + + private static OutputType SectionTypeToOutputType(SectionType type) + { + switch (type) + { + case SectionType.Bundle: + return OutputType.Bundle; + case SectionType.Module: + return OutputType.Module; + case SectionType.Product: + return OutputType.Product; + case SectionType.PatchCreation: + return OutputType.PatchCreation; + case SectionType.Patch: + return OutputType.Patch; + + default: + throw new ArgumentOutOfRangeException(nameof(type)); + } + } + + private static string GetMsiFilenameValue(string shortName, string longName) + { + if (String.IsNullOrEmpty(shortName)) + { + return longName; + } + else + { + return shortName + "|" + longName; + } + } + } +} diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs index aef130b0..ab2e8201 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs @@ -1,67 +1,72 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; + using System.Linq; using WixToolset.Data; - using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; internal class CreateSpecialPropertiesCommand { - public Table PropertyTable { private get; set; } + public CreateSpecialPropertiesCommand(IntermediateSection section) + { + this.Section = section; + } - public Table WixPropertyTable { private get; set; } + private IntermediateSection Section { get; } public void Execute() { - // Create the special properties. - if (null != this.WixPropertyTable) - { - // Create lists of the properties that contribute to the special lists of properties. - SortedSet adminProperties = new SortedSet(); - SortedSet secureProperties = new SortedSet(); - SortedSet hiddenProperties = new SortedSet(); + // Create lists of the properties that contribute to the special lists of properties. + SortedSet adminProperties = new SortedSet(); + SortedSet secureProperties = new SortedSet(); + SortedSet hiddenProperties = new SortedSet(); - foreach (WixPropertyRow wixPropertyRow in this.WixPropertyTable.Rows) + foreach (var wixPropertyRow in this.Section.Tuples.OfType()) + { + if (wixPropertyRow.Admin) { - if (wixPropertyRow.Admin) - { - adminProperties.Add(wixPropertyRow.Id); - } - - if (wixPropertyRow.Hidden) - { - hiddenProperties.Add(wixPropertyRow.Id); - } - - if (wixPropertyRow.Secure) - { - secureProperties.Add(wixPropertyRow.Id); - } + adminProperties.Add(wixPropertyRow.Property_); } - Table propertyTable = this.PropertyTable; - if (0 < adminProperties.Count) + if (wixPropertyRow.Hidden) { - PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); - row.Property = "AdminProperties"; - row.Value = String.Join(";", adminProperties); + hiddenProperties.Add(wixPropertyRow.Property_); } - if (0 < secureProperties.Count) + if (wixPropertyRow.Secure) { - PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); - row.Property = "SecureCustomProperties"; - row.Value = String.Join(";", secureProperties); + secureProperties.Add(wixPropertyRow.Property_); } + } - if (0 < hiddenProperties.Count) - { - PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); - row.Property = "MsiHiddenProperties"; - row.Value = String.Join(";", hiddenProperties); - } + if (0 < adminProperties.Count) + { + var tuple = new PropertyTuple(null, new Identifier("AdminProperties", AccessModifier.Private)); + tuple.Property = "AdminProperties"; + tuple.Value = String.Join(";", adminProperties); + + this.Section.Tuples.Add(tuple); + } + + if (0 < secureProperties.Count) + { + var tuple = new PropertyTuple(null, new Identifier("SecureCustomProperties", AccessModifier.Private)); + tuple.Property = "SecureCustomProperties"; + tuple.Value = String.Join(";", secureProperties); + + this.Section.Tuples.Add(tuple); + } + + if (0 < hiddenProperties.Count) + { + var tuple = new PropertyTuple(null, new Identifier("MsiHiddenProperties", AccessModifier.Private)); + tuple.Property = "MsiHiddenProperties"; + tuple.Value = String.Join(";", hiddenProperties); + + this.Section.Tuples.Add(tuple); } } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs index 0d3e7bd1..32d1cfda 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; @@ -10,7 +10,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases using System.Linq; using System.Runtime.InteropServices; using WixToolset.Data; - using WixToolset.Data.Rows; using WixToolset.MergeMod; using WixToolset.Msi; using WixToolset.Core.Native; @@ -23,13 +22,17 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// internal class ExtractMergeModuleFilesCommand { - public IEnumerable FileFacades { private get; set; } + public ExtractMergeModuleFilesCommand(IntermediateSection section, List wixMergeTuples) + { + this.Section = section; + this.WixMergeTuples = wixMergeTuples; + } - public Table FileTable { private get; set; } + private IntermediateSection Section { get; } - public Table WixFileTable { private get; set; } + private List WixMergeTuples { get; } - public Table WixMergeTable { private get; set; } + public IEnumerable FileFacades { private get; set; } public int OutputInstallerVersion { private get; set; } @@ -41,7 +44,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases public void Execute() { - List mergeModulesFileFacades = new List(); + var mergeModulesFileFacades = new List(); IMsmMerge2 merge = MsmInterop.GetMsmMerge(); @@ -52,9 +55,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let // this case be slightly more expensive because the cost of maintaining an indexed file row collection // is a lot more costly for the common cases. - Dictionary indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal); + var indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal); - foreach (WixMergeRow wixMergeRow in this.WixMergeTable.Rows) + foreach (var wixMergeRow in this.WixMergeTuples) { bool containsFiles = this.CreateFacadesForMergeModuleFiles(wixMergeRow, mergeModulesFileFacades, indexedFileFacades); @@ -68,7 +71,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases this.MergeModulesFileFacades = mergeModulesFileFacades; } - private bool CreateFacadesForMergeModuleFiles(WixMergeRow wixMergeRow, List mergeModulesFileFacades, Dictionary indexedFileFacades) + private bool CreateFacadesForMergeModuleFiles(WixMergeTuple wixMergeRow, List mergeModulesFileFacades, Dictionary indexedFileFacades) { bool containsFiles = false; @@ -98,7 +101,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases // rows are created by merging in the actual modules. var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(record[1], AccessModifier.Private)); fileRow.File = record[1]; - fileRow.Compressed = (wixMergeRow.FileCompression == YesNoType.Yes) ? true : (wixMergeRow.FileCompression == YesNoType.No) ? (bool?)false : null; + fileRow.Compressed = wixMergeRow.FileCompression; //FileRow fileRow = (FileRow)this.FileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); //fileRow.File = record[1]; //fileRow.Compressed = wixMergeRow.FileCompression; @@ -107,7 +110,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases wixFileRow.Directory_ = record[2]; wixFileRow.DiskId = wixMergeRow.DiskId; wixFileRow.PatchGroup = -1; - wixFileRow.Source = Path.Combine(this.IntermediateFolder, "MergeId.", wixMergeRow.Number.ToString(CultureInfo.InvariantCulture), record[1]); + wixFileRow.Source = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]); //WixFileRow wixFileRow = (WixFileRow)this.WixFileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); //wixFileRow.Directory = record[2]; //wixFileRow.DiskId = wixMergeRow.DiskId; @@ -119,11 +122,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases // If case-sensitive collision with another merge module or a user-authored file identifier. if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade)) { - Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, collidingFacade.File.File)); + Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.File)); } else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module { - Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); + Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); } else // no collision { @@ -150,12 +153,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture); if (moduleInstallerVersion > this.OutputInstallerVersion) { - Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleInstallerVersion, this.OutputInstallerVersion)); + Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, moduleInstallerVersion, this.OutputInstallerVersion)); } } catch (FormatException) { - throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile, moduleInstallerVersionString)); + throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile, moduleInstallerVersionString)); } } } @@ -166,24 +169,26 @@ namespace WixToolset.Core.WindowsInstaller.Databases } catch (Win32Exception) { - throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile)); + throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile)); } return containsFiles; } - private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeRow wixMergeRow) + private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeTuple wixMergeRow) { bool moduleOpen = false; short mergeLanguage; + var mergeId = wixMergeRow.Id.Id; + try { mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); } - catch (System.FormatException) + catch (FormatException) { - Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); + Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, mergeId, wixMergeRow.Language.ToString())); return; } @@ -192,13 +197,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage); moduleOpen = true; - string safeMergeId = wixMergeRow.Number.ToString(CultureInfo.InvariantCulture.NumberFormat); - // extract the module cabinet, then explode all of the files to a temp directory - string moduleCabPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, safeMergeId, ".module.cab"); + string moduleCabPath = Path.Combine(this.IntermediateFolder, mergeId + ".cab"); merge.ExtractCAB(moduleCabPath); - string mergeIdPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, "MergeId.", safeMergeId); + string mergeIdPath = Path.Combine(this.IntermediateFolder, mergeId); Directory.CreateDirectory(mergeIdPath); using (var extractCab = new WixExtractCab()) diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs index 47b58058..a3d3ecf7 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs index 9bbb4763..70ba971f 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; @@ -8,57 +8,50 @@ namespace WixToolset.Core.WindowsInstaller.Databases using System.Linq; using WixToolset.Core.Bind; using WixToolset.Data; - using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; internal class GetFileFacadesCommand { - public Table FileTable { private get; set; } - - public Table WixFileTable { private get; set; } - - public Table WixDeltaPatchFileTable { private get; set; } + public GetFileFacadesCommand(IntermediateSection section) + { + this.Section = section; + } - public Table WixDeltaPatchSymbolPathsTable { private get; set; } + private IntermediateSection Section { get; } public List FileFacades { get; private set; } public void Execute() { - throw new NotImplementedException(); -#if TODO - List facades = new List(this.FileTable.Rows.Count); + var facades = new List(); - RowDictionary wixFiles = new RowDictionary(this.WixFileTable); - RowDictionary deltaPatchFiles = new RowDictionary(this.WixDeltaPatchFileTable); + var wixFiles = this.Section.Tuples.OfType().ToDictionary(t => t.File_); + var deltaPatchFiles = this.Section.Tuples.OfType().ToDictionary(t => t.File_); - foreach (FileRow file in this.FileTable.Rows) + foreach (var file in this.Section.Tuples.OfType()) { - WixDeltaPatchFileRow deltaPatchFile = null; + var wixFile = wixFiles[file.File]; - deltaPatchFiles.TryGetValue(file.File, out deltaPatchFile); + deltaPatchFiles.TryGetValue(file.File, out var deltaPatchFile); - facades.Add(new FileFacade(file, wixFiles[file.File], deltaPatchFile)); + facades.Add(new FileFacade(file, wixFile, deltaPatchFile)); } - if (null != this.WixDeltaPatchSymbolPathsTable) - { - this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades); - } + this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades); this.FileFacades = facades; -#endif } /// /// Merge data from the WixPatchSymbolPaths rows into the WixDeltaPatchFile rows. /// - public RowDictionary ResolveDeltaPatchSymbolPaths(RowDictionary deltaPatchFiles, IEnumerable facades) + public void ResolveDeltaPatchSymbolPaths(Dictionary deltaPatchFiles, IEnumerable facades) { ILookup filesByComponent = null; ILookup filesByDirectory = null; ILookup filesByDiskId = null; - foreach (WixDeltaPatchSymbolPathsRow row in this.WixDeltaPatchSymbolPathsTable.RowsAs().OrderBy(r => r.Type)) + foreach (var row in this.Section.Tuples.OfType().OrderBy(r => r.Type)) { switch (row.Type) { @@ -72,7 +65,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases filesByComponent = facades.ToLookup(f => f.File.Component_); } - foreach (FileFacade facade in filesByComponent[row.Id]) + foreach (var facade in filesByComponent[row.Id]) { this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); } @@ -84,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_); } - foreach (FileFacade facade in filesByDirectory[row.Id]) + foreach (var facade in filesByDirectory[row.Id]) { this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); } @@ -96,14 +89,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture)); } - foreach (FileFacade facade in filesByDiskId[row.Id]) + foreach (var facade in filesByDiskId[row.Id]) { this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); } break; case SymbolPathType.Product: - foreach (WixDeltaPatchFileRow fileRow in deltaPatchFiles.Values) + foreach (var fileRow in deltaPatchFiles.Values) { this.MergeSymbolPaths(row, fileRow); } @@ -114,8 +107,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases break; } } - - return deltaPatchFiles; } /// @@ -124,17 +115,18 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// Row from the WixPatchSymbolsPaths table. /// FileRow into which to set symbol information. /// This includes PreviousData as well. - private void MergeSymbolPaths(WixDeltaPatchSymbolPathsRow row, WixDeltaPatchFileRow file) + private void MergeSymbolPaths(WixDeltaPatchSymbolPathsTuple row, WixDeltaPatchFileTuple file) { - if (null == file.Symbols) + if (file.SymbolPaths is null) { - file.Symbols = row.SymbolPaths; + file.SymbolPaths = row.SymbolPaths; } else { - file.Symbols = String.Concat(file.Symbols, ";", row.SymbolPaths); + file.SymbolPaths = String.Concat(file.SymbolPaths, ";", row.SymbolPaths); } +#if REVISIT_FOR_PATCHING Field field = row.Fields[2]; if (null != field.PreviousData) { @@ -147,6 +139,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases file.PreviousSymbols = String.Concat(file.PreviousSymbols, ";", field.PreviousData); } } +#endif } } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs index f1605eca..dcf67c05 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs @@ -1,20 +1,13 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; - using System.Collections.Specialized; - using System.ComponentModel; - using System.Diagnostics; using System.Globalization; using System.IO; - using System.Linq; using System.Runtime.InteropServices; using System.Text; - using System.Xml; - using System.Xml.XPath; - using WixToolset.Clr.Interop; using WixToolset.Data; using WixToolset.Data.Rows; using WixToolset.MergeMod; @@ -35,12 +28,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases public IEnumerable SuppressedTableNames { private get; set; } - public string TempFilesLocation { private get; set; } + public string IntermediateFolder { private get; set; } public void Execute() { - Debug.Assert(OutputType.Product == this.Output.Type); - Table wixMergeTable = this.Output.Tables["WixMerge"]; Table wixFeatureModulesTable = this.Output.Tables["WixFeatureModules"]; @@ -59,7 +50,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases { merge = MsmInterop.GetMsmMerge(); - logPath = Path.Combine(this.TempFilesLocation, "merge.log"); + logPath = Path.Combine(this.IntermediateFolder, "merge.log"); merge.OpenLog(logPath); logOpen = true; @@ -79,7 +70,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases { mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); } - catch (System.FormatException) + catch (FormatException) { Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); continue; @@ -284,7 +275,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases Messaging.Instance.OnMessage(WixVerboses.ResequencingMergeModuleFiles()); using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?")) { - foreach (FileFacade file in this.FileFacades) + foreach (var file in this.FileFacades) { if (!file.FromModule) { @@ -307,32 +298,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases //recordUpdate.SetInteger(1, file.File.Sequence); throw new NotImplementedException(); - // update the file attributes to match the compression specified - // on the Merge element or on the Package element - int attributes = 0; + // Update the file attributes to match the compression specified + // on the Merge element or on the Package element. + var attributes = 0; - // get the current value if its not null + // Get the current value if its not null. if (!recordUpdate.IsNull(2)) { attributes = recordUpdate.GetInteger(2); } - // not specified if (!file.File.Compressed.HasValue) { - // clear any compression bits + // Clear all compression bits. attributes &= ~MsiInterop.MsidbFileAttributesCompressed; attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; } else if (file.File.Compressed.Value) { - // these are mutually exclusive attributes |= MsiInterop.MsidbFileAttributesCompressed; attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; } else if (!file.File.Compressed.Value) { - // these are mutually exclusive attributes |= MsiInterop.MsidbFileAttributesNoncompressed; attributes &= ~MsiInterop.MsidbFileAttributesCompressed; } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs index b3c09b9e..d71724d1 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs @@ -1,39 +1,42 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; - using System.Collections; using System.Collections.Generic; using System.IO; using WixToolset.Data; - using WixToolset.Data.Rows; using WixToolset.Msi; using WixToolset.Core.Native; using WixToolset.Bind; using WixToolset.Core.Bind; using WixToolset.Data.Bind; + using WixToolset.Data.Tuples; + using System.Linq; /// /// Defines the file transfers necessary to layout the uncompressed files. /// internal class ProcessUncompressedFilesCommand { + public ProcessUncompressedFilesCommand(IntermediateSection section) + { + this.Section = section; + } + + private IntermediateSection Section { get; } + public string DatabasePath { private get; set; } public IEnumerable FileFacades { private get; set; } - public RowDictionary MediaRows { private get; set; } - public string LayoutDirectory { private get; set; } public bool Compressed { private get; set; } public bool LongNamesInImage { private get; set; } - public Func ResolveMedia { private get; set; } - - public Table WixMediaTable { private get; set; } + public Func ResolveMedia { private get; set; } public IEnumerable FileTransfers { get; private set; } @@ -41,9 +44,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases { List fileTransfers = new List(); - Hashtable directories = new Hashtable(); + var directories = new Dictionary(); - RowDictionary wixMediaRows = new RowDictionary(this.WixMediaTable); + var mediaRows = this.Section.Tuples.OfType().ToDictionary(t => t.DiskId); + + var wixMediaRows = this.Section.Tuples.OfType().ToDictionary(t => t.DiskId_); using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) { @@ -72,18 +77,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases // for each file in the array of uncompressed files foreach (FileFacade facade in this.FileFacades) { - MediaRow mediaRow = this.MediaRows.Get(facade.WixFile.DiskId); + var mediaTuple = mediaRows[facade.WixFile.DiskId]; string relativeFileLayoutPath = null; - - WixMediaRow wixMediaRow = null; string mediaLayoutFolder = null; - if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) + if (wixMediaRows.TryGetValue(facade.WixFile.DiskId, out var wixMediaRow)) { mediaLayoutFolder = wixMediaRow.Layout; } - string mediaLayoutDirectory = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory); + var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory); // setup up the query record and find the appropriate file in the // previously executed file view @@ -102,8 +105,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases // finally put together the base media layout path and the relative file layout path string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); - FileTransfer transfer; - if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out transfer)) + if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out var transfer)) { fileTransfers.Add(transfer); } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs new file mode 100644 index 00000000..cf9c0332 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs @@ -0,0 +1,671 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core.WindowsInstaller.Bind +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using WixToolset.Core.Native; + using WixToolset.Data; + using WixToolset.Data.Tuples; + + internal class SequenceActionsCommand + { + public SequenceActionsCommand(IntermediateSection section) + { + this.Section = section; + + this.RelativeActionsForActions = new Dictionary(); + + this.StandardActionsById = WindowsInstallerStandard.StandardActions().ToDictionary(a => a.Id.Id); + } + + private IntermediateSection Section { get; } + + private Dictionary RelativeActionsForActions { get; } + + private Dictionary StandardActionsById { get; } + + public Messaging Messaging { private get; set; } + + public void Execute() + { + var actions = this.Section.Tuples.OfType().ToList(); + var suppressActions = this.Section.Tuples.OfType().ToList(); + + this.SequenceActions(actions, suppressActions); + } + + /// + /// Set sequence numbers for all the actions and create rows in the output object. + /// + /// Collection of actions to schedule. + /// Collection of actions to suppress. + private void SequenceActions(List actionRows, List suppressActionRows) + { + var overridableActionRows = new Dictionary(); + var requiredActionRows = new Dictionary(); + + // Get the standard actions required based on tuples in the section. + var requiredActionIds = this.GetRequiredActionIds(); + + foreach (var actionId in requiredActionIds) + { + var standardAction = this.StandardActionsById[actionId]; + + overridableActionRows.Add(standardAction.Id.Id, standardAction); + } + + // Index all the action rows and look for collisions. + foreach (var actionRow in this.Section.Tuples.OfType()) + { + if (actionRow.Overridable) // overridable action + { + if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) + { + this.Messaging.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); + if (null != collidingActionRow.SourceLineNumbers) + { + this.Messaging.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers)); + } + } + else + { + overridableActionRows.Add(actionRow.Id.Id, actionRow); + } + } + else // unsequenced or sequenced action. + { + // Unsequenced action (allowed for certain standard actions). + if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence) + { + if (this.StandardActionsById.TryGetValue(actionRow.Id.Id, out var standardAction)) + { + // Populate the sequence from the standard action + actionRow.Sequence = standardAction.Sequence; + } + else // not a supported unscheduled action. + { + throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); + } + } + + if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) + { + this.Messaging.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); + if (null != collidingActionRow.SourceLineNumbers) + { + this.Messaging.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers)); + } + } + else + { + requiredActionRows.Add(actionRow.Id.Id, actionRow); + } + } + } + + // Add the overridable action rows that are not overridden to the required action rows. + foreach (var actionRow in overridableActionRows.Values) + { + if (!requiredActionRows.ContainsKey(actionRow.Id.Id)) + { + requiredActionRows.Add(actionRow.Id.Id, actionRow); + } + } + + // Suppress the required actions that are overridable. + foreach (var suppressActionRow in suppressActionRows) + { + var key = suppressActionRow.Id.Id; + + // If there is an overridable row to suppress; suppress it. There is no warning if there + // is no action to suppress because the action may be suppressed from a merge module in + // the binder. + if (requiredActionRows.TryGetValue(key, out var requiredActionRow)) + { + if (requiredActionRow.Overridable) + { + this.Messaging.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, suppressActionRow.Action, suppressActionRow.SequenceTable.ToString())); + if (null != requiredActionRow.SourceLineNumbers) + { + this.Messaging.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers)); + } + + requiredActionRows.Remove(key); + } + else // suppressing a non-overridable action row + { + this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, suppressActionRow.SequenceTable.ToString(), suppressActionRow.Action)); + if (null != requiredActionRow.SourceLineNumbers) + { + this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers)); + } + } + } + } + + // Build up dependency trees of the relatively scheduled actions. + // Use ToList() to create a copy of the required action rows so that new tuples can + // be added while enumerating. + foreach (var actionRow in requiredActionRows.Values.ToList()) + { + if (0 == actionRow.Sequence) + { + // check for standard actions that don't have a sequence number in a merge module + if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action)) + { + this.Messaging.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); + } + + this.SequenceActionRow(actionRow, requiredActionRows); + } + else if (SectionType.Module == this.Section.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number + { + this.Messaging.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); + } + } + + // Look for standard actions with sequence restrictions that aren't necessarily scheduled based + // on the presence of a particular table. + if (requiredActionRows.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionRows.ContainsKey("InstallExecuteSequence/InstallFiles")) + { + var standardAction = this.StandardActionsById["InstallExecuteSequence/InstallFiles"]; + requiredActionRows.Add(standardAction.Id.Id, standardAction); + } + + // Schedule actions. + List scheduledActionRows; + if (SectionType.Module == this.Section.Type) + { + scheduledActionRows = requiredActionRows.Values.ToList(); + } + else + { + scheduledActionRows = ScheduleActions(requiredActionRows); + } + + // Remove all existing WixActionTuples from the section then add the + // scheduled actions back to the section. Note: we add the indices in + // reverse order to make it easy to remove them from the list later. + var removeIndices = new List(); + for (var i = this.Section.Tuples.Count - 1; i >= 0; --i) + { + var tuple = this.Section.Tuples[i]; + if (tuple.Definition.Type == TupleDefinitionType.WixAction) + { + removeIndices.Add(i); + } + } + + foreach (var removeIndex in removeIndices) + { + this.Section.Tuples.RemoveAt(removeIndex); + } + + foreach (var action in scheduledActionRows) + { + this.Section.Tuples.Add(action); + } + } + + private List ScheduleActions(Dictionary requiredActionRows) + { + var scheduledActionRows = new List(); + + // Process each sequence table individually. + foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable))) + { + // Create a collection of just the action rows in this sequence + var sequenceActionRows = requiredActionRows.Values.Where(a => a.SequenceTable == sequenceTable).ToList(); + + // Schedule the absolutely scheduled actions (by sorting them by their sequence numbers). + var absoluteActionRows = new List(); + foreach (var actionRow in sequenceActionRows) + { + if (0 != actionRow.Sequence) + { + // Look for sequence number collisions + foreach (var sequenceScheduledActionRow in absoluteActionRows) + { + if (sequenceScheduledActionRow.Sequence == actionRow.Sequence) + { + this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence)); + if (null != sequenceScheduledActionRow.SourceLineNumbers) + { + this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers)); + } + } + } + + absoluteActionRows.Add(actionRow); + } + } + + absoluteActionRows.Sort((x, y) => x.Sequence.CompareTo(y.Sequence)); + + // Schedule the relatively scheduled actions (by resolving the dependency trees). + var previousUsedSequence = 0; + var relativeActionRows = new List(); + for (int j = 0; j < absoluteActionRows.Count; j++) + { + var absoluteActionRow = absoluteActionRows[j]; + + // Get all the relatively scheduled action rows occuring before and after this absolutely scheduled action row. + var relativeActions = this.GetAllRelativeActionsForSequenceType(sequenceTable, absoluteActionRow); + + // Check for relatively scheduled actions occuring before/after a special action + // (those actions with a negative sequence number). + if (absoluteActionRow.Sequence < 0 && (relativeActions.PreviousActions.Any() || relativeActions.NextActions.Any())) + { + // Create errors for all the before actions. + foreach (var actionRow in relativeActions.PreviousActions) + { + this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); + } + + // Create errors for all the after actions. + foreach (var actionRow in relativeActions.NextActions) + { + this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); + } + + // If there is source line information for the absolutely scheduled action display it + if (absoluteActionRow.SourceLineNumbers != null) + { + this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers)); + } + + continue; + } + + // Schedule the action rows before this one. + var unusedSequence = absoluteActionRow.Sequence - 1; + for (var i = relativeActions.PreviousActions.Count - 1; i >= 0; i--) + { + var relativeActionRow = relativeActions.PreviousActions[i]; + + // look for collisions + if (unusedSequence == previousUsedSequence) + { + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); + if (absoluteActionRow.SourceLineNumbers != null) + { + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); + } + + unusedSequence++; + } + + relativeActionRow.Sequence = unusedSequence; + relativeActionRows.Add(relativeActionRow); + + unusedSequence--; + } + + // Determine the next used action sequence number. + var nextUsedSequence = Int16.MaxValue + 1; + if (absoluteActionRows.Count > j + 1) + { + nextUsedSequence = absoluteActionRows[j + 1].Sequence; + } + + // Schedule the action rows after this one. + unusedSequence = absoluteActionRow.Sequence + 1; + for (var i = 0; i < relativeActions.NextActions.Count; i++) + { + var relativeActionRow = relativeActions.NextActions[i]; + + if (unusedSequence == nextUsedSequence) + { + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); + if (absoluteActionRow.SourceLineNumbers != null) + { + this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); + } + + unusedSequence--; + } + + relativeActionRow.Sequence = unusedSequence; + relativeActionRows.Add(relativeActionRow); + + unusedSequence++; + } + + // keep track of this sequence number as the previous used sequence number for the next iteration + previousUsedSequence = absoluteActionRow.Sequence; + } + + // add the absolutely and relatively scheduled actions to the list of scheduled actions + scheduledActionRows.AddRange(absoluteActionRows); + scheduledActionRows.AddRange(relativeActionRows); + } + + return scheduledActionRows; + } + + private IEnumerable GetRequiredActionIds() + { + var set = new HashSet(); + + // gather the required actions for the output type + if (SectionType.Product == this.Section.Type) + { + // AdminExecuteSequence table + set.Add("AdminExecuteSequence/CostFinalize"); + set.Add("AdminExecuteSequence/CostInitialize"); + set.Add("AdminExecuteSequence/FileCost"); + set.Add("AdminExecuteSequence/InstallAdminPackage"); + set.Add("AdminExecuteSequence/InstallFiles"); + set.Add("AdminExecuteSequence/InstallFinalize"); + set.Add("AdminExecuteSequence/InstallInitialize"); + set.Add("AdminExecuteSequence/InstallValidate"); + + // AdminUISequence table + set.Add("AdminUISequence/CostFinalize"); + set.Add("AdminUISequence/CostInitialize"); + set.Add("AdminUISequence/ExecuteAction"); + set.Add("AdminUISequence/FileCost"); + + // AdvtExecuteSequence table + set.Add("AdvtExecuteSequence/CostFinalize"); + set.Add("AdvtExecuteSequence/CostInitialize"); + set.Add("AdvtExecuteSequence/InstallFinalize"); + set.Add("AdvtExecuteSequence/InstallValidate"); + set.Add("AdvtExecuteSequence/PublishFeatures"); + set.Add("AdvtExecuteSequence/PublishProduct"); + + // InstallExecuteSequence table + set.Add("InstallExecuteSequence/CostFinalize"); + set.Add("InstallExecuteSequence/CostInitialize"); + set.Add("InstallExecuteSequence/FileCost"); + set.Add("InstallExecuteSequence/InstallFinalize"); + set.Add("InstallExecuteSequence/InstallInitialize"); + set.Add("InstallExecuteSequence/InstallValidate"); + set.Add("InstallExecuteSequence/ProcessComponents"); + set.Add("InstallExecuteSequence/PublishFeatures"); + set.Add("InstallExecuteSequence/PublishProduct"); + set.Add("InstallExecuteSequence/RegisterProduct"); + set.Add("InstallExecuteSequence/RegisterUser"); + set.Add("InstallExecuteSequence/UnpublishFeatures"); + set.Add("InstallExecuteSequence/ValidateProductID"); + + // InstallUISequence table + set.Add("InstallUISequence/CostFinalize"); + set.Add("InstallUISequence/CostInitialize"); + set.Add("InstallUISequence/ExecuteAction"); + set.Add("InstallUISequence/FileCost"); + set.Add("InstallUISequence/ValidateProductID"); + } + + // Gather the required actions for each tuple type. + foreach (var tupleType in this.Section.Tuples.Select(t => t.Definition.Type).Distinct()) + { + switch (tupleType) + { + case TupleDefinitionType.AppSearch: + set.Add("InstallExecuteSequence/AppSearch"); + set.Add("InstallUISequence/AppSearch"); + break; + case TupleDefinitionType.BindImage: + set.Add("InstallExecuteSequence/BindImage"); + break; + case TupleDefinitionType.CCPSearch: + set.Add("InstallExecuteSequence/AppSearch"); + set.Add("InstallExecuteSequence/CCPSearch"); + set.Add("InstallExecuteSequence/RMCCPSearch"); + set.Add("InstallUISequence/AppSearch"); + set.Add("InstallUISequence/CCPSearch"); + set.Add("InstallUISequence/RMCCPSearch"); + break; + case TupleDefinitionType.Class: + set.Add("AdvtExecuteSequence/RegisterClassInfo"); + set.Add("InstallExecuteSequence/RegisterClassInfo"); + set.Add("InstallExecuteSequence/UnregisterClassInfo"); + break; + case TupleDefinitionType.Complus: + set.Add("InstallExecuteSequence/RegisterComPlus"); + set.Add("InstallExecuteSequence/UnregisterComPlus"); + break; + case TupleDefinitionType.CreateFolder: + set.Add("InstallExecuteSequence/CreateFolders"); + set.Add("InstallExecuteSequence/RemoveFolders"); + break; + case TupleDefinitionType.DuplicateFile: + set.Add("InstallExecuteSequence/DuplicateFiles"); + set.Add("InstallExecuteSequence/RemoveDuplicateFiles"); + break; + case TupleDefinitionType.Environment: + set.Add("InstallExecuteSequence/WriteEnvironmentStrings"); + set.Add("InstallExecuteSequence/RemoveEnvironmentStrings"); + break; + case TupleDefinitionType.Extension: + set.Add("AdvtExecuteSequence/RegisterExtensionInfo"); + set.Add("InstallExecuteSequence/RegisterExtensionInfo"); + set.Add("InstallExecuteSequence/UnregisterExtensionInfo"); + break; + case TupleDefinitionType.File: + set.Add("InstallExecuteSequence/InstallFiles"); + set.Add("InstallExecuteSequence/RemoveFiles"); + break; + case TupleDefinitionType.Font: + set.Add("InstallExecuteSequence/RegisterFonts"); + set.Add("InstallExecuteSequence/UnregisterFonts"); + break; + case TupleDefinitionType.IniFile: + case TupleDefinitionType.RemoveIniFile: + set.Add("InstallExecuteSequence/WriteIniValues"); + set.Add("InstallExecuteSequence/RemoveIniValues"); + break; + case TupleDefinitionType.IsolatedComponent: + set.Add("InstallExecuteSequence/IsolateComponents"); + break; + case TupleDefinitionType.LaunchCondition: + set.Add("InstallExecuteSequence/LaunchConditions"); + set.Add("InstallUISequence/LaunchConditions"); + break; + case TupleDefinitionType.MIME: + set.Add("AdvtExecuteSequence/RegisterMIMEInfo"); + set.Add("InstallExecuteSequence/RegisterMIMEInfo"); + set.Add("InstallExecuteSequence/UnregisterMIMEInfo"); + break; + case TupleDefinitionType.MoveFile: + set.Add("InstallExecuteSequence/MoveFiles"); + break; + case TupleDefinitionType.MsiAssembly: + set.Add("AdvtExecuteSequence/MsiPublishAssemblies"); + set.Add("InstallExecuteSequence/MsiPublishAssemblies"); + set.Add("InstallExecuteSequence/MsiUnpublishAssemblies"); + break; + case TupleDefinitionType.MsiServiceConfig: + case TupleDefinitionType.MsiServiceConfigFailureActions: + set.Add("InstallExecuteSequence/MsiConfigureServices"); + break; + case TupleDefinitionType.ODBCDataSource: + case TupleDefinitionType.ODBCTranslator: + case TupleDefinitionType.ODBCDriver: + set.Add("InstallExecuteSequence/SetODBCFolders"); + set.Add("InstallExecuteSequence/InstallODBC"); + set.Add("InstallExecuteSequence/RemoveODBC"); + break; + case TupleDefinitionType.ProgId: + set.Add("AdvtExecuteSequence/RegisterProgIdInfo"); + set.Add("InstallExecuteSequence/RegisterProgIdInfo"); + set.Add("InstallExecuteSequence/UnregisterProgIdInfo"); + break; + case TupleDefinitionType.PublishComponent: + set.Add("AdvtExecuteSequence/PublishComponents"); + set.Add("InstallExecuteSequence/PublishComponents"); + set.Add("InstallExecuteSequence/UnpublishComponents"); + break; + case TupleDefinitionType.Registry: + case TupleDefinitionType.RemoveRegistry: + set.Add("InstallExecuteSequence/WriteRegistryValues"); + set.Add("InstallExecuteSequence/RemoveRegistryValues"); + break; + case TupleDefinitionType.RemoveFile: + set.Add("InstallExecuteSequence/RemoveFiles"); + break; + case TupleDefinitionType.SelfReg: + set.Add("InstallExecuteSequence/SelfRegModules"); + set.Add("InstallExecuteSequence/SelfUnregModules"); + break; + case TupleDefinitionType.ServiceControl: + set.Add("InstallExecuteSequence/StartServices"); + set.Add("InstallExecuteSequence/StopServices"); + set.Add("InstallExecuteSequence/DeleteServices"); + break; + case TupleDefinitionType.ServiceInstall: + set.Add("InstallExecuteSequence/InstallServices"); + break; + case TupleDefinitionType.Shortcut: + set.Add("AdvtExecuteSequence/CreateShortcuts"); + set.Add("InstallExecuteSequence/CreateShortcuts"); + set.Add("InstallExecuteSequence/RemoveShortcuts"); + break; + case TupleDefinitionType.TypeLib: + set.Add("InstallExecuteSequence/RegisterTypeLibraries"); + set.Add("InstallExecuteSequence/UnregisterTypeLibraries"); + break; + case TupleDefinitionType.Upgrade: + set.Add("InstallExecuteSequence/FindRelatedProducts"); + set.Add("InstallUISequence/FindRelatedProducts"); + + // Only add the MigrateFeatureStates action if MigrateFeature attribute is set on + // at least one UpgradeVersion element. + if (this.Section.Tuples.OfType().Any(t => (t.Attributes & MsiInterop.MsidbUpgradeAttributesMigrateFeatures) == MsiInterop.MsidbUpgradeAttributesMigrateFeatures)) + { + set.Add("InstallExecuteSequence/MigrateFeatureStates"); + set.Add("InstallUISequence/MigrateFeatureStates"); + } + break; + } + } + + return set; + } + + private IEnumerable GetActions(SequenceTable sequence, string[] actionNames) + { + foreach (var action in WindowsInstallerStandard.StandardActions()) + { + if (action.SequenceTable == sequence && actionNames.Contains(action.Action)) + { + yield return action; + } + } + } + + /// + /// Sequence an action before or after a standard action. + /// + /// The action row to be sequenced. + /// Collection of actions which must be included. + private void SequenceActionRow(WixActionTuple actionRow, Dictionary requiredActionRows) + { + var after = false; + + if (actionRow.After != null) + { + after = true; + } + else if (actionRow.Before == null) + { + throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); + } + + var parentActionName = (after ? actionRow.After : actionRow.Before); + var parentActionKey = actionRow.SequenceTable.ToString() + "/" + parentActionName; + + if (!requiredActionRows.TryGetValue(parentActionKey, out var parentActionRow)) + { + // If the missing parent action is a standard action (with a suggested sequence number), add it. + if (this.StandardActionsById.TryGetValue(parentActionKey, out parentActionRow)) + { + // Create a clone to avoid modifying the static copy of the object. + // TODO: consider this: parentActionRow = parentActionRow.Clone(); + + requiredActionRows.Add(parentActionRow.Id.Id, parentActionRow); + } + else + { + throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_FoundActionRowWinNonExistentAction, (after ? "After" : "Before"), parentActionName)); + } + } + else if (actionRow == parentActionRow || this.ContainsChildActionRow(actionRow, parentActionRow)) // cycle detected + { + throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action)); + } + + // Add this action to the appropriate list of dependent action rows. + var relativeActions = this.GetRelativeActions(parentActionRow); + var relatedRows = (after ? relativeActions.NextActions : relativeActions.PreviousActions); + relatedRows.Add(actionRow); + } + + private bool ContainsChildActionRow(WixActionTuple childTuple, WixActionTuple parentTuple) + { + var result = false; + + if (this.RelativeActionsForActions.TryGetValue(childTuple.Id.Id, out var relativeActions)) + { + result = relativeActions.NextActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id) || + relativeActions.PreviousActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id); + } + + return result; + } + + private RelativeActions GetRelativeActions(WixActionTuple action) + { + if (!this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var relativeActions)) + { + relativeActions = new RelativeActions(); + this.RelativeActionsForActions.Add(action.Id.Id, relativeActions); + } + + return relativeActions; + } + + private RelativeActions GetAllRelativeActionsForSequenceType(SequenceTable sequenceType, WixActionTuple action) + { + var relativeActions = new RelativeActions(); + + if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives)) + { + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, relativeActions.PreviousActions); + + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, relativeActions.NextActions); + } + + return relativeActions; + } + + private void RecurseRelativeActionsForSequenceType(SequenceTable sequenceType, List actions, List visitedActions) + { + foreach (var action in actions.Where(a => a.SequenceTable == sequenceType)) + { + if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives)) + { + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, visitedActions); + } + + visitedActions.Add(action); + + if (actionRelatives != null) + { + this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, visitedActions); + } + } + } + + private class RelativeActions + { + public List PreviousActions { get; } = new List(); + + public List NextActions { get; } = new List(); + } + } +} diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs index 7da32206..9579e0f8 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs @@ -1,6 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.IO; diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs index 20058597..030bc4cc 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs @@ -1,10 +1,9 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Core.WindowsInstaller.Databases +namespace WixToolset.Core.WindowsInstaller.Bind { using System; using System.Collections.Generic; - using System.Collections.Specialized; using System.ComponentModel; using System.Globalization; using System.IO; @@ -14,7 +13,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases using WixToolset.Clr.Interop; using WixToolset.Core.Bind; using WixToolset.Data; - using WixToolset.Data.Rows; using WixToolset.Data.Tuples; using WixToolset.Msi; @@ -23,13 +21,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// internal class UpdateFileFacadesCommand { - public IEnumerable FileFacades { private get; set; } + public UpdateFileFacadesCommand(IntermediateSection section) + { + this.Section = section; + } - public IEnumerable UpdateFileFacades { private get; set; } + private IntermediateSection Section { get; } - public string ModularizationGuid { private get; set; } + public IEnumerable FileFacades { private get; set; } - public Output Output { private get; set; } + public IEnumerable UpdateFileFacades { private get; set; } public bool OverwriteHash { private get; set; } @@ -47,6 +48,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases private void UpdateFileFacade(FileFacade file) { + var assemblyNameTuples = new Dictionary(); + foreach (var assemblyTuple in this.Section.Tuples.OfType()) + { + assemblyNameTuples.Add(assemblyTuple.Component_ + "/" + assemblyTuple.Name, assemblyTuple); + } + FileInfo fileInfo = null; try { @@ -149,9 +156,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases if (null == file.Hash) { - //Table msiFileHashTable = this.Output.EnsureTable(this.TableDefinitions["MsiFileHash"]); - //file.Hash = msiFileHashTable.CreateRow(file.File.SourceLineNumbers); - throw new NotImplementedException(); + file.Hash = new MsiFileHashTuple(file.File.SourceLineNumbers, file.File.Id); + this.Section.Tuples.Add(file.Hash); } file.Hash.File_ = file.File.File; @@ -198,13 +204,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases { if (!String.IsNullOrEmpty(file.File.Version)) { - string key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File)); + var key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", file.File.File); this.VariableCache[key] = file.File.Version; } if (!String.IsNullOrEmpty(file.File.Language)) { - string key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", Common.Demodularize(this.Output.Type, ModularizationGuid, file.File.File)); + var key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", file.File.File); this.VariableCache[key] = file.File.Language; } } @@ -214,14 +220,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases if (FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType) { bool targetNetfx1 = false; - StringDictionary assemblyNameValues = new StringDictionary(); + var assemblyNameValues = new Dictionary(); - ClrInterop.IReferenceIdentity referenceIdentity = null; Guid referenceIdentityGuid = ClrInterop.ReferenceIdentityGuid; - uint result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out referenceIdentity); + var result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out var referenceIdentity); if (0 == result && null != referenceIdentity) { - string imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion"); + var imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion"); if (null != imageRuntimeVersion) { targetNetfx1 = imageRuntimeVersion.StartsWith("v1", StringComparison.OrdinalIgnoreCase); @@ -269,15 +274,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases return; } - Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]); - if (assemblyNameValues.ContainsKey("name")) + if (assemblyNameValues.TryGetValue("name", out var value)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "name", assemblyNameValues["name"]); + this.SetMsiAssemblyName(assemblyNameTuples, file, "name", value); } if (!String.IsNullOrEmpty(version)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "fileVersion", version); + this.SetMsiAssemblyName(assemblyNameTuples, file, "fileVersion", version); } if (assemblyNameValues.ContainsKey("version")) @@ -303,33 +307,33 @@ namespace WixToolset.Core.WindowsInstaller.Databases } } - this.SetMsiAssemblyName(assemblyNameTable, file, "version", assemblyVersion); + this.SetMsiAssemblyName(assemblyNameTuples, file, "version", assemblyVersion); } if (assemblyNameValues.ContainsKey("culture")) { - this.SetMsiAssemblyName(assemblyNameTable, file, "culture", assemblyNameValues["culture"]); + this.SetMsiAssemblyName(assemblyNameTuples, file, "culture", assemblyNameValues["culture"]); } if (assemblyNameValues.ContainsKey("publicKeyToken")) { - this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]); + this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]); } if (!String.IsNullOrEmpty(file.WixFile.ProcessorArchitecture)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", file.WixFile.ProcessorArchitecture); + this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", file.WixFile.ProcessorArchitecture); } if (assemblyNameValues.ContainsKey("processorArchitecture")) { - this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]); + this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]); } // add the assembly name to the information cache if (null != this.VariableCache) { - string fileId = Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File); + string fileId = file.File.File; string key = String.Concat("assemblyfullname.", fileId); string assemblyName = String.Concat(assemblyNameValues["name"], ", version=", assemblyNameValues["version"], ", culture=", assemblyNameValues["culture"], ", publicKeyToken=", String.IsNullOrEmpty(assemblyNameValues["publicKeyToken"]) ? "null" : assemblyNameValues["publicKeyToken"]); if (assemblyNameValues.ContainsKey("processorArchitecture")) @@ -437,30 +441,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases Messaging.Instance.OnMessage(WixErrors.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source), "manifest", xe.Message)); } - Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]); if (!String.IsNullOrEmpty(win32Name)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "name", win32Name); + this.SetMsiAssemblyName(assemblyNameTuples, file, "name", win32Name); } if (!String.IsNullOrEmpty(win32Version)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "version", win32Version); + this.SetMsiAssemblyName(assemblyNameTuples, file, "version", win32Version); } if (!String.IsNullOrEmpty(win32Type)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "type", win32Type); + this.SetMsiAssemblyName(assemblyNameTuples, file, "type", win32Type); } if (!String.IsNullOrEmpty(win32ProcessorArchitecture)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", win32ProcessorArchitecture); + this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", win32ProcessorArchitecture); } if (!String.IsNullOrEmpty(win32PublicKeyToken)) { - this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", win32PublicKeyToken); + this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", win32PublicKeyToken); } } } @@ -469,11 +472,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases /// Set an MsiAssemblyName row. If it was directly authored, override the value, otherwise /// create a new row. /// - /// MsiAssemblyName table. + /// MsiAssemblyName table. /// FileFacade containing the assembly read for the MsiAssemblyName row. /// MsiAssemblyName name. /// MsiAssemblyName value. - private void SetMsiAssemblyName(Table assemblyNameTable, FileFacade file, string name, string value) + private void SetMsiAssemblyName(Dictionary assemblyNameTuples, FileFacade file, string name, string value) { // check for null value (this can occur when grabbing the file version from an assembly without one) if (String.IsNullOrEmpty(value)) @@ -482,18 +485,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases } else { - Row assemblyNameRow = null; - - // override directly authored value - foreach (Row row in assemblyNameTable.Rows) - { - if ((string)row[0] == file.File.Component_ && (string)row[1] == name) - { - assemblyNameRow = row; - break; - } - } - // if the assembly will be GAC'd and the name in the file table doesn't match the name in the MsiAssemblyName table, error because the install will fail. if ("name" == name && FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType && String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) && @@ -502,17 +493,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases Messaging.Instance.OnMessage(WixErrors.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value)); } - if (null == assemblyNameRow) + // override directly authored value + var lookup = String.Concat(file.File.Component_, "/", name); + if (assemblyNameTuples.TryGetValue(lookup, out var assemblyNameRow)) { - throw new NotImplementedException(); -#if TODO - assemblyNameRow = assemblyNameTable.CreateRow(file.File.SourceLineNumbers); - assemblyNameRow[0] = file.File.Component_; - assemblyNameRow[1] = name; - assemblyNameRow[2] = value; - - // put the MsiAssemblyName row in the same section as the related File row - assemblyNameRow.SectionId = file.File.SectionId; + assemblyNameRow = new MsiAssemblyNameTuple(file.File.SourceLineNumbers); + assemblyNameRow.Component_ = file.File.Component_; + assemblyNameRow.Name = name; + assemblyNameRow.Value = value; if (null == file.AssemblyNames) { @@ -520,17 +508,15 @@ namespace WixToolset.Core.WindowsInstaller.Databases } file.AssemblyNames.Add(assemblyNameRow); -#endif - } - else - { - assemblyNameRow[2] = value; + this.Section.Tuples.Add(assemblyNameRow); } + assemblyNameRow.Value = value; + if (this.VariableCache != null) { - string key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File)).ToLowerInvariant(); - this.VariableCache[key] = (string)assemblyNameRow[2]; + var key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, file.File.File).ToLowerInvariant(); + this.VariableCache[key] = value; } } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs new file mode 100644 index 00000000..db74eda5 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs @@ -0,0 +1,126 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core.WindowsInstaller.Bind +{ + using System; + using System.Collections.Generic; + using System.Linq; + using WixToolset.Core.Bind; + using WixToolset.Data; + using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; + + internal class UpdateMediaSequencesCommand + { + public UpdateMediaSequencesCommand(Output output, List fileFacades, Dictionary assignedMediaRows) + { + this.Output = output; + this.FileFacades = fileFacades; + } + + private Output Output { get; } + + private List FileFacades { get; } + + public void Execute() + { + var fileRows = new RowDictionary(this.Output.Tables["File"]); + var mediaRows = new RowDictionary(this.Output.Tables["Media"]); + + // Calculate sequence numbers and media disk id layout for all file media information objects. + if (OutputType.Module == this.Output.Type) + { + var lastSequence = 0; + + // Order by Component to group the files by directory. + var optimized = this.OptimizedFileFacades(); + foreach (var fileId in optimized.Select(f => f.File.File)) + { + var fileRow = fileRows.Get(fileId); + fileRow.Sequence = ++lastSequence; + } + } + else + { + int lastSequence = 0; + MediaRow mediaRow = null; + Dictionary> patchGroups = new Dictionary>(); + + // sequence the non-patch-added files + var optimized = this.OptimizedFileFacades(); + foreach (FileFacade facade in optimized) + { + if (null == mediaRow) + { + mediaRow = mediaRows.Get(facade.WixFile.DiskId); + if (OutputType.Patch == this.Output.Type) + { + // patch Media cannot start at zero + lastSequence = mediaRow.LastSequence; + } + } + else if (mediaRow.DiskId != facade.WixFile.DiskId) + { + mediaRow.LastSequence = lastSequence; + mediaRow = mediaRows.Get(facade.WixFile.DiskId); + } + + if (0 < facade.WixFile.PatchGroup) + { + if (patchGroups.TryGetValue(facade.WixFile.PatchGroup, out var patchGroup)) + { + patchGroup = new List(); + patchGroups.Add(facade.WixFile.PatchGroup, patchGroup); + } + + patchGroup.Add(facade); + } + else + { + var fileRow = fileRows.Get(facade.File.File); + fileRow.Sequence = ++lastSequence; + } + } + + if (null != mediaRow) + { + mediaRow.LastSequence = lastSequence; + mediaRow = null; + } + + // sequence the patch-added files + foreach (var patchGroup in patchGroups.Values) + { + foreach (var facade in patchGroup) + { + if (null == mediaRow) + { + mediaRow = mediaRows.Get(facade.WixFile.DiskId); + } + else if (mediaRow.DiskId != facade.WixFile.DiskId) + { + mediaRow.LastSequence = lastSequence; + mediaRow = mediaRows.Get(facade.WixFile.DiskId); + } + + var fileRow = fileRows.Get(facade.File.File); + fileRow.Sequence = ++lastSequence; + } + } + + if (null != mediaRow) + { + mediaRow.LastSequence = lastSequence; + } + } + } + + private IEnumerable OptimizedFileFacades() + { + // TODO: Sort these facades even smarter by directory path and component id + // and maybe file size or file extension and other creative ideas to + // get optimal install speed out of MSI. + return this.FileFacades.OrderBy(f => f.File.Component_); + } + } +} diff --git a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs index 72c876e0..58384325 100644 --- a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs @@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe public InscribeMsiPackageCommand(IInscribeContext context) { this.Context = context; - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); } private IInscribeContext Context { get; } diff --git a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs index 3e40a51f..17617dbc 100644 --- a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs +++ b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs @@ -3,7 +3,6 @@ namespace WixToolset.Core.WindowsInstaller { using System; - using WixToolset.Core.WindowsInstaller.Databases; using WixToolset.Core.WindowsInstaller.Unbind; using WixToolset.Data; using WixToolset.Data.Bind; diff --git a/src/WixToolset.Core.WindowsInstaller/Patch.cs b/src/WixToolset.Core.WindowsInstaller/Patch.cs index f4dac6e6..8e617fdb 100644 --- a/src/WixToolset.Core.WindowsInstaller/Patch.cs +++ b/src/WixToolset.Core.WindowsInstaller/Patch.cs @@ -29,7 +29,7 @@ namespace WixToolset.Data public Patch() { this.inspectorExtensions = new List(); - this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions()); + this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandardInternal.GetTableDefinitions()); } /// diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs index 15445bc8..9cd7b775 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs @@ -27,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind this.SuppressDemodularization = suppressDemodularization; this.SkipSummaryInfo = skipSummaryInfo; - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); } public Messaging Messaging { get; } diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs index c0eda9c7..7eb81ac7 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs @@ -4,16 +4,13 @@ namespace WixToolset.Core.WindowsInstaller.Unbind { using System; using System.Collections; - using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; - using System.Text.RegularExpressions; using WixToolset.Core.Native; - using WixToolset.Core.WindowsInstaller.Databases; + using WixToolset.Core.WindowsInstaller.Bind; using WixToolset.Data; - using WixToolset.Data.Rows; using WixToolset.Extensibility; using WixToolset.Msi; @@ -26,7 +23,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind this.ExportBasePath = exportBasePath; this.IntermediateFolder = intermediateFolder; - this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); + this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); } private Messaging Messaging { get; } diff --git a/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs b/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs index 7de40fb8..7e7c21b1 100644 --- a/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs +++ b/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs @@ -11,7 +11,12 @@ namespace WixToolset.Core.Bind public class ExtractEmbeddedFilesCommand { - public IEnumerable FilesWithEmbeddedFiles { private get; set; } + public ExtractEmbeddedFilesCommand(IEnumerable embeddedFiles) + { + this.FilesWithEmbeddedFiles = embeddedFiles; + } + + private IEnumerable FilesWithEmbeddedFiles { get; } public void Execute() { @@ -28,10 +33,10 @@ namespace WixToolset.Core.Bind // a .wixlib embedded in a WixExtension). if ("embeddedresource" == baseUri.Scheme) { - string assemblyPath = Path.GetFullPath(baseUri.LocalPath); - string resourceName = baseUri.Fragment.TrimStart('#'); + var assemblyPath = Path.GetFullPath(baseUri.LocalPath); + var resourceName = baseUri.Fragment.TrimStart('#'); - Assembly assembly = Assembly.LoadFile(assemblyPath); + var assembly = Assembly.LoadFile(assemblyPath); stream = assembly.GetManifestResourceStream(resourceName); } else // normal file (usually a binary .wixlib on disk). @@ -39,7 +44,7 @@ namespace WixToolset.Core.Bind stream = File.OpenRead(baseUri.LocalPath); } - using (FileStructure fs = FileStructure.Read(stream)) + using (var fs = FileStructure.Read(stream)) { var uniqueIndicies = new SortedSet(); diff --git a/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs b/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs index d05135cf..4585b71a 100644 --- a/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs +++ b/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs @@ -12,25 +12,28 @@ namespace WixToolset.Core.Bind /// Resolves the fields which had variables that needed to be resolved after the file information /// was loaded. /// - public class ResolveDelayedFieldsCommand : ICommand + public class ResolveDelayedFieldsCommand { - public OutputType OutputType { private get; set;} - - public IEnumerable DelayedFields { private get; set;} + /// + /// Resolve delayed fields. + /// + /// The fields which had resolution delayed. + /// The file information to use when resolving variables. + public ResolveDelayedFieldsCommand(IEnumerable delayedFields, Dictionary variableCache) + { + this.DelayedFields = delayedFields; + this.VariableCache = variableCache; + } - public IDictionary VariableCache { private get; set; } + private IEnumerable DelayedFields { get;} - public string ModularizationGuid { private get; set; } + private IDictionary VariableCache { get; } - /// Internal representation of the msi database to operate upon. - /// The fields which had resolution delayed. - /// The file information to use when resolving variables. - /// The modularization guid (used in case of a merge module). public void Execute() { var deferredFields = new List(); - foreach (IDelayedField delayedField in this.DelayedFields) + foreach (var delayedField in this.DelayedFields) { try { @@ -42,7 +45,7 @@ namespace WixToolset.Core.Bind var value = WixVariableResolver.ResolveDelayedVariables(propertyRow.SourceLineNumbers, delayedField.Field.AsString(), this.VariableCache); // update the variable cache with the new value - var key = String.Concat("property.", Common.Demodularize(this.OutputType, this.ModularizationGuid, (string)propertyRow[0])); + var key = String.Concat("property.", propertyRow.AsString(0)); this.VariableCache[key] = value; // update the field data @@ -62,43 +65,31 @@ namespace WixToolset.Core.Bind // add specialization for ProductVersion fields string keyProductVersion = "property.ProductVersion"; - if (this.VariableCache.ContainsKey(keyProductVersion)) + if (this.VariableCache.TryGetValue(keyProductVersion, out var versionValue) && Version.TryParse(versionValue, out Version productVersion)) { - string value = this.VariableCache[keyProductVersion]; - Version productVersion = null; - - try + // Don't add the variable if it already exists (developer defined a property with the same name). + string fieldKey = String.Concat(keyProductVersion, ".Major"); + if (!this.VariableCache.ContainsKey(fieldKey)) { - productVersion = new Version(value); - - // Don't add the variable if it already exists (developer defined a property with the same name). - string fieldKey = String.Concat(keyProductVersion, ".Major"); - if (!this.VariableCache.ContainsKey(fieldKey)) - { - this.VariableCache[fieldKey] = productVersion.Major.ToString(CultureInfo.InvariantCulture); - } - - fieldKey = String.Concat(keyProductVersion, ".Minor"); - if (!this.VariableCache.ContainsKey(fieldKey)) - { - this.VariableCache[fieldKey] = productVersion.Minor.ToString(CultureInfo.InvariantCulture); - } + this.VariableCache[fieldKey] = productVersion.Major.ToString(CultureInfo.InvariantCulture); + } - fieldKey = String.Concat(keyProductVersion, ".Build"); - if (!this.VariableCache.ContainsKey(fieldKey)) - { - this.VariableCache[fieldKey] = productVersion.Build.ToString(CultureInfo.InvariantCulture); - } + fieldKey = String.Concat(keyProductVersion, ".Minor"); + if (!this.VariableCache.ContainsKey(fieldKey)) + { + this.VariableCache[fieldKey] = productVersion.Minor.ToString(CultureInfo.InvariantCulture); + } - fieldKey = String.Concat(keyProductVersion, ".Revision"); - if (!this.VariableCache.ContainsKey(fieldKey)) - { - this.VariableCache[fieldKey] = productVersion.Revision.ToString(CultureInfo.InvariantCulture); - } + fieldKey = String.Concat(keyProductVersion, ".Build"); + if (!this.VariableCache.ContainsKey(fieldKey)) + { + this.VariableCache[fieldKey] = productVersion.Build.ToString(CultureInfo.InvariantCulture); } - catch + + fieldKey = String.Concat(keyProductVersion, ".Revision"); + if (!this.VariableCache.ContainsKey(fieldKey)) { - // Ignore the error introduced by new behavior. + this.VariableCache[fieldKey] = productVersion.Revision.ToString(CultureInfo.InvariantCulture); } } @@ -113,7 +104,6 @@ namespace WixToolset.Core.Bind catch (WixException we) { Messaging.Instance.OnMessage(we.Error); - continue; } } } diff --git a/src/WixToolset.Core/Bind/ResolvedDirectory.cs b/src/WixToolset.Core/Bind/ResolvedDirectory.cs index fca706d8..9d07fc93 100644 --- a/src/WixToolset.Core/Bind/ResolvedDirectory.cs +++ b/src/WixToolset.Core/Bind/ResolvedDirectory.cs @@ -7,15 +7,6 @@ namespace WixToolset.Bind /// public struct ResolvedDirectory { - /// The directory parent. - public string DirectoryParent; - - /// The name of this directory. - public string Name; - - /// The path of this directory. - public string Path; - /// /// Constructor for ResolvedDirectory. /// @@ -27,5 +18,14 @@ namespace WixToolset.Bind this.Name = name; this.Path = null; } + + /// The directory parent. + public string DirectoryParent { get; set; } + + /// The name of this directory. + public string Name { get; set; } + + /// The path of this directory. + public string Path { get; set; } } } diff --git a/src/WixToolset.Core/Binder.cs b/src/WixToolset.Core/Binder.cs index 07a92d02..e282ead8 100644 --- a/src/WixToolset.Core/Binder.cs +++ b/src/WixToolset.Core/Binder.cs @@ -609,9 +609,9 @@ namespace WixToolset.Core /// Directory identifier. /// Canonicalize the path for standard directories. /// Source path of a directory. - public static string GetDirectoryPath(Hashtable directories, Hashtable componentIdGenSeeds, string directory, bool canonicalize) + public static string GetDirectoryPath(Dictionary directories, Dictionary componentIdGenSeeds, string directory, bool canonicalize) { - if (!directories.Contains(directory)) + if (!directories.ContainsKey(directory)) { throw new WixException(WixErrors.ExpectedDirectory(directory)); } @@ -620,7 +620,7 @@ namespace WixToolset.Core if (null == resolvedDirectory.Path) { - if (null != componentIdGenSeeds && componentIdGenSeeds.Contains(directory)) + if (null != componentIdGenSeeds && componentIdGenSeeds.ContainsKey(directory)) { resolvedDirectory.Path = (string)componentIdGenSeeds[directory]; } @@ -670,7 +670,7 @@ namespace WixToolset.Core /// Specifies the package is compressed. /// Specifies the package uses long file names. /// Source path of file relative to package directory. - public static string GetFileSourcePath(Hashtable directories, string directoryId, string fileName, bool compressed, bool useLongName) + public static string GetFileSourcePath(Dictionary directories, string directoryId, string fileName, bool compressed, bool useLongName) { string fileSourcePath = Common.GetName(fileName, true, useLongName); diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index e0475baa..903aae61 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs @@ -7137,7 +7137,7 @@ namespace WixToolset } // finally, schedule RemoveExistingProducts - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixAction); + row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixAction, new Identifier("InstallExecuteSequence/RemoveExistingProducts", AccessModifier.Public)); row.Set(0, "InstallExecuteSequence"); row.Set(1, "RemoveExistingProducts"); // row.Set(2, condition); @@ -7641,11 +7641,11 @@ namespace WixToolset row.Set(4, diskId); if (YesNoType.Yes == fileCompression) { - row.Set(5, 1); + row.Set(5, true); } else if (YesNoType.No == fileCompression) { - row.Set(5, 0); + row.Set(5, false); } else // YesNoType.NotSet == fileCompression { @@ -9525,7 +9525,7 @@ namespace WixToolset var patchIdRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchId); patchIdRow.Set(0, patchId); patchIdRow.Set(1, clientPatchId); - patchIdRow.Set(2, optimizePatchSizeForLargeFiles ? 1 : 0); + patchIdRow.Set(2, optimizePatchSizeForLargeFiles); patchIdRow.Set(3, apiPatchingSymbolFlags); if (allowRemoval) diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index 59481387..7faf69ba 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs @@ -23,9 +23,6 @@ namespace WixToolset.Core private static readonly string emptyGuid = Guid.Empty.ToString("B"); private bool sectionIdOnRows; - //private WixActionRowCollection standardActions; - //private Output activeOutput; - //private TableDefinitionCollection tableDefinitions; /// /// Creates a linker. @@ -34,9 +31,6 @@ namespace WixToolset.Core { this.sectionIdOnRows = true; // TODO: what is the correct value for this? - //this.standardActions = WindowsInstallerStandard.GetStandardActions(); - //this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions()); - //this.extensionData = new List(); //this.inspectorExtensions = new List(); } @@ -108,11 +102,6 @@ namespace WixToolset.Core //this.activeOutput = null; -#if MOVE_TO_BACKEND - var actionRows = new List(); - var suppressActionRows = new List(); -#endif - //TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection(); //IntermediateTuple customRows = new List(); @@ -232,7 +221,7 @@ namespace WixToolset.Core } // Report duplicates that would ultimately end up being primary key collisions. - ReportConflictingSymbolsCommand reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections); + var reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections); reportDupes.Execute(); if (Messaging.Instance.EncounteredError) @@ -394,19 +383,6 @@ namespace WixToolset.Core } break; -#if MOVE_TO_BACKEND - case TupleDefinitionType.WixAction: - //if (this.sectionIdOnRows) - //{ - // foreach (Row row in table.Rows) - // { - // row.SectionId = sectionId; - // } - //} - actionRows.Add(tuple); - break; -#endif - #if SOLVE_CUSTOM_TABLE case "WixCustomTable": this.LinkCustomTable(table, customTableDefinitions); @@ -455,12 +431,6 @@ namespace WixToolset.Core } break; -#if MOVE_TO_BACKEND - case TupleDefinitionType.WixSuppressAction: - suppressActionRows.Add(tuple); - break; -#endif - case TupleDefinitionType.WixComplexReference: copyTuple = false; break; @@ -538,11 +508,6 @@ namespace WixToolset.Core } #endif -#if MOVE_TO_BACKEND - // sequence all the actions - this.SequenceActions(actionRows, suppressActionRows); -#endif - #if MOVE_TO_BACKEND // check for missing table and add them or display an error as appropriate switch (this.activeOutput.Type) @@ -1140,6 +1105,7 @@ namespace WixToolset.Core } } #endif + /// /// Sends a message to the message delegate if there is one. /// @@ -1726,638 +1692,6 @@ namespace WixToolset.Core } #endif -#if MOVE_TO_BACKEND - /// - /// Set sequence numbers for all the actions and create rows in the output object. - /// - /// Collection of actions to schedule. - /// Collection of actions to suppress. - private void SequenceActions(List actionRows, List suppressActionRows) - { - var overridableActionRows = new WixActionRowCollection(); - var requiredActionRows = new WixActionRowCollection(); - ArrayList scheduledActionRows = new ArrayList(); - - // gather the required actions for the output type - if (OutputType.Product == this.activeOutput.Type) - { - // AdminExecuteSequence table - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "FileCost"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallAdminPackage"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFiles"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallValidate"]); - - // AdminUISequence table - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "ExecuteAction"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "FileCost"]); - - // AdvtExecuteSequence table - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallValidate"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishFeatures"]); - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishProduct"]); - - // InstallExecuteSequence table - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FileCost"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallValidate"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ProcessComponents"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishFeatures"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishProduct"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProduct"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterUser"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishFeatures"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ValidateProductID"]); - - // InstallUISequence table - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostFinalize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostInitialize"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ExecuteAction"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FileCost"]); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ValidateProductID"]); - } - - // gather the required actions for each table - foreach (Table table in this.activeOutput.Tables) - { - switch (table.Name) - { - case "AppSearch": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true); - break; - case "BindImage": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "BindImage"], true); - break; - case "CCPSearch": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CCPSearch"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RMCCPSearch"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CCPSearch"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "RMCCPSearch"], true); - break; - case "Class": - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterClassInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterClassInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterClassInfo"], true); - break; - case "Complus": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterComPlus"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterComPlus"], true); - break; - case "CreateFolder": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateFolders"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFolders"], true); - break; - case "DuplicateFile": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DuplicateFiles"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveDuplicateFiles"], true); - break; - case "Environment": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteEnvironmentStrings"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveEnvironmentStrings"], true); - break; - case "Extension": - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterExtensionInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterExtensionInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterExtensionInfo"], true); - break; - case "File": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true); - break; - case "Font": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterFonts"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterFonts"], true); - break; - case "IniFile": - case "RemoveIniFile": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteIniValues"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveIniValues"], true); - break; - case "IsolatedComponent": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "IsolateComponents"], true); - break; - case "LaunchCondition": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "LaunchConditions"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "LaunchConditions"], true); - break; - case "MIME": - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterMIMEInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterMIMEInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterMIMEInfo"], true); - break; - case "MoveFile": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MoveFiles"], true); - break; - case "MsiAssembly": - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "MsiPublishAssemblies"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiPublishAssemblies"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiUnpublishAssemblies"], true); - break; - case "MsiServiceConfig": - case "MsiServiceConfigFailureActions": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiConfigureServices"], true); - break; - case "ODBCDataSource": - case "ODBCTranslator": - case "ODBCDriver": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SetODBCFolders"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallODBC"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveODBC"], true); - break; - case "ProgId": - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterProgIdInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProgIdInfo"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterProgIdInfo"], true); - break; - case "PublishComponent": - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishComponents"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishComponents"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishComponents"], true); - break; - case "Registry": - case "RemoveRegistry": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteRegistryValues"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveRegistryValues"], true); - break; - case "RemoveFile": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true); - break; - case "SelfReg": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfRegModules"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfUnregModules"], true); - break; - case "ServiceControl": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StartServices"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StopServices"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DeleteServices"], true); - break; - case "ServiceInstall": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallServices"], true); - break; - case "Shortcut": - overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CreateShortcuts"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateShortcuts"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveShortcuts"], true); - break; - case "TypeLib": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterTypeLibraries"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterTypeLibraries"], true); - break; - case "Upgrade": - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FindRelatedProducts"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FindRelatedProducts"], true); - // Only add the MigrateFeatureStates action if MigrateFeature attribute is set to yes on at least one UpgradeVersion element. - foreach (Row row in table.Rows) - { - int options = (int)row[4]; - if (MsiInterop.MsidbUpgradeAttributesMigrateFeatures == (options & MsiInterop.MsidbUpgradeAttributesMigrateFeatures)) - { - overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MigrateFeatureStates"], true); - overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "MigrateFeatureStates"], true); - break; - } - } - break; - } - } - - // index all the action rows (look for collisions) - foreach (WixActionRow actionRow in actionRows) - { - if (actionRow.Overridable) // overridable action - { - WixActionRow collidingActionRow = overridableActionRows[actionRow.SequenceTable, actionRow.Action]; - - if (null != collidingActionRow) - { - this.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); - if (null != collidingActionRow.SourceLineNumbers) - { - this.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers)); - } - } - else - { - overridableActionRows.Add(actionRow); - } - } - else // unscheduled/scheduled action - { - // unscheduled action (allowed for certain standard actions) - if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence) - { - WixActionRow standardAction = this.standardActions[actionRow.SequenceTable, actionRow.Action]; - - if (null != standardAction) - { - // populate the sequence from the standard action - actionRow.Sequence = standardAction.Sequence; - } - else // not a supported unscheduled action - { - throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); - } - } - - WixActionRow collidingActionRow = requiredActionRows[actionRow.SequenceTable, actionRow.Action]; - - if (null != collidingActionRow) - { - this.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); - if (null != collidingActionRow.SourceLineNumbers) - { - this.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers)); - } - } - else - { - requiredActionRows.Add(actionRow.Clone()); - } - } - } - - // add the overridable action rows that are not overridden to the required action rows - foreach (WixActionRow actionRow in overridableActionRows) - { - if (null == requiredActionRows[actionRow.SequenceTable, actionRow.Action]) - { - requiredActionRows.Add(actionRow.Clone()); - } - } - - // suppress the required actions that are overridable - foreach (Row suppressActionRow in suppressActionRows) - { - SequenceTable sequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), (string)suppressActionRow[0]); - string action = (string)suppressActionRow[1]; - - // get the action being suppressed (if it exists) - WixActionRow requiredActionRow = requiredActionRows[sequenceTable, action]; - - // if there is an overridable row to suppress; suppress it - // there is no warning if there is no action to suppress because the action may be suppressed from a merge module in the binder - if (null != requiredActionRow) - { - if (requiredActionRow.Overridable) - { - this.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, action, sequenceTable.ToString())); - if (null != requiredActionRow.SourceLineNumbers) - { - this.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers)); - } - requiredActionRows.Remove(sequenceTable, action); - } - else // suppressing a non-overridable action row - { - this.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, sequenceTable.ToString(), action)); - if (null != requiredActionRow.SourceLineNumbers) - { - this.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers)); - } - } - } - } - - // create a copy of the required action rows so that new rows can be added while enumerating - WixActionRow[] copyOfRequiredActionRows = new WixActionRow[requiredActionRows.Count]; - requiredActionRows.CopyTo(copyOfRequiredActionRows, 0); - - // build up dependency trees of the relatively scheduled actions - foreach (WixActionRow actionRow in copyOfRequiredActionRows) - { - if (0 == actionRow.Sequence) - { - // check for standard actions that don't have a sequence number in a merge module - if (OutputType.Module == this.activeOutput.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action)) - { - this.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); - } - - this.SequenceActionRow(actionRow, requiredActionRows); - } - else if (OutputType.Module == this.activeOutput.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number - { - this.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); - } - } - - // look for standard actions with sequence restrictions that aren't necessarily scheduled based on the presence of a particular table - if (requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "DuplicateFiles") && !requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "InstallFiles")) - { - requiredActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true); - } - - // schedule actions - if (OutputType.Module == this.activeOutput.Type) - { - // add the action row to the list of scheduled action rows - scheduledActionRows.AddRange(requiredActionRows); - } - else - { - // process each sequence table individually - foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable))) - { - // create a collection of just the action rows in this sequence - WixActionRowCollection sequenceActionRows = new WixActionRowCollection(); - foreach (WixActionRow actionRow in requiredActionRows) - { - if (sequenceTable == actionRow.SequenceTable) - { - sequenceActionRows.Add(actionRow); - } - } - - // schedule the absolutely scheduled actions (by sorting them by their sequence numbers) - ArrayList absoluteActionRows = new ArrayList(); - foreach (WixActionRow actionRow in sequenceActionRows) - { - if (0 != actionRow.Sequence) - { - // look for sequence number collisions - foreach (WixActionRow sequenceScheduledActionRow in absoluteActionRows) - { - if (sequenceScheduledActionRow.Sequence == actionRow.Sequence) - { - this.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence)); - if (null != sequenceScheduledActionRow.SourceLineNumbers) - { - this.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers)); - } - } - } - - absoluteActionRows.Add(actionRow); - } - } - absoluteActionRows.Sort(); - - // schedule the relatively scheduled actions (by resolving the dependency trees) - int previousUsedSequence = 0; - ArrayList relativeActionRows = new ArrayList(); - for (int j = 0; j < absoluteActionRows.Count; j++) - { - WixActionRow absoluteActionRow = (WixActionRow)absoluteActionRows[j]; - int unusedSequence; - - // get all the relatively scheduled action rows occuring before this absolutely scheduled action row - RowIndexedList allPreviousActionRows = new RowIndexedList(); - absoluteActionRow.GetAllPreviousActionRows(sequenceTable, allPreviousActionRows); - - // get all the relatively scheduled action rows occuring after this absolutely scheduled action row - RowIndexedList allNextActionRows = new RowIndexedList(); - absoluteActionRow.GetAllNextActionRows(sequenceTable, allNextActionRows); - - // check for relatively scheduled actions occuring before/after a special action (these have a negative sequence number) - if (0 > absoluteActionRow.Sequence && (0 < allPreviousActionRows.Count || 0 < allNextActionRows.Count)) - { - // create errors for all the before actions - foreach (WixActionRow actionRow in allPreviousActionRows) - { - this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); - } - - // create errors for all the after actions - foreach (WixActionRow actionRow in allNextActionRows) - { - this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); - } - - // if there is source line information for the absolutely scheduled action display it - if (null != absoluteActionRow.SourceLineNumbers) - { - this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers)); - } - - continue; - } - - // schedule the action rows before this one - unusedSequence = absoluteActionRow.Sequence - 1; - for (int i = allPreviousActionRows.Count - 1; i >= 0; i--) - { - WixActionRow relativeActionRow = (WixActionRow)allPreviousActionRows[i]; - - // look for collisions - if (unusedSequence == previousUsedSequence) - { - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); - if (null != absoluteActionRow.SourceLineNumbers) - { - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); - } - - unusedSequence++; - } - - relativeActionRow.Sequence = unusedSequence; - relativeActionRows.Add(relativeActionRow); - - unusedSequence--; - } - - // determine the next used action sequence number - int nextUsedSequence; - if (absoluteActionRows.Count > j + 1) - { - nextUsedSequence = ((WixActionRow)absoluteActionRows[j + 1]).Sequence; - } - else - { - nextUsedSequence = short.MaxValue + 1; - } - - // schedule the action rows after this one - unusedSequence = absoluteActionRow.Sequence + 1; - for (int i = 0; i < allNextActionRows.Count; i++) - { - WixActionRow relativeActionRow = (WixActionRow)allNextActionRows[i]; - - if (unusedSequence == nextUsedSequence) - { - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); - if (null != absoluteActionRow.SourceLineNumbers) - { - this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); - } - - unusedSequence--; - } - - relativeActionRow.Sequence = unusedSequence; - relativeActionRows.Add(relativeActionRow); - - unusedSequence++; - } - - // keep track of this sequence number as the previous used sequence number for the next iteration - previousUsedSequence = absoluteActionRow.Sequence; - } - - // add the absolutely and relatively scheduled actions to the list of scheduled actions - scheduledActionRows.AddRange(absoluteActionRows); - scheduledActionRows.AddRange(relativeActionRows); - } - } - - // create the action rows for sequences that are not suppressed - foreach (WixActionRow actionRow in scheduledActionRows) - { - // get the table definition for the action (and ensure the proper table exists for a module) - TableDefinition sequenceTableDefinition = null; - switch (actionRow.SequenceTable) - { - case SequenceTable.AdminExecuteSequence: - if (OutputType.Module == this.activeOutput.Type) - { - this.activeOutput.EnsureTable(this.tableDefinitions["AdminExecuteSequence"]); - sequenceTableDefinition = this.tableDefinitions["ModuleAdminExecuteSequence"]; - } - else - { - sequenceTableDefinition = this.tableDefinitions["AdminExecuteSequence"]; - } - break; - case SequenceTable.AdminUISequence: - if (OutputType.Module == this.activeOutput.Type) - { - this.activeOutput.EnsureTable(this.tableDefinitions["AdminUISequence"]); - sequenceTableDefinition = this.tableDefinitions["ModuleAdminUISequence"]; - } - else - { - sequenceTableDefinition = this.tableDefinitions["AdminUISequence"]; - } - break; - case SequenceTable.AdvtExecuteSequence: - if (OutputType.Module == this.activeOutput.Type) - { - this.activeOutput.EnsureTable(this.tableDefinitions["AdvtExecuteSequence"]); - sequenceTableDefinition = this.tableDefinitions["ModuleAdvtExecuteSequence"]; - } - else - { - sequenceTableDefinition = this.tableDefinitions["AdvtExecuteSequence"]; - } - break; - case SequenceTable.InstallExecuteSequence: - if (OutputType.Module == this.activeOutput.Type) - { - this.activeOutput.EnsureTable(this.tableDefinitions["InstallExecuteSequence"]); - sequenceTableDefinition = this.tableDefinitions["ModuleInstallExecuteSequence"]; - } - else - { - sequenceTableDefinition = this.tableDefinitions["InstallExecuteSequence"]; - } - break; - case SequenceTable.InstallUISequence: - if (OutputType.Module == this.activeOutput.Type) - { - this.activeOutput.EnsureTable(this.tableDefinitions["InstallUISequence"]); - sequenceTableDefinition = this.tableDefinitions["ModuleInstallUISequence"]; - } - else - { - sequenceTableDefinition = this.tableDefinitions["InstallUISequence"]; - } - break; - } - - // create the action sequence row in the output - Table sequenceTable = this.activeOutput.EnsureTable(sequenceTableDefinition); - Row row = sequenceTable.CreateRow(actionRow.SourceLineNumbers); - if (this.sectionIdOnRows) - { - row.SectionId = actionRow.SectionId; - } - - if (OutputType.Module == this.activeOutput.Type) - { - row[0] = actionRow.Action; - if (0 != actionRow.Sequence) - { - row[1] = actionRow.Sequence; - } - else - { - bool after = (null == actionRow.Before); - row[2] = after ? actionRow.After : actionRow.Before; - row[3] = after ? 1 : 0; - } - row[4] = actionRow.Condition; - } - else - { - row[0] = actionRow.Action; - row[1] = actionRow.Condition; - row[2] = actionRow.Sequence; - } - } - } - - /// - /// Sequence an action before or after a standard action. - /// - /// The action row to be sequenced. - /// Collection of actions which must be included. - [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")] - private void SequenceActionRow(WixActionRow actionRow, WixActionRowCollection requiredActionRows) - { - bool after = false; - if (actionRow.After != null) - { - after = true; - } - else if (actionRow.Before == null) - { - throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); - } - - string parentActionName = (after ? actionRow.After : actionRow.Before); - WixActionRow parentActionRow = requiredActionRows[actionRow.SequenceTable, parentActionName]; - - if (null == parentActionRow) - { - parentActionRow = this.standardActions[actionRow.SequenceTable, parentActionName]; - - // if the missing parent action is a standard action (with a suggested sequence number), add it - if (null != parentActionRow) - { - // Create a clone to avoid modifying the static copy of the object. - parentActionRow = parentActionRow.Clone(); - requiredActionRows.Add(parentActionRow); - } - else - { - throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_FoundActionRowWinNonExistentAction, (after ? "After" : "Before"), parentActionName)); - } - } - else if (actionRow == parentActionRow || actionRow.ContainsChildActionRow(parentActionRow)) // cycle detected - { - throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action)); - } - - // Add this action to the appropriate list of dependent action rows. - WixActionRowCollection relatedRows = (after ? parentActionRow.NextActionRows : parentActionRow.PreviousActionRows); - relatedRows.Add(actionRow); - } -#endif /// /// Resolve features for columns that have null guid placeholders. diff --git a/src/WixToolset.Core/WindowsInstallerStandard.cs b/src/WixToolset.Core/WindowsInstallerStandard.cs deleted file mode 100644 index 90a53e6a..00000000 --- a/src/WixToolset.Core/WindowsInstallerStandard.cs +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.Core -{ - using System.Collections.Generic; - using WixToolset.Data; - using WixToolset.Data.Tuples; - - internal class WindowsInstallerStandard - { - private static readonly HashSet standardActionNames = new HashSet - { - "AllocateRegistrySpace", - "AppSearch", - "BindImage", - "CCPSearch", - "CostFinalize", - "CostInitialize", - "CreateFolders", - "CreateShortcuts", - "DeleteServices", - "DisableRollback", - "DuplicateFiles", - "ExecuteAction", - "FileCost", - "FindRelatedProducts", - "ForceReboot", - "InstallAdminPackage", - "InstallExecute", - "InstallExecuteAgain", - "InstallFiles", - "InstallFinalize", - "InstallInitialize", - "InstallODBC", - "InstallServices", - "InstallSFPCatalogFile", - "InstallValidate", - "IsolateComponents", - "LaunchConditions", - "MigrateFeatureStates", - "MoveFiles", - "MsiConfigureServices", - "MsiPublishAssemblies", - "MsiUnpublishAssemblies", - "PatchFiles", - "ProcessComponents", - "PublishComponents", - "PublishFeatures", - "PublishProduct", - "RegisterClassInfo", - "RegisterComPlus", - "RegisterExtensionInfo", - "RegisterFonts", - "RegisterMIMEInfo", - "RegisterProduct", - "RegisterProgIdInfo", - "RegisterTypeLibraries", - "RegisterUser", - "RemoveDuplicateFiles", - "RemoveEnvironmentStrings", - "RemoveExistingProducts", - "RemoveFiles", - "RemoveFolders", - "RemoveIniValues", - "RemoveODBC", - "RemoveRegistryValues", - "RemoveShortcuts", - "ResolveSource", - "RMCCPSearch", - "ScheduleReboot", - "SelfRegModules", - "SelfUnregModules", - "SetODBCFolders", - "StartServices", - "StopServices", - "UnpublishComponents", - "UnpublishFeatures", - "UnregisterClassInfo", - "UnregisterComPlus", - "UnregisterExtensionInfo", - "UnregisterFonts", - "UnregisterMIMEInfo", - "UnregisterProgIdInfo", - "UnregisterTypeLibraries", - "ValidateProductID", - "WriteEnvironmentStrings", - "WriteIniValues", - "WriteRegistryValues", - }; - - private static readonly WixActionTuple[] standardActions = new[] - { - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.AdminExecuteSequence }, - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.AdvtExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.InstallExecuteSequence }, - - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallExecute", AccessModifier.Public)) { Action="InstallExecute", Sequence=6500, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, - - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallExecuteAgain", AccessModifier.Public)) { Action="InstallExecuteAgain", Sequence=6550, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, - - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.AdminExecuteSequence }, - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.AdvtExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.InstallExecuteSequence }, - - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallFiles", AccessModifier.Public)) { Action="InstallFiles", Sequence=4000, SequenceTable=SequenceTable.AdminExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallFiles", AccessModifier.Public)) { Action="InstallFiles", Sequence=4000, SequenceTable=SequenceTable.InstallExecuteSequence }, - - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallAdminPackage", AccessModifier.Public)) { Action="InstallAdminPackage", Sequence=3900, SequenceTable=SequenceTable.AdminExecuteSequence }, - - new WixActionTuple(null, new Identifier("AdminExecuteSequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.AdminExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallUISequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.InstallUISequence }, - - new WixActionTuple(null, new Identifier("AdminExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdminExecuteSequence }, - new WixActionTuple(null, new Identifier("AdminUISequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdminUISequence }, - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdvtExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallUISequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.InstallUISequence }, - - new WixActionTuple(null, new Identifier("AdminExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdminExecuteSequence }, - new WixActionTuple(null, new Identifier("AdminUISequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdminUISequence }, - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdvtExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallUISequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.InstallUISequence }, - - new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.AdminExecuteSequence }, - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.AdvtExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.InstallExecuteSequence }, - - new WixActionTuple(null, new Identifier("AdminUISequence/ExecuteAction", AccessModifier.Public)) { Action="ExecuteAction", Sequence=1300, SequenceTable=SequenceTable.AdminUISequence }, - new WixActionTuple(null, new Identifier("InstallUISequence/ExecuteAction", AccessModifier.Public)) { Action="ExecuteAction", Sequence=1300, SequenceTable=SequenceTable.InstallUISequence }, - - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CreateShortcuts", AccessModifier.Public)) { Action="CreateShortcuts", Sequence=4500, SequenceTable=SequenceTable.AdvtExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CreateShortcuts", AccessModifier.Public)) { Action="CreateShortcuts", Sequence=4500, SequenceTable=SequenceTable.InstallExecuteSequence }, - - new WixActionTuple(null, new Identifier("AdvtExecuteSequence/MsiPublishAssemblies", AccessModifier.Public)) { Action="MsiPublishAssemblies", Sequence=6250, SequenceTable=SequenceTable.AdvtExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/MsiPublishAssemblies", AccessModifier.Public)) { Action="MsiPublishAssemblies", Sequence=6250, SequenceTable=SequenceTable.InstallExecuteSequence }, - - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - - - new WixActionTuple(null, new Identifier("InstallExecuteSequence/CCPSearch", AccessModifier.Public)) { Action="CCPSearch", Sequence=500, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, - new WixActionTuple(null, new Identifier("InstallUISequence/CCPSearch", AccessModifier.Public)) { Action="CCPSearch", Sequence=500, SequenceTable=SequenceTable.InstallUISequence, Condition="NOT Installed" }, - - new WixActionTuple(null, new Identifier("InstallExecuteSequence/DeleteServices", AccessModifier.Public)) { Action="DeleteServices", Sequence=2000, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" }, - - new WixActionTuple(null, new Identifier("InstallExecuteSequence/RMCCPSearch", AccessModifier.Public)) { Action="RMCCPSearch", Sequence=600, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, - new WixActionTuple(null, new Identifier("InstallUISequence/RMCCPSearch", AccessModifier.Public)) { Action="RMCCPSearch", Sequence=600, SequenceTable=SequenceTable.InstallUISequence, Condition="NOT Installed" }, - - new WixActionTuple(null, new Identifier("InstallExecuteSequence/StartServices", AccessModifier.Public)) { Action="StartServices", Sequence=5900, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/StopServices", AccessModifier.Public)) { Action="StopServices", Sequence=1900, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" }, - - new WixActionTuple(null, new Identifier("InstallExecuteSequence/MsiUnpublishAssemblies", AccessModifier.Public)) { Action="MsiUnpublishAssemblies", Sequence=1750, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnpublishComponents", AccessModifier.Public)) { Action="UnpublishComponents", Sequence=1700, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnpublishFeatures", AccessModifier.Public)) { Action="UnpublishFeatures", Sequence=1800, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterClassInfo", AccessModifier.Public)) { Action="UnregisterClassInfo", Sequence=2700, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterComPlus", AccessModifier.Public)) { Action="UnregisterComPlus", Sequence=2100, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterExtensionInfo", AccessModifier.Public)) { Action="UnregisterExtensionInfo", Sequence=2800, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterFonts", AccessModifier.Public)) { Action="UnregisterFonts", Sequence=2500, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterMIMEInfo", AccessModifier.Public)) { Action="UnregisterMIMEInfo", Sequence=3000, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterProgIdInfo", AccessModifier.Public)) { Action="UnregisterProgIdInfo", Sequence=2900, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterTypeLibraries", AccessModifier.Public)) { Action="UnregisterTypeLibraries", Sequence=2300, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/ValidateProductID", AccessModifier.Public)) { Action="ValidateProductID", Sequence=700, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteEnvironmentStrings", AccessModifier.Public)) { Action="WriteEnvironmentStrings", Sequence=5200, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteIniValues", AccessModifier.Public)) { Action="WriteIniValues", Sequence=5100, SequenceTable=SequenceTable.InstallExecuteSequence }, - new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteRegistryValues", AccessModifier.Public)) { Action="WriteRegistryValues", Sequence=5000, SequenceTable=SequenceTable.InstallExecuteSequence }, - }; - - private static readonly HashSet standardDirectories = new HashSet - { - "TARGETDIR", - "AdminToolsFolder", - "AppDataFolder", - "CommonAppDataFolder", - "CommonFilesFolder", - "DesktopFolder", - "FavoritesFolder", - "FontsFolder", - "LocalAppDataFolder", - "MyPicturesFolder", - "PersonalFolder", - "ProgramFilesFolder", - "ProgramMenuFolder", - "SendToFolder", - "StartMenuFolder", - "StartupFolder", - "System16Folder", - "SystemFolder", - "TempFolder", - "TemplateFolder", - "WindowsFolder", - "CommonFiles64Folder", - "ProgramFiles64Folder", - "System64Folder", - "NetHoodFolder", - "PrintHoodFolder", - "RecentFolder", - "WindowsVolume", - }; - - /// - /// Find out if an action is a standard action. - /// - /// Name of the action. - /// true if the action is standard, false otherwise. - public static bool IsStandardAction(string actionName) - { - return standardActionNames.Contains(actionName); - } - - public static WixActionTuple[] StandardActions() => standardActions; - - /// - /// Find out if a directory is a standard directory. - /// - /// Name of the directory. - /// true if the directory is standard, false otherwise. - public static bool IsStandardDirectory(string directoryName) - { - return standardDirectories.Contains(directoryName); - } - } -} diff --git a/src/WixToolset.Core/WixStrings.Designer.cs b/src/WixToolset.Core/WixStrings.Designer.cs index 75e2b908..36e64267 100644 --- a/src/WixToolset.Core/WixStrings.Designer.cs +++ b/src/WixToolset.Core/WixStrings.Designer.cs @@ -163,7 +163,7 @@ namespace WixToolset { /// /// Looks up a localized string similar to Found an ActionRow with a non-existent {0} action: {1}.. /// - internal static string EXP_FoundActionRowWinNonExistentAction { + public static string EXP_FoundActionRowWinNonExistentAction { get { return ResourceManager.GetString("EXP_FoundActionRowWinNonExistentAction", resourceCulture); } @@ -172,7 +172,7 @@ namespace WixToolset { /// /// Looks up a localized string similar to Found an ActionRow with no Sequence, Before, or After column set.. /// - internal static string EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet { + public static string EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet { get { return ResourceManager.GetString("EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet", resourceCulture); } diff --git a/src/WixToolset.Data.WindowsInstaller/Data/tables.xml b/src/WixToolset.Data.WindowsInstaller/Data/tables.xml index 280d87a8..e4b5e954 100644 --- a/src/WixToolset.Data.WindowsInstaller/Data/tables.xml +++ b/src/WixToolset.Data.WindowsInstaller/Data/tables.xml @@ -1468,7 +1468,7 @@ - + diff --git a/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs b/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs index a0cc5302..5756db71 100644 --- a/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs +++ b/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs @@ -77,8 +77,7 @@ namespace WixToolset.Data /// Row or null if key is not found. public T Get(string key) { - T result; - return this.TryGetValue(key, out result) ? result : null; + return this.TryGetValue(key, out var result) ? result : null; } } } diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs b/src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs deleted file mode 100644 index 964e1caa..00000000 --- a/src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.Data.Rows -{ - /// - /// The types that the WixDeltaPatchSymbolPaths table can hold. - /// - /// The order of these values is important since WixDeltaPatchSymbolPaths are sorted by this type. - public enum SymbolPathType - { - File, - Component, - Directory, - Media, - Product - }; -} diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs index 3009e59d..d1be706e 100644 --- a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs +++ b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs @@ -8,27 +8,28 @@ namespace WixToolset.Data.Rows using System.Globalization; using System.Xml; using System.Xml.Schema; + using WixToolset.Data.Tuples; /// /// The Sequence tables that actions may belong to. /// - public enum SequenceTable - { - /// AdminUISequence - AdminUISequence, + //public enum SequenceTable + //{ + // /// AdminUISequence + // AdminUISequence, - /// AdminExecuteSequence - AdminExecuteSequence, + // /// AdminExecuteSequence + // AdminExecuteSequence, - /// AdvtExecuteSequence - AdvtExecuteSequence, + // /// AdvtExecuteSequence + // AdvtExecuteSequence, - /// InstallUISequence - InstallUISequence, + // /// InstallUISequence + // InstallUISequence, - /// InstallExecuteSequence - InstallExecuteSequence - } + // /// InstallExecuteSequence + // InstallExecuteSequence + //} /// /// Specialization of a row for the sequence tables. @@ -55,15 +56,15 @@ namespace WixToolset.Data.Rows /// The name of the standard action. /// The condition of the standard action. /// The suggested sequence number of the standard action. - private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) : - base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"]) - { - this.SequenceTable = sequenceTable; - this.Action = action; - this.Condition = condition; - this.Sequence = sequence; - this.Overridable = true; // all standard actions are overridable by default - } + //private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) : + // base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"]) + //{ + // this.SequenceTable = sequenceTable; + // this.Action = action; + // this.Condition = condition; + // this.Sequence = sequence; + // this.Overridable = true; // all standard actions are overridable by default + //} /// /// Instantiates an ActionRow by copying data from another ActionRow. @@ -296,13 +297,15 @@ namespace WixToolset.Data.Rows WixActionRow[] actionRows = new WixActionRow[sequenceCount]; for (int i = 0; i < sequenceCount; i++) { - WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence); - actionRows[i] = actionRow; + //WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence); + //actionRows[i] = actionRow; + throw new NotImplementedException(); } return actionRows; } +#if DEAD_CODE /// /// Determines whether this ActionRow contains the specified ActionRow as a child in its dependency tree. /// @@ -370,5 +373,6 @@ namespace WixToolset.Data.Rows } } } +#endif } } diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs index 513a104f..9fab6b5d 100644 --- a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs +++ b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs @@ -6,6 +6,7 @@ namespace WixToolset.Data.Rows using System.Collections; using System.Diagnostics; using System.Xml; + using WixToolset.Data.Tuples; /// /// A collection of action rows sorted by their sequence table and action name. diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs b/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs index b6c0b840..3be5a56d 100644 --- a/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs +++ b/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs @@ -2,6 +2,8 @@ namespace WixToolset.Data.Rows { + using WixToolset.Data.Tuples; + /// /// Specialization of a row for the WixDeltaPatchSymbolPaths table. /// diff --git a/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs b/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs index 553f0eaa..26d56387 100644 --- a/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs +++ b/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs @@ -68,6 +68,17 @@ namespace WixToolset.Data } } + /// + /// Tries to get a table definition by name. + /// + /// Name of table to locate. + /// Table definition if found. + /// True if table definition was found otherwise false. + public bool TryGet(string tableName, out TableDefinition table) + { + return this.collection.TryGetValue(tableName, out table); + } + /// /// Load a table definition collection from an XmlReader. /// diff --git a/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs b/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs deleted file mode 100644 index ee4a5103..00000000 --- a/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs +++ /dev/null @@ -1,442 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.Data -{ - using System.Collections.Generic; - using System.Reflection; - using System.Xml; - using WixToolset.Data.Rows; - - /// - /// Represents the Windows Installer standard objects. - /// - public static class WindowsInstallerStandard - { - private static readonly object lockObject = new object(); - - private static TableDefinitionCollection tableDefinitions; - private static WixActionRowCollection standardActions; - - private static HashSet standardActionNames; - private static HashSet standardDirectories; - private static HashSet standardProperties; - - /// - /// Gets the table definitions stored in this assembly. - /// - /// Table definition collection for tables stored in this assembly. - public static TableDefinitionCollection GetTableDefinitions() - { - lock (lockObject) - { - if (null == WindowsInstallerStandard.tableDefinitions) - { - using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.tables.xml"))) - { - tableDefinitions = TableDefinitionCollection.Load(reader); - } - } - } - - return WindowsInstallerStandard.tableDefinitions; - } - - /// - /// Gets the standard actions stored in this assembly. - /// - /// Collection of standard actions in this assembly. - public static WixActionRowCollection GetStandardActions() - { - lock (lockObject) - { - if (null == standardActions) - { - using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.actions.xml"))) - { - standardActions = WixActionRowCollection.Load(reader); - } - } - } - - return standardActions; - } - - /// - /// Gets (and loads if not yet loaded) the list of standard MSI directories. - /// - /// The list of standard MSI directories. - public static HashSet GetStandardDirectories() - { - lock (lockObject) - { - if (null == standardDirectories) - { - LoadStandardDirectories(); - } - } - - return standardDirectories; - } - - /// - /// Find out if an action is a standard action. - /// - /// Name of the action. - /// true if the action is standard, false otherwise. - public static bool IsStandardAction(string actionName) - { - lock (lockObject) - { - if (null == standardActionNames) - { - standardActionNames = new HashSet(); - standardActionNames.Add("AllocateRegistrySpace"); - standardActionNames.Add("AppSearch"); - standardActionNames.Add("BindImage"); - standardActionNames.Add("CCPSearch"); - standardActionNames.Add("CostFinalize"); - standardActionNames.Add("CostInitialize"); - standardActionNames.Add("CreateFolders"); - standardActionNames.Add("CreateShortcuts"); - standardActionNames.Add("DeleteServices"); - standardActionNames.Add("DisableRollback"); - standardActionNames.Add("DuplicateFiles"); - standardActionNames.Add("ExecuteAction"); - standardActionNames.Add("FileCost"); - standardActionNames.Add("FindRelatedProducts"); - standardActionNames.Add("ForceReboot"); - standardActionNames.Add("InstallAdminPackage"); - standardActionNames.Add("InstallExecute"); - standardActionNames.Add("InstallExecuteAgain"); - standardActionNames.Add("InstallFiles"); - standardActionNames.Add("InstallFinalize"); - standardActionNames.Add("InstallInitialize"); - standardActionNames.Add("InstallODBC"); - standardActionNames.Add("InstallServices"); - standardActionNames.Add("InstallSFPCatalogFile"); - standardActionNames.Add("InstallValidate"); - standardActionNames.Add("IsolateComponents"); - standardActionNames.Add("LaunchConditions"); - standardActionNames.Add("MigrateFeatureStates"); - standardActionNames.Add("MoveFiles"); - standardActionNames.Add("MsiConfigureServices"); - standardActionNames.Add("MsiPublishAssemblies"); - standardActionNames.Add("MsiUnpublishAssemblies"); - standardActionNames.Add("PatchFiles"); - standardActionNames.Add("ProcessComponents"); - standardActionNames.Add("PublishComponents"); - standardActionNames.Add("PublishFeatures"); - standardActionNames.Add("PublishProduct"); - standardActionNames.Add("RegisterClassInfo"); - standardActionNames.Add("RegisterComPlus"); - standardActionNames.Add("RegisterExtensionInfo"); - standardActionNames.Add("RegisterFonts"); - standardActionNames.Add("RegisterMIMEInfo"); - standardActionNames.Add("RegisterProduct"); - standardActionNames.Add("RegisterProgIdInfo"); - standardActionNames.Add("RegisterTypeLibraries"); - standardActionNames.Add("RegisterUser"); - standardActionNames.Add("RemoveDuplicateFiles"); - standardActionNames.Add("RemoveEnvironmentStrings"); - standardActionNames.Add("RemoveExistingProducts"); - standardActionNames.Add("RemoveFiles"); - standardActionNames.Add("RemoveFolders"); - standardActionNames.Add("RemoveIniValues"); - standardActionNames.Add("RemoveODBC"); - standardActionNames.Add("RemoveRegistryValues"); - standardActionNames.Add("RemoveShortcuts"); - standardActionNames.Add("ResolveSource"); - standardActionNames.Add("RMCCPSearch"); - standardActionNames.Add("ScheduleReboot"); - standardActionNames.Add("SelfRegModules"); - standardActionNames.Add("SelfUnregModules"); - standardActionNames.Add("SetODBCFolders"); - standardActionNames.Add("StartServices"); - standardActionNames.Add("StopServices"); - standardActionNames.Add("UnpublishComponents"); - standardActionNames.Add("UnpublishFeatures"); - standardActionNames.Add("UnregisterClassInfo"); - standardActionNames.Add("UnregisterComPlus"); - standardActionNames.Add("UnregisterExtensionInfo"); - standardActionNames.Add("UnregisterFonts"); - standardActionNames.Add("UnregisterMIMEInfo"); - standardActionNames.Add("UnregisterProgIdInfo"); - standardActionNames.Add("UnregisterTypeLibraries"); - standardActionNames.Add("ValidateProductID"); - standardActionNames.Add("WriteEnvironmentStrings"); - standardActionNames.Add("WriteIniValues"); - standardActionNames.Add("WriteRegistryValues"); - } - } - - return standardActionNames.Contains(actionName); - } - - /// - /// Find out if a directory is a standard directory. - /// - /// Name of the directory. - /// true if the directory is standard, false otherwise. - public static bool IsStandardDirectory(string directoryName) - { - lock (lockObject) - { - if (null == standardDirectories) - { - LoadStandardDirectories(); - } - } - - return standardDirectories.Contains(directoryName); - } - - /// - /// Find out if a property is a standard property. - /// References: - /// Title: Property Reference [Windows Installer]: - /// URL: http://msdn.microsoft.com/library/en-us/msi/setup/property_reference.asp - /// - /// Name of the property. - /// true if a property is standard, false otherwise. - public static bool IsStandardProperty(string propertyName) - { - lock (lockObject) - { - if (null == standardProperties) - { - standardProperties = new HashSet(); - standardProperties.Add("~"); // REG_MULTI_SZ/NULL marker - standardProperties.Add("ACTION"); - standardProperties.Add("ADDDEFAULT"); - standardProperties.Add("ADDLOCAL"); - standardProperties.Add("ADDDSOURCE"); - standardProperties.Add("AdminProperties"); - standardProperties.Add("AdminUser"); - standardProperties.Add("ADVERTISE"); - standardProperties.Add("AFTERREBOOT"); - standardProperties.Add("AllowProductCodeMismatches"); - standardProperties.Add("AllowProductVersionMajorMismatches"); - standardProperties.Add("ALLUSERS"); - standardProperties.Add("Alpha"); - standardProperties.Add("ApiPatchingSymbolFlags"); - standardProperties.Add("ARPAUTHORIZEDCDFPREFIX"); - standardProperties.Add("ARPCOMMENTS"); - standardProperties.Add("ARPCONTACT"); - standardProperties.Add("ARPHELPLINK"); - standardProperties.Add("ARPHELPTELEPHONE"); - standardProperties.Add("ARPINSTALLLOCATION"); - standardProperties.Add("ARPNOMODIFY"); - standardProperties.Add("ARPNOREMOVE"); - standardProperties.Add("ARPNOREPAIR"); - standardProperties.Add("ARPPRODUCTIONICON"); - standardProperties.Add("ARPREADME"); - standardProperties.Add("ARPSIZE"); - standardProperties.Add("ARPSYSTEMCOMPONENT"); - standardProperties.Add("ARPULRINFOABOUT"); - standardProperties.Add("ARPURLUPDATEINFO"); - standardProperties.Add("AVAILABLEFREEREG"); - standardProperties.Add("BorderSize"); - standardProperties.Add("BorderTop"); - standardProperties.Add("CaptionHeight"); - standardProperties.Add("CCP_DRIVE"); - standardProperties.Add("ColorBits"); - standardProperties.Add("COMPADDLOCAL"); - standardProperties.Add("COMPADDSOURCE"); - standardProperties.Add("COMPANYNAME"); - standardProperties.Add("ComputerName"); - standardProperties.Add("CostingComplete"); - standardProperties.Add("Date"); - standardProperties.Add("DefaultUIFont"); - standardProperties.Add("DISABLEADVTSHORTCUTS"); - standardProperties.Add("DISABLEMEDIA"); - standardProperties.Add("DISABLEROLLBACK"); - standardProperties.Add("DiskPrompt"); - standardProperties.Add("DontRemoveTempFolderWhenFinished"); - standardProperties.Add("EnableUserControl"); - standardProperties.Add("EXECUTEACTION"); - standardProperties.Add("EXECUTEMODE"); - standardProperties.Add("FASTOEM"); - standardProperties.Add("FILEADDDEFAULT"); - standardProperties.Add("FILEADDLOCAL"); - standardProperties.Add("FILEADDSOURCE"); - standardProperties.Add("IncludeWholeFilesOnly"); - standardProperties.Add("Installed"); - standardProperties.Add("INSTALLLEVEL"); - standardProperties.Add("Intel"); - standardProperties.Add("Intel64"); - standardProperties.Add("IsAdminPackage"); - standardProperties.Add("LeftUnit"); - standardProperties.Add("LIMITUI"); - standardProperties.Add("ListOfPatchGUIDsToReplace"); - standardProperties.Add("ListOfTargetProductCode"); - standardProperties.Add("LOGACTION"); - standardProperties.Add("LogonUser"); - standardProperties.Add("Manufacturer"); - standardProperties.Add("MEDIAPACKAGEPATH"); - standardProperties.Add("MediaSourceDir"); - standardProperties.Add("MinimumRequiredMsiVersion"); - standardProperties.Add("MsiAMD64"); - standardProperties.Add("MSIAPRSETTINGSIDENTIFIER"); - standardProperties.Add("MSICHECKCRCS"); - standardProperties.Add("MSIDISABLERMRESTART"); - standardProperties.Add("MSIENFORCEUPGRADECOMPONENTRULES"); - standardProperties.Add("MSIFASTINSTALL"); - standardProperties.Add("MsiFileToUseToCreatePatchTables"); - standardProperties.Add("MsiHiddenProperties"); - standardProperties.Add("MSIINSTALLPERUSER"); - standardProperties.Add("MSIINSTANCEGUID"); - standardProperties.Add("MsiLogFileLocation"); - standardProperties.Add("MsiLogging"); - standardProperties.Add("MsiNetAssemblySupport"); - standardProperties.Add("MSINEWINSTANCE"); - standardProperties.Add("MSINODISABLEMEDIA"); - standardProperties.Add("MsiNTProductType"); - standardProperties.Add("MsiNTSuiteBackOffice"); - standardProperties.Add("MsiNTSuiteDataCenter"); - standardProperties.Add("MsiNTSuiteEnterprise"); - standardProperties.Add("MsiNTSuiteSmallBusiness"); - standardProperties.Add("MsiNTSuiteSmallBusinessRestricted"); - standardProperties.Add("MsiNTSuiteWebServer"); - standardProperties.Add("MsiNTSuitePersonal"); - standardProperties.Add("MsiPatchRemovalList"); - standardProperties.Add("MSIPATCHREMOVE"); - standardProperties.Add("MSIRESTARTMANAGERCONTROL"); - standardProperties.Add("MsiRestartManagerSessionKey"); - standardProperties.Add("MSIRMSHUTDOWN"); - standardProperties.Add("MsiRunningElevated"); - standardProperties.Add("MsiUIHideCancel"); - standardProperties.Add("MsiUIProgressOnly"); - standardProperties.Add("MsiUISourceResOnly"); - standardProperties.Add("MsiSystemRebootPending"); - standardProperties.Add("MsiWin32AssemblySupport"); - standardProperties.Add("NOCOMPANYNAME"); - standardProperties.Add("NOUSERNAME"); - standardProperties.Add("OLEAdvtSupport"); - standardProperties.Add("OptimizePatchSizeForLargeFiles"); - standardProperties.Add("OriginalDatabase"); - standardProperties.Add("OutOfDiskSpace"); - standardProperties.Add("OutOfNoRbDiskSpace"); - standardProperties.Add("ParentOriginalDatabase"); - standardProperties.Add("ParentProductCode"); - standardProperties.Add("PATCH"); - standardProperties.Add("PATCH_CACHE_DIR"); - standardProperties.Add("PATCH_CACHE_ENABLED"); - standardProperties.Add("PatchGUID"); - standardProperties.Add("PATCHNEWPACKAGECODE"); - standardProperties.Add("PATCHNEWSUMMARYCOMMENTS"); - standardProperties.Add("PATCHNEWSUMMARYSUBJECT"); - standardProperties.Add("PatchOutputPath"); - standardProperties.Add("PatchSourceList"); - standardProperties.Add("PhysicalMemory"); - standardProperties.Add("PIDKEY"); - standardProperties.Add("PIDTemplate"); - standardProperties.Add("Preselected"); - standardProperties.Add("PRIMARYFOLDER"); - standardProperties.Add("PrimaryVolumePath"); - standardProperties.Add("PrimaryVolumeSpaceAvailable"); - standardProperties.Add("PrimaryVolumeSpaceRemaining"); - standardProperties.Add("PrimaryVolumeSpaceRequired"); - standardProperties.Add("Privileged"); - standardProperties.Add("ProductCode"); - standardProperties.Add("ProductID"); - standardProperties.Add("ProductLanguage"); - standardProperties.Add("ProductName"); - standardProperties.Add("ProductState"); - standardProperties.Add("ProductVersion"); - standardProperties.Add("PROMPTROLLBACKCOST"); - standardProperties.Add("REBOOT"); - standardProperties.Add("REBOOTPROMPT"); - standardProperties.Add("RedirectedDllSupport"); - standardProperties.Add("REINSTALL"); - standardProperties.Add("REINSTALLMODE"); - standardProperties.Add("RemoveAdminTS"); - standardProperties.Add("REMOVE"); - standardProperties.Add("ReplacedInUseFiles"); - standardProperties.Add("RestrictedUserControl"); - standardProperties.Add("RESUME"); - standardProperties.Add("RollbackDisabled"); - standardProperties.Add("ROOTDRIVE"); - standardProperties.Add("ScreenX"); - standardProperties.Add("ScreenY"); - standardProperties.Add("SecureCustomProperties"); - standardProperties.Add("ServicePackLevel"); - standardProperties.Add("ServicePackLevelMinor"); - standardProperties.Add("SEQUENCE"); - standardProperties.Add("SharedWindows"); - standardProperties.Add("ShellAdvtSupport"); - standardProperties.Add("SHORTFILENAMES"); - standardProperties.Add("SourceDir"); - standardProperties.Add("SOURCELIST"); - standardProperties.Add("SystemLanguageID"); - standardProperties.Add("TARGETDIR"); - standardProperties.Add("TerminalServer"); - standardProperties.Add("TextHeight"); - standardProperties.Add("Time"); - standardProperties.Add("TRANSFORMS"); - standardProperties.Add("TRANSFORMSATSOURCE"); - standardProperties.Add("TRANSFORMSSECURE"); - standardProperties.Add("TTCSupport"); - standardProperties.Add("UILevel"); - standardProperties.Add("UpdateStarted"); - standardProperties.Add("UpgradeCode"); - standardProperties.Add("UPGRADINGPRODUCTCODE"); - standardProperties.Add("UserLanguageID"); - standardProperties.Add("USERNAME"); - standardProperties.Add("UserSID"); - standardProperties.Add("Version9X"); - standardProperties.Add("VersionDatabase"); - standardProperties.Add("VersionMsi"); - standardProperties.Add("VersionNT"); - standardProperties.Add("VersionNT64"); - standardProperties.Add("VirtualMemory"); - standardProperties.Add("WindowsBuild"); - standardProperties.Add("WindowsVolume"); - } - } - - return standardProperties.Contains(propertyName); - } - - /// - /// Sets up a hashtable with the set of standard MSI directories - /// - private static void LoadStandardDirectories() - { - lock (lockObject) - { - if (null == standardDirectories) - { - standardDirectories = new HashSet(); - standardDirectories.Add("TARGETDIR"); - standardDirectories.Add("AdminToolsFolder"); - standardDirectories.Add("AppDataFolder"); - standardDirectories.Add("CommonAppDataFolder"); - standardDirectories.Add("CommonFilesFolder"); - standardDirectories.Add("DesktopFolder"); - standardDirectories.Add("FavoritesFolder"); - standardDirectories.Add("FontsFolder"); - standardDirectories.Add("LocalAppDataFolder"); - standardDirectories.Add("MyPicturesFolder"); - standardDirectories.Add("PersonalFolder"); - standardDirectories.Add("ProgramFilesFolder"); - standardDirectories.Add("ProgramMenuFolder"); - standardDirectories.Add("SendToFolder"); - standardDirectories.Add("StartMenuFolder"); - standardDirectories.Add("StartupFolder"); - standardDirectories.Add("System16Folder"); - standardDirectories.Add("SystemFolder"); - standardDirectories.Add("TempFolder"); - standardDirectories.Add("TemplateFolder"); - standardDirectories.Add("WindowsFolder"); - standardDirectories.Add("CommonFiles64Folder"); - standardDirectories.Add("ProgramFiles64Folder"); - standardDirectories.Add("System64Folder"); - standardDirectories.Add("NetHoodFolder"); - standardDirectories.Add("PrintHoodFolder"); - standardDirectories.Add("RecentFolder"); - standardDirectories.Add("WindowsVolume"); - } - } - } - } -} diff --git a/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs b/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs new file mode 100644 index 00000000..cc6754c3 --- /dev/null +++ b/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs @@ -0,0 +1,59 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Data +{ + using System.Reflection; + using System.Xml; + using WixToolset.Data.Rows; + + /// + /// Represents the Windows Installer standard objects. + /// + public static class WindowsInstallerStandardInternal + { + private static readonly object lockObject = new object(); + + private static TableDefinitionCollection tableDefinitions; + private static WixActionRowCollection standardActions; + + /// + /// Gets the table definitions stored in this assembly. + /// + /// Table definition collection for tables stored in this assembly. + public static TableDefinitionCollection GetTableDefinitions() + { + lock (lockObject) + { + if (null == WindowsInstallerStandardInternal.tableDefinitions) + { + using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.tables.xml"))) + { + WindowsInstallerStandardInternal.tableDefinitions = TableDefinitionCollection.Load(reader); + } + } + } + + return WindowsInstallerStandardInternal.tableDefinitions; + } + + /// + /// Gets the standard actions stored in this assembly. + /// + /// Collection of standard actions in this assembly. + public static WixActionRowCollection GetStandardActionRows() + { + lock (lockObject) + { + if (null == WindowsInstallerStandardInternal.standardActions) + { + using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.actions.xml"))) + { + WindowsInstallerStandardInternal.standardActions = WixActionRowCollection.Load(reader); + } + } + } + + return WindowsInstallerStandardInternal.standardActions; + } + } +} diff --git a/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs b/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs index 46d15ed8..4b4daeda 100644 --- a/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs @@ -26,18 +26,17 @@ namespace WixToolsetTest.CoreIntegrationFixture var result = program.Run(new WixToolsetServiceProvider(), new[] { "build", "Package.wxs", "PackageComponents.wxs", "-loc", "Package.en-us.wxl", "-bindpath", "data", "-intermediateFolder", intermediateFolder, "-o", $@"{intermediateFolder}\bin\test.msi" }); Assert.Equal(0, result); -#if FIXED_MSI_BACKEND + Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi"))); Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb"))); Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\test.txt"))); -#else - var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.msi")); + + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir")); Assert.Single(intermediate.Sections); var wixFile = intermediate.Sections.SelectMany(s => s.Tuples).OfType().Single(); Assert.Equal(@"data\test.txt", wixFile[WixFileTupleFields.Source].AsPath().Path); Assert.Equal(@"test.txt", wixFile[WixFileTupleFields.Source].PreviousValue.AsPath().Path); -#endif } } } -- cgit v1.2.3-55-g6feb