From b645ddc2c1386c1199ca1e7790201d7a5ab6627b Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 22 May 2019 00:54:09 -0700 Subject: Integrate latest changes to tuple definitions --- .../ConvertTuplesCommand.cs | 928 +++++++++++++-------- .../ConvertTuplesFixture.cs | 747 ++++++++++------- 2 files changed, 1020 insertions(+), 655 deletions(-) (limited to 'src') diff --git a/src/WixToolset.Converters.Tupleizer/ConvertTuplesCommand.cs b/src/WixToolset.Converters.Tupleizer/ConvertTuplesCommand.cs index c07dd42e..007b9c62 100644 --- a/src/WixToolset.Converters.Tupleizer/ConvertTuplesCommand.cs +++ b/src/WixToolset.Converters.Tupleizer/ConvertTuplesCommand.cs @@ -3,6 +3,7 @@ namespace WixToolset.Converters.Tupleizer { using System; + using System.Collections.Generic; using System.Linq; using WixToolset.Data; using WixToolset.Data.Tuples; @@ -21,11 +22,17 @@ namespace WixToolset.Converters.Tupleizer { var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type), output.Codepage); + var wixMediaByDiskId = IndexWixMediaTableByDiskId(output); + var bindPathsById = IndexById(output, "BindPath"); + var fontsById = IndexById(output, "Font"); + var selfRegById = IndexById(output, "SelfReg"); + var wixDirectoryById = IndexById(output, "WixDirectory"); + foreach (Wix3.Table table in output.Tables) { foreach (Wix3.Row row in table.Rows) { - var tuple = GenerateTupleFromRow(row); + var tuple = GenerateTupleFromRow(row, wixMediaByDiskId, fontsById, bindPathsById, selfRegById, wixDirectoryById); if (tuple != null) { section.Tuples.Add(tuple); @@ -36,353 +43,534 @@ namespace WixToolset.Converters.Tupleizer return new Intermediate(String.Empty, new[] { section }, localizationsByCulture: null, embedFilePaths: null); } - private static IntermediateTuple GenerateTupleFromRow(Wix3.Row row) + private static Dictionary IndexWixMediaTableByDiskId(Wix3.Output output) + { + var wixMediaByDiskId = new Dictionary(); + var wixMediaTable = output.Tables["WixMedia"]; + + if (wixMediaTable != null) + { + foreach (Wix3.WixMediaRow row in wixMediaTable.Rows) + { + wixMediaByDiskId.Add(FieldAsInt(row, 0), row); + } + } + + return wixMediaByDiskId; + } + + private static Dictionary IndexById(Wix3.Output output, string tableName) where T : Wix3.Row + { + var byId = new Dictionary(); + var table = output.Tables[tableName]; + + if (table != null) + { + foreach (T row in table.Rows) + { + byId.Add(FieldAsString(row, 0), row); + } + } + + return byId; + } + + private static IntermediateTuple GenerateTupleFromRow(Wix3.Row row, Dictionary wixMediaByDiskId, Dictionary fontsById, Dictionary bindPathsById, Dictionary selfRegById, Dictionary wixDirectoryById) { var name = row.Table.Name; switch (name) { - case "_SummaryInformation": - return DefaultTupleFromRow(typeof(_SummaryInformationTuple), row, columnZeroIsId: false); - case "ActionText": - return DefaultTupleFromRow(typeof(ActionTextTuple), row, columnZeroIsId: false); - case "AdvtExecuteSequence": - return DefaultTupleFromRow(typeof(AdvtExecuteSequenceTuple), row, columnZeroIsId: false); - case "AppId": - return DefaultTupleFromRow(typeof(AppIdTuple), row, columnZeroIsId: false); - case "AppSearch": - return DefaultTupleFromRow(typeof(AppSearchTuple), row, columnZeroIsId: false); - case "Binary": - return DefaultTupleFromRow(typeof(BinaryTuple), row, columnZeroIsId: false); - case "Class": - return DefaultTupleFromRow(typeof(ClassTuple), row, columnZeroIsId: false); - case "CompLocator": - return DefaultTupleFromRow(typeof(CompLocatorTuple), row, columnZeroIsId: true); - case "Component": - { - var attributes = FieldAsNullableInt(row, 3); - - var location = ComponentLocation.LocalOnly; - if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) == WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) - { - location = ComponentLocation.SourceOnly; - } - else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesOptional) == WindowsInstallerConstants.MsidbComponentAttributesOptional) - { - location = ComponentLocation.Either; - } + case "_SummaryInformation": + return DefaultTupleFromRow(typeof(SummaryInformationTuple), row, columnZeroIsId: false); + case "ActionText": + return DefaultTupleFromRow(typeof(ActionTextTuple), row, columnZeroIsId: false); + case "AdvtExecuteSequence": + return DefaultTupleFromRow(typeof(AdvtExecuteSequenceTuple), row, columnZeroIsId: false); + case "AppId": + return DefaultTupleFromRow(typeof(AppIdTuple), row, columnZeroIsId: false); + case "AppSearch": + return DefaultTupleFromRow(typeof(AppSearchTuple), row, columnZeroIsId: false); + case "Billboard": + return DefaultTupleFromRow(typeof(BillboardTuple), row, columnZeroIsId: true); + case "Binary": + return DefaultTupleFromRow(typeof(BinaryTuple), row, columnZeroIsId: true); + case "BindPath": + return null; + case "CCPSearch": + return DefaultTupleFromRow(typeof(CCPSearchTuple), row, columnZeroIsId: true); + case "Class": + return DefaultTupleFromRow(typeof(ClassTuple), row, columnZeroIsId: false); + case "CompLocator": + return DefaultTupleFromRow(typeof(CompLocatorTuple), row, columnZeroIsId: true); + case "Component": + { + var attributes = FieldAsNullableInt(row, 3); - var keyPathType = ComponentKeyPathType.File; - if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) - { - keyPathType = ComponentKeyPathType.Registry; - } - else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) - { - keyPathType = ComponentKeyPathType.OdbcDataSource; - } + var location = ComponentLocation.LocalOnly; + if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) == WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) + { + location = ComponentLocation.SourceOnly; + } + else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesOptional) == WindowsInstallerConstants.MsidbComponentAttributesOptional) + { + location = ComponentLocation.Either; + } - return new ComponentTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - ComponentId = FieldAsString(row, 1), - Directory_ = FieldAsString(row, 2), - Condition = FieldAsString(row, 4), - KeyPath = FieldAsString(row, 5), - Location = location, - DisableRegistryReflection = (attributes & WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection) == WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection, - NeverOverwrite = (attributes & WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite) == WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite, - Permanent = (attributes & WindowsInstallerConstants.MsidbComponentAttributesPermanent) == WindowsInstallerConstants.MsidbComponentAttributesPermanent, - SharedDllRefCount = (attributes & WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount) == WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount, - Shared = (attributes & WindowsInstallerConstants.MsidbComponentAttributesShared) == WindowsInstallerConstants.MsidbComponentAttributesShared, - Transitive = (attributes & WindowsInstallerConstants.MsidbComponentAttributesTransitive) == WindowsInstallerConstants.MsidbComponentAttributesTransitive, - UninstallWhenSuperseded = (attributes & WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence) == WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence, - Win64 = (attributes & WindowsInstallerConstants.MsidbComponentAttributes64bit) == WindowsInstallerConstants.MsidbComponentAttributes64bit, - KeyPathType = keyPathType, - }; + var keyPathType = ComponentKeyPathType.File; + if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) + { + keyPathType = ComponentKeyPathType.Registry; + } + else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) + { + keyPathType = ComponentKeyPathType.OdbcDataSource; } - case "Condition": - return DefaultTupleFromRow(typeof(ConditionTuple), row, columnZeroIsId: false); - case "CreateFolder": - return DefaultTupleFromRow(typeof(CreateFolderTuple), row, columnZeroIsId: false); - case "CustomAction": + return new ComponentTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) { - var caType = FieldAsInt(row, 1); - var executionType = DetermineCustomActionExecutionType(caType); - var sourceType = DetermineCustomActionSourceType(caType); - var targetType = DetermineCustomActionTargetType(caType); + ComponentId = FieldAsString(row, 1), + DirectoryRef = FieldAsString(row, 2), + Condition = FieldAsString(row, 4), + KeyPath = FieldAsString(row, 5), + Location = location, + DisableRegistryReflection = (attributes & WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection) == WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection, + NeverOverwrite = (attributes & WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite) == WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite, + Permanent = (attributes & WindowsInstallerConstants.MsidbComponentAttributesPermanent) == WindowsInstallerConstants.MsidbComponentAttributesPermanent, + SharedDllRefCount = (attributes & WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount) == WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount, + Shared = (attributes & WindowsInstallerConstants.MsidbComponentAttributesShared) == WindowsInstallerConstants.MsidbComponentAttributesShared, + Transitive = (attributes & WindowsInstallerConstants.MsidbComponentAttributesTransitive) == WindowsInstallerConstants.MsidbComponentAttributesTransitive, + UninstallWhenSuperseded = (attributes & WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence) == WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence, + Win64 = (attributes & WindowsInstallerConstants.MsidbComponentAttributes64bit) == WindowsInstallerConstants.MsidbComponentAttributes64bit, + KeyPathType = keyPathType, + }; + } - return new CustomActionTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - ExecutionType = executionType, - SourceType = sourceType, - Source = FieldAsString(row, 2), - TargetType = targetType, - Target = FieldAsString(row, 3), - Win64 = (caType & WindowsInstallerConstants.MsidbCustomActionType64BitScript) == WindowsInstallerConstants.MsidbCustomActionType64BitScript, - TSAware = (caType & WindowsInstallerConstants.MsidbCustomActionTypeTSAware) == WindowsInstallerConstants.MsidbCustomActionTypeTSAware, - Impersonate = (caType & WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate) != WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate, - IgnoreResult = (caType & WindowsInstallerConstants.MsidbCustomActionTypeContinue) == WindowsInstallerConstants.MsidbCustomActionTypeContinue, - Hidden = (caType & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) == WindowsInstallerConstants.MsidbCustomActionTypeHideTarget, - Async = (caType & WindowsInstallerConstants.MsidbCustomActionTypeAsync) == WindowsInstallerConstants.MsidbCustomActionTypeAsync, - }; - } + case "Condition": + return DefaultTupleFromRow(typeof(ConditionTuple), row, columnZeroIsId: false); + case "CreateFolder": + return DefaultTupleFromRow(typeof(CreateFolderTuple), row, columnZeroIsId: false); + case "CustomAction": + { + var caType = FieldAsInt(row, 1); + var executionType = DetermineCustomActionExecutionType(caType); + var sourceType = DetermineCustomActionSourceType(caType); + var targetType = DetermineCustomActionTargetType(caType); - case "Directory": - return DefaultTupleFromRow(typeof(DirectoryTuple), row, columnZeroIsId: false); - case "DrLocator": - return DefaultTupleFromRow(typeof(DrLocatorTuple), row, columnZeroIsId: false); - case "Error": - return DefaultTupleFromRow(typeof(ErrorTuple), row, columnZeroIsId: false); - case "Extension": - return DefaultTupleFromRow(typeof(ExtensionTuple), row, columnZeroIsId: false); - case "Feature": - { - int attributes = FieldAsInt(row, 7); - var installDefault = FeatureInstallDefault.Local; - if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) == WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) - { - installDefault = FeatureInstallDefault.FollowParent; - } - else - if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) == WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) - { - installDefault = FeatureInstallDefault.Source; - } + return new CustomActionTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + ExecutionType = executionType, + SourceType = sourceType, + Source = FieldAsString(row, 2), + TargetType = targetType, + Target = FieldAsString(row, 3), + Win64 = (caType & WindowsInstallerConstants.MsidbCustomActionType64BitScript) == WindowsInstallerConstants.MsidbCustomActionType64BitScript, + TSAware = (caType & WindowsInstallerConstants.MsidbCustomActionTypeTSAware) == WindowsInstallerConstants.MsidbCustomActionTypeTSAware, + Impersonate = (caType & WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate) != WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate, + IgnoreResult = (caType & WindowsInstallerConstants.MsidbCustomActionTypeContinue) == WindowsInstallerConstants.MsidbCustomActionTypeContinue, + Hidden = (caType & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) == WindowsInstallerConstants.MsidbCustomActionTypeHideTarget, + Async = (caType & WindowsInstallerConstants.MsidbCustomActionTypeAsync) == WindowsInstallerConstants.MsidbCustomActionTypeAsync, + }; + } - return new FeatureTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - Feature_Parent = FieldAsString(row, 1), - Title = FieldAsString(row, 2), - Description = FieldAsString(row, 3), - Display = FieldAsInt(row, 4), // BUGBUGBUG: FieldAsNullableInt(row, 4), - Level = FieldAsInt(row, 5), - Directory_ = FieldAsString(row, 6), - DisallowAbsent = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent) == WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent, - DisallowAdvertise = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise, - InstallDefault = installDefault, - TypicalDefault = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise ? FeatureTypicalDefault.Advertise : FeatureTypicalDefault.Install, - }; + case "Directory": + { + var id = FieldAsString(row, 0); + var splits = SplitDefaultDir(FieldAsString(row, 2)); + + var tuple = new DirectoryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id)) + { + ParentDirectoryRef = FieldAsString(row, 1), + Name = splits[0], + ShortName = splits[1], + SourceName = splits[2], + SourceShortName = splits[3] + }; + + if (wixDirectoryById.TryGetValue(id, out var wixDirectoryRow)) + { + tuple.ComponentGuidGenerationSeed = FieldAsString(wixDirectoryRow, 1); } - case "FeatureComponents": - return DefaultTupleFromRow(typeof(FeatureComponentsTuple), row, columnZeroIsId: false); - case "File": - { - var attributes = FieldAsNullableInt(row, 6); - var readOnly = (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly; - var hidden = (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden; - var system = (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem; - var vital = (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital; - var checksum = (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum; - bool? compressed = null; - if ((attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed) - { - compressed = false; - } - else if ((attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed) - { - compressed = true; - } + return tuple; + } + case "DrLocator": + return DefaultTupleFromRow(typeof(DrLocatorTuple), row, columnZeroIsId: false); + case "DuplicateFile": + return DefaultTupleFromRow(typeof(DuplicateFileTuple), row, columnZeroIsId: true); + case "Error": + return DefaultTupleFromRow(typeof(ErrorTuple), row, columnZeroIsId: false); + case "Extension": + return DefaultTupleFromRow(typeof(ExtensionTuple), row, columnZeroIsId: false); + case "Feature": + { + var attributes = FieldAsInt(row, 7); + var installDefault = FeatureInstallDefault.Local; + if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) == WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) + { + installDefault = FeatureInstallDefault.FollowParent; + } + else if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) == WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) + { + installDefault = FeatureInstallDefault.Source; + } - return new FileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - Component_ = FieldAsString(row, 1), - LongFileName = FieldAsString(row, 2), - FileSize = FieldAsInt(row, 3), - Version = FieldAsString(row, 4), - Language = FieldAsString(row, 5), - ReadOnly = readOnly, - Hidden = hidden, - System = system, - Vital = vital, - Checksum = checksum, - Compressed = compressed, - }; + return new FeatureTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + ParentFeatureRef = FieldAsString(row, 1), + Title = FieldAsString(row, 2), + Description = FieldAsString(row, 3), + Display = FieldAsInt(row, 4), // BUGBUGBUG: FieldAsNullableInt(row, 4), + Level = FieldAsInt(row, 5), + DirectoryRef = FieldAsString(row, 6), + DisallowAbsent = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent) == WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent, + DisallowAdvertise = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise, + InstallDefault = installDefault, + TypicalDefault = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise ? FeatureTypicalDefault.Advertise : FeatureTypicalDefault.Install, + }; + } + + case "FeatureComponents": + return DefaultTupleFromRow(typeof(FeatureComponentsTuple), row, columnZeroIsId: false); + case "File": + { + var attributes = FieldAsNullableInt(row, 6); + var readOnly = (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly; + var hidden = (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden; + var system = (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem; + var vital = (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital; + var checksum = (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum; + bool? compressed = null; + if ((attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed) + { + compressed = false; + } + else if ((attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed) + { + compressed = true; } - case "Font": - return DefaultTupleFromRow(typeof(FontTuple), row, columnZeroIsId: false); - case "Icon": - return DefaultTupleFromRow(typeof(IconTuple), row, columnZeroIsId: false); - case "InstallExecuteSequence": - return DefaultTupleFromRow(typeof(InstallExecuteSequenceTuple), row, columnZeroIsId: false); - case "LockPermissions": - return DefaultTupleFromRow(typeof(LockPermissionsTuple), row, columnZeroIsId: false); - case "Media": - return DefaultTupleFromRow(typeof(MediaTuple), row, columnZeroIsId: false); - case "MIME": - return DefaultTupleFromRow(typeof(MIMETuple), row, columnZeroIsId: false); - case "MoveFile": - return DefaultTupleFromRow(typeof(MoveFileTuple), row, columnZeroIsId: false); - case "MsiAssembly": - return DefaultTupleFromRow(typeof(MsiAssemblyTuple), row, columnZeroIsId: false); - case "MsiShortcutProperty": - return DefaultTupleFromRow(typeof(MsiShortcutPropertyTuple), row, columnZeroIsId: false); - case "ProgId": - return DefaultTupleFromRow(typeof(ProgIdTuple), row, columnZeroIsId: false); - case "Property": - return DefaultTupleFromRow(typeof(PropertyTuple), row, columnZeroIsId: false); - case "PublishComponent": - return DefaultTupleFromRow(typeof(PublishComponentTuple), row, columnZeroIsId: false); - case "Registry": - { - var value = FieldAsString(row, 4); - var valueType = RegistryValueType.String; - var valueAction = RegistryValueActionType.Write; - - if (!String.IsNullOrEmpty(value)) - { - if (value.StartsWith("#x", StringComparison.Ordinal)) - { - valueType = RegistryValueType.Binary; - value = value.Substring(2); - } - else if (value.StartsWith("#%", StringComparison.Ordinal)) - { - valueType = RegistryValueType.Expandable; - value = value.Substring(2); - } - else if (value.StartsWith("#", StringComparison.Ordinal)) - { - valueType = RegistryValueType.Integer; - value = value.Substring(1); - } - else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal)) - { - value = value.Substring(3, value.Length - 6); - valueType = RegistryValueType.MultiString; - valueAction = RegistryValueActionType.Write; - } - else if (value.StartsWith("[~]", StringComparison.Ordinal)) - { - value = value.Substring(3); - valueType = RegistryValueType.MultiString; - valueAction = RegistryValueActionType.Append; - } - else if (value.EndsWith("[~]", StringComparison.Ordinal)) - { - value = value.Substring(0, value.Length - 3); - valueType = RegistryValueType.MultiString; - valueAction = RegistryValueActionType.Prepend; - } - } + var id = FieldAsString(row, 0); - return new RegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - Root = (RegistryRootType)FieldAsInt(row, 1), - Key = FieldAsString(row, 2), - Name = FieldAsString(row, 3), - Value = value, - Component_ = FieldAsString(row, 5), - ValueAction = valueAction, - ValueType = valueType, - }; + var tuple = new FileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id)) + { + ComponentRef = FieldAsString(row, 1), + Name = FieldAsString(row, 2), + FileSize = FieldAsInt(row, 3), + Version = FieldAsString(row, 4), + Language = FieldAsString(row, 5), + ReadOnly = readOnly, + Hidden = hidden, + System = system, + Vital = vital, + Checksum = checksum, + Compressed = compressed, + }; + + if (bindPathsById.TryGetValue(id, out var bindPathRow)) + { + tuple.BindPath = FieldAsString(bindPathRow, 1) ?? String.Empty; } - case "RegLocator": - return DefaultTupleFromRow(typeof(RegLocatorTuple), row, columnZeroIsId: false); - case "RemoveFile": - return DefaultTupleFromRow(typeof(RemoveFileTuple), row, columnZeroIsId: false); - case "RemoveRegistry": + if (fontsById.TryGetValue(id, out var fontRow)) { - return new RemoveRegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - Action = RemoveRegistryActionType.RemoveOnInstall, - Root = (RegistryRootType)FieldAsInt(row, 1), - Key = FieldAsString(row, 2), - Name = FieldAsString(row, 3), - Component_ = FieldAsString(row, 4), - }; + tuple.FontTitle = FieldAsString(fontRow, 1) ?? String.Empty; } - case "ReserveCost": - return DefaultTupleFromRow(typeof(ReserveCostTuple), row, columnZeroIsId: false); - case "ServiceControl": + if (selfRegById.TryGetValue(id, out var selfRegRow)) { - var events = FieldAsInt(row, 2); - var wait = FieldAsNullableInt(row, 4); - return new ServiceControlTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - Name = FieldAsString(row, 1), - Arguments = FieldAsString(row, 3), - Wait = !wait.HasValue || wait.Value == 1, - Component_ = FieldAsString(row, 5), - InstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventDelete) == WindowsInstallerConstants.MsidbServiceControlEventDelete, - UninstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete) == WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete, - InstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventStart) == WindowsInstallerConstants.MsidbServiceControlEventStart, - UninstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStart) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStart, - InstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventStop) == WindowsInstallerConstants.MsidbServiceControlEventStop, - UninstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStop) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStop, - }; + tuple.SelfRegCost = FieldAsNullableInt(selfRegRow, 1) ?? 0; } - case "ServiceInstall": - return DefaultTupleFromRow(typeof(ServiceInstallTuple), row, columnZeroIsId: true); - case "Shortcut": - return DefaultTupleFromRow(typeof(ShortcutTuple), row, columnZeroIsId: true); - case "Signature": - return DefaultTupleFromRow(typeof(SignatureTuple), row, columnZeroIsId: false); - case "Upgrade": + return tuple; + } + case "Font": + return null; + case "Icon": + return DefaultTupleFromRow(typeof(IconTuple), row, columnZeroIsId: true); + case "InstallExecuteSequence": + return DefaultTupleFromRow(typeof(InstallExecuteSequenceTuple), row, columnZeroIsId: false); + case "LockPermissions": + return DefaultTupleFromRow(typeof(LockPermissionsTuple), row, columnZeroIsId: false); + case "Media": + { + var diskId = FieldAsInt(row, 0); + var tuple = new MediaTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, diskId)) { - var attributes = FieldAsInt(row, 4); - return new UpgradeTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - UpgradeCode = FieldAsString(row, 0), - VersionMin = FieldAsString(row, 1), - VersionMax = FieldAsString(row, 2), - Language = FieldAsString(row, 3), - Remove = FieldAsString(row, 5), - ActionProperty = FieldAsString(row, 6), - MigrateFeatures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures) == WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures, - OnlyDetect = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect, - IgnoreRemoveFailures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure) == WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure, - VersionMinInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive, - VersionMaxInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive, - ExcludeLanguages = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive, - }; + DiskId = diskId, + LastSequence = FieldAsNullableInt(row, 1), + DiskPrompt = FieldAsString(row, 2), + Cabinet = FieldAsString(row, 3), + VolumeLabel = FieldAsString(row, 4), + Source = FieldAsString(row, 5) + }; + + if (wixMediaByDiskId.TryGetValue(diskId, out var wixMediaRow)) + { + var compressionLevel = FieldAsString(wixMediaRow, 1); + + tuple.CompressionLevel = String.IsNullOrEmpty(compressionLevel) ? null : (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), compressionLevel, true); + tuple.Layout = wixMediaRow.Layout; } - case "Verb": - return DefaultTupleFromRow(typeof(VerbTuple), row, columnZeroIsId: false); - //case "WixAction": - // return new WixActionTuple(SourceLineNumber4(row.SourceLineNumbers)) - // { - // SequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), FieldAsString(row, 0)), - // Action = FieldAsString(row, 1), - // Condition = FieldAsString(row, 2), - // Sequence = FieldAsInt(row, 3), - // Before = FieldAsString(row, 4), - // After = FieldAsString(row, 5), - // Overridable = FieldAsNullableInt(row, 6) != 0, - // }; - case "WixFile": - var assemblyAttributes3 = FieldAsNullableInt(row, 1); - return new WixFileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + return tuple; + } + case "MIME": + return DefaultTupleFromRow(typeof(MIMETuple), row, columnZeroIsId: false); + case "ModuleIgnoreTable": + return DefaultTupleFromRow(typeof(ModuleIgnoreTableTuple), row, columnZeroIsId: true); + case "MoveFile": + return DefaultTupleFromRow(typeof(MoveFileTuple), row, columnZeroIsId: true); + case "MsiAssembly": + return DefaultTupleFromRow(typeof(MsiAssemblyTuple), row, columnZeroIsId: false); + case "MsiLockPermissionsEx": + return DefaultTupleFromRow(typeof(MsiLockPermissionsExTuple), row, columnZeroIsId: true); + case "MsiShortcutProperty": + return DefaultTupleFromRow(typeof(MsiShortcutPropertyTuple), row, columnZeroIsId: true); + case "ODBCDataSource": + return DefaultTupleFromRow(typeof(ODBCDataSourceTuple), row, columnZeroIsId: true); + case "ODBCDriver": + return DefaultTupleFromRow(typeof(ODBCDriverTuple), row, columnZeroIsId: true); + case "ODBCTranslator": + return DefaultTupleFromRow(typeof(ODBCTranslatorTuple), row, columnZeroIsId: true); + case "ProgId": + return DefaultTupleFromRow(typeof(ProgIdTuple), row, columnZeroIsId: false); + case "Property": + return DefaultTupleFromRow(typeof(PropertyTuple), row, columnZeroIsId: true); + case "PublishComponent": + return DefaultTupleFromRow(typeof(PublishComponentTuple), row, columnZeroIsId: false); + case "Registry": + { + var value = FieldAsString(row, 4); + var valueType = RegistryValueType.String; + var valueAction = RegistryValueActionType.Write; + + if (!String.IsNullOrEmpty(value)) + { + if (value.StartsWith("#x", StringComparison.Ordinal)) { - AssemblyType = assemblyAttributes3 == 0 ? FileAssemblyType.DotNetAssembly : assemblyAttributes3 == 1 ? FileAssemblyType.Win32Assembly : FileAssemblyType.NotAnAssembly, - File_AssemblyManifest = FieldAsString(row, 2), - File_AssemblyApplication = FieldAsString(row, 3), - Directory_ = FieldAsString(row, 4), - DiskId = FieldAsInt(row, 5), // TODO: BUGBUGBUG: AB#2626: DiskId is nullable in WiX v3. - Source = new IntermediateFieldPathValue() { Path = FieldAsString(row, 6) }, - ProcessorArchitecture = FieldAsString(row, 7), - PatchGroup = FieldAsInt(row, 8), - Attributes = FieldAsInt(row, 9), - }; - case "WixProperty": - { - var attributes = FieldAsInt(row, 1); - return new WixPropertyTuple(SourceLineNumber4(row.SourceLineNumbers)) + valueType = RegistryValueType.Binary; + value = value.Substring(2); + } + else if (value.StartsWith("#%", StringComparison.Ordinal)) + { + valueType = RegistryValueType.Expandable; + value = value.Substring(2); + } + else if (value.StartsWith("#", StringComparison.Ordinal)) + { + valueType = RegistryValueType.Integer; + value = value.Substring(1); + } + else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal)) + { + value = value.Substring(3, value.Length - 6); + valueType = RegistryValueType.MultiString; + valueAction = RegistryValueActionType.Write; + } + else if (value.StartsWith("[~]", StringComparison.Ordinal)) + { + value = value.Substring(3); + valueType = RegistryValueType.MultiString; + valueAction = RegistryValueActionType.Append; + } + else if (value.EndsWith("[~]", StringComparison.Ordinal)) { - Property_ = FieldAsString(row, 0), - Admin = (attributes & 0x1) == 0x1, - Hidden = (attributes & 0x2) == 0x2, - Secure = (attributes & 0x4) == 0x4, - }; + value = value.Substring(0, value.Length - 3); + valueType = RegistryValueType.MultiString; + valueAction = RegistryValueActionType.Prepend; + } } - default: - return GenericTupleFromCustomRow(row, columnZeroIsId: false); + return new RegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + Root = (RegistryRootType)FieldAsInt(row, 1), + Key = FieldAsString(row, 2), + Name = FieldAsString(row, 3), + Value = value, + ComponentRef = FieldAsString(row, 5), + ValueAction = valueAction, + ValueType = valueType, + }; + } + case "RegLocator": + { + var type = FieldAsInt(row, 4); + + return new RegLocatorTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + Root = (RegistryRootType)FieldAsInt(row, 1), + Key = FieldAsString(row, 2), + Name = FieldAsString(row, 3), + Type = (RegLocatorType)(type & 0xF), + Win64 = (type & WindowsInstallerConstants.MsidbLocatorType64bit) == WindowsInstallerConstants.MsidbLocatorType64bit + }; + } + case "RemoveFile": + { + var installMode = FieldAsInt(row, 4); + return new RemoveFileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + ComponentRef = FieldAsString(row, 1), + FileName = FieldAsString(row, 2), + DirProperty = FieldAsString(row, 3), + OnInstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall ? (bool?)true : null, + OnUninstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove ? (bool?)true : null + }; + } + case "RemoveRegistry": + { + return new RemoveRegistryTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + Action = RemoveRegistryActionType.RemoveOnInstall, + Root = (RegistryRootType)FieldAsInt(row, 1), + Key = FieldAsString(row, 2), + Name = FieldAsString(row, 3), + ComponentRef = FieldAsString(row, 4), + }; + } + + case "ReserveCost": + return DefaultTupleFromRow(typeof(ReserveCostTuple), row, columnZeroIsId: true); + case "SelfReg": + return null; + case "ServiceControl": + { + var events = FieldAsInt(row, 2); + var wait = FieldAsNullableInt(row, 4); + return new ServiceControlTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + Name = FieldAsString(row, 1), + Arguments = FieldAsString(row, 3), + Wait = !wait.HasValue || wait.Value == 1, + ComponentRef = FieldAsString(row, 5), + InstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventDelete) == WindowsInstallerConstants.MsidbServiceControlEventDelete, + UninstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete) == WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete, + InstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventStart) == WindowsInstallerConstants.MsidbServiceControlEventStart, + UninstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStart) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStart, + InstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventStop) == WindowsInstallerConstants.MsidbServiceControlEventStop, + UninstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStop) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStop, + }; + } + + case "ServiceInstall": + return DefaultTupleFromRow(typeof(ServiceInstallTuple), row, columnZeroIsId: true); + case "Shortcut": + { + var splitName = FieldAsString(row, 2).Split('|'); + + return new ShortcutTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + DirectoryRef = FieldAsString(row, 1), + Name = splitName.Length > 1 ? splitName[1] : splitName[0], + ShortName = splitName.Length > 1 ? splitName[0] : null, + ComponentRef = FieldAsString(row, 3), + Target = FieldAsString(row, 4), + Arguments = FieldAsString(row, 5), + Description = FieldAsString(row, 6), + Hotkey = FieldAsNullableInt(row, 7), + IconRef = FieldAsString(row, 8), + IconIndex = FieldAsNullableInt(row, 9), + Show = (ShortcutShowType?)FieldAsNullableInt(row, 10), + WorkingDirectory = FieldAsString(row, 11), + DisplayResourceDll = FieldAsString(row, 12), + DisplayResourceId = FieldAsNullableInt(row, 13), + DescriptionResourceDll = FieldAsString(row, 14), + DescriptionResourceId= FieldAsNullableInt(row, 15), + }; + } + case "Signature": + return DefaultTupleFromRow(typeof(SignatureTuple), row, columnZeroIsId: false); + case "UIText": + return DefaultTupleFromRow(typeof(UITextTuple), row, columnZeroIsId: true); + case "Upgrade": + { + var attributes = FieldAsInt(row, 4); + return new UpgradeTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + UpgradeCode = FieldAsString(row, 0), + VersionMin = FieldAsString(row, 1), + VersionMax = FieldAsString(row, 2), + Language = FieldAsString(row, 3), + Remove = FieldAsString(row, 5), + ActionProperty = FieldAsString(row, 6), + MigrateFeatures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures) == WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures, + OnlyDetect = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect, + IgnoreRemoveFailures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure) == WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure, + VersionMinInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive, + VersionMaxInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive, + ExcludeLanguages = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive, + }; + } + case "Verb": + return DefaultTupleFromRow(typeof(VerbTuple), row, columnZeroIsId: false); + case "WixAction": + var sequenceTable = FieldAsString(row, 0); + return new WixActionTuple(SourceLineNumber4(row.SourceLineNumbers)) + { + SequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), sequenceTable == "AdvtExecuteSequence" ? nameof(SequenceTable.AdvertiseExecuteSequence) : sequenceTable), + Action = FieldAsString(row, 1), + Condition = FieldAsString(row, 2), + Sequence = FieldAsNullableInt(row, 3), + Before = FieldAsString(row, 4), + After = FieldAsString(row, 5), + Overridable = FieldAsNullableInt(row, 6) != 0, + }; + case "WixBootstrapperApplication": + return DefaultTupleFromRow(typeof(WixBootstrapperApplicationTuple), row, columnZeroIsId: true); + case "WixBundleContainer": + return DefaultTupleFromRow(typeof(WixBundleContainerTuple), row, columnZeroIsId: true); + case "WixBundleVariable": + return DefaultTupleFromRow(typeof(WixBundleVariableTuple), row, columnZeroIsId: true); + case "WixChainItem": + return DefaultTupleFromRow(typeof(WixChainItemTuple), row, columnZeroIsId: true); + case "WixCustomTable": + return DefaultTupleFromRow(typeof(WixCustomTableTuple), row, columnZeroIsId: true); + case "WixDeltaPatchFile": + return DefaultTupleFromRow(typeof(WixDeltaPatchFileTuple), row, columnZeroIsId: true); + case "WixDirectory": + return null; + case "WixFile": + var assemblyAttributes3 = FieldAsNullableInt(row, 1); + return new WixFileTuple(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + AssemblyType = assemblyAttributes3 == 0 ? FileAssemblyType.DotNetAssembly : assemblyAttributes3 == 1 ? FileAssemblyType.Win32Assembly : FileAssemblyType.NotAnAssembly, + AssemblyManifestFileRef = FieldAsString(row, 2), + AssemblyApplicationFileRef = FieldAsString(row, 3), + DirectoryRef = FieldAsString(row, 4), + DiskId = FieldAsNullableInt(row, 5) ?? 0, + Source = new IntermediateFieldPathValue() { Path = FieldAsString(row, 6) }, + ProcessorArchitecture = FieldAsString(row, 7), + PatchGroup = FieldAsInt(row, 8), + Attributes = FieldAsInt(row, 9), + PatchAttributes = (PatchAttributeType)FieldAsInt(row, 10), + }; + case "WixInstanceTransforms": + return DefaultTupleFromRow(typeof(WixInstanceTransformsTuple), row, columnZeroIsId: true); + case "WixMedia": + return null; + case "WixMerge": + return DefaultTupleFromRow(typeof(WixMergeTuple), row, columnZeroIsId: true); + case "WixPatchBaseline": + return DefaultTupleFromRow(typeof(WixPatchBaselineTuple), row, columnZeroIsId: true); + case "WixProperty": + { + var attributes = FieldAsInt(row, 1); + return new WixPropertyTuple(SourceLineNumber4(row.SourceLineNumbers)) + { + PropertyRef = FieldAsString(row, 0), + Admin = (attributes & 0x1) == 0x1, + Hidden = (attributes & 0x2) == 0x2, + Secure = (attributes & 0x4) == 0x4, + }; + } + case "WixSuppressModularization": + return DefaultTupleFromRow(typeof(WixSuppressModularizationTuple), row, columnZeroIsId: true); + case "WixUI": + return DefaultTupleFromRow(typeof(WixUITuple), row, columnZeroIsId: true); + case "WixVariable": + return DefaultTupleFromRow(typeof(WixVariableTuple), row, columnZeroIsId: true); + default: + return GenericTupleFromCustomRow(row, columnZeroIsId: false); } } @@ -470,16 +658,16 @@ namespace WixToolset.Converters.Tupleizer { switch (columnType) { - case Wix3.ColumnType.Number: - return IntermediateFieldType.Number; - case Wix3.ColumnType.Object: - return IntermediateFieldType.Path; - case Wix3.ColumnType.Unknown: - case Wix3.ColumnType.String: - case Wix3.ColumnType.Localized: - case Wix3.ColumnType.Preserved: - default: - return IntermediateFieldType.String; + case Wix3.ColumnType.Number: + return IntermediateFieldType.Number; + case Wix3.ColumnType.Object: + return IntermediateFieldType.Path; + case Wix3.ColumnType.Unknown: + case Wix3.ColumnType.String: + case Wix3.ColumnType.Localized: + case Wix3.ColumnType.Preserved: + default: + return IntermediateFieldType.String; } } @@ -520,22 +708,22 @@ namespace WixToolset.Converters.Tupleizer var column = row.Fields[i].Column; switch (column.Type) { - case Wix3.ColumnType.String: - case Wix3.ColumnType.Localized: - case Wix3.ColumnType.Object: - case Wix3.ColumnType.Preserved: - tuple.Set(i - offset, FieldAsString(row, i)); - break; - case Wix3.ColumnType.Number: - int? nullableValue = FieldAsNullableInt(row, i); - // TODO: Consider whether null values should be coerced to their default value when - // a column is not nullable. For now, just pass through the null. - //int value = FieldAsInt(row, i); - //tuple.Set(i - offset, column.IsNullable ? nullableValue : value); - tuple.Set(i - offset, nullableValue); + case Wix3.ColumnType.String: + case Wix3.ColumnType.Localized: + case Wix3.ColumnType.Object: + case Wix3.ColumnType.Preserved: + tuple.Set(i - offset, FieldAsString(row, i)); + break; + case Wix3.ColumnType.Number: + int? nullableValue = FieldAsNullableInt(row, i); + // TODO: Consider whether null values should be coerced to their default value when + // a column is not nullable. For now, just pass through the null. + //int value = FieldAsInt(row, i); + //tuple.Set(i - offset, column.IsNullable ? nullableValue : value); + tuple.Set(i - offset, nullableValue); + break; + case Wix3.ColumnType.Unknown: break; - case Wix3.ColumnType.Unknown: - break; } } } @@ -545,15 +733,15 @@ namespace WixToolset.Converters.Tupleizer var column = row.Fields[0].Column; switch (column.Type) { - case Wix3.ColumnType.String: - case Wix3.ColumnType.Localized: - case Wix3.ColumnType.Object: - case Wix3.ColumnType.Preserved: - return new Identifier(AccessModifier.Public, (string)row.Fields[0].Data); - case Wix3.ColumnType.Number: - return new Identifier(AccessModifier.Public, FieldAsInt(row, 0)); - default: - return null; + case Wix3.ColumnType.String: + case Wix3.ColumnType.Localized: + case Wix3.ColumnType.Object: + case Wix3.ColumnType.Preserved: + return new Identifier(AccessModifier.Public, (string)row.Fields[0].Data); + case Wix3.ColumnType.Number: + return new Identifier(AccessModifier.Public, FieldAsInt(row, 0)); + default: + return null; } } @@ -561,20 +749,20 @@ namespace WixToolset.Converters.Tupleizer { switch (outputType) { - case Wix3.OutputType.Bundle: - return SectionType.Bundle; - case Wix3.OutputType.Module: - return SectionType.Module; - case Wix3.OutputType.Patch: - return SectionType.Patch; - case Wix3.OutputType.PatchCreation: - return SectionType.PatchCreation; - case Wix3.OutputType.Product: - return SectionType.Product; - case Wix3.OutputType.Transform: - case Wix3.OutputType.Unknown: - default: - return SectionType.Unknown; + case Wix3.OutputType.Bundle: + return SectionType.Bundle; + case Wix3.OutputType.Module: + return SectionType.Module; + case Wix3.OutputType.Patch: + return SectionType.Patch; + case Wix3.OutputType.PatchCreation: + return SectionType.PatchCreation; + case Wix3.OutputType.Product: + return SectionType.Product; + case Wix3.OutputType.Transform: + case Wix3.OutputType.Unknown: + default: + return SectionType.Unknown; } } @@ -605,5 +793,19 @@ namespace WixToolset.Converters.Tupleizer return Convert.ToInt32(field.Data); } } + + private static string[] SplitDefaultDir(string defaultDir) + { + var split1 = defaultDir.Split(':'); + var targetSplit = split1.Length > 1 ? split1[1].Split('|') : split1[0].Split('|'); + var sourceSplit = split1.Length > 1 ? split1[0].Split('|') : new[] { String.Empty }; + return new[] + { + targetSplit.Length > 1 ? targetSplit[1] : targetSplit[0], + targetSplit.Length > 1 ? targetSplit[0] : null, + sourceSplit.Length > 1 ? sourceSplit[1] : sourceSplit[0], + sourceSplit.Length > 1 ? sourceSplit[0] : null + }; + } } } diff --git a/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs b/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs index ae33d6b1..9b1fa4cf 100644 --- a/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs +++ b/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs @@ -3,6 +3,7 @@ namespace WixToolsetTest.Converters.Tupleizer { using System; + using System.Collections.Generic; using System.IO; using System.Linq; using WixBuildTools.TestSupport; @@ -42,350 +43,512 @@ namespace WixToolsetTest.Converters.Tupleizer intermediate = Intermediate.Load(wixiplFile); + var wixMediaByDiskId = IndexWixMediaTableByDiskId(output); + // Dump to text for easy diffing, with some massaging to keep v3 and v4 diffable. // var tables = output.Tables.Cast(); var wix3Dump = tables .SelectMany(table => table.Rows.Cast() - .Select(row => RowToString(row))) + .SelectMany(row => RowToStrings(row, wixMediaByDiskId))) + .Where(s => !String.IsNullOrEmpty(s)) + .OrderBy(s => s) .ToArray(); var tuples = intermediate.Sections.SelectMany(s => s.Tuples); - var wix4Dump = tuples.Select(tuple => TupleToString(tuple)).ToArray(); + var wix4Dump = tuples + .SelectMany(tuple => TupleToStrings(tuple)) + .OrderBy(s => s) + .ToArray(); +#if false Assert.Equal(wix3Dump, wix4Dump); +#else // useful when you want to diff the outputs with another diff tool. + var wix3TextDump = String.Join(Environment.NewLine, wix3Dump); + var wix4TextDump = String.Join(Environment.NewLine, wix4Dump); - // Useful when you want to diff the outputs with another diff tool... - // - //var wix3TextDump = String.Join(Environment.NewLine, wix3Dump.OrderBy(val => val)); - //var wix4TextDump = String.Join(Environment.NewLine, wix4Dump.OrderBy(val => val)); - //Assert.Equal(wix3TextDump, wix4TextDump); + File.WriteAllText(Path.Combine(Path.GetTempPath(), "~3.txt"), wix3TextDump); + File.WriteAllText(Path.Combine(Path.GetTempPath(), "~4.txt"), wix4TextDump); + + Assert.Equal(wix3TextDump, wix4TextDump); +#endif } } - private static string RowToString(Wix3.Row row) + private static Dictionary IndexWixMediaTableByDiskId(Wix3.Output output) { - var fields = String.Join(",", row.Fields.Select(field => field.Data?.ToString())); + var wixMediaByDiskId = new Dictionary(); + var wixMediaTable = output.Tables["WixMedia"]; - // Massage output to match WiX v3 rows and v4 tuples. - // - switch (row.Table.Name) + if (wixMediaTable != null) { - case "File": - var fieldValues = row.Fields.Take(7).Select(field => field.Data?.ToString()).ToArray(); - if (fieldValues[3] == null) - { - // "Somebody" sometimes writes out a null field even when the column definition says - // it's non-nullable. Not naming names or anything. (SWID tags.) - fieldValues[3] = "0"; - } - fields = String.Join(",", fieldValues); - break; - case "WixFile": - fields = String.Join(",", row.Fields.Take(8).Select(field => field.Data?.ToString())); - break; + foreach (Wix3.WixMediaRow row in wixMediaTable.Rows) + { + wixMediaByDiskId.Add((int)row[0], row); + } } - return $"{row.Table.Name},{fields}"; + return wixMediaByDiskId; } - private static string TupleToString(WixToolset.Data.IntermediateTuple tuple) + private static IEnumerable RowToStrings(Wix3.Row row, Dictionary wixMediaByDiskId) { - var fields = String.Join(",", tuple.Fields.Select(field => field?.AsString())); + string fields = null; - switch (tuple.Definition.Name) + // Massage output to match WiX v3 rows and v4 tuples. + // + switch (row.Table.Name) { - // Massage output to match WiX v3 rows and v4 tuples. - // - case "Component": - { - var componentTuple = (ComponentTuple)tuple; - var attributes = ComponentLocation.Either == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0; - attributes |= ComponentLocation.SourceOnly == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0; - attributes |= ComponentKeyPathType.Registry == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0; - attributes |= ComponentKeyPathType.OdbcDataSource == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0; - attributes |= componentTuple.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0; - attributes |= componentTuple.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0; - attributes |= componentTuple.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0; - attributes |= componentTuple.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0; - attributes |= componentTuple.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0; - attributes |= componentTuple.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0; - attributes |= componentTuple.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; - attributes |= componentTuple.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; - - fields = String.Join(",", - componentTuple.ComponentId, - componentTuple.Directory_, - attributes.ToString(), - componentTuple.Condition, - componentTuple.KeyPath - ); - break; - } - case "CustomAction": + case "Directory": + var dirs = SplitDefaultDir((string)row[2]); + fields = String.Join(",", row[0], row[1], dirs[0], dirs[1], dirs[2], dirs[3]); + break; + case "File": + { + var fieldValues = row.Fields.Take(7).Select(SafeConvertField).ToArray(); + if (fieldValues[3] == null) { - var customActionTuple = (CustomActionTuple)tuple; - var type = customActionTuple.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0; - type |= customActionTuple.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0; - type |= customActionTuple.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate; - type |= customActionTuple.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0; - type |= customActionTuple.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0; - type |= customActionTuple.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0; - type |= CustomActionExecutionType.FirstSequence == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0; - type |= CustomActionExecutionType.OncePerProcess == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0; - type |= CustomActionExecutionType.ClientRepeat == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0; - type |= CustomActionExecutionType.Deferred == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0; - type |= CustomActionExecutionType.Rollback == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0; - type |= CustomActionExecutionType.Commit == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0; - type |= CustomActionSourceType.File == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0; - type |= CustomActionSourceType.Directory == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0; - type |= CustomActionSourceType.Property == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0; - type |= CustomActionTargetType.Dll == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0; - type |= CustomActionTargetType.Exe == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0; - type |= CustomActionTargetType.TextData == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0; - type |= CustomActionTargetType.JScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0; - type |= CustomActionTargetType.VBScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0; - - fields = String.Join(",", - type.ToString(), - customActionTuple.Source, - customActionTuple.Target, - customActionTuple.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null - ); - break; + // "Somebody" sometimes writes out a null field even when the column definition says + // it's non-nullable. Not naming names or anything. (SWID tags.) + fieldValues[3] = "0"; } - case "Feature": - { - var featureTuple = (FeatureTuple)tuple; - var attributes = featureTuple.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0; - attributes |= featureTuple.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0; - attributes |= FeatureInstallDefault.FollowParent == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0; - attributes |= FeatureInstallDefault.Source == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0; - attributes |= FeatureTypicalDefault.Advertise == featureTuple.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0; - - fields = String.Join(",", - featureTuple.Feature_Parent, - featureTuple.Title, - featureTuple.Description, - featureTuple.Display.ToString(), - featureTuple.Level.ToString(), - featureTuple.Directory_, - attributes.ToString()); - break; - } - case "File": + fields = String.Join(",", fieldValues); + break; + } + case "Media": + var compression = wixMediaByDiskId.TryGetValue((int)row[0], out var wixMedia) ? (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), SafeConvertField(wixMedia.Fields[1]), true) : null; + + fields = String.Join(",", row.Fields.Select(SafeConvertField)); + fields = String.Join(",", fields, (int?)compression, SafeConvertField(wixMedia?.Fields[2])); + break; + case "RegLocator": + var type = (int)row[4]; + fields = String.Join(",", row[0], row[1], row[2], row[3], type & 0xF, (type & 0x10) == 0x10); + break; + case "RemoveFile": + var attributes = (int)row[4]; + var onInstall = (attributes & 1) == 1 ? (bool?)true : null; + var onUninstall = (attributes & 2) == 2 ? (bool?)true : null; + fields = String.Join(",", row.Fields.Take(4).Select(SafeConvertField)); + fields = String.Join(",", fields, onInstall, onUninstall); + break; + case "Shortcut": + var split = ((string)row[2]).Split('|'); + var afterName = String.Join(",", row.Fields.Skip(3).Select(SafeConvertField)); + fields = String.Join(",", row[0], row[1], split.Length > 1 ? split[1] : split[0], split.Length > 1 ? split[0] : String.Empty, afterName); + break; + case "WixAction": + var table = (int)SequenceStringToSequenceTable(row[0]); + fields = String.Join(",", table, row[1], row[2], row[3], row[4], row[5], row[6]); + break; + case "WixFile": + { + var fieldValues = row.Fields.Take(10).Select(SafeConvertField).ToArray(); + if (fieldValues[8] == null) { - var fileTuple = (FileTuple)tuple; - fields = String.Join(",", - fileTuple.Component_, - fileTuple.LongFileName, - fileTuple.FileSize.ToString(), - fileTuple.Version, - fileTuple.Language, - ((fileTuple.ReadOnly ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0) - | (fileTuple.Hidden ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0) - | (fileTuple.System ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0) - | (fileTuple.Vital ? WindowsInstallerConstants.MsidbFileAttributesVital : 0) - | (fileTuple.Checksum ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0) - | ((fileTuple.Compressed.HasValue && fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0) - | ((fileTuple.Compressed.HasValue && !fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0)) - .ToString()); - break; + // "Somebody" sometimes writes out a null field even when the column definition says + // it's non-nullable. Not naming names or anything. (SWID tags.) + fieldValues[8] = "0"; } + fields = String.Join(",", fieldValues); + break; + } + case "WixMedia": + break; + default: + fields = String.Join(",", row.Fields.Select(SafeConvertField)); + break; + } - case "Registry": - { - var registryTuple = (RegistryTuple)tuple; - var value = registryTuple.Value; - - switch (registryTuple.ValueType) - { - case RegistryValueType.Binary: - value = String.Concat("#x", value); - break; - case RegistryValueType.Expandable: - value = String.Concat("#%", value); - break; - case RegistryValueType.Integer: - value = String.Concat("#", value); - break; - case RegistryValueType.MultiString: - switch (registryTuple.ValueAction) - { - case RegistryValueActionType.Append: - value = String.Concat("[~]", value); - break; - case RegistryValueActionType.Prepend: - value = String.Concat(value, "[~]"); - break; - case RegistryValueActionType.Write: - default: - if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal)) - { - value = String.Concat("[~]", value, "[~]"); - } - break; - } - break; - case RegistryValueType.String: - // escape the leading '#' character for string registry keys - if (null != value && value.StartsWith("#", StringComparison.Ordinal)) - { - value = String.Concat("#", value); - } - break; - } + if (fields != null) + { + yield return $"{row.Table.Name}:{fields}"; + } + } - fields = String.Join(",", - ((int)registryTuple.Root).ToString(), - registryTuple.Key, - registryTuple.Name, - value, - registryTuple.Component_ - ); - break; - } + private static IEnumerable TupleToStrings(IntermediateTuple tuple) + { + string fields; + switch (tuple.Definition.Name) + { + // Massage output to match WiX v3 rows and v4 tuples. + // + case "Component": + { + var componentTuple = (ComponentTuple)tuple; + var attributes = ComponentLocation.Either == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0; + attributes |= ComponentLocation.SourceOnly == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0; + attributes |= ComponentKeyPathType.Registry == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0; + attributes |= ComponentKeyPathType.OdbcDataSource == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0; + attributes |= componentTuple.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0; + attributes |= componentTuple.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0; + attributes |= componentTuple.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0; + attributes |= componentTuple.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0; + attributes |= componentTuple.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0; + attributes |= componentTuple.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0; + attributes |= componentTuple.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; + attributes |= componentTuple.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; + + fields = String.Join(",", + componentTuple.ComponentId, + componentTuple.DirectoryRef, + attributes.ToString(), + componentTuple.Condition, + componentTuple.KeyPath + ); + break; + } + case "CustomAction": + { + var customActionTuple = (CustomActionTuple)tuple; + var type = customActionTuple.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0; + type |= customActionTuple.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0; + type |= customActionTuple.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate; + type |= customActionTuple.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0; + type |= customActionTuple.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0; + type |= customActionTuple.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0; + type |= CustomActionExecutionType.FirstSequence == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0; + type |= CustomActionExecutionType.OncePerProcess == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0; + type |= CustomActionExecutionType.ClientRepeat == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0; + type |= CustomActionExecutionType.Deferred == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0; + type |= CustomActionExecutionType.Rollback == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0; + type |= CustomActionExecutionType.Commit == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0; + type |= CustomActionSourceType.File == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0; + type |= CustomActionSourceType.Directory == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0; + type |= CustomActionSourceType.Property == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0; + type |= CustomActionTargetType.Dll == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0; + type |= CustomActionTargetType.Exe == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0; + type |= CustomActionTargetType.TextData == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0; + type |= CustomActionTargetType.JScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0; + type |= CustomActionTargetType.VBScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0; + + fields = String.Join(",", + type.ToString(), + customActionTuple.Source, + customActionTuple.Target, + customActionTuple.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null + ); + break; + } + case "Directory": + { + var directoryTuple = (DirectoryTuple)tuple; - case "RemoveRegistry": + if (!String.IsNullOrEmpty(directoryTuple.ComponentGuidGenerationSeed)) { - var removeRegistryTuple = (RemoveRegistryTuple)tuple; - fields = String.Join(",", - ((int)removeRegistryTuple.Root).ToString(), - removeRegistryTuple.Key, - removeRegistryTuple.Name, - removeRegistryTuple.Component_ - ); - break; + yield return $"WixDirectory:{directoryTuple.Id.Id},{directoryTuple.ComponentGuidGenerationSeed}"; } - case "ServiceControl": - { - var serviceControlTuple = (ServiceControlTuple)tuple; - - var events = serviceControlTuple.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0; - events |= serviceControlTuple.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0; - events |= serviceControlTuple.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0; - events |= serviceControlTuple.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0; - events |= serviceControlTuple.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0; - events |= serviceControlTuple.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0; - - fields = String.Join(",", - serviceControlTuple.Name, - events.ToString(), - serviceControlTuple.Arguments, - serviceControlTuple.Wait == true ? "1" : "0", - serviceControlTuple.Component_ - ); - break; - } + fields = String.Join(",", directoryTuple.ParentDirectoryRef, directoryTuple.Name, directoryTuple.ShortName, directoryTuple.SourceName, directoryTuple.SourceShortName); + break; + } + case "Feature": + { + var featureTuple = (FeatureTuple)tuple; + var attributes = featureTuple.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0; + attributes |= featureTuple.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0; + attributes |= FeatureInstallDefault.FollowParent == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0; + attributes |= FeatureInstallDefault.Source == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0; + attributes |= FeatureTypicalDefault.Advertise == featureTuple.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0; + + fields = String.Join(",", + featureTuple.ParentFeatureRef, + featureTuple.Title, + featureTuple.Description, + featureTuple.Display.ToString(), + featureTuple.Level.ToString(), + featureTuple.DirectoryRef, + attributes.ToString()); + break; + } + case "File": + { + var fileTuple = (FileTuple)tuple; - case "ServiceInstall": + if (fileTuple.BindPath != null) { - var serviceInstallTuple = (ServiceInstallTuple)tuple; - - var errorControl = (int)serviceInstallTuple.ErrorControl; - errorControl |= serviceInstallTuple.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0; - - var serviceType = (int)serviceInstallTuple.ServiceType; - serviceType |= serviceInstallTuple.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0; - - fields = String.Join(",", - serviceInstallTuple.Name, - serviceInstallTuple.DisplayName, - serviceType.ToString(), - ((int)serviceInstallTuple.StartType).ToString(), - errorControl.ToString(), - serviceInstallTuple.LoadOrderGroup, - serviceInstallTuple.Dependencies, - serviceInstallTuple.StartName, - serviceInstallTuple.Password, - serviceInstallTuple.Arguments, - serviceInstallTuple.Component_, - serviceInstallTuple.Description - ); - break; + yield return $"BindImage:{fileTuple.Id.Id},{fileTuple.BindPath}"; } - case "Upgrade": + if (fileTuple.FontTitle != null) { - var upgradeTuple = (UpgradeTuple)tuple; - - var attributes = upgradeTuple.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0; - attributes |= upgradeTuple.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0; - attributes |= upgradeTuple.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0; - attributes |= upgradeTuple.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0; - attributes |= upgradeTuple.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0; - attributes |= upgradeTuple.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0; - - fields = String.Join(",", - upgradeTuple.VersionMin, - upgradeTuple.VersionMax, - upgradeTuple.Language, - attributes.ToString(), - upgradeTuple.Remove, - upgradeTuple.ActionProperty - ); - break; + yield return $"Font:{fileTuple.Id.Id},{fileTuple.FontTitle}"; } - case "WixAction": + if (fileTuple.SelfRegCost.HasValue) { - var wixActionTuple = (WixActionTuple)tuple; - fields = String.Join(",", - wixActionTuple.SequenceTable, - wixActionTuple.Action, - wixActionTuple.Condition, - // BUGBUGBUG: AB#2626 - wixActionTuple.Sequence == 0 ? String.Empty : wixActionTuple.Sequence.ToString(), - wixActionTuple.Before, - wixActionTuple.After, - wixActionTuple.Overridable == true ? "1" : "0" - ); - break; + yield return $"SelfReg:{fileTuple.Id.Id},{fileTuple.SelfRegCost}"; } - case "WixComplexReference": - { - var wixComplexReferenceTuple = (WixComplexReferenceTuple)tuple; - fields = String.Join(",", - wixComplexReferenceTuple.Parent, - ((int)wixComplexReferenceTuple.ParentType).ToString(), - wixComplexReferenceTuple.ParentLanguage, - wixComplexReferenceTuple.Child, - ((int)wixComplexReferenceTuple.ChildType).ToString(), - wixComplexReferenceTuple.IsPrimary ? "1" : "0" - ); - break; - } + fields = String.Join(",", + fileTuple.ComponentRef, + fileTuple.Name, + fileTuple.FileSize.ToString(), + fileTuple.Version, + fileTuple.Language, + ((fileTuple.ReadOnly ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0) + | (fileTuple.Hidden ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0) + | (fileTuple.System ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0) + | (fileTuple.Vital ? WindowsInstallerConstants.MsidbFileAttributesVital : 0) + | (fileTuple.Checksum ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0) + | ((fileTuple.Compressed.HasValue && fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0) + | ((fileTuple.Compressed.HasValue && !fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0)) + .ToString()); + break; + } - case "WixFile": - { - var wixFileTuple = (WixFileTuple)tuple; - fields = String.Concat( - wixFileTuple.AssemblyType == FileAssemblyType.DotNetAssembly ? "0" : wixFileTuple.AssemblyType == FileAssemblyType.Win32Assembly ? "1" : String.Empty, ",", - String.Join(",", tuple.Fields.Skip(2).Take(6).Select(field => (string)field).ToArray())); - break; - } + case "Media": + fields = String.Join(",", tuple.Fields.Skip(1).Select(SafeConvertField)); + break; + + case "Registry": + { + var registryTuple = (RegistryTuple)tuple; + var value = registryTuple.Value; - case "WixProperty": + switch (registryTuple.ValueType) { - var wixPropertyTuple = (WixPropertyTuple)tuple; - var attributes = 0; - attributes |= wixPropertyTuple.Admin ? 0x1 : 0; - attributes |= wixPropertyTuple.Hidden ? 0x2 : 0; - attributes |= wixPropertyTuple.Secure ? 0x4 : 0; - - fields = String.Join(",", - wixPropertyTuple.Property_, - attributes.ToString() - ); + case RegistryValueType.Binary: + value = String.Concat("#x", value); + break; + case RegistryValueType.Expandable: + value = String.Concat("#%", value); + break; + case RegistryValueType.Integer: + value = String.Concat("#", value); + break; + case RegistryValueType.MultiString: + switch (registryTuple.ValueAction) + { + case RegistryValueActionType.Append: + value = String.Concat("[~]", value); + break; + case RegistryValueActionType.Prepend: + value = String.Concat(value, "[~]"); + break; + case RegistryValueActionType.Write: + default: + if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal)) + { + value = String.Concat("[~]", value, "[~]"); + } + break; + } + break; + case RegistryValueType.String: + // escape the leading '#' character for string registry keys + if (null != value && value.StartsWith("#", StringComparison.Ordinal)) + { + value = String.Concat("#", value); + } break; } + fields = String.Join(",", + ((int)registryTuple.Root).ToString(), + registryTuple.Key, + registryTuple.Name, + value, + registryTuple.ComponentRef + ); + break; + } + + case "RemoveRegistry": + { + var removeRegistryTuple = (RemoveRegistryTuple)tuple; + fields = String.Join(",", + ((int)removeRegistryTuple.Root).ToString(), + removeRegistryTuple.Key, + removeRegistryTuple.Name, + removeRegistryTuple.ComponentRef + ); + break; + } + + case "ServiceControl": + { + var serviceControlTuple = (ServiceControlTuple)tuple; + + var events = serviceControlTuple.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0; + events |= serviceControlTuple.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0; + events |= serviceControlTuple.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0; + events |= serviceControlTuple.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0; + events |= serviceControlTuple.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0; + events |= serviceControlTuple.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0; + + fields = String.Join(",", + serviceControlTuple.Name, + events.ToString(), + serviceControlTuple.Arguments, + serviceControlTuple.Wait == true ? "1" : "0", + serviceControlTuple.ComponentRef + ); + break; + } + + case "ServiceInstall": + { + var serviceInstallTuple = (ServiceInstallTuple)tuple; + + var errorControl = (int)serviceInstallTuple.ErrorControl; + errorControl |= serviceInstallTuple.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0; + + var serviceType = (int)serviceInstallTuple.ServiceType; + serviceType |= serviceInstallTuple.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0; + + fields = String.Join(",", + serviceInstallTuple.Name, + serviceInstallTuple.DisplayName, + serviceType.ToString(), + ((int)serviceInstallTuple.StartType).ToString(), + errorControl.ToString(), + serviceInstallTuple.LoadOrderGroup, + serviceInstallTuple.Dependencies, + serviceInstallTuple.StartName, + serviceInstallTuple.Password, + serviceInstallTuple.Arguments, + serviceInstallTuple.ComponentRef, + serviceInstallTuple.Description + ); + break; + } + + case "Upgrade": + { + var upgradeTuple = (UpgradeTuple)tuple; + + var attributes = upgradeTuple.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0; + attributes |= upgradeTuple.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0; + attributes |= upgradeTuple.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0; + attributes |= upgradeTuple.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0; + attributes |= upgradeTuple.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0; + attributes |= upgradeTuple.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0; + + fields = String.Join(",", + upgradeTuple.VersionMin, + upgradeTuple.VersionMax, + upgradeTuple.Language, + attributes.ToString(), + upgradeTuple.Remove, + upgradeTuple.ActionProperty + ); + break; + } + + case "WixAction": + { + var wixActionTuple = (WixActionTuple)tuple; + var data = wixActionTuple.Fields[(int)WixActionTupleFields.SequenceTable].AsObject(); + var sequenceTableAsInt = data is string ? (int)SequenceStringToSequenceTable(data) : (int)wixActionTuple.SequenceTable; + + fields = String.Join(",", + sequenceTableAsInt, + wixActionTuple.Action, + wixActionTuple.Condition, + wixActionTuple.Sequence?.ToString() ?? String.Empty, + wixActionTuple.Before, + wixActionTuple.After, + wixActionTuple.Overridable == true ? "1" : "0" + ); + break; + } + + case "WixComplexReference": + { + var wixComplexReferenceTuple = (WixComplexReferenceTuple)tuple; + fields = String.Join(",", + wixComplexReferenceTuple.Parent, + (int)wixComplexReferenceTuple.ParentType, + wixComplexReferenceTuple.ParentLanguage, + wixComplexReferenceTuple.Child, + (int)wixComplexReferenceTuple.ChildType, + wixComplexReferenceTuple.IsPrimary ? "1" : "0" + ); + break; + } + + case "WixFile": + { + var wixFileTuple = (WixFileTuple)tuple; + fields = String.Concat( + wixFileTuple.AssemblyType == FileAssemblyType.DotNetAssembly ? "0" : wixFileTuple.AssemblyType == FileAssemblyType.Win32Assembly ? "1" : String.Empty, ",", + String.Join(",", tuple.Fields.Skip(1).Take(8).Select(field => (string)field))); + break; + } + + case "WixProperty": + { + var wixPropertyTuple = (WixPropertyTuple)tuple; + var attributes = wixPropertyTuple.Admin ? 0x1 : 0; + attributes |= wixPropertyTuple.Hidden ? 0x2 : 0; + attributes |= wixPropertyTuple.Secure ? 0x4 : 0; + + fields = String.Join(",", + wixPropertyTuple.PropertyRef, + attributes.ToString() + ); + break; + } + + default: + fields = String.Join(",", tuple.Fields.Select(SafeConvertField)); + break; + } + + var name = tuple.Definition.Type == TupleDefinitionType.SummaryInformation ? "_SummaryInformation" : tuple.Definition.Name; + var id = tuple.Id?.Id ?? String.Empty; + fields = String.IsNullOrEmpty(id) ? fields : String.IsNullOrEmpty(fields) ? id : $"{id},{fields}"; + yield return $"{name}:{fields}"; + } + + private static SequenceTable SequenceStringToSequenceTable(object sequenceString) + { + switch (sequenceString) + { + case "AdminExecuteSequence": + return SequenceTable.AdminExecuteSequence; + case "AdminUISequence": + return SequenceTable.AdminUISequence; + case "AdvtExecuteSequence": + return SequenceTable.AdvertiseExecuteSequence; + case "InstallExecuteSequence": + return SequenceTable.InstallExecuteSequence; + case "InstallUISequence": + return SequenceTable.InstallUISequence; + default: + throw new ArgumentException($"Unknown sequence: {sequenceString}"); } + } - var id = tuple.Id == null ? String.Empty : String.Concat(",", tuple.Id.Id); - return $"{tuple.Definition.Name}{id},{fields}"; + private static string SafeConvertField(Wix3.Field field) + { + return field?.Data?.ToString(); + } + + private static string SafeConvertField(IntermediateField field) + { + var data = field.AsObject(); + if (data is IntermediateFieldPathValue path) + { + return path.Path; + } + + return data?.ToString(); + } + + private static string[] SplitDefaultDir(string defaultDir) + { + var split1 = defaultDir.Split(':'); + var targetSplit = split1.Length > 1 ? split1[1].Split('|') : split1[0].Split('|'); + var sourceSplit = split1.Length > 1 ? split1[0].Split('|') : new[] { String.Empty }; + return new[] + { + targetSplit.Length > 1 ? targetSplit[1] : targetSplit[0], + targetSplit.Length > 1 ? targetSplit[0] : String.Empty, + sourceSplit.Length > 1 ? sourceSplit[1] : sourceSplit[0], + sourceSplit.Length > 1 ? sourceSplit[0] : String.Empty + }; } } } -- cgit v1.2.3-55-g6feb