From 026c2fdb94a0333bfb840decee9464ba2f839705 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 25 Jun 2020 15:47:34 -0700 Subject: The Great Tuple to Symbol File Rename (tm) --- .../ConvertSymbols.cs | 814 +++++++++++++++++++++ .../ConvertTuples.cs | 814 --------------------- .../ConvertSymbolsFixture.cs | 606 +++++++++++++++ .../ConvertTuplesFixture.cs | 606 --------------- 4 files changed, 1420 insertions(+), 1420 deletions(-) create mode 100644 src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs delete mode 100644 src/WixToolset.Converters.Symbolizer/ConvertTuples.cs create mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/ConvertTuplesFixture.cs (limited to 'src') diff --git a/src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs b/src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs new file mode 100644 index 00000000..76a0440f --- /dev/null +++ b/src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs @@ -0,0 +1,814 @@ +// 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.Converters.Symbolizer +{ + using System; + using System.Collections.Generic; + using System.Linq; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using WixToolset.Data.WindowsInstaller; + using Wix3 = Microsoft.Tools.WindowsInstallerXml; + + public static class ConvertSymbols + { + public static Intermediate ConvertFile(string path) + { + var output = Wix3.Output.Load(path, suppressVersionCheck: true, suppressSchema: true); + return ConvertOutput(output); + } + + public static Intermediate ConvertOutput(Wix3.Output output) + { + var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type), output.Codepage); + + var wixMediaByDiskId = IndexWixMediaTableByDiskId(output); + var componentsById = IndexById(output, "Component"); + var bindPathsById = IndexById(output, "BindPath"); + var fontsById = IndexById(output, "Font"); + var selfRegById = IndexById(output, "SelfReg"); + var wixDirectoryById = IndexById(output, "WixDirectory"); + var wixFileById = IndexById(output, "WixFile"); + + foreach (Wix3.Table table in output.Tables) + { + foreach (Wix3.Row row in table.Rows) + { + var symbol = GenerateSymbolFromRow(row, wixMediaByDiskId, componentsById, fontsById, bindPathsById, selfRegById, wixFileById, wixDirectoryById); + if (symbol != null) + { + section.Symbols.Add(symbol); + } + } + } + + return new Intermediate(String.Empty, new[] { section }, localizationsByCulture: null); + } + + 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 IntermediateSymbol GenerateSymbolFromRow(Wix3.Row row, Dictionary wixMediaByDiskId, Dictionary componentsById, Dictionary fontsById, Dictionary bindPathsById, Dictionary selfRegById, Dictionary wixFileById, Dictionary wixDirectoryById) + { + var name = row.Table.Name; + switch (name) + { + case "_SummaryInformation": + return DefaultSymbolFromRow(typeof(SummaryInformationSymbol), row, columnZeroIsId: false); + case "ActionText": + return DefaultSymbolFromRow(typeof(ActionTextSymbol), row, columnZeroIsId: false); + case "AppId": + return DefaultSymbolFromRow(typeof(AppIdSymbol), row, columnZeroIsId: false); + case "AppSearch": + return DefaultSymbolFromRow(typeof(AppSearchSymbol), row, columnZeroIsId: false); + case "Billboard": + return DefaultSymbolFromRow(typeof(BillboardSymbol), row, columnZeroIsId: true); + case "Binary": + return DefaultSymbolFromRow(typeof(BinarySymbol), row, columnZeroIsId: true); + case "BindPath": + return null; + case "CCPSearch": + return DefaultSymbolFromRow(typeof(CCPSearchSymbol), row, columnZeroIsId: true); + case "Class": + return DefaultSymbolFromRow(typeof(ClassSymbol), row, columnZeroIsId: false); + case "CompLocator": + return DefaultSymbolFromRow(typeof(CompLocatorSymbol), row, columnZeroIsId: false); + 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; + } + + var keyPath = FieldAsString(row, 5); + var keyPathType = String.IsNullOrEmpty(keyPath) ? ComponentKeyPathType.Directory : ComponentKeyPathType.File; + if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) + { + keyPathType = ComponentKeyPathType.Registry; + } + else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) + { + keyPathType = ComponentKeyPathType.OdbcDataSource; + } + + return new ComponentSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) + { + ComponentId = FieldAsString(row, 1), + DirectoryRef = FieldAsString(row, 2), + Condition = FieldAsString(row, 4), + KeyPath = keyPath, + 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, + }; + } + + case "Condition": + return DefaultSymbolFromRow(typeof(ConditionSymbol), row, columnZeroIsId: false); + case "CreateFolder": + return DefaultSymbolFromRow(typeof(CreateFolderSymbol), row, columnZeroIsId: false); + case "CustomAction": + { + var caType = FieldAsInt(row, 1); + var executionType = DetermineCustomActionExecutionType(caType); + var sourceType = DetermineCustomActionSourceType(caType); + var targetType = DetermineCustomActionTargetType(caType); + + return new CustomActionSymbol(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 "Directory": + { + var id = FieldAsString(row, 0); + var splits = SplitDefaultDir(FieldAsString(row, 2)); + + var symbol = new DirectorySymbol(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)) + { + symbol.ComponentGuidGenerationSeed = FieldAsString(wixDirectoryRow, 1); + } + + return symbol; + } + case "DrLocator": + return DefaultSymbolFromRow(typeof(DrLocatorSymbol), row, columnZeroIsId: false); + case "DuplicateFile": + return DefaultSymbolFromRow(typeof(DuplicateFileSymbol), row, columnZeroIsId: true); + case "Error": + return DefaultSymbolFromRow(typeof(ErrorSymbol), row, columnZeroIsId: false); + case "Extension": + return DefaultSymbolFromRow(typeof(ExtensionSymbol), 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 FeatureSymbol(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 DefaultSymbolFromRow(typeof(FeatureComponentsSymbol), row, columnZeroIsId: false); + case "File": + { + var attributes = FieldAsNullableInt(row, 6); + + FileSymbolAttributes symbolAttributes = 0; + symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly ? FileSymbolAttributes.ReadOnly : 0; + symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden ? FileSymbolAttributes.Hidden : 0; + symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem ? FileSymbolAttributes.System : 0; + symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital ? FileSymbolAttributes.Vital : 0; + symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum ? FileSymbolAttributes.Checksum : 0; + symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed ? FileSymbolAttributes.Uncompressed : 0; + symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed ? FileSymbolAttributes.Compressed : 0; + + var id = FieldAsString(row, 0); + + var symbol = new FileSymbol(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), + Attributes = symbolAttributes + }; + + if (bindPathsById.TryGetValue(id, out var bindPathRow)) + { + symbol.BindPath = FieldAsString(bindPathRow, 1) ?? String.Empty; + } + + if (fontsById.TryGetValue(id, out var fontRow)) + { + symbol.FontTitle = FieldAsString(fontRow, 1) ?? String.Empty; + } + + if (selfRegById.TryGetValue(id, out var selfRegRow)) + { + symbol.SelfRegCost = FieldAsNullableInt(selfRegRow, 1) ?? 0; + } + + if (wixFileById.TryGetValue(id, out var wixFileRow)) + { + symbol.DirectoryRef = FieldAsString(wixFileRow, 4); + symbol.DiskId = FieldAsNullableInt(wixFileRow, 5) ?? 0; + symbol.Source = new IntermediateFieldPathValue { Path = FieldAsString(wixFileRow, 6) }; + symbol.PatchGroup = FieldAsInt(wixFileRow, 8); + symbol.Attributes |= FieldAsInt(wixFileRow, 9) != 0 ? FileSymbolAttributes.GeneratedShortFileName : 0; + symbol.PatchAttributes = (PatchAttributeType)FieldAsInt(wixFileRow, 10); + } + + return symbol; + } + case "Font": + return null; + case "Icon": + return DefaultSymbolFromRow(typeof(IconSymbol), row, columnZeroIsId: true); + case "IniLocator": + return DefaultSymbolFromRow(typeof(IniLocatorSymbol), row, columnZeroIsId: false); + case "LockPermissions": + return DefaultSymbolFromRow(typeof(LockPermissionsSymbol), row, columnZeroIsId: false); + case "Media": + { + var diskId = FieldAsInt(row, 0); + var symbol = new MediaSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, diskId)) + { + 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); + + symbol.CompressionLevel = String.IsNullOrEmpty(compressionLevel) ? null : (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), compressionLevel, true); + symbol.Layout = wixMediaRow.Layout; + } + + return symbol; + } + case "MIME": + return DefaultSymbolFromRow(typeof(MIMESymbol), row, columnZeroIsId: false); + case "ModuleIgnoreTable": + return DefaultSymbolFromRow(typeof(ModuleIgnoreTableSymbol), row, columnZeroIsId: true); + case "MoveFile": + return DefaultSymbolFromRow(typeof(MoveFileSymbol), row, columnZeroIsId: true); + case "MsiAssembly": + { + var componentId = FieldAsString(row, 0); + if (componentsById.TryGetValue(componentId, out var componentRow)) + { + return new AssemblySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(componentRow, 5))) + { + ComponentRef = componentId, + FeatureRef = FieldAsString(row, 1), + ManifestFileRef = FieldAsString(row, 2), + ApplicationFileRef = FieldAsString(row, 3), + Type = FieldAsNullableInt(row, 4) == 1 ? AssemblyType.Win32Assembly : AssemblyType.DotNetAssembly, + }; + } + + return null; + } + case "MsiLockPermissionsEx": + return DefaultSymbolFromRow(typeof(MsiLockPermissionsExSymbol), row, columnZeroIsId: true); + case "MsiShortcutProperty": + return DefaultSymbolFromRow(typeof(MsiShortcutPropertySymbol), row, columnZeroIsId: true); + case "ODBCDataSource": + return DefaultSymbolFromRow(typeof(ODBCDataSourceSymbol), row, columnZeroIsId: true); + case "ODBCDriver": + return DefaultSymbolFromRow(typeof(ODBCDriverSymbol), row, columnZeroIsId: true); + case "ODBCTranslator": + return DefaultSymbolFromRow(typeof(ODBCTranslatorSymbol), row, columnZeroIsId: true); + case "ProgId": + return DefaultSymbolFromRow(typeof(ProgIdSymbol), row, columnZeroIsId: false); + case "Property": + return DefaultSymbolFromRow(typeof(PropertySymbol), row, columnZeroIsId: true); + case "PublishComponent": + return DefaultSymbolFromRow(typeof(PublishComponentSymbol), 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; + } + } + + return new RegistrySymbol(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 RegLocatorSymbol(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 RemoveFileSymbol(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 RemoveRegistrySymbol(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 DefaultSymbolFromRow(typeof(ReserveCostSymbol), row, columnZeroIsId: true); + case "SelfReg": + return null; + case "ServiceControl": + { + var events = FieldAsInt(row, 2); + var wait = FieldAsNullableInt(row, 4); + return new ServiceControlSymbol(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 DefaultSymbolFromRow(typeof(ServiceInstallSymbol), row, columnZeroIsId: true); + case "Shortcut": + { + var splitName = FieldAsString(row, 2).Split('|'); + + return new ShortcutSymbol(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 DefaultSymbolFromRow(typeof(SignatureSymbol), row, columnZeroIsId: true); + case "UIText": + return DefaultSymbolFromRow(typeof(UITextSymbol), row, columnZeroIsId: true); + case "Upgrade": + { + var attributes = FieldAsInt(row, 4); + return new UpgradeSymbol(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 DefaultSymbolFromRow(typeof(VerbSymbol), row, columnZeroIsId: false); + case "WixAction": + { + var sequenceTable = FieldAsString(row, 0); + return new WixActionSymbol(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 DefaultSymbolFromRow(typeof(WixBootstrapperApplicationSymbol), row, columnZeroIsId: true); + case "WixBundleContainer": + return DefaultSymbolFromRow(typeof(WixBundleContainerSymbol), row, columnZeroIsId: true); + case "WixBundleVariable": + return DefaultSymbolFromRow(typeof(WixBundleVariableSymbol), row, columnZeroIsId: true); + case "WixChainItem": + return DefaultSymbolFromRow(typeof(WixChainItemSymbol), row, columnZeroIsId: true); + case "WixCustomTable": + return DefaultSymbolFromRow(typeof(WixCustomTableSymbol), row, columnZeroIsId: true); + case "WixDirectory": + return null; + case "WixFile": + return null; + case "WixInstanceTransforms": + return DefaultSymbolFromRow(typeof(WixInstanceTransformsSymbol), row, columnZeroIsId: true); + case "WixMedia": + return null; + case "WixMerge": + return DefaultSymbolFromRow(typeof(WixMergeSymbol), row, columnZeroIsId: true); + case "WixPatchBaseline": + return DefaultSymbolFromRow(typeof(WixPatchBaselineSymbol), row, columnZeroIsId: true); + case "WixProperty": + { + var attributes = FieldAsInt(row, 1); + return new WixPropertySymbol(SourceLineNumber4(row.SourceLineNumbers)) + { + PropertyRef = FieldAsString(row, 0), + Admin = (attributes & 0x1) == 0x1, + Hidden = (attributes & 0x2) == 0x2, + Secure = (attributes & 0x4) == 0x4, + }; + } + case "WixSuppressModularization": + return DefaultSymbolFromRow(typeof(WixSuppressModularizationSymbol), row, columnZeroIsId: true); + case "WixUI": + return DefaultSymbolFromRow(typeof(WixUISymbol), row, columnZeroIsId: true); + case "WixVariable": + return DefaultSymbolFromRow(typeof(WixVariableSymbol), row, columnZeroIsId: true); + default: + return GenericSymbolFromCustomRow(row, columnZeroIsId: false); + } + } + + private static CustomActionTargetType DetermineCustomActionTargetType(int type) + { + var targetType = default(CustomActionTargetType); + + if ((type & WindowsInstallerConstants.MsidbCustomActionTypeVBScript) == WindowsInstallerConstants.MsidbCustomActionTypeVBScript) + { + targetType = CustomActionTargetType.VBScript; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeJScript) == WindowsInstallerConstants.MsidbCustomActionTypeJScript) + { + targetType = CustomActionTargetType.JScript; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeTextData) == WindowsInstallerConstants.MsidbCustomActionTypeTextData) + { + targetType = CustomActionTargetType.TextData; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeExe) == WindowsInstallerConstants.MsidbCustomActionTypeExe) + { + targetType = CustomActionTargetType.Exe; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeDll) == WindowsInstallerConstants.MsidbCustomActionTypeDll) + { + targetType = CustomActionTargetType.Dll; + } + + return targetType; + } + + private static CustomActionSourceType DetermineCustomActionSourceType(int type) + { + var sourceType = CustomActionSourceType.Binary; + + if ((type & WindowsInstallerConstants.MsidbCustomActionTypeProperty) == WindowsInstallerConstants.MsidbCustomActionTypeProperty) + { + sourceType = CustomActionSourceType.Property; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeDirectory) == WindowsInstallerConstants.MsidbCustomActionTypeDirectory) + { + sourceType = CustomActionSourceType.Directory; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeSourceFile) == WindowsInstallerConstants.MsidbCustomActionTypeSourceFile) + { + sourceType = CustomActionSourceType.File; + } + + return sourceType; + } + + private static CustomActionExecutionType DetermineCustomActionExecutionType(int type) + { + var executionType = CustomActionExecutionType.Immediate; + + if ((type & (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit)) == (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit)) + { + executionType = CustomActionExecutionType.Commit; + } + else if ((type & (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback)) == (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback)) + { + executionType = CustomActionExecutionType.Rollback; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeInScript) == WindowsInstallerConstants.MsidbCustomActionTypeInScript) + { + executionType = CustomActionExecutionType.Deferred; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat) == WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat) + { + executionType = CustomActionExecutionType.ClientRepeat; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess) == WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess) + { + executionType = CustomActionExecutionType.OncePerProcess; + } + else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence) == WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence) + { + executionType = CustomActionExecutionType.FirstSequence; + } + + return executionType; + } + + private static IntermediateFieldType ColumnType3ToIntermediateFieldType4(Wix3.ColumnType columnType) + { + 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; + } + } + + private static IntermediateSymbol DefaultSymbolFromRow(Type symbolType, Wix3.Row row, bool columnZeroIsId) + { + var symbol = Activator.CreateInstance(symbolType) as IntermediateSymbol; + + SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); + + symbol.SourceLineNumbers = SourceLineNumber4(row.SourceLineNumbers); + return symbol; + } + + private static IntermediateSymbol GenericSymbolFromCustomRow(Wix3.Row row, bool columnZeroIsId) + { + var columnDefinitions = row.Table.Definition.Columns.Cast(); + var fieldDefinitions = columnDefinitions.Select(columnDefinition => + new IntermediateFieldDefinition(columnDefinition.Name, ColumnType3ToIntermediateFieldType4(columnDefinition.Type))).ToArray(); + var symbolDefinition = new IntermediateSymbolDefinition(row.Table.Name, fieldDefinitions, null); + var symbol = new IntermediateSymbol(symbolDefinition, SourceLineNumber4(row.SourceLineNumbers)); + + SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); + + return symbol; + } + + private static void SetSymbolFieldsFromRow(Wix3.Row row, IntermediateSymbol symbol, bool columnZeroIsId) + { + int offset = 0; + if (columnZeroIsId) + { + symbol.Id = GetIdentifierForRow(row); + offset = 1; + } + + for (var i = offset; i < row.Fields.Length; ++i) + { + 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: + symbol.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); + //symbol.Set(i - offset, column.IsNullable ? nullableValue : value); + symbol.Set(i - offset, nullableValue); + break; + case Wix3.ColumnType.Unknown: + break; + } + } + } + + private static Identifier GetIdentifierForRow(Wix3.Row row) + { + 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; + } + } + + private static SectionType OutputType3ToSectionType4(Wix3.OutputType outputType) + { + 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; + } + } + + private static SourceLineNumber SourceLineNumber4(Wix3.SourceLineNumberCollection source) + { + return String.IsNullOrEmpty(source?.EncodedSourceLineNumbers) ? null : SourceLineNumber.CreateFromEncoded(source.EncodedSourceLineNumbers); + } + + private static string FieldAsString(Wix3.Row row, int column) + { + return (string)row[column]; + } + + private static int FieldAsInt(Wix3.Row row, int column) + { + return Convert.ToInt32(row[column]); + } + + private static int? FieldAsNullableInt(Wix3.Row row, int column) + { + var field = row.Fields[column]; + if (field.Data == null) + { + return null; + } + else + { + 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/WixToolset.Converters.Symbolizer/ConvertTuples.cs b/src/WixToolset.Converters.Symbolizer/ConvertTuples.cs deleted file mode 100644 index 76a0440f..00000000 --- a/src/WixToolset.Converters.Symbolizer/ConvertTuples.cs +++ /dev/null @@ -1,814 +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.Converters.Symbolizer -{ - using System; - using System.Collections.Generic; - using System.Linq; - using WixToolset.Data; - using WixToolset.Data.Symbols; - using WixToolset.Data.WindowsInstaller; - using Wix3 = Microsoft.Tools.WindowsInstallerXml; - - public static class ConvertSymbols - { - public static Intermediate ConvertFile(string path) - { - var output = Wix3.Output.Load(path, suppressVersionCheck: true, suppressSchema: true); - return ConvertOutput(output); - } - - public static Intermediate ConvertOutput(Wix3.Output output) - { - var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type), output.Codepage); - - var wixMediaByDiskId = IndexWixMediaTableByDiskId(output); - var componentsById = IndexById(output, "Component"); - var bindPathsById = IndexById(output, "BindPath"); - var fontsById = IndexById(output, "Font"); - var selfRegById = IndexById(output, "SelfReg"); - var wixDirectoryById = IndexById(output, "WixDirectory"); - var wixFileById = IndexById(output, "WixFile"); - - foreach (Wix3.Table table in output.Tables) - { - foreach (Wix3.Row row in table.Rows) - { - var symbol = GenerateSymbolFromRow(row, wixMediaByDiskId, componentsById, fontsById, bindPathsById, selfRegById, wixFileById, wixDirectoryById); - if (symbol != null) - { - section.Symbols.Add(symbol); - } - } - } - - return new Intermediate(String.Empty, new[] { section }, localizationsByCulture: null); - } - - 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 IntermediateSymbol GenerateSymbolFromRow(Wix3.Row row, Dictionary wixMediaByDiskId, Dictionary componentsById, Dictionary fontsById, Dictionary bindPathsById, Dictionary selfRegById, Dictionary wixFileById, Dictionary wixDirectoryById) - { - var name = row.Table.Name; - switch (name) - { - case "_SummaryInformation": - return DefaultSymbolFromRow(typeof(SummaryInformationSymbol), row, columnZeroIsId: false); - case "ActionText": - return DefaultSymbolFromRow(typeof(ActionTextSymbol), row, columnZeroIsId: false); - case "AppId": - return DefaultSymbolFromRow(typeof(AppIdSymbol), row, columnZeroIsId: false); - case "AppSearch": - return DefaultSymbolFromRow(typeof(AppSearchSymbol), row, columnZeroIsId: false); - case "Billboard": - return DefaultSymbolFromRow(typeof(BillboardSymbol), row, columnZeroIsId: true); - case "Binary": - return DefaultSymbolFromRow(typeof(BinarySymbol), row, columnZeroIsId: true); - case "BindPath": - return null; - case "CCPSearch": - return DefaultSymbolFromRow(typeof(CCPSearchSymbol), row, columnZeroIsId: true); - case "Class": - return DefaultSymbolFromRow(typeof(ClassSymbol), row, columnZeroIsId: false); - case "CompLocator": - return DefaultSymbolFromRow(typeof(CompLocatorSymbol), row, columnZeroIsId: false); - 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; - } - - var keyPath = FieldAsString(row, 5); - var keyPathType = String.IsNullOrEmpty(keyPath) ? ComponentKeyPathType.Directory : ComponentKeyPathType.File; - if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) - { - keyPathType = ComponentKeyPathType.Registry; - } - else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) - { - keyPathType = ComponentKeyPathType.OdbcDataSource; - } - - return new ComponentSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0))) - { - ComponentId = FieldAsString(row, 1), - DirectoryRef = FieldAsString(row, 2), - Condition = FieldAsString(row, 4), - KeyPath = keyPath, - 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, - }; - } - - case "Condition": - return DefaultSymbolFromRow(typeof(ConditionSymbol), row, columnZeroIsId: false); - case "CreateFolder": - return DefaultSymbolFromRow(typeof(CreateFolderSymbol), row, columnZeroIsId: false); - case "CustomAction": - { - var caType = FieldAsInt(row, 1); - var executionType = DetermineCustomActionExecutionType(caType); - var sourceType = DetermineCustomActionSourceType(caType); - var targetType = DetermineCustomActionTargetType(caType); - - return new CustomActionSymbol(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 "Directory": - { - var id = FieldAsString(row, 0); - var splits = SplitDefaultDir(FieldAsString(row, 2)); - - var symbol = new DirectorySymbol(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)) - { - symbol.ComponentGuidGenerationSeed = FieldAsString(wixDirectoryRow, 1); - } - - return symbol; - } - case "DrLocator": - return DefaultSymbolFromRow(typeof(DrLocatorSymbol), row, columnZeroIsId: false); - case "DuplicateFile": - return DefaultSymbolFromRow(typeof(DuplicateFileSymbol), row, columnZeroIsId: true); - case "Error": - return DefaultSymbolFromRow(typeof(ErrorSymbol), row, columnZeroIsId: false); - case "Extension": - return DefaultSymbolFromRow(typeof(ExtensionSymbol), 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 FeatureSymbol(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 DefaultSymbolFromRow(typeof(FeatureComponentsSymbol), row, columnZeroIsId: false); - case "File": - { - var attributes = FieldAsNullableInt(row, 6); - - FileSymbolAttributes symbolAttributes = 0; - symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly ? FileSymbolAttributes.ReadOnly : 0; - symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden ? FileSymbolAttributes.Hidden : 0; - symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem ? FileSymbolAttributes.System : 0; - symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital ? FileSymbolAttributes.Vital : 0; - symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum ? FileSymbolAttributes.Checksum : 0; - symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed ? FileSymbolAttributes.Uncompressed : 0; - symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed ? FileSymbolAttributes.Compressed : 0; - - var id = FieldAsString(row, 0); - - var symbol = new FileSymbol(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), - Attributes = symbolAttributes - }; - - if (bindPathsById.TryGetValue(id, out var bindPathRow)) - { - symbol.BindPath = FieldAsString(bindPathRow, 1) ?? String.Empty; - } - - if (fontsById.TryGetValue(id, out var fontRow)) - { - symbol.FontTitle = FieldAsString(fontRow, 1) ?? String.Empty; - } - - if (selfRegById.TryGetValue(id, out var selfRegRow)) - { - symbol.SelfRegCost = FieldAsNullableInt(selfRegRow, 1) ?? 0; - } - - if (wixFileById.TryGetValue(id, out var wixFileRow)) - { - symbol.DirectoryRef = FieldAsString(wixFileRow, 4); - symbol.DiskId = FieldAsNullableInt(wixFileRow, 5) ?? 0; - symbol.Source = new IntermediateFieldPathValue { Path = FieldAsString(wixFileRow, 6) }; - symbol.PatchGroup = FieldAsInt(wixFileRow, 8); - symbol.Attributes |= FieldAsInt(wixFileRow, 9) != 0 ? FileSymbolAttributes.GeneratedShortFileName : 0; - symbol.PatchAttributes = (PatchAttributeType)FieldAsInt(wixFileRow, 10); - } - - return symbol; - } - case "Font": - return null; - case "Icon": - return DefaultSymbolFromRow(typeof(IconSymbol), row, columnZeroIsId: true); - case "IniLocator": - return DefaultSymbolFromRow(typeof(IniLocatorSymbol), row, columnZeroIsId: false); - case "LockPermissions": - return DefaultSymbolFromRow(typeof(LockPermissionsSymbol), row, columnZeroIsId: false); - case "Media": - { - var diskId = FieldAsInt(row, 0); - var symbol = new MediaSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, diskId)) - { - 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); - - symbol.CompressionLevel = String.IsNullOrEmpty(compressionLevel) ? null : (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), compressionLevel, true); - symbol.Layout = wixMediaRow.Layout; - } - - return symbol; - } - case "MIME": - return DefaultSymbolFromRow(typeof(MIMESymbol), row, columnZeroIsId: false); - case "ModuleIgnoreTable": - return DefaultSymbolFromRow(typeof(ModuleIgnoreTableSymbol), row, columnZeroIsId: true); - case "MoveFile": - return DefaultSymbolFromRow(typeof(MoveFileSymbol), row, columnZeroIsId: true); - case "MsiAssembly": - { - var componentId = FieldAsString(row, 0); - if (componentsById.TryGetValue(componentId, out var componentRow)) - { - return new AssemblySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(componentRow, 5))) - { - ComponentRef = componentId, - FeatureRef = FieldAsString(row, 1), - ManifestFileRef = FieldAsString(row, 2), - ApplicationFileRef = FieldAsString(row, 3), - Type = FieldAsNullableInt(row, 4) == 1 ? AssemblyType.Win32Assembly : AssemblyType.DotNetAssembly, - }; - } - - return null; - } - case "MsiLockPermissionsEx": - return DefaultSymbolFromRow(typeof(MsiLockPermissionsExSymbol), row, columnZeroIsId: true); - case "MsiShortcutProperty": - return DefaultSymbolFromRow(typeof(MsiShortcutPropertySymbol), row, columnZeroIsId: true); - case "ODBCDataSource": - return DefaultSymbolFromRow(typeof(ODBCDataSourceSymbol), row, columnZeroIsId: true); - case "ODBCDriver": - return DefaultSymbolFromRow(typeof(ODBCDriverSymbol), row, columnZeroIsId: true); - case "ODBCTranslator": - return DefaultSymbolFromRow(typeof(ODBCTranslatorSymbol), row, columnZeroIsId: true); - case "ProgId": - return DefaultSymbolFromRow(typeof(ProgIdSymbol), row, columnZeroIsId: false); - case "Property": - return DefaultSymbolFromRow(typeof(PropertySymbol), row, columnZeroIsId: true); - case "PublishComponent": - return DefaultSymbolFromRow(typeof(PublishComponentSymbol), 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; - } - } - - return new RegistrySymbol(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 RegLocatorSymbol(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 RemoveFileSymbol(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 RemoveRegistrySymbol(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 DefaultSymbolFromRow(typeof(ReserveCostSymbol), row, columnZeroIsId: true); - case "SelfReg": - return null; - case "ServiceControl": - { - var events = FieldAsInt(row, 2); - var wait = FieldAsNullableInt(row, 4); - return new ServiceControlSymbol(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 DefaultSymbolFromRow(typeof(ServiceInstallSymbol), row, columnZeroIsId: true); - case "Shortcut": - { - var splitName = FieldAsString(row, 2).Split('|'); - - return new ShortcutSymbol(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 DefaultSymbolFromRow(typeof(SignatureSymbol), row, columnZeroIsId: true); - case "UIText": - return DefaultSymbolFromRow(typeof(UITextSymbol), row, columnZeroIsId: true); - case "Upgrade": - { - var attributes = FieldAsInt(row, 4); - return new UpgradeSymbol(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 DefaultSymbolFromRow(typeof(VerbSymbol), row, columnZeroIsId: false); - case "WixAction": - { - var sequenceTable = FieldAsString(row, 0); - return new WixActionSymbol(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 DefaultSymbolFromRow(typeof(WixBootstrapperApplicationSymbol), row, columnZeroIsId: true); - case "WixBundleContainer": - return DefaultSymbolFromRow(typeof(WixBundleContainerSymbol), row, columnZeroIsId: true); - case "WixBundleVariable": - return DefaultSymbolFromRow(typeof(WixBundleVariableSymbol), row, columnZeroIsId: true); - case "WixChainItem": - return DefaultSymbolFromRow(typeof(WixChainItemSymbol), row, columnZeroIsId: true); - case "WixCustomTable": - return DefaultSymbolFromRow(typeof(WixCustomTableSymbol), row, columnZeroIsId: true); - case "WixDirectory": - return null; - case "WixFile": - return null; - case "WixInstanceTransforms": - return DefaultSymbolFromRow(typeof(WixInstanceTransformsSymbol), row, columnZeroIsId: true); - case "WixMedia": - return null; - case "WixMerge": - return DefaultSymbolFromRow(typeof(WixMergeSymbol), row, columnZeroIsId: true); - case "WixPatchBaseline": - return DefaultSymbolFromRow(typeof(WixPatchBaselineSymbol), row, columnZeroIsId: true); - case "WixProperty": - { - var attributes = FieldAsInt(row, 1); - return new WixPropertySymbol(SourceLineNumber4(row.SourceLineNumbers)) - { - PropertyRef = FieldAsString(row, 0), - Admin = (attributes & 0x1) == 0x1, - Hidden = (attributes & 0x2) == 0x2, - Secure = (attributes & 0x4) == 0x4, - }; - } - case "WixSuppressModularization": - return DefaultSymbolFromRow(typeof(WixSuppressModularizationSymbol), row, columnZeroIsId: true); - case "WixUI": - return DefaultSymbolFromRow(typeof(WixUISymbol), row, columnZeroIsId: true); - case "WixVariable": - return DefaultSymbolFromRow(typeof(WixVariableSymbol), row, columnZeroIsId: true); - default: - return GenericSymbolFromCustomRow(row, columnZeroIsId: false); - } - } - - private static CustomActionTargetType DetermineCustomActionTargetType(int type) - { - var targetType = default(CustomActionTargetType); - - if ((type & WindowsInstallerConstants.MsidbCustomActionTypeVBScript) == WindowsInstallerConstants.MsidbCustomActionTypeVBScript) - { - targetType = CustomActionTargetType.VBScript; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeJScript) == WindowsInstallerConstants.MsidbCustomActionTypeJScript) - { - targetType = CustomActionTargetType.JScript; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeTextData) == WindowsInstallerConstants.MsidbCustomActionTypeTextData) - { - targetType = CustomActionTargetType.TextData; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeExe) == WindowsInstallerConstants.MsidbCustomActionTypeExe) - { - targetType = CustomActionTargetType.Exe; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeDll) == WindowsInstallerConstants.MsidbCustomActionTypeDll) - { - targetType = CustomActionTargetType.Dll; - } - - return targetType; - } - - private static CustomActionSourceType DetermineCustomActionSourceType(int type) - { - var sourceType = CustomActionSourceType.Binary; - - if ((type & WindowsInstallerConstants.MsidbCustomActionTypeProperty) == WindowsInstallerConstants.MsidbCustomActionTypeProperty) - { - sourceType = CustomActionSourceType.Property; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeDirectory) == WindowsInstallerConstants.MsidbCustomActionTypeDirectory) - { - sourceType = CustomActionSourceType.Directory; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeSourceFile) == WindowsInstallerConstants.MsidbCustomActionTypeSourceFile) - { - sourceType = CustomActionSourceType.File; - } - - return sourceType; - } - - private static CustomActionExecutionType DetermineCustomActionExecutionType(int type) - { - var executionType = CustomActionExecutionType.Immediate; - - if ((type & (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit)) == (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit)) - { - executionType = CustomActionExecutionType.Commit; - } - else if ((type & (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback)) == (WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback)) - { - executionType = CustomActionExecutionType.Rollback; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeInScript) == WindowsInstallerConstants.MsidbCustomActionTypeInScript) - { - executionType = CustomActionExecutionType.Deferred; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat) == WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat) - { - executionType = CustomActionExecutionType.ClientRepeat; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess) == WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess) - { - executionType = CustomActionExecutionType.OncePerProcess; - } - else if ((type & WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence) == WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence) - { - executionType = CustomActionExecutionType.FirstSequence; - } - - return executionType; - } - - private static IntermediateFieldType ColumnType3ToIntermediateFieldType4(Wix3.ColumnType columnType) - { - 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; - } - } - - private static IntermediateSymbol DefaultSymbolFromRow(Type symbolType, Wix3.Row row, bool columnZeroIsId) - { - var symbol = Activator.CreateInstance(symbolType) as IntermediateSymbol; - - SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); - - symbol.SourceLineNumbers = SourceLineNumber4(row.SourceLineNumbers); - return symbol; - } - - private static IntermediateSymbol GenericSymbolFromCustomRow(Wix3.Row row, bool columnZeroIsId) - { - var columnDefinitions = row.Table.Definition.Columns.Cast(); - var fieldDefinitions = columnDefinitions.Select(columnDefinition => - new IntermediateFieldDefinition(columnDefinition.Name, ColumnType3ToIntermediateFieldType4(columnDefinition.Type))).ToArray(); - var symbolDefinition = new IntermediateSymbolDefinition(row.Table.Name, fieldDefinitions, null); - var symbol = new IntermediateSymbol(symbolDefinition, SourceLineNumber4(row.SourceLineNumbers)); - - SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); - - return symbol; - } - - private static void SetSymbolFieldsFromRow(Wix3.Row row, IntermediateSymbol symbol, bool columnZeroIsId) - { - int offset = 0; - if (columnZeroIsId) - { - symbol.Id = GetIdentifierForRow(row); - offset = 1; - } - - for (var i = offset; i < row.Fields.Length; ++i) - { - 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: - symbol.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); - //symbol.Set(i - offset, column.IsNullable ? nullableValue : value); - symbol.Set(i - offset, nullableValue); - break; - case Wix3.ColumnType.Unknown: - break; - } - } - } - - private static Identifier GetIdentifierForRow(Wix3.Row row) - { - 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; - } - } - - private static SectionType OutputType3ToSectionType4(Wix3.OutputType outputType) - { - 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; - } - } - - private static SourceLineNumber SourceLineNumber4(Wix3.SourceLineNumberCollection source) - { - return String.IsNullOrEmpty(source?.EncodedSourceLineNumbers) ? null : SourceLineNumber.CreateFromEncoded(source.EncodedSourceLineNumbers); - } - - private static string FieldAsString(Wix3.Row row, int column) - { - return (string)row[column]; - } - - private static int FieldAsInt(Wix3.Row row, int column) - { - return Convert.ToInt32(row[column]); - } - - private static int? FieldAsNullableInt(Wix3.Row row, int column) - { - var field = row.Fields[column]; - if (field.Data == null) - { - return null; - } - else - { - 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.Symbolizer/ConvertSymbolsFixture.cs b/src/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs new file mode 100644 index 00000000..ae054079 --- /dev/null +++ b/src/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs @@ -0,0 +1,606 @@ +// 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 WixToolsetTest.Converters.Symbolizer +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using WixBuildTools.TestSupport; + using Wix3 = Microsoft.Tools.WindowsInstallerXml; + using WixToolset.Converters.Symbolizer; + using WixToolset.Data; + using WixToolset.Data.WindowsInstaller; + using WixToolset.Data.Symbols; + using Xunit; + + public class ConvertSymbolsFixture + { + [Fact] + public void CanLoadWixoutAndConvertToIntermediate() + { + var rootFolder = TestData.Get(); + var dataFolder = TestData.Get(@"TestData\Integration"); + + using (var fs = new DisposableFileSystem()) + { + var intermediateFolder = fs.GetFolder(); + + var path = Path.Combine(dataFolder, "test.wixout"); + + var intermediate = ConvertSymbols.ConvertFile(path); + + Assert.NotNull(intermediate); + Assert.Single(intermediate.Sections); + Assert.Equal(String.Empty, intermediate.Id); + + // Save and load to guarantee round-tripping support. + // + var wixiplFile = Path.Combine(intermediateFolder, "test.wixipl"); + intermediate.Save(wixiplFile); + + intermediate = Intermediate.Load(wixiplFile); + + var output = Wix3.Output.Load(path, suppressVersionCheck: true, suppressSchema: true); + 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() + .SelectMany(row => RowToStrings(row, wixMediaByDiskId))) + .Where(s => !String.IsNullOrEmpty(s)) + .OrderBy(s => s) + .ToArray(); + + var symbols = intermediate.Sections.SelectMany(s => s.Symbols); + + var assemblySymbolsByFileId = symbols.OfType().ToDictionary(a => a.Id.Id); + + var wix4Dump = symbols + .SelectMany(symbol => SymbolToStrings(symbol, assemblySymbolsByFileId)) + .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); + + var path3 = Path.Combine(Path.GetTempPath(), "~3.txt"); + var path4 = Path.Combine(Path.GetTempPath(), "~4.txt"); + + File.WriteAllText(path3, wix3TextDump); + File.WriteAllText(path4, wix4TextDump); + + Assert.Equal(wix3TextDump, wix4TextDump); +#endif + } + } + + 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((int)row[0], row); + } + } + + return wixMediaByDiskId; + } + + private static IEnumerable RowToStrings(Wix3.Row row, Dictionary wixMediaByDiskId) + { + string fields = null; + + // Massage output to match WiX v3 rows and v4 symbols. + // + switch (row.Table.Name) + { + 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) + { + // "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 "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.Select(SafeConvertField).ToArray(); + if (fieldValues[8] == 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[8] = "0"; + } + if (fieldValues[10] == null) + { + // WixFile rows that come from merge modules will not have the attributes column set + // so initilaize with 0. + fieldValues[10] = "0"; + } + fields = String.Join(",", fieldValues); + break; + } + case "WixMedia": + break; + default: + fields = String.Join(",", row.Fields.Select(SafeConvertField)); + break; + } + + if (fields != null) + { + yield return $"{row.Table.Name}:{fields}"; + } + } + + private static IEnumerable SymbolToStrings(IntermediateSymbol symbol, Dictionary assemblySymbolsByFileId) + { + var name = symbol.Definition.Type == SymbolDefinitionType.SummaryInformation ? "_SummaryInformation" : symbol.Definition.Name; + var id = symbol.Id?.Id ?? String.Empty; + + string fields; + switch (symbol.Definition.Name) + { + // Massage output to match WiX v3 rows and v4 symbols. + // + case "Component": + { + var componentSymbol = (ComponentSymbol)symbol; + var attributes = ComponentLocation.Either == componentSymbol.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0; + attributes |= ComponentLocation.SourceOnly == componentSymbol.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0; + attributes |= ComponentKeyPathType.Registry == componentSymbol.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0; + attributes |= ComponentKeyPathType.OdbcDataSource == componentSymbol.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0; + attributes |= componentSymbol.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0; + attributes |= componentSymbol.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0; + attributes |= componentSymbol.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0; + attributes |= componentSymbol.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0; + attributes |= componentSymbol.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0; + attributes |= componentSymbol.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0; + attributes |= componentSymbol.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; + attributes |= componentSymbol.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; + + fields = String.Join(",", + componentSymbol.ComponentId, + componentSymbol.DirectoryRef, + attributes.ToString(), + componentSymbol.Condition, + componentSymbol.KeyPath + ); + break; + } + case "CustomAction": + { + var customActionSymbol = (CustomActionSymbol)symbol; + var type = customActionSymbol.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0; + type |= customActionSymbol.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0; + type |= customActionSymbol.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate; + type |= customActionSymbol.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0; + type |= customActionSymbol.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0; + type |= customActionSymbol.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0; + type |= CustomActionExecutionType.FirstSequence == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0; + type |= CustomActionExecutionType.OncePerProcess == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0; + type |= CustomActionExecutionType.ClientRepeat == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0; + type |= CustomActionExecutionType.Deferred == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0; + type |= CustomActionExecutionType.Rollback == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0; + type |= CustomActionExecutionType.Commit == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0; + type |= CustomActionSourceType.File == customActionSymbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0; + type |= CustomActionSourceType.Directory == customActionSymbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0; + type |= CustomActionSourceType.Property == customActionSymbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0; + type |= CustomActionTargetType.Dll == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0; + type |= CustomActionTargetType.Exe == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0; + type |= CustomActionTargetType.TextData == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0; + type |= CustomActionTargetType.JScript == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0; + type |= CustomActionTargetType.VBScript == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0; + + fields = String.Join(",", + type.ToString(), + customActionSymbol.Source, + customActionSymbol.Target, + customActionSymbol.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null + ); + break; + } + case "Directory": + { + var directorySymbol = (DirectorySymbol)symbol; + + if (!String.IsNullOrEmpty(directorySymbol.ComponentGuidGenerationSeed)) + { + yield return $"WixDirectory:{directorySymbol.Id.Id},{directorySymbol.ComponentGuidGenerationSeed}"; + } + + fields = String.Join(",", directorySymbol.ParentDirectoryRef, directorySymbol.Name, directorySymbol.ShortName, directorySymbol.SourceName, directorySymbol.SourceShortName); + break; + } + case "Feature": + { + var featureSymbol = (FeatureSymbol)symbol; + var attributes = featureSymbol.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0; + attributes |= featureSymbol.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0; + attributes |= FeatureInstallDefault.FollowParent == featureSymbol.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0; + attributes |= FeatureInstallDefault.Source == featureSymbol.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0; + attributes |= FeatureTypicalDefault.Advertise == featureSymbol.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0; + + fields = String.Join(",", + featureSymbol.ParentFeatureRef, + featureSymbol.Title, + featureSymbol.Description, + featureSymbol.Display.ToString(), + featureSymbol.Level.ToString(), + featureSymbol.DirectoryRef, + attributes.ToString()); + break; + } + case "File": + { + var fileSymbol = (FileSymbol)symbol; + + if (fileSymbol.BindPath != null) + { + yield return $"BindImage:{fileSymbol.Id.Id},{fileSymbol.BindPath}"; + } + + if (fileSymbol.FontTitle != null) + { + yield return $"Font:{fileSymbol.Id.Id},{fileSymbol.FontTitle}"; + } + + if (fileSymbol.SelfRegCost.HasValue) + { + yield return $"SelfReg:{fileSymbol.Id.Id},{fileSymbol.SelfRegCost}"; + } + + int? assemblyAttributes = null; + if (assemblySymbolsByFileId.TryGetValue(fileSymbol.Id.Id, out var assemblySymbol)) + { + if (assemblySymbol.Type == AssemblyType.DotNetAssembly) + { + assemblyAttributes = 0; + } + else if (assemblySymbol.Type == AssemblyType.Win32Assembly) + { + assemblyAttributes = 1; + } + } + + yield return "WixFile:" + String.Join(",", + fileSymbol.Id.Id, + assemblyAttributes, + assemblySymbol?.ManifestFileRef, + assemblySymbol?.ApplicationFileRef, + fileSymbol.DirectoryRef, + fileSymbol.DiskId, + fileSymbol.Source.Path, + null, // assembly processor arch + fileSymbol.PatchGroup, + (fileSymbol.Attributes & FileSymbolAttributes.GeneratedShortFileName) != 0 ? 1 : 0, + (int)fileSymbol.PatchAttributes, + fileSymbol.RetainLengths, + fileSymbol.IgnoreOffsets, + fileSymbol.IgnoreLengths, + fileSymbol.RetainOffsets + ); + + var fileAttributes = 0; + fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.ReadOnly) != 0 ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0; + fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Hidden) != 0 ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0; + fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.System) != 0 ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0; + fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Vital) != 0 ? WindowsInstallerConstants.MsidbFileAttributesVital : 0; + fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Checksum) != 0 ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0; + fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Compressed) != 0 ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0; + fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Uncompressed) != 0 ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0; + + fields = String.Join(",", + fileSymbol.ComponentRef, + fileSymbol.Name, + fileSymbol.FileSize.ToString(), + fileSymbol.Version, + fileSymbol.Language, + fileAttributes); + break; + } + + case "Media": + fields = String.Join(",", symbol.Fields.Skip(1).Select(SafeConvertField)); + break; + + case "Assembly": + { + var assemblySymbol = (AssemblySymbol)symbol; + + id = null; + name = "MsiAssembly"; + fields = String.Join(",", assemblySymbol.ComponentRef, assemblySymbol.FeatureRef, assemblySymbol.ManifestFileRef, assemblySymbol.ApplicationFileRef, assemblySymbol.Type == AssemblyType.Win32Assembly ? 1 : 0); + break; + } + case "RegLocator": + { + var locatorSymbol = (RegLocatorSymbol)symbol; + + fields = String.Join(",", (int)locatorSymbol.Root, locatorSymbol.Key, locatorSymbol.Name, (int)locatorSymbol.Type, locatorSymbol.Win64); + break; + } + case "Registry": + { + var registrySymbol = (RegistrySymbol)symbol; + var value = registrySymbol.Value; + + switch (registrySymbol.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 (registrySymbol.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)registrySymbol.Root).ToString(), + registrySymbol.Key, + registrySymbol.Name, + value, + registrySymbol.ComponentRef + ); + break; + } + + case "RemoveRegistry": + { + var removeRegistrySymbol = (RemoveRegistrySymbol)symbol; + fields = String.Join(",", + ((int)removeRegistrySymbol.Root).ToString(), + removeRegistrySymbol.Key, + removeRegistrySymbol.Name, + removeRegistrySymbol.ComponentRef + ); + break; + } + + case "ServiceControl": + { + var serviceControlSymbol = (ServiceControlSymbol)symbol; + + var events = serviceControlSymbol.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0; + events |= serviceControlSymbol.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0; + events |= serviceControlSymbol.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0; + events |= serviceControlSymbol.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0; + events |= serviceControlSymbol.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0; + events |= serviceControlSymbol.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0; + + fields = String.Join(",", + serviceControlSymbol.Name, + events.ToString(), + serviceControlSymbol.Arguments, + serviceControlSymbol.Wait == true ? "1" : "0", + serviceControlSymbol.ComponentRef + ); + break; + } + + case "ServiceInstall": + { + var serviceInstallSymbol = (ServiceInstallSymbol)symbol; + + var errorControl = (int)serviceInstallSymbol.ErrorControl; + errorControl |= serviceInstallSymbol.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0; + + var serviceType = (int)serviceInstallSymbol.ServiceType; + serviceType |= serviceInstallSymbol.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0; + + fields = String.Join(",", + serviceInstallSymbol.Name, + serviceInstallSymbol.DisplayName, + serviceType.ToString(), + ((int)serviceInstallSymbol.StartType).ToString(), + errorControl.ToString(), + serviceInstallSymbol.LoadOrderGroup, + serviceInstallSymbol.Dependencies, + serviceInstallSymbol.StartName, + serviceInstallSymbol.Password, + serviceInstallSymbol.Arguments, + serviceInstallSymbol.ComponentRef, + serviceInstallSymbol.Description + ); + break; + } + + case "Upgrade": + { + var upgradeSymbol = (UpgradeSymbol)symbol; + + var attributes = upgradeSymbol.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0; + attributes |= upgradeSymbol.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0; + attributes |= upgradeSymbol.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0; + attributes |= upgradeSymbol.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0; + attributes |= upgradeSymbol.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0; + attributes |= upgradeSymbol.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0; + + fields = String.Join(",", + upgradeSymbol.VersionMin, + upgradeSymbol.VersionMax, + upgradeSymbol.Language, + attributes.ToString(), + upgradeSymbol.Remove, + upgradeSymbol.ActionProperty + ); + break; + } + + case "WixAction": + { + var wixActionSymbol = (WixActionSymbol)symbol; + var data = wixActionSymbol.Fields[(int)WixActionSymbolFields.SequenceTable].AsObject(); + var sequenceTableAsInt = data is string ? (int)SequenceStringToSequenceTable(data) : (int)wixActionSymbol.SequenceTable; + + fields = String.Join(",", + sequenceTableAsInt, + wixActionSymbol.Action, + wixActionSymbol.Condition, + wixActionSymbol.Sequence?.ToString() ?? String.Empty, + wixActionSymbol.Before, + wixActionSymbol.After, + wixActionSymbol.Overridable == true ? "1" : "0" + ); + break; + } + + case "WixComplexReference": + { + var wixComplexReferenceSymbol = (WixComplexReferenceSymbol)symbol; + fields = String.Join(",", + wixComplexReferenceSymbol.Parent, + (int)wixComplexReferenceSymbol.ParentType, + wixComplexReferenceSymbol.ParentLanguage, + wixComplexReferenceSymbol.Child, + (int)wixComplexReferenceSymbol.ChildType, + wixComplexReferenceSymbol.IsPrimary ? "1" : "0" + ); + break; + } + + case "WixProperty": + { + var wixPropertySymbol = (WixPropertySymbol)symbol; + var attributes = wixPropertySymbol.Admin ? 0x1 : 0; + attributes |= wixPropertySymbol.Hidden ? 0x2 : 0; + attributes |= wixPropertySymbol.Secure ? 0x4 : 0; + + fields = String.Join(",", + wixPropertySymbol.PropertyRef, + attributes.ToString() + ); + break; + } + + default: + fields = String.Join(",", symbol.Fields.Select(SafeConvertField)); + break; + } + + 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}"); + } + } + + 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 + }; + } + } +} diff --git a/src/test/WixToolsetTest.Converters.Symbolizer/ConvertTuplesFixture.cs b/src/test/WixToolsetTest.Converters.Symbolizer/ConvertTuplesFixture.cs deleted file mode 100644 index ae054079..00000000 --- a/src/test/WixToolsetTest.Converters.Symbolizer/ConvertTuplesFixture.cs +++ /dev/null @@ -1,606 +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 WixToolsetTest.Converters.Symbolizer -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using WixBuildTools.TestSupport; - using Wix3 = Microsoft.Tools.WindowsInstallerXml; - using WixToolset.Converters.Symbolizer; - using WixToolset.Data; - using WixToolset.Data.WindowsInstaller; - using WixToolset.Data.Symbols; - using Xunit; - - public class ConvertSymbolsFixture - { - [Fact] - public void CanLoadWixoutAndConvertToIntermediate() - { - var rootFolder = TestData.Get(); - var dataFolder = TestData.Get(@"TestData\Integration"); - - using (var fs = new DisposableFileSystem()) - { - var intermediateFolder = fs.GetFolder(); - - var path = Path.Combine(dataFolder, "test.wixout"); - - var intermediate = ConvertSymbols.ConvertFile(path); - - Assert.NotNull(intermediate); - Assert.Single(intermediate.Sections); - Assert.Equal(String.Empty, intermediate.Id); - - // Save and load to guarantee round-tripping support. - // - var wixiplFile = Path.Combine(intermediateFolder, "test.wixipl"); - intermediate.Save(wixiplFile); - - intermediate = Intermediate.Load(wixiplFile); - - var output = Wix3.Output.Load(path, suppressVersionCheck: true, suppressSchema: true); - 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() - .SelectMany(row => RowToStrings(row, wixMediaByDiskId))) - .Where(s => !String.IsNullOrEmpty(s)) - .OrderBy(s => s) - .ToArray(); - - var symbols = intermediate.Sections.SelectMany(s => s.Symbols); - - var assemblySymbolsByFileId = symbols.OfType().ToDictionary(a => a.Id.Id); - - var wix4Dump = symbols - .SelectMany(symbol => SymbolToStrings(symbol, assemblySymbolsByFileId)) - .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); - - var path3 = Path.Combine(Path.GetTempPath(), "~3.txt"); - var path4 = Path.Combine(Path.GetTempPath(), "~4.txt"); - - File.WriteAllText(path3, wix3TextDump); - File.WriteAllText(path4, wix4TextDump); - - Assert.Equal(wix3TextDump, wix4TextDump); -#endif - } - } - - 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((int)row[0], row); - } - } - - return wixMediaByDiskId; - } - - private static IEnumerable RowToStrings(Wix3.Row row, Dictionary wixMediaByDiskId) - { - string fields = null; - - // Massage output to match WiX v3 rows and v4 symbols. - // - switch (row.Table.Name) - { - 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) - { - // "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 "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.Select(SafeConvertField).ToArray(); - if (fieldValues[8] == 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[8] = "0"; - } - if (fieldValues[10] == null) - { - // WixFile rows that come from merge modules will not have the attributes column set - // so initilaize with 0. - fieldValues[10] = "0"; - } - fields = String.Join(",", fieldValues); - break; - } - case "WixMedia": - break; - default: - fields = String.Join(",", row.Fields.Select(SafeConvertField)); - break; - } - - if (fields != null) - { - yield return $"{row.Table.Name}:{fields}"; - } - } - - private static IEnumerable SymbolToStrings(IntermediateSymbol symbol, Dictionary assemblySymbolsByFileId) - { - var name = symbol.Definition.Type == SymbolDefinitionType.SummaryInformation ? "_SummaryInformation" : symbol.Definition.Name; - var id = symbol.Id?.Id ?? String.Empty; - - string fields; - switch (symbol.Definition.Name) - { - // Massage output to match WiX v3 rows and v4 symbols. - // - case "Component": - { - var componentSymbol = (ComponentSymbol)symbol; - var attributes = ComponentLocation.Either == componentSymbol.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0; - attributes |= ComponentLocation.SourceOnly == componentSymbol.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0; - attributes |= ComponentKeyPathType.Registry == componentSymbol.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0; - attributes |= ComponentKeyPathType.OdbcDataSource == componentSymbol.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0; - attributes |= componentSymbol.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0; - attributes |= componentSymbol.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0; - attributes |= componentSymbol.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0; - attributes |= componentSymbol.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0; - attributes |= componentSymbol.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0; - attributes |= componentSymbol.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0; - attributes |= componentSymbol.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; - attributes |= componentSymbol.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0; - - fields = String.Join(",", - componentSymbol.ComponentId, - componentSymbol.DirectoryRef, - attributes.ToString(), - componentSymbol.Condition, - componentSymbol.KeyPath - ); - break; - } - case "CustomAction": - { - var customActionSymbol = (CustomActionSymbol)symbol; - var type = customActionSymbol.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0; - type |= customActionSymbol.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0; - type |= customActionSymbol.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate; - type |= customActionSymbol.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0; - type |= customActionSymbol.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0; - type |= customActionSymbol.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0; - type |= CustomActionExecutionType.FirstSequence == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0; - type |= CustomActionExecutionType.OncePerProcess == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0; - type |= CustomActionExecutionType.ClientRepeat == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0; - type |= CustomActionExecutionType.Deferred == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0; - type |= CustomActionExecutionType.Rollback == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0; - type |= CustomActionExecutionType.Commit == customActionSymbol.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0; - type |= CustomActionSourceType.File == customActionSymbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0; - type |= CustomActionSourceType.Directory == customActionSymbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0; - type |= CustomActionSourceType.Property == customActionSymbol.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0; - type |= CustomActionTargetType.Dll == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0; - type |= CustomActionTargetType.Exe == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0; - type |= CustomActionTargetType.TextData == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0; - type |= CustomActionTargetType.JScript == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0; - type |= CustomActionTargetType.VBScript == customActionSymbol.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0; - - fields = String.Join(",", - type.ToString(), - customActionSymbol.Source, - customActionSymbol.Target, - customActionSymbol.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null - ); - break; - } - case "Directory": - { - var directorySymbol = (DirectorySymbol)symbol; - - if (!String.IsNullOrEmpty(directorySymbol.ComponentGuidGenerationSeed)) - { - yield return $"WixDirectory:{directorySymbol.Id.Id},{directorySymbol.ComponentGuidGenerationSeed}"; - } - - fields = String.Join(",", directorySymbol.ParentDirectoryRef, directorySymbol.Name, directorySymbol.ShortName, directorySymbol.SourceName, directorySymbol.SourceShortName); - break; - } - case "Feature": - { - var featureSymbol = (FeatureSymbol)symbol; - var attributes = featureSymbol.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0; - attributes |= featureSymbol.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0; - attributes |= FeatureInstallDefault.FollowParent == featureSymbol.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0; - attributes |= FeatureInstallDefault.Source == featureSymbol.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0; - attributes |= FeatureTypicalDefault.Advertise == featureSymbol.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0; - - fields = String.Join(",", - featureSymbol.ParentFeatureRef, - featureSymbol.Title, - featureSymbol.Description, - featureSymbol.Display.ToString(), - featureSymbol.Level.ToString(), - featureSymbol.DirectoryRef, - attributes.ToString()); - break; - } - case "File": - { - var fileSymbol = (FileSymbol)symbol; - - if (fileSymbol.BindPath != null) - { - yield return $"BindImage:{fileSymbol.Id.Id},{fileSymbol.BindPath}"; - } - - if (fileSymbol.FontTitle != null) - { - yield return $"Font:{fileSymbol.Id.Id},{fileSymbol.FontTitle}"; - } - - if (fileSymbol.SelfRegCost.HasValue) - { - yield return $"SelfReg:{fileSymbol.Id.Id},{fileSymbol.SelfRegCost}"; - } - - int? assemblyAttributes = null; - if (assemblySymbolsByFileId.TryGetValue(fileSymbol.Id.Id, out var assemblySymbol)) - { - if (assemblySymbol.Type == AssemblyType.DotNetAssembly) - { - assemblyAttributes = 0; - } - else if (assemblySymbol.Type == AssemblyType.Win32Assembly) - { - assemblyAttributes = 1; - } - } - - yield return "WixFile:" + String.Join(",", - fileSymbol.Id.Id, - assemblyAttributes, - assemblySymbol?.ManifestFileRef, - assemblySymbol?.ApplicationFileRef, - fileSymbol.DirectoryRef, - fileSymbol.DiskId, - fileSymbol.Source.Path, - null, // assembly processor arch - fileSymbol.PatchGroup, - (fileSymbol.Attributes & FileSymbolAttributes.GeneratedShortFileName) != 0 ? 1 : 0, - (int)fileSymbol.PatchAttributes, - fileSymbol.RetainLengths, - fileSymbol.IgnoreOffsets, - fileSymbol.IgnoreLengths, - fileSymbol.RetainOffsets - ); - - var fileAttributes = 0; - fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.ReadOnly) != 0 ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0; - fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Hidden) != 0 ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0; - fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.System) != 0 ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0; - fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Vital) != 0 ? WindowsInstallerConstants.MsidbFileAttributesVital : 0; - fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Checksum) != 0 ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0; - fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Compressed) != 0 ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0; - fileAttributes |= (fileSymbol.Attributes & FileSymbolAttributes.Uncompressed) != 0 ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0; - - fields = String.Join(",", - fileSymbol.ComponentRef, - fileSymbol.Name, - fileSymbol.FileSize.ToString(), - fileSymbol.Version, - fileSymbol.Language, - fileAttributes); - break; - } - - case "Media": - fields = String.Join(",", symbol.Fields.Skip(1).Select(SafeConvertField)); - break; - - case "Assembly": - { - var assemblySymbol = (AssemblySymbol)symbol; - - id = null; - name = "MsiAssembly"; - fields = String.Join(",", assemblySymbol.ComponentRef, assemblySymbol.FeatureRef, assemblySymbol.ManifestFileRef, assemblySymbol.ApplicationFileRef, assemblySymbol.Type == AssemblyType.Win32Assembly ? 1 : 0); - break; - } - case "RegLocator": - { - var locatorSymbol = (RegLocatorSymbol)symbol; - - fields = String.Join(",", (int)locatorSymbol.Root, locatorSymbol.Key, locatorSymbol.Name, (int)locatorSymbol.Type, locatorSymbol.Win64); - break; - } - case "Registry": - { - var registrySymbol = (RegistrySymbol)symbol; - var value = registrySymbol.Value; - - switch (registrySymbol.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 (registrySymbol.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)registrySymbol.Root).ToString(), - registrySymbol.Key, - registrySymbol.Name, - value, - registrySymbol.ComponentRef - ); - break; - } - - case "RemoveRegistry": - { - var removeRegistrySymbol = (RemoveRegistrySymbol)symbol; - fields = String.Join(",", - ((int)removeRegistrySymbol.Root).ToString(), - removeRegistrySymbol.Key, - removeRegistrySymbol.Name, - removeRegistrySymbol.ComponentRef - ); - break; - } - - case "ServiceControl": - { - var serviceControlSymbol = (ServiceControlSymbol)symbol; - - var events = serviceControlSymbol.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0; - events |= serviceControlSymbol.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0; - events |= serviceControlSymbol.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0; - events |= serviceControlSymbol.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0; - events |= serviceControlSymbol.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0; - events |= serviceControlSymbol.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0; - - fields = String.Join(",", - serviceControlSymbol.Name, - events.ToString(), - serviceControlSymbol.Arguments, - serviceControlSymbol.Wait == true ? "1" : "0", - serviceControlSymbol.ComponentRef - ); - break; - } - - case "ServiceInstall": - { - var serviceInstallSymbol = (ServiceInstallSymbol)symbol; - - var errorControl = (int)serviceInstallSymbol.ErrorControl; - errorControl |= serviceInstallSymbol.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0; - - var serviceType = (int)serviceInstallSymbol.ServiceType; - serviceType |= serviceInstallSymbol.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0; - - fields = String.Join(",", - serviceInstallSymbol.Name, - serviceInstallSymbol.DisplayName, - serviceType.ToString(), - ((int)serviceInstallSymbol.StartType).ToString(), - errorControl.ToString(), - serviceInstallSymbol.LoadOrderGroup, - serviceInstallSymbol.Dependencies, - serviceInstallSymbol.StartName, - serviceInstallSymbol.Password, - serviceInstallSymbol.Arguments, - serviceInstallSymbol.ComponentRef, - serviceInstallSymbol.Description - ); - break; - } - - case "Upgrade": - { - var upgradeSymbol = (UpgradeSymbol)symbol; - - var attributes = upgradeSymbol.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0; - attributes |= upgradeSymbol.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0; - attributes |= upgradeSymbol.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0; - attributes |= upgradeSymbol.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0; - attributes |= upgradeSymbol.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0; - attributes |= upgradeSymbol.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0; - - fields = String.Join(",", - upgradeSymbol.VersionMin, - upgradeSymbol.VersionMax, - upgradeSymbol.Language, - attributes.ToString(), - upgradeSymbol.Remove, - upgradeSymbol.ActionProperty - ); - break; - } - - case "WixAction": - { - var wixActionSymbol = (WixActionSymbol)symbol; - var data = wixActionSymbol.Fields[(int)WixActionSymbolFields.SequenceTable].AsObject(); - var sequenceTableAsInt = data is string ? (int)SequenceStringToSequenceTable(data) : (int)wixActionSymbol.SequenceTable; - - fields = String.Join(",", - sequenceTableAsInt, - wixActionSymbol.Action, - wixActionSymbol.Condition, - wixActionSymbol.Sequence?.ToString() ?? String.Empty, - wixActionSymbol.Before, - wixActionSymbol.After, - wixActionSymbol.Overridable == true ? "1" : "0" - ); - break; - } - - case "WixComplexReference": - { - var wixComplexReferenceSymbol = (WixComplexReferenceSymbol)symbol; - fields = String.Join(",", - wixComplexReferenceSymbol.Parent, - (int)wixComplexReferenceSymbol.ParentType, - wixComplexReferenceSymbol.ParentLanguage, - wixComplexReferenceSymbol.Child, - (int)wixComplexReferenceSymbol.ChildType, - wixComplexReferenceSymbol.IsPrimary ? "1" : "0" - ); - break; - } - - case "WixProperty": - { - var wixPropertySymbol = (WixPropertySymbol)symbol; - var attributes = wixPropertySymbol.Admin ? 0x1 : 0; - attributes |= wixPropertySymbol.Hidden ? 0x2 : 0; - attributes |= wixPropertySymbol.Secure ? 0x4 : 0; - - fields = String.Join(",", - wixPropertySymbol.PropertyRef, - attributes.ToString() - ); - break; - } - - default: - fields = String.Join(",", symbol.Fields.Select(SafeConvertField)); - break; - } - - 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}"); - } - } - - 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