From 612dc390ecd90bf4079ad7545f4a4832ce8f702d Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 27 Apr 2021 22:37:33 -0700 Subject: Move Converters into wix --- .editorconfig | 37 - README.md | 2 - WixToolset.Converters.sln | 85 - WixToolset.Converters.v3.ncrunchsolution | 6 - appveyor.cmd | 20 - appveyor.yml | 44 - nuget.config | 14 - src/.editorconfig | 37 + src/Directory.Build.props | 27 - src/Directory.Build.targets | 51 - src/Directory.csproj.props | 13 - src/Directory.csproj.targets | 26 - .../ConvertSymbols.cs | 876 ------- .../WixToolset.Converters.Symbolizer.csproj | 32 - src/WixToolset.Converters/ConvertCommand.cs | 60 - .../ConverterExtensionCommandLine.cs | 46 - .../ConverterExtensionFactory.cs | 30 - src/WixToolset.Converters/FixupCommandBase.cs | 288 --- src/WixToolset.Converters/FormatCommand.cs | 60 - src/WixToolset.Converters/WixConverter.cs | 2435 -------------------- .../WixToolset.Converters.csproj | 24 - .../WixToolsetCoreServiceProviderExtensions.cs | 25 - src/deps/wix.dll | Bin 1753088 -> 0 bytes .../ConvertSymbolsFixture.cs | 606 ----- .../TestData/Integration/test.wixout | Bin 148559 -> 0 bytes .../TestData/Integration/test.wixproj | 47 - .../TestData/Integration/test.wxs | 36 - .../WixToolsetTest.Converters.Symbolizer.csproj | 33 - ...setTest.Converters.Symbolizer.v3.ncrunchproject | 9 - .../BaseConverterFixture.cs | 33 - .../WixToolsetTest.Converters/BitnessFixture.cs | 187 -- .../BootstrapperApplicationFixture.cs | 418 ---- .../WixToolsetTest.Converters/ConditionFixture.cs | 297 --- .../WixToolsetTest.Converters/ConverterFixture.cs | 449 ---- .../ConverterIntegrationFixture.cs | 195 -- .../CustomActionFixture.cs | 88 - .../CustomTableFixture.cs | 363 --- .../WixToolsetTest.Converters/DependencyFixture.cs | 178 -- .../WixToolsetTest.Converters/DirectoryFixture.cs | 92 - .../WixToolsetTest.Converters/ExePackageFixture.cs | 49 - .../WixToolsetTest.Converters/FeatureFixture.cs | 110 - .../FirewallExtensionFixture.cs | 47 - .../WixToolsetTest.Converters/FormatFixture.cs | 117 - .../WixToolsetTest.Converters/IncludeFixture.cs | 68 - .../Mocks/MockCoreServiceProvider.cs | 51 - .../Mocks/MockMessaging.cs | 39 - .../ProductPackageFixture.cs | 278 --- .../WixToolsetTest.Converters/PropertyFixture.cs | 108 - .../WixToolsetTest.Converters/RegistryFixture.cs | 54 - .../RemotePayloadFixture.cs | 104 - .../WixToolsetTest.Converters/SequenceFixture.cs | 49 - src/test/WixToolsetTest.Converters/TagFixture.cs | 111 - .../PackageSummaryInformation/TypicalV3.msi | Bin 32768 -> 0 bytes .../PackageSummaryInformation/TypicalV3.wxs | 37 - .../TestData/PermissionEx/v3.wxs | 26 - .../TestData/PermissionEx/v4_expected.wxs | 26 - .../Preprocessor/ConvertedPreprocessor.wxs | 61 - .../TestData/Preprocessor/Preprocessor.wxs | 63 - .../TestData/Preprocessor/wixcop.settings.xml | 9 - .../TestData/QtExec.bad/v3.wxs | 64 - .../TestData/QtExec.bad/v4_expected.wxs | 63 - .../TestData/QtExec/v3.wxs | 64 - .../TestData/QtExec/v4_expected.wxs | 62 - .../TestData/SingleFile/ConvertedSingleFile.wxs | 59 - .../TestData/SingleFile/SingleFile.wxs | 61 - .../UtilExtensionFixture.cs | 190 -- .../WixToolsetTest.Converters/VariableFixture.cs | 86 - .../Wix4ConversionFixture.cs | 54 - .../WixToolsetTest.Converters.csproj | 31 - src/version.json | 11 + src/wix/Directory.Build.props | 27 + src/wix/Directory.Build.targets | 51 + src/wix/Directory.csproj.props | 13 + src/wix/Directory.csproj.targets | 26 + src/wix/README.md | 2 + .../ConvertSymbols.cs | 876 +++++++ .../WixToolset.Converters.Symbolizer.csproj | 32 + src/wix/WixToolset.Converters.sln | 85 + src/wix/WixToolset.Converters.v3.ncrunchsolution | 6 + src/wix/WixToolset.Converters/ConvertCommand.cs | 60 + .../ConverterExtensionCommandLine.cs | 46 + .../ConverterExtensionFactory.cs | 30 + src/wix/WixToolset.Converters/FixupCommandBase.cs | 288 +++ src/wix/WixToolset.Converters/FormatCommand.cs | 60 + src/wix/WixToolset.Converters/WixConverter.cs | 2435 ++++++++++++++++++++ .../WixToolset.Converters.csproj | 24 + .../WixToolsetCoreServiceProviderExtensions.cs | 25 + src/wix/appveyor.cmd | 20 + src/wix/appveyor.yml | 44 + src/wix/deps/wix.dll | Bin 0 -> 1753088 bytes src/wix/nuget.config | 14 + .../ConvertSymbolsFixture.cs | 606 +++++ .../TestData/Integration/test.wixout | Bin 0 -> 148559 bytes .../TestData/Integration/test.wixproj | 47 + .../TestData/Integration/test.wxs | 36 + .../WixToolsetTest.Converters.Symbolizer.csproj | 33 + ...setTest.Converters.Symbolizer.v3.ncrunchproject | 9 + .../BaseConverterFixture.cs | 33 + .../WixToolsetTest.Converters/BitnessFixture.cs | 187 ++ .../BootstrapperApplicationFixture.cs | 418 ++++ .../WixToolsetTest.Converters/ConditionFixture.cs | 297 +++ .../WixToolsetTest.Converters/ConverterFixture.cs | 449 ++++ .../ConverterIntegrationFixture.cs | 195 ++ .../CustomActionFixture.cs | 88 + .../CustomTableFixture.cs | 363 +++ .../WixToolsetTest.Converters/DependencyFixture.cs | 178 ++ .../WixToolsetTest.Converters/DirectoryFixture.cs | 92 + .../WixToolsetTest.Converters/ExePackageFixture.cs | 49 + .../WixToolsetTest.Converters/FeatureFixture.cs | 110 + .../FirewallExtensionFixture.cs | 47 + .../WixToolsetTest.Converters/FormatFixture.cs | 117 + .../WixToolsetTest.Converters/IncludeFixture.cs | 68 + .../Mocks/MockCoreServiceProvider.cs | 51 + .../Mocks/MockMessaging.cs | 39 + .../ProductPackageFixture.cs | 278 +++ .../WixToolsetTest.Converters/PropertyFixture.cs | 108 + .../WixToolsetTest.Converters/RegistryFixture.cs | 54 + .../RemotePayloadFixture.cs | 104 + .../WixToolsetTest.Converters/SequenceFixture.cs | 49 + .../test/WixToolsetTest.Converters/TagFixture.cs | 111 + .../PackageSummaryInformation/TypicalV3.msi | Bin 0 -> 32768 bytes .../PackageSummaryInformation/TypicalV3.wxs | 37 + .../TestData/PermissionEx/v3.wxs | 26 + .../TestData/PermissionEx/v4_expected.wxs | 26 + .../Preprocessor/ConvertedPreprocessor.wxs | 61 + .../TestData/Preprocessor/Preprocessor.wxs | 63 + .../TestData/Preprocessor/wixcop.settings.xml | 9 + .../TestData/QtExec.bad/v3.wxs | 64 + .../TestData/QtExec.bad/v4_expected.wxs | 63 + .../TestData/QtExec/v3.wxs | 64 + .../TestData/QtExec/v4_expected.wxs | 62 + .../TestData/SingleFile/ConvertedSingleFile.wxs | 59 + .../TestData/SingleFile/SingleFile.wxs | 61 + .../UtilExtensionFixture.cs | 190 ++ .../WixToolsetTest.Converters/VariableFixture.cs | 86 + .../Wix4ConversionFixture.cs | 54 + .../WixToolsetTest.Converters.csproj | 31 + version.json | 11 - 138 files changed, 9384 insertions(+), 9384 deletions(-) delete mode 100644 .editorconfig delete mode 100644 README.md delete mode 100644 WixToolset.Converters.sln delete mode 100644 WixToolset.Converters.v3.ncrunchsolution delete mode 100644 appveyor.cmd delete mode 100644 appveyor.yml delete mode 100644 nuget.config create mode 100644 src/.editorconfig delete mode 100644 src/Directory.Build.props delete mode 100644 src/Directory.Build.targets delete mode 100644 src/Directory.csproj.props delete mode 100644 src/Directory.csproj.targets delete mode 100644 src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs delete mode 100644 src/WixToolset.Converters.Symbolizer/WixToolset.Converters.Symbolizer.csproj delete mode 100644 src/WixToolset.Converters/ConvertCommand.cs delete mode 100644 src/WixToolset.Converters/ConverterExtensionCommandLine.cs delete mode 100644 src/WixToolset.Converters/ConverterExtensionFactory.cs delete mode 100644 src/WixToolset.Converters/FixupCommandBase.cs delete mode 100644 src/WixToolset.Converters/FormatCommand.cs delete mode 100644 src/WixToolset.Converters/WixConverter.cs delete mode 100644 src/WixToolset.Converters/WixToolset.Converters.csproj delete mode 100644 src/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs delete mode 100644 src/deps/wix.dll delete mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixout delete mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj delete mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs delete mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj delete mode 100644 src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject delete mode 100644 src/test/WixToolsetTest.Converters/BaseConverterFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/BitnessFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/ConditionFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/ConverterFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/CustomActionFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/CustomTableFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/DependencyFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/DirectoryFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/ExePackageFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/FeatureFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/FormatFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/IncludeFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs delete mode 100644 src/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs delete mode 100644 src/test/WixToolsetTest.Converters/ProductPackageFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/PropertyFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/RegistryFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/RemotePayloadFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/SequenceFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/TagFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi delete mode 100644 src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml delete mode 100644 src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs delete mode 100644 src/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs delete mode 100644 src/test/WixToolsetTest.Converters/UtilExtensionFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/VariableFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs delete mode 100644 src/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj create mode 100644 src/version.json create mode 100644 src/wix/Directory.Build.props create mode 100644 src/wix/Directory.Build.targets create mode 100644 src/wix/Directory.csproj.props create mode 100644 src/wix/Directory.csproj.targets create mode 100644 src/wix/README.md create mode 100644 src/wix/WixToolset.Converters.Symbolizer/ConvertSymbols.cs create mode 100644 src/wix/WixToolset.Converters.Symbolizer/WixToolset.Converters.Symbolizer.csproj create mode 100644 src/wix/WixToolset.Converters.sln create mode 100644 src/wix/WixToolset.Converters.v3.ncrunchsolution create mode 100644 src/wix/WixToolset.Converters/ConvertCommand.cs create mode 100644 src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs create mode 100644 src/wix/WixToolset.Converters/ConverterExtensionFactory.cs create mode 100644 src/wix/WixToolset.Converters/FixupCommandBase.cs create mode 100644 src/wix/WixToolset.Converters/FormatCommand.cs create mode 100644 src/wix/WixToolset.Converters/WixConverter.cs create mode 100644 src/wix/WixToolset.Converters/WixToolset.Converters.csproj create mode 100644 src/wix/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs create mode 100644 src/wix/appveyor.cmd create mode 100644 src/wix/appveyor.yml create mode 100644 src/wix/deps/wix.dll create mode 100644 src/wix/nuget.config create mode 100644 src/wix/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixout create mode 100644 src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj create mode 100644 src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj create mode 100644 src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject create mode 100644 src/wix/test/WixToolsetTest.Converters/BaseConverterFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/BitnessFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/CustomActionFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/CustomTableFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/DependencyFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/DirectoryFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/ExePackageFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/FeatureFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/FormatFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/IncludeFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/ProductPackageFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/PropertyFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/RegistryFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/RemotePayloadFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/SequenceFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/TagFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs create mode 100644 src/wix/test/WixToolsetTest.Converters/UtilExtensionFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/VariableFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs create mode 100644 src/wix/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj delete mode 100644 version.json diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 1d72e683..00000000 --- a/.editorconfig +++ /dev/null @@ -1,37 +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. -# -# Do NOT modify this file. Update the canonical version in Home\repo-template\src\.editorconfig -# then update all of the repos. - -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true - -[*.{cs,vb}] -dotnet_sort_system_directives_first = true - -[*.cs] -csharp_indent_case_contents = true : error -csharp_indent_switch_labels = true : error -csharp_new_line_before_open_brace = all -csharp_prefer_braces = true : error -csharp_style_expression_bodied_methods = when_on_single_line : suggestion -csharp_style_expression_bodied_constructors = when_on_single_line : suggestion -csharp_style_expression_bodied_operators = when_on_single_line : suggestion -csharp_style_expression_bodied_properties = when_on_single_line : suggestion -csharp_style_expression_bodied_indexers = when_on_single_line : suggestion -csharp_style_expression_bodied_accessors = when_on_single_line : suggestion -csharp_style_var_elsewhere = true : suggestion -csharp_style_var_for_built_in_types = true : suggestion -csharp_style_var_when_type_is_apparent = true : suggestion -dotnet_style_qualification_for_event = true : error -dotnet_style_qualification_for_field = true : error -dotnet_style_qualification_for_method = true : error -dotnet_style_qualification_for_property = true : error - -[*.targets] -indent_size = 2 diff --git a/README.md b/README.md deleted file mode 100644 index f031cf7c..00000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Converters -WixToolset.Converters, conversion related functionality diff --git a/WixToolset.Converters.sln b/WixToolset.Converters.sln deleted file mode 100644 index a67df266..00000000 --- a/WixToolset.Converters.sln +++ /dev/null @@ -1,85 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Converters", "src\WixToolset.Converters\WixToolset.Converters.csproj", "{6FAF6385-6598-4B89-972B-C31AFCA14538}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Converters.Symbolizer", "src\WixToolset.Converters.Symbolizer\WixToolset.Converters.Symbolizer.csproj", "{F051BCAF-698C-41D5-8427-164537CE5C5C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{1B16A6C1-2B5D-4F9A-9DD5-FBC89B3CE31E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Converters", "src\test\WixToolsetTest.Converters\WixToolsetTest.Converters.csproj", "{485C5038-97E1-4729-A54D-848CC69569FD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Converters.Symbolizer", "src\test\WixToolsetTest.Converters.Symbolizer\WixToolsetTest.Converters.Symbolizer.csproj", "{9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x64.ActiveCfg = Debug|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x64.Build.0 = Debug|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x86.ActiveCfg = Debug|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x86.Build.0 = Debug|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|Any CPU.Build.0 = Release|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x64.ActiveCfg = Release|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x64.Build.0 = Release|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x86.ActiveCfg = Release|Any CPU - {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x86.Build.0 = Release|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x64.ActiveCfg = Debug|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x64.Build.0 = Debug|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x86.ActiveCfg = Debug|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x86.Build.0 = Debug|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|Any CPU.Build.0 = Release|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x64.ActiveCfg = Release|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x64.Build.0 = Release|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x86.ActiveCfg = Release|Any CPU - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x86.Build.0 = Release|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x64.ActiveCfg = Debug|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x64.Build.0 = Debug|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x86.ActiveCfg = Debug|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x86.Build.0 = Debug|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|Any CPU.Build.0 = Release|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x64.ActiveCfg = Release|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x64.Build.0 = Release|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x86.ActiveCfg = Release|Any CPU - {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x86.Build.0 = Release|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x64.ActiveCfg = Debug|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x64.Build.0 = Debug|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x86.ActiveCfg = Debug|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x86.Build.0 = Debug|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Release|Any CPU.Build.0 = Release|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x64.ActiveCfg = Release|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x64.Build.0 = Release|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x86.ActiveCfg = Release|Any CPU - {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C} = {1B16A6C1-2B5D-4F9A-9DD5-FBC89B3CE31E} - {485C5038-97E1-4729-A54D-848CC69569FD} = {1B16A6C1-2B5D-4F9A-9DD5-FBC89B3CE31E} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {2E71F0EC-CF75-44DA-8353-7066EBD06564} - EndGlobalSection -EndGlobal diff --git a/WixToolset.Converters.v3.ncrunchsolution b/WixToolset.Converters.v3.ncrunchsolution deleted file mode 100644 index f774ab93..00000000 --- a/WixToolset.Converters.v3.ncrunchsolution +++ /dev/null @@ -1,6 +0,0 @@ - - - False - True - - \ No newline at end of file diff --git a/appveyor.cmd b/appveyor.cmd deleted file mode 100644 index 02db695b..00000000 --- a/appveyor.cmd +++ /dev/null @@ -1,20 +0,0 @@ -@setlocal -@pushd %~dp0 -@set _P=%~dp0build\Release\publish -@set _C=Release -@if /i "%1"=="debug" set _C=Debug - -:: Restore -msbuild -p:Configuration=%_C% -t:Restore || exit /b - -:: Build -msbuild -p:Configuration=%_C% || exit /b - -:: Test -dotnet test -c %_C% --no-build || exit /b - -:: Pack -msbuild -p:Configuration=%_C% -p:NoBuild=true -t:Pack || exit /b - -@popd -@endlocal diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 364569cf..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,44 +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. -# -# Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml -# then update all of the repos. - -branches: - only: - - master - - develop - -image: Visual Studio 2019 - -version: 0.0.0.{build} -configuration: Release - -environment: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true - DOTNET_CLI_TELEMETRY_OPTOUT: 1 - NUGET_XMLDOC_MODE: skip - -build_script: - - appveyor.cmd - -test: off - -pull_requests: - do_not_increment_build_number: true - -nuget: - disable_publish_on_pr: true - -skip_branch_with_pr: true -skip_tags: true - -artifacts: -- path: build\Release\**\*.nupkg - name: nuget -- path: build\Release\**\*.snupkg - name: snupkg - -notifications: -- provider: Slack - incoming_webhook: - secure: p5xuu+4x2JHfwGDMDe5KcG1k7gZxqYc4jWVwvyNZv5cvkubPD2waJs5yXMAXZNN7Z63/3PWHb7q4KoY/99AjauYa1nZ4c5qYqRPFRBKTHfA= diff --git a/nuget.config b/nuget.config deleted file mode 100644 index 31435a21..00000000 --- a/nuget.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/.editorconfig b/src/.editorconfig new file mode 100644 index 00000000..1d72e683 --- /dev/null +++ b/src/.editorconfig @@ -0,0 +1,37 @@ +# 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. +# +# Do NOT modify this file. Update the canonical version in Home\repo-template\src\.editorconfig +# then update all of the repos. + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.{cs,vb}] +dotnet_sort_system_directives_first = true + +[*.cs] +csharp_indent_case_contents = true : error +csharp_indent_switch_labels = true : error +csharp_new_line_before_open_brace = all +csharp_prefer_braces = true : error +csharp_style_expression_bodied_methods = when_on_single_line : suggestion +csharp_style_expression_bodied_constructors = when_on_single_line : suggestion +csharp_style_expression_bodied_operators = when_on_single_line : suggestion +csharp_style_expression_bodied_properties = when_on_single_line : suggestion +csharp_style_expression_bodied_indexers = when_on_single_line : suggestion +csharp_style_expression_bodied_accessors = when_on_single_line : suggestion +csharp_style_var_elsewhere = true : suggestion +csharp_style_var_for_built_in_types = true : suggestion +csharp_style_var_when_type_is_apparent = true : suggestion +dotnet_style_qualification_for_event = true : error +dotnet_style_qualification_for_field = true : error +dotnet_style_qualification_for_method = true : error +dotnet_style_qualification_for_property = true : error + +[*.targets] +indent_size = 2 diff --git a/src/Directory.Build.props b/src/Directory.Build.props deleted file mode 100644 index b3c6287c..00000000 --- a/src/Directory.Build.props +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - Debug - false - MSB3246 - - $(MSBuildProjectName) - $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\)) - $(BaseOutputPath)obj\$(ProjectName)\ - $(BaseOutputPath)$(Configuration)\ - - WiX Toolset Team - WiX Toolset - Copyright (c) .NET Foundation and contributors. All rights reserved. - MS-RL - WiX Toolset - - - - - diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets deleted file mode 100644 index 2fcc765a..00000000 --- a/src/Directory.Build.targets +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - true - $(SolutionPath) - $(NCrunchOriginalSolutionPath) - - - - - - - $([System.IO.File]::ReadAllText($(TheSolutionPath))) - $([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) )) - (?<="[PackageName]", ")(.*)(?=", ") - - - - - - %(Identity) - $(SolutionFileContent.Contains('\%(Identity).csproj')) - - - - - $(RegexPattern.Replace('[PackageName]','%(PackageName)') ) - $([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)')) - - - - - - - - - - - - - - diff --git a/src/Directory.csproj.props b/src/Directory.csproj.props deleted file mode 100644 index 81d24ad1..00000000 --- a/src/Directory.csproj.props +++ /dev/null @@ -1,13 +0,0 @@ - - - - - true - true - $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk)) - false - - diff --git a/src/Directory.csproj.targets b/src/Directory.csproj.targets deleted file mode 100644 index c3270426..00000000 --- a/src/Directory.csproj.targets +++ /dev/null @@ -1,26 +0,0 @@ - - - - - false - $(OutputPath)\$(AssemblyName).xml - - - - - $(PrivateRepositoryUrl.Replace('.git','')) - - $(MSBuildProjectName).nuspec - $(OutputPath)..\ - $(NuspecProperties);Id=$(PackageId);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description);Title=$(Title) - $(NuspecProperties);Version=$(PackageVersion);RepositoryCommit=$(SourceRevisionId);RepositoryType=$(RepositoryType);RepositoryUrl=$(PrivateRepositoryUrl);ProjectFolder=$(MSBuildProjectDirectory)\;ProjectUrl=$(ProjectUrl) - true - snupkg - - - - diff --git a/src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs b/src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs deleted file mode 100644 index 6418b2a6..00000000 --- a/src/WixToolset.Converters.Symbolizer/ConvertSymbols.cs +++ /dev/null @@ -1,876 +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; - -#pragma warning disable 1591 // TODO: add documentation - 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) -#pragma warning restore 1591 - { - var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type)); - - 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.AddSymbol(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.Global, 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.Global, 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.Global, 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": - { - var splitName = FieldAsString(row, 3)?.Split('|'); - - var symbol = new DuplicateFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) - { - ComponentRef = FieldAsString(row, 1), - FileRef = FieldAsString(row, 2), - DestinationName = splitName == null ? null : splitName.Length > 1 ? splitName[1] : splitName[0], - DestinationShortName = splitName == null ? null : splitName.Length > 1 ? splitName[0] : null, - DestinationFolder = FieldAsString(row, 4) - }; - - return symbol; - } - 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.Global, 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 splitName = FieldAsString(row, 2).Split('|'); - - var symbol = new FileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, id)) - { - ComponentRef = FieldAsString(row, 1), - Name = splitName.Length > 1 ? splitName[1] : splitName[0], - ShortName = splitName.Length > 1 ? splitName[0] : null, - 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.PatchAttributes = (PatchAttributeType)FieldAsInt(wixFileRow, 10); - } - - return symbol; - } - case "Font": - return null; - case "Icon": - return DefaultSymbolFromRow(typeof(IconSymbol), row, columnZeroIsId: true); - case "IniFile": - { - var splitName = FieldAsString(row, 1).Split('|'); - var action = FieldAsInt(row, 6); - - var symbol = new IniFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) - { - FileName = splitName.Length > 1 ? splitName[1] : splitName[0], - ShortFileName = splitName.Length > 1 ? splitName[0] : null, - DirProperty = FieldAsString(row, 2), - Section = FieldAsString(row, 3), - Key = FieldAsString(row, 4), - Value = FieldAsString(row, 5), - Action = action == 3 ? IniFileActionType.AddTag : action == 1 ? IniFileActionType.CreateLine : IniFileActionType.AddLine, - ComponentRef = FieldAsString(row, 7), - }; - - return symbol; - } - case "IniLocator": - { - var splitName = FieldAsString(row, 1).Split('|'); - - var symbol = new IniLocatorSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) - { - FileName = splitName.Length > 1 ? splitName[1] : splitName[0], - ShortFileName = splitName.Length > 1 ? splitName[0] : null, - Section = FieldAsString(row, 2), - Key = FieldAsString(row, 3), - Field = FieldAsInt(row, 4), - Type = FieldAsInt(row, 5), - }; - - return symbol; - } - 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.Global, 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.Global, 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.Global, 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.Global, 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 splitName = FieldAsString(row, 2).Split('|'); - var installMode = FieldAsInt(row, 4); - - return new RemoveFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) - { - ComponentRef = FieldAsString(row, 1), - FileName = splitName.Length > 1 ? splitName[1] : splitName[0], - ShortFileName = splitName.Length > 1 ? splitName[0] : null, - DirPropertyRef = 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.Global, 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.Global, 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.Global, 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.Global, 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 new WixSuppressModularizationSymbol(SourceLineNumber4(row.SourceLineNumbers)) - { - SuppressIdentifier = FieldAsString(row, 0) - }; - } - 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 id = columnZeroIsId ? GetIdentifierForRow(row) : null; - - var createSymbol = symbolType.GetConstructor(new[] { typeof(SourceLineNumber), typeof(Identifier) }); - var symbol = (IntermediateSymbol)createSymbol.Invoke(new object[] { SourceLineNumber4(row.SourceLineNumbers), id }); - - SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); - - 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 id = columnZeroIsId ? GetIdentifierForRow(row) : null; - - var createSymbol = typeof(IntermediateSymbol).GetConstructor(new[] { typeof(IntermediateSymbolDefinition), typeof(SourceLineNumber), typeof(Identifier) }); - var symbol = (IntermediateSymbol)createSymbol.Invoke(new object[] { symbolDefinition, SourceLineNumber4(row.SourceLineNumbers), id }); - - SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); - - return symbol; - } - - private static void SetSymbolFieldsFromRow(Wix3.Row row, IntermediateSymbol symbol, bool columnZeroIsId) - { - var offset = 0; - if (columnZeroIsId) - { - 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.Global, (string)row.Fields[0].Data); - case Wix3.ColumnType.Number: - return new Identifier(AccessModifier.Global, 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/WixToolset.Converters.Symbolizer.csproj b/src/WixToolset.Converters.Symbolizer/WixToolset.Converters.Symbolizer.csproj deleted file mode 100644 index 445c3500..00000000 --- a/src/WixToolset.Converters.Symbolizer/WixToolset.Converters.Symbolizer.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - netstandard2.0 - $(TargetFrameworks);net461;net472 - Symbolizer - WiX Toolset Converters Tuplizer - embedded - true - true - - - - - - - - - - - - - - - - - - - diff --git a/src/WixToolset.Converters/ConvertCommand.cs b/src/WixToolset.Converters/ConvertCommand.cs deleted file mode 100644 index b6826f43..00000000 --- a/src/WixToolset.Converters/ConvertCommand.cs +++ /dev/null @@ -1,60 +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 -{ - using System; - using System.Threading; - using System.Threading.Tasks; - using WixToolset.Extensibility.Services; - - internal class ConvertCommand : FixupCommandBase - { - private const string SettingsFileDefault = "wix.convert.settings.xml"; - - public ConvertCommand(IServiceProvider serviceProvider) - { - this.Messaging = serviceProvider.GetService(); - } - - private IMessaging Messaging { get; } - - public override Task ExecuteAsync(CancellationToken cancellationToken) - { - if (this.ShowHelp) - { - DisplayHelp(); - return Task.FromResult(-1); - } - - this.ParseSettings(SettingsFileDefault); - - var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); - - var errors = base.Inspect(Inspector, cancellationToken); - - return Task.FromResult(errors); - - int Inspector(string file, bool fix) - { - return converter.ConvertFile(file, fix); - } - } - - private static void DisplayHelp() - { - Console.WriteLine(); - Console.WriteLine("Usage: wix convert [options] sourceFile [sourceFile ...]"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" --nologo Suppress displaying the logo information."); - Console.WriteLine(" -n|--dry-run Only display errors, do not update files."); - Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs."); - Console.WriteLine(" -set1 Primary settings file."); - Console.WriteLine(" -set2 Secondary settings file (overrides primary)."); - Console.WriteLine(" -indent: Indentation multiple (overrides default of 4)."); - Console.WriteLine(); - Console.WriteLine(" sourceFile may use wildcards like *.wxs"); - } - } -} diff --git a/src/WixToolset.Converters/ConverterExtensionCommandLine.cs b/src/WixToolset.Converters/ConverterExtensionCommandLine.cs deleted file mode 100644 index 06d3658c..00000000 --- a/src/WixToolset.Converters/ConverterExtensionCommandLine.cs +++ /dev/null @@ -1,46 +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 -{ - using System; - using System.Collections.Generic; - using WixToolset.Extensibility; - using WixToolset.Extensibility.Data; - using WixToolset.Extensibility.Services; - - /// - /// Parses the "convert" command-line command. See ConvertCommand for - /// the bulk of the command-line processing. - /// - internal class ConverterExtensionCommandLine : BaseExtensionCommandLine - { - public ConverterExtensionCommandLine(IServiceProvider serviceProvider) - { - this.ServiceProvider = serviceProvider; - } - - private IServiceProvider ServiceProvider { get; } - - public override IReadOnlyCollection CommandLineSwitches => new ExtensionCommandLineSwitch[] - { - new ExtensionCommandLineSwitch { Switch = "convert", Description = "Convert v3 source code to v4 source code." }, - new ExtensionCommandLineSwitch { Switch = "format", Description = "Ensures consistent formatting of source code." }, - }; - - public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command) - { - command = null; - - if ("convert".Equals(argument, StringComparison.OrdinalIgnoreCase)) - { - command = new ConvertCommand(this.ServiceProvider); - } - else if ("format".Equals(argument, StringComparison.OrdinalIgnoreCase)) - { - command = new FormatCommand(this.ServiceProvider); - } - - return command != null; - } - } -} diff --git a/src/WixToolset.Converters/ConverterExtensionFactory.cs b/src/WixToolset.Converters/ConverterExtensionFactory.cs deleted file mode 100644 index d4f480aa..00000000 --- a/src/WixToolset.Converters/ConverterExtensionFactory.cs +++ /dev/null @@ -1,30 +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 -{ - using System; - using WixToolset.Extensibility; - using WixToolset.Extensibility.Services; - - internal class ConverterExtensionFactory : IExtensionFactory - { - public ConverterExtensionFactory(IServiceProvider serviceProvider) - { - this.ServiceProvider = serviceProvider; - } - - private IServiceProvider ServiceProvider { get; } - - public bool TryCreateExtension(Type extensionType, out object extension) - { - extension = null; - - if (extensionType == typeof(IExtensionCommandLine)) - { - extension = new ConverterExtensionCommandLine(this.ServiceProvider); - } - - return extension != null; - } - } -} diff --git a/src/WixToolset.Converters/FixupCommandBase.cs b/src/WixToolset.Converters/FixupCommandBase.cs deleted file mode 100644 index 21282d07..00000000 --- a/src/WixToolset.Converters/FixupCommandBase.cs +++ /dev/null @@ -1,288 +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 -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Threading; - using System.Threading.Tasks; - using System.Xml; - using WixToolset.Extensibility.Data; - using WixToolset.Extensibility.Services; - - internal abstract class FixupCommandBase : ICommandLineCommand - { - protected FixupCommandBase() - { - this.IndentationAmount = 4; // default indentation amount - this.ErrorsAsWarnings = new HashSet(); - this.ExemptFiles = new HashSet(); - this.IgnoreErrors = new HashSet(); - this.SearchPatternResults = new HashSet(); - this.SearchPatterns = new List(); - } - - public bool ShowLogo { get; private set; } - - public bool StopParsing { get; private set; } - - protected bool ShowHelp { get; set; } - - protected CustomTableTarget CustomTableSetting { get; set; } - - protected bool DryRun { get; set; } - - protected HashSet ErrorsAsWarnings { get; } - - protected HashSet IgnoreErrors { get; } - - protected HashSet ExemptFiles { get; } - - protected int IndentationAmount { get; set; } - - protected bool Recurse { get; set; } - - private HashSet SearchPatternResults { get; } - - private List SearchPatterns { get; } - - private string SettingsFile1 { get; set; } - - private string SettingsFile2 { get; set; } - - public bool TryParseArgument(ICommandLineParser parser, string argument) - { - if (!parser.IsSwitch(argument)) - { - this.SearchPatterns.Add(argument); - return true; - } - - var parameter = argument.Substring(1); - switch (parameter.ToLowerInvariant()) - { - case "?": - case "h": - case "-help": - this.ShowHelp = true; - this.ShowLogo = true; - this.StopParsing = true; - return true; - - case "-custom-table": - var customTableSetting = parser.GetNextArgumentOrError(argument); - switch (customTableSetting) - { - case "bundle": - this.CustomTableSetting = CustomTableTarget.Bundle; - break; - case "msi": - this.CustomTableSetting = CustomTableTarget.Msi; - break; - default: - parser.ReportErrorArgument(argument); - break; - } - return true; - - case "n": - case "-dry-run": - this.DryRun = true; - return true; - - case "nologo": - case "-nologo": - this.ShowLogo = false; - return true; - - case "s": - case "r": - case "-recurse": - case "-recursive": - this.Recurse = true; - return true; - - default: // other parameters - if (parameter.StartsWith("set1", StringComparison.Ordinal)) - { - this.SettingsFile1 = parameter.Substring(4); - return true; - } - else if (parameter.StartsWith("set2", StringComparison.Ordinal)) - { - this.SettingsFile2 = parameter.Substring(4); - return true; - } - else if (parameter.StartsWith("indent:", StringComparison.Ordinal)) - { - try - { - this.IndentationAmount = Convert.ToInt32(parameter.Substring(7)); - } - catch - { - parser.ReportErrorArgument(parameter); // $"Invalid numeric argument: {parameter}"; - } - return true; - } - - return false; - } - } - - public abstract Task ExecuteAsync(CancellationToken cancellationToken); - - protected void ParseSettings(string defaultSettingsFile) - { - // parse the settings if any were specified - if (null != this.SettingsFile1 || null != this.SettingsFile2) - { - this.ParseSettingsFiles(this.SettingsFile1, this.SettingsFile2); - } - else - { - if (File.Exists(defaultSettingsFile)) - { - this.ParseSettingsFiles(defaultSettingsFile, null); - } - } - } - - protected int Inspect(Func inspector, CancellationToken cancellationToken) - { - var errors = this.InspectSubDirectories(inspector, Path.GetFullPath("."), cancellationToken); - - foreach (var searchPattern in this.SearchPatterns) - { - if (!this.SearchPatternResults.Contains(searchPattern)) - { - Console.Error.WriteLine("Could not find file \"{0}\"", searchPattern); - errors++; - } - } - - return errors; - } - - /// - /// Inspect sub-directories. - /// - /// - /// The directory whose sub-directories will be inspected. - /// - /// The number of errors that were found. - private int InspectSubDirectories(Func inspector, string directory, CancellationToken cancellationToken) - { - var errors = 0; - - foreach (var searchPattern in this.SearchPatterns) - { - foreach (var sourceFilePath in GetFiles(directory, searchPattern)) - { - cancellationToken.ThrowIfCancellationRequested(); - - var file = new FileInfo(sourceFilePath); - - if (!this.ExemptFiles.Contains(file.Name.ToUpperInvariant())) - { - this.SearchPatternResults.Add(searchPattern); - errors += inspector(file.FullName, !this.DryRun); - } - } - } - - if (this.Recurse) - { - foreach (var childDirectoryPath in Directory.GetDirectories(directory)) - { - errors += this.InspectSubDirectories(inspector, childDirectoryPath, cancellationToken); - } - } - - return errors; - } - - /// - /// Parse the primary and secondary settings files. - /// - /// The primary settings file. - /// The secondary settings file. - private void ParseSettingsFiles(string localSettingsFile1, string localSettingsFile2) - { - if (null == localSettingsFile1 && null != localSettingsFile2) - { - throw new ArgumentException("Cannot specify a secondary settings file (set2) without a primary settings file (set1).", nameof(localSettingsFile2)); - } - - var settingsFile = localSettingsFile1; - while (null != settingsFile) - { - var doc = new XmlDocument(); - doc.Load(settingsFile); - - // get the types of tests that will have their errors displayed as warnings - var testsIgnoredElements = doc.SelectNodes("/Settings/IgnoreErrors/Test"); - foreach (XmlElement test in testsIgnoredElements) - { - var key = test.GetAttribute("Id"); - this.IgnoreErrors.Add(key); - } - - // get the types of tests that will have their errors displayed as warnings - var testsAsWarningsElements = doc.SelectNodes("/Settings/ErrorsAsWarnings/Test"); - foreach (XmlElement test in testsAsWarningsElements) - { - var key = test.GetAttribute("Id"); - this.ErrorsAsWarnings.Add(key); - } - - // get the exempt files - var localExemptFiles = doc.SelectNodes("/Settings/ExemptFiles/File"); - foreach (XmlElement file in localExemptFiles) - { - var key = file.GetAttribute("Name").ToUpperInvariant(); - this.ExemptFiles.Add(key); - } - - settingsFile = localSettingsFile2; - localSettingsFile2 = null; - } - } - - /// - /// Get the files that match a search path pattern. - /// - /// The base directory at which to begin the search. - /// The search path pattern. - /// The files matching the pattern. - private static string[] GetFiles(string baseDir, string searchPath) - { - // convert alternate directory separators to the standard one - var filePath = searchPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); - var lastSeparator = filePath.LastIndexOf(Path.DirectorySeparatorChar); - string[] files = null; - - try - { - if (0 > lastSeparator) - { - files = Directory.GetFiles(baseDir, filePath); - } - else // found directory separator - { - var searchPattern = filePath.Substring(lastSeparator + 1); - - files = Directory.GetFiles(filePath.Substring(0, lastSeparator + 1), searchPattern); - } - } - catch (DirectoryNotFoundException) - { - // don't let this function throw the DirectoryNotFoundException. (this exception - // occurs for non-existant directories and invalid characters in the searchPattern) - } - - return files; - } - } -} diff --git a/src/WixToolset.Converters/FormatCommand.cs b/src/WixToolset.Converters/FormatCommand.cs deleted file mode 100644 index 0861fc51..00000000 --- a/src/WixToolset.Converters/FormatCommand.cs +++ /dev/null @@ -1,60 +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 -{ - using System; - using System.Threading; - using System.Threading.Tasks; - using WixToolset.Extensibility.Services; - - internal class FormatCommand : FixupCommandBase - { - private const string SettingsFileDefault = "wix.format.settings.xml"; - - public FormatCommand(IServiceProvider serviceProvider) - { - this.Messaging = serviceProvider.GetService(); - } - - private IMessaging Messaging { get; } - - public override Task ExecuteAsync(CancellationToken cancellationToken) - { - if (this.ShowHelp) - { - DisplayHelp(); - return Task.FromResult(-1); - } - - var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); - - this.ParseSettings(SettingsFileDefault); - - var errors = base.Inspect(Inspector, cancellationToken); - - return Task.FromResult(errors); - - int Inspector(string file, bool fix) - { - return converter.FormatFile(file, fix); - } - } - - private static void DisplayHelp() - { - Console.WriteLine(); - Console.WriteLine("Usage: wix format [options] sourceFile [sourceFile ...]"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" --nologo Suppress displaying the logo information."); - Console.WriteLine(" -n|--dry-run Only display errors, do not update files."); - Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs."); - Console.WriteLine(" -set1 Primary settings file."); - Console.WriteLine(" -set2 Secondary settings file (overrides primary)."); - Console.WriteLine(" -indent: Indentation multiple (overrides default of 4)."); - Console.WriteLine(); - Console.WriteLine(" sourceFile may use wildcards like *.wxs"); - } - } -} diff --git a/src/WixToolset.Converters/WixConverter.cs b/src/WixToolset.Converters/WixConverter.cs deleted file mode 100644 index e42d0605..00000000 --- a/src/WixToolset.Converters/WixConverter.cs +++ /dev/null @@ -1,2435 +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 -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Text; - using System.Text.RegularExpressions; - using System.Xml; - using System.Xml.Linq; - using WixToolset.Data; - using WixToolset.Data.WindowsInstaller; - using WixToolset.Extensibility.Services; - - /// - /// How to convert CustomTable elements. - /// - public enum CustomTableTarget - { - /// - /// Ambiguous elements will be left alone. - /// - Unknown, - - /// - /// Use CustomTable, CustomTableRef, and Unreal. - /// - Msi, - - /// - /// Use BundleCustomData and BundleCustomDataRef. - /// - Bundle, - } - - /// - /// WiX source code converter. - /// - public sealed class WixConverter - { - private enum ConvertOperation - { - Convert, - Format, - } - - private static readonly Regex AddPrefix = new Regex(@"^[^a-zA-Z_]", RegexOptions.Compiled); - private static readonly Regex IllegalIdentifierCharacters = new Regex(@"[^A-Za-z0-9_\.]|\.{2,}", RegexOptions.Compiled); // non 'words' and assorted valid characters - - private const char XDocumentNewLine = '\n'; // XDocument normalizes "\r\n" to just "\n". - private static readonly XNamespace WixNamespace = "http://wixtoolset.org/schemas/v4/wxs"; - private static readonly XNamespace Wix3Namespace = "http://schemas.microsoft.com/wix/2006/wi"; - private static readonly XNamespace WixBalNamespace = "http://wixtoolset.org/schemas/v4/wxs/bal"; - private static readonly XNamespace WixDependencyNamespace = "http://wixtoolset.org/schemas/v4/wxs/dependency"; - private static readonly XNamespace WixUtilNamespace = "http://wixtoolset.org/schemas/v4/wxs/util"; - private static readonly XNamespace WixFirewallNamespace = "http://wixtoolset.org/schemas/v4/wxs/firewall"; - - private static readonly XName AdminExecuteSequenceElementName = WixNamespace + "AdminExecuteSequence"; - private static readonly XName AdminUISequenceSequenceElementName = WixNamespace + "AdminUISequence"; - private static readonly XName AdvertiseExecuteSequenceElementName = WixNamespace + "AdvertiseExecuteSequence"; - private static readonly XName InstallExecuteSequenceElementName = WixNamespace + "InstallExecuteSequence"; - private static readonly XName InstallUISequenceSequenceElementName = WixNamespace + "InstallUISequence"; - private static readonly XName BootstrapperApplicationElementName = WixNamespace + "BootstrapperApplication"; - private static readonly XName BootstrapperApplicationDllElementName = WixNamespace + "BootstrapperApplicationDll"; - private static readonly XName BootstrapperApplicationRefElementName = WixNamespace + "BootstrapperApplicationRef"; - private static readonly XName ApprovedExeForElevationElementName = WixNamespace + "ApprovedExeForElevation"; - private static readonly XName BundleAttributeElementName = WixNamespace + "BundleAttribute"; - private static readonly XName BundleAttributeDefinitionElementName = WixNamespace + "BundleAttributeDefinition"; - private static readonly XName BundleCustomDataElementName = WixNamespace + "BundleCustomData"; - private static readonly XName BundleCustomDataRefElementName = WixNamespace + "BundleCustomDataRef"; - private static readonly XName BundleElementElementName = WixNamespace + "BundleElement"; - private static readonly XName CustomTableElementName = WixNamespace + "CustomTable"; - private static readonly XName CustomTableRefElementName = WixNamespace + "CustomTableRef"; - private static readonly XName CatalogElementName = WixNamespace + "Catalog"; - private static readonly XName ColumnElementName = WixNamespace + "Column"; - private static readonly XName ComponentElementName = WixNamespace + "Component"; - private static readonly XName ControlElementName = WixNamespace + "Control"; - private static readonly XName ConditionElementName = WixNamespace + "Condition"; - private static readonly XName CreateFolderElementName = WixNamespace + "CreateFolder"; - private static readonly XName DataElementName = WixNamespace + "Data"; - private static readonly XName OldProvidesElementName = WixDependencyNamespace + "Provides"; - private static readonly XName OldRequiresElementName = WixDependencyNamespace + "Requires"; - private static readonly XName OldRequiresRefElementName = WixDependencyNamespace + "RequiresRef"; - private static readonly XName DirectoryElementName = WixNamespace + "Directory"; - private static readonly XName EmbeddedChainerElementName = WixNamespace + "EmbeddedChainer"; - private static readonly XName ErrorElementName = WixNamespace + "Error"; - private static readonly XName FeatureElementName = WixNamespace + "Feature"; - private static readonly XName FileElementName = WixNamespace + "File"; - private static readonly XName FragmentElementName = WixNamespace + "Fragment"; - private static readonly XName FirewallRemoteAddressElementName = WixFirewallNamespace + "RemoteAddress"; - private static readonly XName LaunchElementName = WixNamespace + "Launch"; - private static readonly XName LevelElementName = WixNamespace + "Level"; - private static readonly XName ExePackageElementName = WixNamespace + "ExePackage"; - private static readonly XName ExePackagePayloadElementName = WixNamespace + "ExePackagePayload"; - private static readonly XName ModuleElementName = WixNamespace + "Module"; - private static readonly XName MsiPackageElementName = WixNamespace + "MsiPackage"; - private static readonly XName MspPackageElementName = WixNamespace + "MspPackage"; - private static readonly XName MsuPackageElementName = WixNamespace + "MsuPackage"; - private static readonly XName MsuPackagePayloadElementName = WixNamespace + "MsuPackagePayload"; - private static readonly XName PackageElementName = WixNamespace + "Package"; - private static readonly XName PayloadElementName = WixNamespace + "Payload"; - private static readonly XName PermissionExElementName = WixNamespace + "PermissionEx"; - private static readonly XName ProductElementName = WixNamespace + "Product"; - private static readonly XName ProgressTextElementName = WixNamespace + "ProgressText"; - private static readonly XName PropertyRefElementName = WixNamespace + "PropertyRef"; - private static readonly XName PublishElementName = WixNamespace + "Publish"; - private static readonly XName ProvidesElementName = WixNamespace + "Provides"; - private static readonly XName RequiresElementName = WixNamespace + "Requires"; - private static readonly XName RequiresRefElementName = WixNamespace + "RequiresRef"; - private static readonly XName MultiStringValueElementName = WixNamespace + "MultiStringValue"; - private static readonly XName RemotePayloadElementName = WixNamespace + "RemotePayload"; - private static readonly XName RegistryKeyElementName = WixNamespace + "RegistryKey"; - private static readonly XName RegistrySearchElementName = WixNamespace + "RegistrySearch"; - private static readonly XName RequiredPrivilegeElementName = WixNamespace + "RequiredPrivilege"; - private static readonly XName RowElementName = WixNamespace + "Row"; - private static readonly XName ServiceArgumentElementName = WixNamespace + "ServiceArgument"; - private static readonly XName SetDirectoryElementName = WixNamespace + "SetDirectory"; - private static readonly XName SetPropertyElementName = WixNamespace + "SetProperty"; - private static readonly XName ShortcutPropertyElementName = WixNamespace + "ShortcutProperty"; - private static readonly XName SoftwareTagElementName = WixNamespace + "SoftwareTag"; - private static readonly XName SoftwareTagRefElementName = WixNamespace + "SoftwareTagRef"; - private static readonly XName StandardDirectoryElementName = WixNamespace + "StandardDirectory"; - private static readonly XName TagElementName = XNamespace.None + "Tag"; - private static readonly XName TagRefElementName = XNamespace.None + "TagRef"; - private static readonly XName TextElementName = WixNamespace + "Text"; - private static readonly XName UITextElementName = WixNamespace + "UIText"; - private static readonly XName VariableElementName = WixNamespace + "Variable"; - private static readonly XName VerbElementName = WixNamespace + "Verb"; - private static readonly XName BalUseUILanguagesName = WixBalNamespace + "UseUILanguages"; - private static readonly XName BalStandardBootstrapperApplicationName = WixBalNamespace + "WixStandardBootstrapperApplication"; - private static readonly XName BalManagedBootstrapperApplicationHostName = WixBalNamespace + "WixManagedBootstrapperApplicationHost"; - private static readonly XName BalOldDotNetCoreBootstrapperApplicationName = WixBalNamespace + "WixDotNetCoreBootstrapperApplication"; - private static readonly XName BalNewDotNetCoreBootstrapperApplicationName = WixBalNamespace + "WixDotNetCoreBootstrapperApplicationHost"; - private static readonly XName UtilCloseApplicationElementName = WixUtilNamespace + "CloseApplication"; - private static readonly XName UtilPermissionExElementName = WixUtilNamespace + "PermissionEx"; - private static readonly XName UtilRegistrySearchName = WixUtilNamespace + "RegistrySearch"; - private static readonly XName UtilXmlConfigElementName = WixUtilNamespace + "XmlConfig"; - private static readonly XName CustomActionElementName = WixNamespace + "CustomAction"; - private static readonly XName CustomActionRefElementName = WixNamespace + "CustomActionRef"; - private static readonly XName PropertyElementName = WixNamespace + "Property"; - private static readonly XName Wix4ElementName = WixNamespace + "Wix"; - private static readonly XName Wix3ElementName = Wix3Namespace + "Wix"; - private static readonly XName WixElementWithoutNamespaceName = XNamespace.None + "Wix"; - private static readonly XName Include4ElementName = WixNamespace + "Include"; - private static readonly XName Include3ElementName = Wix3Namespace + "Include"; - private static readonly XName IncludeElementWithoutNamespaceName = XNamespace.None + "Include"; - private static readonly XName SummaryInformationElementName = WixNamespace + "SummaryInformation"; - private static readonly XName MediaTemplateElementName = WixNamespace + "MediaTemplate"; - - private static readonly XName DependencyCheckAttributeName = WixDependencyNamespace + "Check"; - private static readonly XName DependencyEnforceAttributeName = WixDependencyNamespace + "Enforce"; - - private static readonly Dictionary OldToNewNamespaceMapping = new Dictionary() - { - { "http://schemas.microsoft.com/wix/BalExtension", "http://wixtoolset.org/schemas/v4/wxs/bal" }, - { "http://schemas.microsoft.com/wix/ComPlusExtension", "http://wixtoolset.org/schemas/v4/wxs/complus" }, - { "http://schemas.microsoft.com/wix/DependencyExtension", WixDependencyNamespace }, - { "http://schemas.microsoft.com/wix/DifxAppExtension", "http://wixtoolset.org/schemas/v4/wxs/difxapp" }, - { "http://schemas.microsoft.com/wix/FirewallExtension", "http://wixtoolset.org/schemas/v4/wxs/firewall" }, - { "http://schemas.microsoft.com/wix/HttpExtension", "http://wixtoolset.org/schemas/v4/wxs/http" }, - { "http://schemas.microsoft.com/wix/IIsExtension", "http://wixtoolset.org/schemas/v4/wxs/iis" }, - { "http://schemas.microsoft.com/wix/MsmqExtension", "http://wixtoolset.org/schemas/v4/wxs/msmq" }, - { "http://schemas.microsoft.com/wix/NetFxExtension", "http://wixtoolset.org/schemas/v4/wxs/netfx" }, - { "http://schemas.microsoft.com/wix/PSExtension", "http://wixtoolset.org/schemas/v4/wxs/powershell" }, - { "http://schemas.microsoft.com/wix/SqlExtension", "http://wixtoolset.org/schemas/v4/wxs/sql" }, - { "http://schemas.microsoft.com/wix/TagExtension", XNamespace.None }, - { "http://schemas.microsoft.com/wix/UtilExtension", WixUtilNamespace }, - { "http://schemas.microsoft.com/wix/VSExtension", "http://wixtoolset.org/schemas/v4/wxs/vs" }, - { "http://wixtoolset.org/schemas/thmutil/2010", "http://wixtoolset.org/schemas/v4/thmutil" }, - { "http://schemas.microsoft.com/wix/2009/Lux", "http://wixtoolset.org/schemas/v4/lux" }, - { "http://schemas.microsoft.com/wix/2006/wi", "http://wixtoolset.org/schemas/v4/wxs" }, - { "http://schemas.microsoft.com/wix/2006/localization", "http://wixtoolset.org/schemas/v4/wxl" }, - { "http://schemas.microsoft.com/wix/2006/libraries", "http://wixtoolset.org/schemas/v4/wixlib" }, - { "http://schemas.microsoft.com/wix/2006/objects", "http://wixtoolset.org/schemas/v4/wixobj" }, - { "http://schemas.microsoft.com/wix/2006/outputs", "http://wixtoolset.org/schemas/v4/wixout" }, - { "http://schemas.microsoft.com/wix/2007/pdbs", "http://wixtoolset.org/schemas/v4/wixpdb" }, - { "http://schemas.microsoft.com/wix/2003/04/actions", "http://wixtoolset.org/schemas/v4/wi/actions" }, - { "http://schemas.microsoft.com/wix/2006/tables", "http://wixtoolset.org/schemas/v4/wi/tables" }, - { "http://schemas.microsoft.com/wix/2006/WixUnit", "http://wixtoolset.org/schemas/v4/wixunit" }, - }; - - private readonly Dictionary> ConvertElementMapping; - private readonly Regex DeprecatedPrefixRegex = new Regex(@"(?<=(^|[^\$])(\$\$)*)\$(?=\(loc\.[^.].*\))", - RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture); - - /// - /// Instantiate a new Converter class. - /// - /// - /// Indentation value to use when validating leading whitespace. - /// Test errors to display as warnings. - /// Test errors to ignore. - /// How to convert CustomTable elements. - public WixConverter(IMessaging messaging, int indentationAmount, IEnumerable errorsAsWarnings = null, IEnumerable ignoreErrors = null, CustomTableTarget customTableTarget = CustomTableTarget.Unknown) - { - this.ConvertElementMapping = new Dictionary> - { - { WixConverter.AdminExecuteSequenceElementName, this.ConvertSequenceElement }, - { WixConverter.AdminUISequenceSequenceElementName, this.ConvertSequenceElement }, - { WixConverter.AdvertiseExecuteSequenceElementName, this.ConvertSequenceElement }, - { WixConverter.InstallUISequenceSequenceElementName, this.ConvertSequenceElement }, - { WixConverter.InstallExecuteSequenceElementName, this.ConvertSequenceElement }, - { WixConverter.BootstrapperApplicationElementName, this.ConvertBootstrapperApplicationElement }, - { WixConverter.BootstrapperApplicationRefElementName, this.ConvertBootstrapperApplicationRefElement }, - { WixConverter.ApprovedExeForElevationElementName, this.ConvertApprovedExeForElevationElement }, - { WixConverter.CatalogElementName, this.ConvertCatalogElement }, - { WixConverter.ColumnElementName, this.ConvertColumnElement }, - { WixConverter.ComponentElementName, this.ConvertComponentElement }, - { WixConverter.ControlElementName, this.ConvertControlElement }, - { WixConverter.CustomActionElementName, this.ConvertCustomActionElement }, - { WixConverter.CustomTableElementName, this.ConvertCustomTableElement }, - { WixConverter.DataElementName, this.ConvertDataElement }, - { WixConverter.DirectoryElementName, this.ConvertDirectoryElement }, - { WixConverter.FeatureElementName, this.ConvertFeatureElement }, - { WixConverter.FileElementName, this.ConvertFileElement }, - { WixConverter.FragmentElementName, this.ConvertFragmentElement }, - { WixConverter.FirewallRemoteAddressElementName, this.ConvertFirewallRemoteAddressElement }, - { WixConverter.EmbeddedChainerElementName, this.ConvertEmbeddedChainerElement }, - { WixConverter.ErrorElementName, this.ConvertErrorElement }, - { WixConverter.ExePackageElementName, this.ConvertExePackageElement }, - { WixConverter.ModuleElementName, this.ConvertModuleElement }, - { WixConverter.MsiPackageElementName, this.ConvertWindowsInstallerPackageElement }, - { WixConverter.MspPackageElementName, this.ConvertWindowsInstallerPackageElement }, - { WixConverter.MsuPackageElementName, this.ConvertSuppressSignatureValidation }, - { WixConverter.OldProvidesElementName, this.ConvertProvidesElement }, - { WixConverter.OldRequiresElementName, this.ConvertRequiresElement }, - { WixConverter.OldRequiresRefElementName, this.ConvertRequiresRefElement }, - { WixConverter.PayloadElementName, this.ConvertSuppressSignatureValidation }, - { WixConverter.PermissionExElementName, this.ConvertPermissionExElement }, - { WixConverter.ProductElementName, this.ConvertProductElement }, - { WixConverter.ProgressTextElementName, this.ConvertProgressTextElement }, - { WixConverter.PropertyRefElementName, this.ConvertPropertyRefElement }, - { WixConverter.PublishElementName, this.ConvertPublishElement }, - { WixConverter.MultiStringValueElementName, this.ConvertMultiStringValueElement }, - { WixConverter.RegistryKeyElementName, this.ConvertRegistryKeyElement }, - { WixConverter.RegistrySearchElementName, this.ConvertRegistrySearchElement }, - { WixConverter.RemotePayloadElementName, this.ConvertRemotePayloadElement }, - { WixConverter.RequiredPrivilegeElementName, this.ConvertRequiredPrivilegeElement }, - { WixConverter.CustomActionRefElementName, this.ConvertCustomActionRefElement }, - { WixConverter.ServiceArgumentElementName, this.ConvertServiceArgumentElement }, - { WixConverter.SetDirectoryElementName, this.ConvertSetDirectoryElement }, - { WixConverter.SetPropertyElementName, this.ConvertSetPropertyElement }, - { WixConverter.ShortcutPropertyElementName, this.ConvertShortcutPropertyElement }, - { WixConverter.TagElementName, this.ConvertTagElement }, - { WixConverter.TagRefElementName, this.ConvertTagRefElement }, - { WixConverter.TextElementName, this.ConvertTextElement }, - { WixConverter.UITextElementName, this.ConvertUITextElement }, - { WixConverter.VariableElementName, this.ConvertVariableElement }, - { WixConverter.UtilCloseApplicationElementName, this.ConvertUtilCloseApplicationElementName }, - { WixConverter.UtilPermissionExElementName, this.ConvertUtilPermissionExElement }, - { WixConverter.UtilRegistrySearchName, this.ConvertUtilRegistrySearchElement }, - { WixConverter.UtilXmlConfigElementName, this.ConvertUtilXmlConfigElement }, - { WixConverter.PropertyElementName, this.ConvertPropertyElement }, - { WixConverter.WixElementWithoutNamespaceName, this.ConvertElementWithoutNamespace }, - { WixConverter.IncludeElementWithoutNamespaceName, this.ConvertElementWithoutNamespace }, - { WixConverter.VerbElementName, this.ConvertVerbElement }, - }; - - this.Messaging = messaging; - - this.IndentationAmount = indentationAmount; - - this.ErrorsAsWarnings = new HashSet(this.YieldConverterTypes(errorsAsWarnings)); - - this.IgnoreErrors = new HashSet(this.YieldConverterTypes(ignoreErrors)); - - this.CustomTableSetting = customTableTarget; - } - - private CustomTableTarget CustomTableSetting { get; } - - private int Errors { get; set; } - - private HashSet ErrorsAsWarnings { get; set; } - - private HashSet IgnoreErrors { get; set; } - - private IMessaging Messaging { get; } - - private int IndentationAmount { get; set; } - - private ConvertOperation Operation { get; set; } - - private string SourceFile { get; set; } - - private int SourceVersion { get; set; } - - /// - /// Convert a file. - /// - /// The file to convert. - /// Option to save the converted errors that are found. - /// The number of errors found. - public int ConvertFile(string sourceFile, bool saveConvertedFile) - { - var document = this.OpenSourceFile(sourceFile); - - if (document is null) - { - return 1; - } - - this.ConvertDocument(document); - - // Fix errors if requested and necessary. - if (saveConvertedFile && 0 < this.Errors) - { - this.SaveDocument(document); - } - - return this.Errors; - } - - /// - /// Convert a document. - /// - /// The document to convert. - /// The number of errors found. - public int ConvertDocument(XDocument document) - { - // Reset the instance info. - this.Errors = 0; - this.SourceVersion = 0; - this.Operation = ConvertOperation.Convert; - - // Remove the declaration. - if (null != document.Declaration - && this.OnError(ConverterTestType.DeclarationPresent, null, "This file contains an XML declaration on the first line.")) - { - document.Declaration = null; - TrimLeadingText(document); - } - - // Start converting the nodes at the top. - this.ConvertNodes(document.Nodes(), 0); - this.RemoveUnusedNamespaces(document.Root); - - return this.Errors; - } - - /// - /// Format a file. - /// - /// The file to format. - /// Option to save the format errors that are found. - /// The number of errors found. - public int FormatFile(string sourceFile, bool saveConvertedFile) - { - var document = this.OpenSourceFile(sourceFile); - - if (document is null) - { - return 1; - } - - this.FormatDocument(document); - - // Fix errors if requested and necessary. - if (saveConvertedFile && 0 < this.Errors) - { - this.SaveDocument(document); - } - - return this.Errors; - } - - /// - /// Format a document. - /// - /// The document to format. - /// The number of errors found. - public int FormatDocument(XDocument document) - { - // Reset the instance info. - this.Errors = 0; - this.SourceVersion = 0; - this.Operation = ConvertOperation.Format; - - // Remove the declaration. - if (null != document.Declaration - && this.OnError(ConverterTestType.DeclarationPresent, null, "This file contains an XML declaration on the first line.")) - { - document.Declaration = null; - TrimLeadingText(document); - } - - // Start converting the nodes at the top. - this.ConvertNodes(document.Nodes(), 0); - this.RemoveUnusedNamespaces(document.Root); - - return this.Errors; - } - - private XDocument OpenSourceFile(string sourceFile) - { - this.SourceFile = sourceFile; - - try - { - return XDocument.Load(this.SourceFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - } - catch (XmlException e) - { - this.OnError(ConverterTestType.XmlException, null, "The xml is invalid. Detail: '{0}'", e.Message); - } - - return null; - } - - private void SaveDocument(XDocument document) - { - var ignoreDeclarationError = this.IgnoreErrors.Contains(ConverterTestType.DeclarationPresent); - - try - { - using (var writer = XmlWriter.Create(this.SourceFile, new XmlWriterSettings { OmitXmlDeclaration = !ignoreDeclarationError })) - { - document.Save(writer); - } - } - catch (UnauthorizedAccessException) - { - this.OnError(ConverterTestType.UnauthorizedAccessException, null, "Could not write to file."); - } - } - - private void ConvertNodes(IEnumerable nodes, int level) - { - // Note we operate on a copy of the node list since we may - // remove some whitespace nodes during this processing. - foreach (var node in nodes.ToList()) - { - if (node is XText text) - { - if (null != text.Value) - { - if (this.TryFixDeprecatedLocalizationPrefixes(node, text.Value, out var newValue, ConverterTestType.DeprecatedLocalizationVariablePrefixInTextValue)) - { - text.Value = newValue; - } - } - if (!String.IsNullOrWhiteSpace(text.Value)) - { - text.Value = text.Value.Trim(); - } - else if (node.NextNode is XCData cdata) - { - this.EnsurePrecedingWhitespaceRemoved(text, node, ConverterTestType.WhitespacePrecedingNodeWrong); - } - else if (node.NextNode is XElement element) - { - this.EnsurePrecedingWhitespaceCorrect(text, node, level, ConverterTestType.WhitespacePrecedingNodeWrong); - } - else if (node.NextNode is null) // this is the space before the close element - { - if (node.PreviousNode is null || node.PreviousNode is XCData) - { - this.EnsurePrecedingWhitespaceRemoved(text, node.Parent, ConverterTestType.WhitespacePrecedingEndElementWrong); - } - else if (level == 0) // root element's close tag - { - this.EnsurePrecedingWhitespaceCorrect(text, node, 0, ConverterTestType.WhitespacePrecedingEndElementWrong); - } - else - { - this.EnsurePrecedingWhitespaceCorrect(text, node, level - 1, ConverterTestType.WhitespacePrecedingEndElementWrong); - } - } - } - else if (node is XElement element) - { - this.ConvertElement(element); - - var before = element.Nodes().ToList(); - - this.ConvertNodes(before, level + 1); - - // If any nodes were added during the processing of the children, - // ensure those added children get processed as well. - var added = element.Nodes().Except(before).ToList(); - - if (added.Any()) - { - this.ConvertNodes(added, level + 1); - } - } - } - } - - private bool TryFixDeprecatedLocalizationPrefixes(XNode node, string value, out string newValue, ConverterTestType testType) - { - newValue = this.DeprecatedPrefixRegex.Replace(value, "!"); - - if (object.ReferenceEquals(newValue, value)) - { - return false; - } - - var message = testType == ConverterTestType.DeprecatedLocalizationVariablePrefixInTextValue ? "The prefix on the localization variable in the inner text is incorrect." : "The prefix on the localization variable in the attribute value is incorrect."; - - return this.OnError(testType, node, message); - } - - private void EnsurePrecedingWhitespaceCorrect(XText whitespace, XNode node, int level, ConverterTestType testType) - { - if (!WixConverter.LeadingWhitespaceValid(this.IndentationAmount, level, whitespace.Value)) - { - var message = testType == ConverterTestType.WhitespacePrecedingEndElementWrong ? "The whitespace preceding this end element is incorrect." : "The whitespace preceding this node is incorrect."; - - if (this.OnError(testType, node, message)) - { - WixConverter.FixupWhitespace(this.IndentationAmount, level, whitespace); - } - } - } - - private void EnsurePrecedingWhitespaceRemoved(XText whitespace, XNode node, ConverterTestType testType) - { - if (!String.IsNullOrEmpty(whitespace.Value) && whitespace.NodeType != XmlNodeType.CDATA) - { - var message = testType == ConverterTestType.WhitespacePrecedingEndElementWrong ? "The whitespace preceding this end element is incorrect." : "The whitespace preceding this node is incorrect."; - - if (this.OnError(testType, node, message)) - { - whitespace.Remove(); - } - } - } - - private void ConvertElement(XElement element) - { - var deprecatedToUpdatedNamespaces = new Dictionary(); - - foreach (var attribute in element.Attributes()) - { - if (attribute.IsNamespaceDeclaration) - { - // Gather any deprecated namespaces, then update this element tree based on those deprecations. - var declaration = attribute; - - if (element.Name == Wix3ElementName || element.Name == Include3ElementName) - { - this.SourceVersion = 3; - } - else if (element.Name == Wix4ElementName || element.Name == Include4ElementName) - { - this.SourceVersion = 4; - } - - if (WixConverter.OldToNewNamespaceMapping.TryGetValue(declaration.Value, out var ns)) - { - if (this.OnError(ConverterTestType.XmlnsValueWrong, declaration, "The namespace '{0}' is out of date. It must be '{1}'.", declaration.Value, ns.NamespaceName)) - { - deprecatedToUpdatedNamespaces.Add(declaration.Value, ns); - } - } - } - else - { - if (null != attribute.Value) - { - if (this.TryFixDeprecatedLocalizationPrefixes(element, attribute.Value, out var newValue, ConverterTestType.DeprecatedLocalizationVariablePrefixInAttributeValue)) - { - attribute.Value = newValue; - } - } - } - } - - if (deprecatedToUpdatedNamespaces.Any()) - { - WixConverter.UpdateElementsWithDeprecatedNamespaces(element.DescendantsAndSelf(), deprecatedToUpdatedNamespaces); - } - - // Apply any specialized conversion actions. - if (this.ConvertElementMapping.TryGetValue(element.Name, out var convert)) - { - convert(element); - } - } - - private void ConvertBootstrapperApplicationElement(XElement element) - { - var xUseUILanguages = element.Attribute(BalUseUILanguagesName); - if (xUseUILanguages != null && - this.OnError(ConverterTestType.BalUseUILanguagesDeprecated, element, "bal:UseUILanguages is deprecated, 'true' is now the standard behavior.")) - { - xUseUILanguages.Remove(); - } - - var xBADll = element.Elements(BootstrapperApplicationDllElementName).FirstOrDefault(); - if (xBADll == null) - { - xBADll = this.CreateBootstrapperApplicationDllElement(element); - - if (xBADll != null) - { - element.Add(Environment.NewLine); - element.Add(xBADll); - element.Add(Environment.NewLine); - } - } - } - - private XElement CreateBootstrapperApplicationDllElement(XElement element) - { - XElement xBADll = null; - var xSource = element.Attribute("SourceFile"); - var xDpiAwareness = element.Attribute("DpiAwareness"); - - if (xSource != null) - { - if (xBADll != null || CreateBADllElement(element, out xBADll)) - { - MoveAttribute(element, "SourceFile", xBADll); - MoveAttribute(element, "Name", xBADll); - } - } - else if (xDpiAwareness != null || this.SourceVersion < 4) // older code might be relying on old behavior of first Payload element being the BA dll. - { - var xFirstChild = element.Elements().FirstOrDefault(); - if (xFirstChild?.Name == PayloadElementName) - { - if (xBADll != null || CreateBADllElement(element, out xBADll)) - { - var attributes = xFirstChild.Attributes().ToList(); - xFirstChild.Remove(); - - foreach (var attribute in attributes) - { - xBADll.Add(attribute); - } - } - } - else - { - this.OnError(ConverterTestType.BootstrapperApplicationDllRequired, element, "The new BootstrapperApplicationDll element is required but could not be added automatically since the bootstrapper application dll was not directly specified."); - } - } - - if (xDpiAwareness != null) - { - if (xBADll != null || CreateBADllElement(element, out xBADll)) - { - MoveAttribute(element, "DpiAwareness", xBADll); - } - } - else if (this.SourceVersion < 4 && xBADll != null && - this.OnError(ConverterTestType.AssignBootstrapperApplicationDpiAwareness, element, "The BootstrapperApplicationDll DpiAwareness attribute is being set to 'unaware' to ensure it remains the same as the v3 default")) - { - xBADll.Add(new XAttribute("DpiAwareness", "unaware")); - } - - return xBADll; - - bool CreateBADllElement(XObject node, out XElement xCreatedBADll) - { - var create = this.OnError(ConverterTestType.BootstrapperApplicationDll, node, "The bootstrapper application dll is now specified in the BootstrapperApplicationDll element."); - xCreatedBADll = create ? new XElement(BootstrapperApplicationDllElementName) : null; - return create; - } - } - - private void ConvertBootstrapperApplicationRefElement(XElement element) - { - var xUseUILanguages = element.Attribute(BalUseUILanguagesName); - if (xUseUILanguages != null && - this.OnError(ConverterTestType.BalUseUILanguagesDeprecated, element, "bal:UseUILanguages is deprecated, 'true' is now the standard behavior.")) - { - xUseUILanguages.Remove(); - } - - var xId = element.Attribute("Id"); - if (xId != null) - { - XName balBAName = null; - XName oldBalBAName = null; - string theme = null; - - switch (xId.Value) - { - case "WixStandardBootstrapperApplication.RtfLicense": - balBAName = BalStandardBootstrapperApplicationName; - theme = "rtfLicense"; - break; - case "WixStandardBootstrapperApplication.RtfLargeLicense": - balBAName = BalStandardBootstrapperApplicationName; - theme = "rtfLargeLicense"; - break; - case "WixStandardBootstrapperApplication.HyperlinkLicense": - balBAName = BalStandardBootstrapperApplicationName; - theme = "hyperlinkLicense"; - break; - case "WixStandardBootstrapperApplication.HyperlinkLargeLicense": - balBAName = BalStandardBootstrapperApplicationName; - theme = "hyperlinkLargeLicense"; - break; - case "WixStandardBootstrapperApplication.HyperlinkSidebarLicense": - balBAName = BalStandardBootstrapperApplicationName; - theme = "hyperlinkSidebarLicense"; - break; - case "WixStandardBootstrapperApplication.Foundation": - balBAName = BalStandardBootstrapperApplicationName; - theme = "none"; - break; - case "ManagedBootstrapperApplicationHost": - case "ManagedBootstrapperApplicationHost.RtfLicense": - balBAName = BalManagedBootstrapperApplicationHostName; - theme = "standard"; - break; - case "ManagedBootstrapperApplicationHost.Minimal": - case "ManagedBootstrapperApplicationHost.RtfLicense.Minimal": - case "ManagedBootstrapperApplicationHost.Foundation": - balBAName = BalManagedBootstrapperApplicationHostName; - theme = "none"; - break; - case "DotNetCoreBootstrapperApplicationHost": - case "DotNetCoreBootstrapperApplicationHost.RtfLicense": - balBAName = BalNewDotNetCoreBootstrapperApplicationName; - oldBalBAName = BalOldDotNetCoreBootstrapperApplicationName; - theme = "standard"; - break; - case "DotNetCoreBootstrapperApplicationHost.Minimal": - case "DotNetCoreBootstrapperApplicationHost.RtfLicense.Minimal": - case "DotNetCoreBootstrapperApplicationHost.Foundation": - balBAName = BalNewDotNetCoreBootstrapperApplicationName; - oldBalBAName = BalOldDotNetCoreBootstrapperApplicationName; - theme = "none"; - break; - } - - if (balBAName != null && theme != null && - this.OnError(ConverterTestType.BalBootstrapperApplicationRefToElement, element, "Built-in bootstrapper applications must be referenced through their custom element")) - { - element.Name = BootstrapperApplicationElementName; - xId.Remove(); - this.ConvertBalBootstrapperApplicationRef(element, theme, balBAName, oldBalBAName); - } - } - } - - private void ConvertApprovedExeForElevationElement(XElement element) - { - this.RenameWin64ToBitness(element); - } - - private void ConvertBalBootstrapperApplicationRef(XElement element, string theme, XName balBAElementName, XName oldBalBAElementName = null) - { - var xBalBa = element.Element(oldBalBAElementName ?? balBAElementName); - if (xBalBa == null) - { - xBalBa = new XElement(balBAElementName); - element.Add(Environment.NewLine); - element.Add(xBalBa); - element.Add(Environment.NewLine); - } - else if (oldBalBAElementName != null) - { - xBalBa.Name = BalNewDotNetCoreBootstrapperApplicationName; - } - - if (theme != "standard") - { - xBalBa.Add(new XAttribute("Theme", theme)); - } - } - - private void ConvertCatalogElement(XElement element) - { - if (this.OnError(ConverterTestType.BundleSignatureValidationObsolete, element, "The Catalog element is obsolete. Signature validation is no longer supported. The element will be removed.")) - { - element.Remove(); - } - } - - private void ConvertColumnElement(XElement element) - { - var category = element.Attribute("Category"); - if (category != null) - { - var camelCaseValue = LowercaseFirstChar(category.Value); - if (category.Value != camelCaseValue && - this.OnError(ConverterTestType.ColumnCategoryCamelCase, element, "The CustomTable Category attribute contains an incorrectly cased '{0}' value. Lowercase the first character instead.", category.Name)) - { - category.Value = camelCaseValue; - } - } - - var modularization = element.Attribute("Modularize"); - if (modularization != null) - { - var camelCaseValue = LowercaseFirstChar(modularization.Value); - if (modularization.Value != camelCaseValue && - this.OnError(ConverterTestType.ColumnModularizeCamelCase, element, "The CustomTable Modularize attribute contains an incorrectly cased '{0}' value. Lowercase the first character instead.", modularization.Name)) - { - modularization.Value = camelCaseValue; - } - } - } - - private void ConvertCustomTableElement(XElement element) - { - var bootstrapperApplicationData = element.Attribute("BootstrapperApplicationData"); - if (bootstrapperApplicationData?.Value == "no") - { - if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'Unreal' attribute instead.", bootstrapperApplicationData.Name)) - { - bootstrapperApplicationData.Remove(); - } - } - else - { - if (element.Elements(ColumnElementName).Any() || bootstrapperApplicationData != null) - { - // Table definition - if (bootstrapperApplicationData != null) - { - switch (this.CustomTableSetting) - { - case CustomTableTarget.Bundle: - if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'BundleCustomData' element for Bundles.", bootstrapperApplicationData.Name)) - { - element.Name = WixConverter.BundleCustomDataElementName; - bootstrapperApplicationData.Remove(); - this.ConvertCustomTableElementToBundle(element); - } - break; - case CustomTableTarget.Msi: - if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'Unreal' attribute instead.", bootstrapperApplicationData.Name)) - { - element.Add(new XAttribute("Unreal", bootstrapperApplicationData.Value)); - bootstrapperApplicationData.Remove(); - } - break; - default: - this.OnError(ConverterTestType.CustomTableNotAlwaysConvertable, element, "The CustomTable element contains deprecated '{0}' attribute so can't be converted. Use the 'Unreal' attribute for MSI. Use the 'BundleCustomData' element for Bundles. Use the --custom-table argument to force conversion to 'msi' or 'bundle'", bootstrapperApplicationData.Name); - break; - } - } - } - else - { - // Table ref - switch (this.CustomTableSetting) - { - case CustomTableTarget.Bundle: - if (this.OnError(ConverterTestType.CustomTableRef, element, "CustomTable elements that don't contain the table definition are now BundleCustomDataRef for Bundles.")) - { - element.Name = WixConverter.BundleCustomDataRefElementName; - this.ConvertCustomTableElementToBundle(element); - } - break; - case CustomTableTarget.Msi: - if (this.OnError(ConverterTestType.CustomTableRef, element, "CustomTable elements that don't contain the table definition are now CustomTableRef for MSI.")) - { - element.Name = WixConverter.CustomTableRefElementName; - } - break; - default: - this.OnError(ConverterTestType.CustomTableNotAlwaysConvertable, element, "The CustomTable element contains no 'Column' elements so can't be converted. Use the 'CustomTableRef' element for MSI. Use the 'BundleCustomDataRef' element for Bundles. Use the --custom-table argument to force conversion to 'msi' or 'bundle'"); - break; - } - } - } - } - - private void ConvertCustomTableElementToBundle(XElement element) - { - foreach (var xColumn in element.Elements(ColumnElementName)) - { - xColumn.Name = WixConverter.BundleAttributeDefinitionElementName; - - foreach (var xAttribute in xColumn.Attributes().ToList()) - { - if (xAttribute.Name.LocalName != "Id" && - (xAttribute.Name.Namespace == WixConverter.Wix3Namespace || - xAttribute.Name.Namespace == WixConverter.WixNamespace || - String.IsNullOrEmpty(xAttribute.Name.Namespace.NamespaceName))) - { - xAttribute.Remove(); - } - } - } - - foreach (var xRow in element.Elements(RowElementName)) - { - xRow.Name = WixConverter.BundleElementElementName; - - foreach (var xData in xRow.Elements(DataElementName)) - { - xData.Name = WixConverter.BundleAttributeElementName; - - var xColumn = xData.Attribute("Column"); - if (xColumn != null) - { - xData.Add(new XAttribute("Id", xColumn.Value)); - xColumn.Remove(); - } - - this.ConvertInnerTextToAttribute(xData, "Value"); - } - } - } - - private void ConvertControlElement(XElement element) - { - var remove = new List(); - - foreach (var xCondition in element.Elements(ConditionElementName)) - { - var action = UppercaseFirstChar(xCondition.Attribute("Action")?.Value); - if (!String.IsNullOrEmpty(action) && - TryGetInnerText(xCondition, out var text) && - this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}Condition' attribute instead.", xCondition.Name.LocalName, action)) - { - element.Add(new XAttribute(action + "Condition", text)); - remove.Add(xCondition); - } - } - - for (var i = remove.Count - 1; i >= 0; i--) - { - remove[i].Remove(); - } - } - - private void ConvertComponentElement(XElement element) - { - var guid = element.Attribute("Guid"); - if (guid != null && guid.Value == "*") - { - if (this.OnError(ConverterTestType.AutoGuidUnnecessary, element, "Using '*' for the Component Guid attribute is unnecessary. Remove the attribute to remove the redundancy.")) - { - guid.Remove(); - } - } - - var xCondition = element.Element(ConditionElementName); - if (xCondition != null) - { - if (TryGetInnerText(xCondition, out var text) && - this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) - { - element.Add(new XAttribute("Condition", text)); - xCondition.Remove(); - } - } - - this.RenameWin64ToBitness(element); - } - - private void ConvertDirectoryElement(XElement element) - { - if (null == element.Attribute("Name")) - { - var attribute = element.Attribute("ShortName"); - if (null != attribute) - { - var shortName = attribute.Value; - if (this.OnError(ConverterTestType.AssignDirectoryNameFromShortName, element, "The directory ShortName attribute is being renamed to Name since Name wasn't specified for value '{0}'", shortName)) - { - element.Add(new XAttribute("Name", shortName)); - attribute.Remove(); - } - } - } - - var id = element.Attribute("Id")?.Value; - - if (id == "TARGETDIR" && - this.OnError(ConverterTestType.TargetDirDeprecated, element, "The TARGETDIR directory should not longer be explicitly defined. Remove the Directory element with Id attribute 'TARGETDIR'.")) - { - var parentElement = element.Parent; - - element.Remove(); - - if (parentElement.FirstNode is XText text && String.IsNullOrWhiteSpace(text.Value)) - { - parentElement.FirstNode.Remove(); - } - - foreach (var child in element.Nodes()) - { - parentElement.Add(child); - } - - element.RemoveAll(); - - if (parentElement.FirstNode is XText textAgain && String.IsNullOrWhiteSpace(textAgain.Value)) - { - parentElement.FirstNode.Remove(); - } - } - else if (id != null && - WindowsInstallerStandard.IsStandardDirectory(id) && - this.OnError(ConverterTestType.DefiningStandardDirectoryDeprecated, element, "Standard directories such as '{0}' should no longer be defined using the Directory element. Use the StandardDirectory element instead.", id)) - { - element.Name = StandardDirectoryElementName; - - foreach (var attrib in element.Attributes().Where(a => a.Name.LocalName != "Id").ToList()) - { - attrib.Remove(); - } - } - } - - private void ConvertFeatureElement(XElement element) - { - var xAbsent = element.Attribute("Absent"); - if (xAbsent != null && - this.OnError(ConverterTestType.FeatureAbsentAttributeReplaced, element, "The Feature element's Absent attribute has been replaced with the AllowAbsent attribute. Use the 'AllowAbsent' attribute instead.")) - { - if (xAbsent.Value == "disallow") - { - element.Add(new XAttribute("AllowAbsent", "no")); - } - xAbsent.Remove(); - } - - var xAllowAdvertise = element.Attribute("AllowAdvertise"); - if (xAllowAdvertise != null) - { - if ((xAllowAdvertise.Value == "system" || xAllowAdvertise.Value == "allow") && - this.OnError(ConverterTestType.FeatureAllowAdvertiseValueDeprecated, element, "The AllowAdvertise attribute's '{0}' value is deprecated. Set the value to 'yes' instead.", xAllowAdvertise.Value)) - { - xAllowAdvertise.Value = "yes"; - } - else if (xAllowAdvertise.Value == "disallow" && - this.OnError(ConverterTestType.FeatureAllowAdvertiseValueDeprecated, element, "The AllowAdvertise attribute's '{0}' value is deprecated. Remove the value instead.", xAllowAdvertise.Value)) - { - xAllowAdvertise.Remove(); - } - } - - var xCondition = element.Element(ConditionElementName); - if (xCondition != null) - { - var level = xCondition.Attribute("Level")?.Value; - if (!String.IsNullOrEmpty(level) && - TryGetInnerText(xCondition, out var text) && - this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Level' element instead.", xCondition.Name.LocalName)) - { - xCondition.AddAfterSelf(new XElement(LevelElementName, - new XAttribute("Value", level), - new XAttribute("Condition", text) - )); - xCondition.Remove(); - } - } - } - - private void ConvertFileElement(XElement element) - { - if (this.SourceVersion < 4 && null == element.Attribute("Id")) - { - var attribute = element.Attribute("Name"); - - if (null == attribute) - { - attribute = element.Attribute("Source"); - } - - if (null != attribute) - { - var name = Path.GetFileName(attribute.Value); - - if (this.OnError(ConverterTestType.AssignAnonymousFileId, element, "The file id is being updated to '{0}' to ensure it remains the same as the v3 default", name)) - { - IEnumerable attributes = element.Attributes().ToList(); - element.RemoveAttributes(); - element.Add(new XAttribute("Id", GetIdentifierFromName(name))); - element.Add(attributes); - } - } - } - } - - private void ConvertFragmentElement(XElement element) - { - var remove = new List(); - - foreach (var xCondition in element.Elements(ConditionElementName)) - { - var message = xCondition.Attribute("Message")?.Value; - - if (!String.IsNullOrEmpty(message) && - TryGetInnerText(xCondition, out var text) && - this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Launch' element instead.", xCondition.Name.LocalName)) - { - xCondition.AddAfterSelf(new XElement(LaunchElementName, - new XAttribute("Condition", text), - new XAttribute("Message", message) - )); - remove.Add(xCondition); - } - } - - for (var i = remove.Count - 1; i >= 0; i--) - { - remove[i].Remove(); - } - } - - private void ConvertFirewallRemoteAddressElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - private void ConvertEmbeddedChainerElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); - - private void ConvertErrorElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Message"); - - private void ConvertExePackageElement(XElement element) - { - this.ConvertSuppressSignatureValidation(element); - - foreach (var attributeName in new[] { "InstallCommand", "RepairCommand", "UninstallCommand" }) - { - var newName = attributeName.Replace("Command", "Arguments"); - var attribute = element.Attribute(attributeName); - - if (attribute != null && - this.OnError(ConverterTestType.RenameExePackageCommandToArguments, element, "The {0} element {1} attribute has been renamed {2}.", element.Name.LocalName, attribute.Name.LocalName, newName)) - { - element.Add(new XAttribute(newName, attribute.Value)); - attribute.Remove(); - } - } - } - - private void ConvertPermissionExElement(XElement element) - { - var xCondition = element.Element(ConditionElementName); - if (xCondition != null) - { - if (TryGetInnerText(xCondition, out var text) && - this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) - { - element.Add(new XAttribute("Condition", text)); - xCondition.Remove(); - } - } - } - - private void ConvertProgressTextElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Message"); - - private void ConvertModuleElement(XElement element) - { - if (element.Attribute("Guid") == null // skip already-converted Module elements - && this.OnError(ConverterTestType.ModuleAndPackageRenamed, element, "The Module and Package elements have been renamed and reorganized for simplicity.")) - { - var xModule = element; - - var xSummaryInformation = xModule.Element(PackageElementName); - if (xSummaryInformation != null) - { - xSummaryInformation.Name = SummaryInformationElementName; - - var xInstallerVersion = xSummaryInformation.Attribute("InstallerVersion"); - if (this.SourceVersion < 4 && xInstallerVersion == null) - { - this.OnError(ConverterTestType.InstallerVersionBehaviorChange, element, "Breaking change: The default value for Package/@InstallerVersion has been changed to '500' regardless of build platform. If you need a lower version, set it manually in the Module element."); - } - - RemoveAttribute(xSummaryInformation, "AdminImage"); - RemoveAttribute(xSummaryInformation, "Comments"); - MoveAttribute(xSummaryInformation, "Id", xModule, "Guid"); - MoveAttribute(xSummaryInformation, "InstallerVersion", xModule); - RemoveAttribute(xSummaryInformation, "Languages"); - RemoveAttribute(xSummaryInformation, "Platform"); - RemoveAttribute(xSummaryInformation, "Platforms"); - RemoveAttribute(xSummaryInformation, "ReadOnly"); - MoveAttribute(xSummaryInformation, "SummaryCodepage", xSummaryInformation, "Codepage", defaultValue: "1252"); - - if (!xSummaryInformation.HasAttributes) - { - xSummaryInformation.Remove(); - } - } - } - } - - private void ConvertProductElement(XElement element) - { - var id = element.Attribute("Id"); - if (id != null && id.Value == "*") - { - if (this.OnError(ConverterTestType.AutoGuidUnnecessary, element, "Using '*' for the Product Id attribute is unnecessary. Remove the attribute to remove the redundancy.")) - { - id.Remove(); - } - } - - var xConditions = element.Elements(ConditionElementName).ToList(); - foreach (var xCondition in xConditions) - { - var message = xCondition.Attribute("Message")?.Value; - - if (!String.IsNullOrEmpty(message) && - TryGetInnerText(xCondition, out var text) && - this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Launch' element instead.", xCondition.Name.LocalName)) - { - xCondition.AddAfterSelf(new XElement(LaunchElementName, - new XAttribute("Condition", text), - new XAttribute("Message", message) - )); - xCondition.Remove(); - } - } - - var xMediaTemplate = element.Element(MediaTemplateElementName); - if (xMediaTemplate?.HasAttributes == false - && this.OnError(ConverterTestType.DefaultMediaTemplate, element, "A MediaTemplate with no attributes set is now provided by default. Remove the element.")) - { - xMediaTemplate.Remove(); - } - - if (this.OnError(ConverterTestType.ProductAndPackageRenamed, element, "The Product and Package elements have been renamed and reorganized for simplicity.")) - { - var xPackage = element; - xPackage.Name = PackageElementName; - - var xSummaryInformation = xPackage.Element(PackageElementName); - if (xSummaryInformation != null) - { - xSummaryInformation.Name = SummaryInformationElementName; - - var xInstallerVersion = xSummaryInformation.Attribute("InstallerVersion"); - if (this.SourceVersion < 4 && xInstallerVersion == null) - { - this.OnError(ConverterTestType.InstallerVersionBehaviorChange, element, "Breaking change: The default value for Package/@InstallerVersion has been changed to '500' regardless of build platform. If you need a lower version, set it manually in the Package element."); - } - - if (xSummaryInformation.Attribute("Compressed") == null) - { - xPackage.SetAttributeValue("Compressed", "no"); - } - else - { - MoveAttribute(xSummaryInformation, "Compressed", xPackage, defaultValue: "yes"); - } - - RemoveAttribute(xSummaryInformation, "AdminImage"); - RemoveAttribute(xSummaryInformation, "Comments"); - RemoveAttribute(xSummaryInformation, "Id"); - MoveAttribute(xSummaryInformation, "InstallerVersion", xPackage, defaultValue: "500"); - MoveAttribute(xSummaryInformation, "InstallScope", xPackage, "Scope", defaultValue: "perMachine"); - RemoveAttribute(xSummaryInformation, "Languages"); - RemoveAttribute(xSummaryInformation, "Platform"); - RemoveAttribute(xSummaryInformation, "Platforms"); - RemoveAttribute(xSummaryInformation, "ReadOnly"); - MoveAttribute(xSummaryInformation, "ShortNames", xPackage); - MoveAttribute(xSummaryInformation, "SummaryCodepage", xSummaryInformation, "Codepage", defaultValue: "1252"); - MoveAttribute(xPackage, "Id", xPackage, "ProductCode"); - - var xInstallPrivileges = xSummaryInformation.Attribute("InstallPrivileges"); - switch (xInstallPrivileges?.Value) - { - case "limited": - xPackage.SetAttributeValue("Scope", "perUser"); - break; - case "elevated": - { - var xAllUsers = xPackage.Elements(PropertyElementName).SingleOrDefault(p => p.Attribute("Id")?.Value == "ALLUSERS"); - if (xAllUsers?.Attribute("Value")?.Value == "1") - { - xAllUsers?.Remove(); - } - } - break; - } - - xInstallPrivileges?.Remove(); - - if (!xSummaryInformation.HasAttributes) - { - xSummaryInformation.Remove(); - } - } - } - } - - private static void MoveAttribute(XElement xSource, string attributeName, XElement xDestination, string destinationAttributeName = null, string defaultValue = null) - { - var xAttribute = xSource.Attribute(attributeName); - if (xAttribute != null && (defaultValue == null || xAttribute.Value != defaultValue)) - { - xDestination.SetAttributeValue(destinationAttributeName ?? attributeName, xAttribute.Value); - } - - xAttribute?.Remove(); - } - - private static void RemoveAttribute(XElement xSummaryInformation, string attributeName) - { - var xAttribute = xSummaryInformation.Attribute(attributeName); - xAttribute?.Remove(); - } - - private void ConvertPropertyRefElement(XElement element) - { - var newElementName = String.Empty; - - var id = element.Attribute("Id"); - switch (id?.Value) - { - case "WIX_SUITE_BACKOFFICE": - case "WIX_SUITE_BLADE": - case "WIX_SUITE_COMMUNICATIONS": - case "WIX_SUITE_COMPUTE_SERVER": - case "WIX_SUITE_DATACENTER": - case "WIX_SUITE_EMBEDDED_RESTRICTED": - case "WIX_SUITE_EMBEDDEDNT": - case "WIX_SUITE_ENTERPRISE": - case "WIX_SUITE_MEDIACENTER": - case "WIX_SUITE_PERSONAL": - case "WIX_SUITE_SECURITY_APPLIANCE": - case "WIX_SUITE_SERVERR2": - case "WIX_SUITE_SINGLEUSERTS": - case "WIX_SUITE_SMALLBUSINESS": - case "WIX_SUITE_SMALLBUSINESS_RESTRICTED": - case "WIX_SUITE_STARTER": - case "WIX_SUITE_STORAGE_SERVER": - case "WIX_SUITE_TABLETPC": - case "WIX_SUITE_TERMINAL": - case "WIX_SUITE_WH_SERVER": - newElementName = "QueryWindowsSuiteInfo"; - break; - case "WIX_DIR_ADMINTOOLS": - case "WIX_DIR_ALTSTARTUP": - case "WIX_DIR_CDBURN_AREA": - case "WIX_DIR_COMMON_ADMINTOOLS": - case "WIX_DIR_COMMON_ALTSTARTUP": - case "WIX_DIR_COMMON_DOCUMENTS": - case "WIX_DIR_COMMON_FAVORITES": - case "WIX_DIR_COMMON_MUSIC": - case "WIX_DIR_COMMON_PICTURES": - case "WIX_DIR_COMMON_VIDEO": - case "WIX_DIR_COOKIES": - case "WIX_DIR_DESKTOP": - case "WIX_DIR_HISTORY": - case "WIX_DIR_INTERNET_CACHE": - case "WIX_DIR_MYMUSIC": - case "WIX_DIR_MYPICTURES": - case "WIX_DIR_MYVIDEO": - case "WIX_DIR_NETHOOD": - case "WIX_DIR_PERSONAL": - case "WIX_DIR_PRINTHOOD": - case "WIX_DIR_PROFILE": - case "WIX_DIR_RECENT": - case "WIX_DIR_RESOURCES": - newElementName = "QueryWindowsDirectories"; - break; - case "WIX_DWM_COMPOSITION_ENABLED": - case "WIX_WDDM_DRIVER_PRESENT": - newElementName = "QueryWindowsDriverInfo"; - break; - case "WIX_ACCOUNT_LOCALSYSTEM": - case "WIX_ACCOUNT_LOCALSERVICE": - case "WIX_ACCOUNT_NETWORKSERVICE": - case "WIX_ACCOUNT_ADMINISTRATORS": - case "WIX_ACCOUNT_USERS": - case "WIX_ACCOUNT_GUESTS": - case "WIX_ACCOUNT_PERFLOGUSERS": - case "WIX_ACCOUNT_PERFLOGUSERS_NODOMAIN": - newElementName = "QueryWindowsWellKnownSIDs"; - break; - } - - if (!String.IsNullOrEmpty(newElementName) - && this.OnError(ConverterTestType.UtilReferencesReplaced, element, "Custom action and property reference {0} to WixUtilExtension have been replaced with strongly-typed elements.", id)) - { - element.AddAfterSelf(new XElement(WixUtilNamespace + newElementName)); - element.Remove(); - } - } - - private void ConvertCustomActionRefElement(XElement element) - { - var newElementName = String.Empty; - - var id = element.Attribute("Id"); - switch (id?.Value) - { - case "WixBroadcastSettingChange": - case "WixBroadcastEnvironmentChange": - case "WixCheckRebootRequired": - case "WixExitEarlyWithSuccess": - case "WixFailWhenDeferred": - case "WixWaitForEvent": - case "WixWaitForEventDeferred": - newElementName = id?.Value.Substring(3); // strip leading Wix - break; - } - - if (!String.IsNullOrEmpty(newElementName) - && this.OnError(ConverterTestType.UtilReferencesReplaced, element, "Custom action and property reference {0} to WixUtilExtension have been replaced with strongly-typed elements.", id)) - { - element.AddAfterSelf(new XElement(WixUtilNamespace + newElementName)); - element.Remove(); - } - } - - private void ConvertPublishElement(XElement element) - { - this.ConvertInnerTextToAttribute(element, "Condition"); - - var xCondition = element.Attribute("Condition"); - if (xCondition?.Value == "1" && - this.OnError(ConverterTestType.PublishConditionOneUnnecessary, element, "Adding Condition='1' on {0} elements is no longer necessary. Remove the Condition attribute.", xCondition.Name.LocalName)) - { - xCondition.Remove(); - } - } - - private void ConvertMultiStringValueElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - private void ConvertRegistryKeyElement(XElement element) - { - var xAction = element.Attribute("Action"); - - if (xAction != null - && this.OnError(ConverterTestType.RegistryKeyActionObsolete, element, "The RegistryKey element's Action attribute is obsolete. Action='create' will be converted to ForceCreateOnInstall='yes'. Action='createAndRemoveOnUninstall' will be converted to ForceCreateOnInstall='yes' and ForceDeleteOnUninstall='yes'.")) - { - switch (xAction?.Value) - { - case "create": - element.SetAttributeValue("ForceCreateOnInstall", "yes"); - break; - case "createAndRemoveOnUninstall": - element.SetAttributeValue("ForceCreateOnInstall", "yes"); - element.SetAttributeValue("ForceDeleteOnUninstall", "yes"); - break; - } - - xAction.Remove(); - } - } - - private void ConvertRemotePayloadElement(XElement element) - { - var xParent = element.Parent; - - if (xParent.Name == ExePackageElementName && - this.OnError(ConverterTestType.RemotePayloadRenamed, element, "The RemotePayload element has been renamed. Use the 'ExePackagePayload' instead.")) - { - element.Name = ExePackagePayloadElementName; - } - else if (xParent.Name == MsuPackageElementName && - this.OnError(ConverterTestType.RemotePayloadRenamed, element, "The RemotePayload element has been renamed. Use the 'MsuPackagePayload' instead.")) - { - element.Name = MsuPackagePayloadElementName; - } - - var xName = xParent.Attribute("Name"); - if (xName != null && - this.OnError(ConverterTestType.NameAttributeMovedToRemotePayload, xParent, "The Name attribute must be specified on the child XxxPackagePayload element when using a remote payload.")) - { - element.SetAttributeValue("Name", xName.Value); - xName.Remove(); - } - - var xDownloadUrl = xParent.Attribute("DownloadUrl"); - if (xDownloadUrl != null && - this.OnError(ConverterTestType.DownloadUrlAttributeMovedToRemotePayload, xParent, "The DownloadUrl attribute must be specified on the child XxxPackagePayload element when using a remote payload.")) - { - element.SetAttributeValue("DownloadUrl", xDownloadUrl.Value); - xDownloadUrl.Remove(); - } - - var xCompressed = xParent.Attribute("Compressed"); - if (xCompressed != null && - this.OnError(ConverterTestType.CompressedAttributeUnnecessaryForRemotePayload, xParent, "The Compressed attribute should not be specified when using a remote payload.")) - { - xCompressed.Remove(); - } - - this.OnError(ConverterTestType.BurnHashAlgorithmChanged, element, "The hash algorithm for bundles changed from SHA1 to SHA512."); - - this.RemoveAttributeIfPresent(element, "CertificatePublicKey", ConverterTestType.BundleSignatureValidationObsolete, "The {0} element contains obsolete '{1}' attribute. Signature validation is no longer supported. The attribute will be removed."); - this.RemoveAttributeIfPresent(element, "CertificateThumbprint", ConverterTestType.BundleSignatureValidationObsolete, "The {0} element contains obsolete '{1}' attribute. Signature validation is no longer supported. The attribute will be removed."); - } - - private void ConvertRegistrySearchElement(XElement element) - { - this.RenameWin64ToBitness(element); - } - - private void ConvertRequiredPrivilegeElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Name"); - - private void ConvertDataElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - private void ConvertSequenceElement(XElement element) - { - foreach (var child in element.Elements()) - { - this.ConvertInnerTextToAttribute(child, "Condition"); - } - } - - private void ConvertServiceArgumentElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - private void ConvertSetDirectoryElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); - - private void ConvertSetPropertyElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); - - private void ConvertShortcutPropertyElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - private void ConvertProvidesElement(XElement element) - { - if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Provides element has been integrated into the WiX v4 namespace. Remove the namespace.")) - { - element.Name = ProvidesElementName; - } - - if (element.Parent.Name == ComponentElementName && - this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Provides element has been integrated into the WiX v4 namespace. Add the 'Check' attribute from the WixDependency.wixext to match v3 runtime behavior.")) - { - element.Add(new XAttribute(DependencyCheckAttributeName, "yes")); - } - } - - private void ConvertRequiresElement(XElement element) - { - if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Requires element has been integrated into the WiX v4 namespace. Remove the namespace.")) - { - element.Name = RequiresElementName; - } - - if (element.Parent.Name == ProvidesElementName && - element.Parent.Parent?.Name == ComponentElementName && - this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Requires element has been integrated into the WiX v4 namespace. Add the 'Enforce' attribute from the WixDependency.wixext to match v3 runtime behavior.")) - { - element.Add(new XAttribute(DependencyEnforceAttributeName, "yes")); - } - } - - private void ConvertRequiresRefElement(XElement element) - { - if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The RequiresRef element has been integrated into the WiX v4 namespace. Remove the namespace.")) - { - element.Name = RequiresRefElementName; - } - - if (element.Parent.Name == ProvidesElementName && - element.Parent.Parent?.Name == ComponentElementName && - this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The RequiresRef element has been integrated into the WiX v4 namespace. Add the 'Enforce' attribute from the WixDependency.wixext to match v3 runtime behavior.")) - { - element.Add(new XAttribute(DependencyEnforceAttributeName, "yes")); - } - } - - private void ConvertSuppressSignatureValidation(XElement element) - { - var suppressSignatureValidation = element.Attribute("SuppressSignatureValidation"); - - if (null != suppressSignatureValidation - && this.OnError(ConverterTestType.BundleSignatureValidationObsolete, element, "The chain package element contains obsolete '{0}' attribute. Signature validation is no longer supported. The attribute will be removed.", suppressSignatureValidation.Name)) - { - suppressSignatureValidation.Remove(); - } - } - - private void ConvertTagElement(XElement element) - { - if (this.OnError(ConverterTestType.TagElementRenamed, element, "The Tag element has been renamed. Use the 'SoftwareTag' element instead.")) - { - element.Name = SoftwareTagElementName; - } - - this.RemoveAttributeIfPresent(element, "Licensed", ConverterTestType.SoftwareTagLicensedObsolete, "The {0} element contains obsolete '{1}' attribute. The attribute will be removed."); - this.RemoveAttributeIfPresent(element, "Type", ConverterTestType.SoftwareTagLicensedObsolete, "The {0} element contains obsolete '{1}' attribute. The attribute will be removed."); - this.RenameWin64ToBitness(element); - } - - private void ConvertTagRefElement(XElement element) - { - if (this.OnError(ConverterTestType.TagRefElementRenamed, element, "The TagRef element has been renamed. Use the 'SoftwareTagRef' element instead.")) - { - element.Name = SoftwareTagRefElementName; - } - } - - private void ConvertTextElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - private void ConvertUITextElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - private void ConvertWindowsInstallerPackageElement(XElement element) - { - this.ConvertSuppressSignatureValidation(element); - - if (null != element.Attribute("DisplayInternalUI")) - { - this.OnError(ConverterTestType.DisplayInternalUiNotConvertable, element, "The DisplayInternalUI functionality has fundamentally changed and requires BootstrapperApplication support."); - } - } - - private void ConvertVerbElement(XElement element) - { - if (null != element.Attribute("Target")) - { - this.OnError(ConverterTestType.VerbTargetNotConvertable, element, "The Verb/@Target attribute has been replaced with typed @TargetFile and @TargetProperty attributes."); - } - } - - private void ConvertCustomActionElement(XElement xCustomAction) - { - var xBinaryKey = xCustomAction.Attribute("BinaryKey"); - if (xBinaryKey != null && this.OnError(ConverterTestType.CustomActionKeysAreNowRefs, xCustomAction, "The CustomAction attributes have been renamed from BinaryKey and FileKey to BinaryRef and FileRef.")) - { - xCustomAction.SetAttributeValue("BinaryRef", xBinaryKey.Value); - xBinaryKey.Remove(); - xBinaryKey = xCustomAction.Attribute("BinaryRef"); - } - - var xFileKey = xCustomAction.Attribute("FileKey"); - if (xFileKey != null && this.OnError(ConverterTestType.CustomActionKeysAreNowRefs, xCustomAction, "The CustomAction attributes have been renamed from BinaryKey and FileKey to BinaryRef and FileRef.")) - { - xCustomAction.SetAttributeValue("FileRef", xFileKey.Value); - xFileKey.Remove(); - } - - if (xBinaryKey?.Value == "WixCA" || xBinaryKey?.Value == "UtilCA") - { - if (this.OnError(ConverterTestType.WixCABinaryIdRenamed, xCustomAction, "The WixCA custom action DLL Binary table id has been renamed. Use the id 'Wix4UtilCA_X86' instead.")) - { - xBinaryKey.Value = "Wix4UtilCA_X86"; - } - } - - if (xBinaryKey?.Value == "WixCA_x64" || xBinaryKey?.Value == "UtilCA_x64") - { - if (this.OnError(ConverterTestType.WixCABinaryIdRenamed, xCustomAction, "The WixCA_x64 custom action DLL Binary table id has been renamed. Use the id 'Wix4UtilCA_X64' instead.")) - { - xBinaryKey.Value = "Wix4UtilCA_X64"; - } - } - - var xDllEntry = xCustomAction.Attribute("DllEntry"); - - if (xDllEntry?.Value == "CAQuietExec" || xDllEntry?.Value == "CAQuietExec64") - { - if (this.OnError(ConverterTestType.QuietExecCustomActionsRenamed, xCustomAction, "The CAQuietExec and CAQuietExec64 custom action ids have been renamed. Use the ids 'WixQuietExec' and 'WixQuietExec64' instead.")) - { - xDllEntry.Value = xDllEntry.Value.Replace("CAQuietExec", "WixQuietExec"); - } - } - - var xProperty = xCustomAction.Attribute("Property"); - - if (xProperty?.Value == "QtExecCmdLine" || xProperty?.Value == "QtExec64CmdLine") - { - if (this.OnError(ConverterTestType.QuietExecCustomActionsRenamed, xCustomAction, "The QtExecCmdLine and QtExec64CmdLine property ids have been renamed. Use the ids 'WixQuietExecCmdLine' and 'WixQuietExec64CmdLine' instead.")) - { - xProperty.Value = xProperty.Value.Replace("QtExec", "WixQuietExec"); - } - } - - var xScript = xCustomAction.Attribute("Script"); - - if (xScript != null && TryGetInnerText(xCustomAction, out var scriptText)) - { - if (this.OnError(ConverterTestType.InnerTextDeprecated, xCustomAction, "Using {0} element text is deprecated. Extract the text to a file and use the 'ScriptSourceFile' attribute to reference it.", xCustomAction.Name.LocalName)) - { - var scriptFolder = Path.GetDirectoryName(this.SourceFile) ?? String.Empty; - var id = xCustomAction.Attribute("Id")?.Value ?? Guid.NewGuid().ToString("N"); - var ext = (xScript.Value == "jscript") ? ".js" : (xScript.Value == "vbscript") ? ".vbs" : ".txt"; - - var scriptFile = Path.Combine(scriptFolder, id + ext); - File.WriteAllText(scriptFile, scriptText); - - RemoveChildren(xCustomAction); - xCustomAction.Add(new XAttribute("ScriptSourceFile", scriptFile)); - } - } - } - - private void ConvertVariableElement(XElement xVariable) - { - var xType = xVariable.Attribute("Type"); - var xValue = xVariable.Attribute("Value"); - if (this.SourceVersion < 4) - { - if (xType == null) - { - if (WasImplicitlyStringTyped(xValue?.Value) && - this.OnError(ConverterTestType.AssignVariableTypeFormatted, xVariable, "The \"string\" variable type now denotes a literal string. Use \"formatted\" to keep the previous behavior.")) - { - xVariable.Add(new XAttribute("Type", "formatted")); - } - } - else if (xType.Value == "string" && - this.OnError(ConverterTestType.AssignVariableTypeFormatted, xVariable, "The \"string\" variable type now denotes a literal string. Use \"formatted\" to keep the previous behavior.")) - { - xType.Value = "formatted"; - } - } - } - - private void ConvertPropertyElement(XElement xProperty) - { - var xId = xProperty.Attribute("Id"); - - if (xId.Value == "QtExecCmdTimeout") - { - this.OnError(ConverterTestType.QtExecCmdTimeoutAmbiguous, xProperty, "QtExecCmdTimeout was previously used for both CAQuietExec and CAQuietExec64. For WixQuietExec, use WixQuietExecCmdTimeout. For WixQuietExec64, use WixQuietExec64CmdTimeout."); - } - - this.ConvertInnerTextToAttribute(xProperty, "Value"); - } - - private void ConvertUtilCloseApplicationElementName(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); - - private void ConvertUtilPermissionExElement(XElement element) - { - if (this.SourceVersion < 4 && null == element.Attribute("Inheritable")) - { - var inheritable = element.Parent.Name == CreateFolderElementName; - if (!inheritable) - { - if (this.OnError(ConverterTestType.AssignPermissionExInheritable, element, "The PermissionEx Inheritable attribute is being set to 'no' to ensure it remains the same as the v3 default.")) - { - element.Add(new XAttribute("Inheritable", "no")); - } - } - } - } - - private void ConvertUtilRegistrySearchElement(XElement element) - { - this.RenameWin64ToBitness(element); - - if (this.SourceVersion < 4) - { - var result = element.Attribute("Result")?.Value; - if (result == null || result == "value") - { - this.OnError(ConverterTestType.UtilRegistryValueSearchBehaviorChange, element, "Breaking change: util:RegistrySearch for a value no longer clears the variable when the key or value is missing."); - } - } - } - - private void ConvertUtilXmlConfigElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); - - /// - /// Converts a Wix element. - /// - /// The Wix element to convert. - /// The converted element. - private void ConvertElementWithoutNamespace(XElement element) - { - if (this.OnError(ConverterTestType.XmlnsMissing, element, "The xmlns attribute is missing. It must be present with a value of '{0}'.", WixNamespace.NamespaceName)) - { - element.Name = WixNamespace.GetName(element.Name.LocalName); - - element.Add(new XAttribute("xmlns", WixNamespace.NamespaceName)); // set the default namespace. - - foreach (var elementWithoutNamespace in element.DescendantsAndSelf().Where(e => XNamespace.None == e.Name.Namespace)) - { - elementWithoutNamespace.Name = WixNamespace.GetName(elementWithoutNamespace.Name.LocalName); - } - } - } - - private void ConvertInnerTextToAttribute(XElement element, string attributeName) - { - if (TryGetInnerText(element, out var text) && - this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}' attribute instead.", element.Name.LocalName, attributeName)) - { - element.Add(new XAttribute(attributeName, text)); - RemoveChildren(element); - } - } - - void RemoveAttributeIfPresent(XElement element, string attributeName, ConverterTestType type, string format) - { - var xAttribute = element.Attribute(attributeName); - if (null != xAttribute && this.OnError(type, element, format, element.Name.LocalName, xAttribute.Name)) - { - xAttribute.Remove(); - } - } - - private void RenameWin64ToBitness(XElement element) - { - var win64 = element.Attribute("Win64"); - if (win64 != null && this.OnError(ConverterTestType.Win64AttributeRenamed, element, "The {0} element's Win64 attribute has been renamed. Use the Bitness attribute instead.", element.Name.LocalName)) - { - var value = this.UpdateWin64ValueToBitnessValue(win64); - element.Add(new XAttribute("Bitness", value)); - win64.Remove(); - } - } - - private string UpdateWin64ValueToBitnessValue(XAttribute xWin64Attribute) - { - var value = xWin64Attribute.Value ?? String.Empty; - switch (value) - { - case "yes": - return "always64"; - case "no": - return "always32"; - default: - this.OnError(ConverterTestType.Win64AttributeRenameCannotBeAutomatic, xWin64Attribute, "Breaking change: The Win64 attribute's value '{0}' cannot be converted automatically to the new Bitness attribute.", value); - return value; - } - } - - private IEnumerable YieldConverterTypes(IEnumerable types) - { - if (null != types) - { - foreach (var type in types) - { - if (Enum.TryParse(type, true, out var itt)) - { - yield return itt; - } - else // not a known ConverterTestType - { - this.OnError(ConverterTestType.ConverterTestTypeUnknown, null, "Unknown error type: '{0}'.", type); - } - } - } - } - - private static void UpdateElementsWithDeprecatedNamespaces(IEnumerable elements, Dictionary deprecatedToUpdatedNamespaces) - { - foreach (var element in elements) - { - if (deprecatedToUpdatedNamespaces.TryGetValue(element.Name.Namespace, out var ns)) - { - element.Name = ns.GetName(element.Name.LocalName); - } - - // Remove all the attributes and add them back to with their namespace updated (as necessary). - IEnumerable attributes = element.Attributes().ToList(); - element.RemoveAttributes(); - - foreach (var attribute in attributes) - { - var convertedAttribute = attribute; - - if (attribute.IsNamespaceDeclaration) - { - if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Value, out ns)) - { - if (ns == XNamespace.None) - { - continue; - } - - convertedAttribute = ("xmlns" == attribute.Name.LocalName) ? new XAttribute(attribute.Name.LocalName, ns.NamespaceName) : new XAttribute(XNamespace.Xmlns + attribute.Name.LocalName, ns.NamespaceName); - } - } - else if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Name.Namespace, out ns)) - { - convertedAttribute = new XAttribute(ns.GetName(attribute.Name.LocalName), attribute.Value); - } - - element.Add(convertedAttribute); - } - } - } - - /// - /// Determine if the whitespace preceding a node is appropriate for its depth level. - /// - /// Indentation value to use when validating leading whitespace. - /// The depth level that should match this whitespace. - /// The whitespace to validate. - /// true if the whitespace is legal; false otherwise. - private static bool LeadingWhitespaceValid(int indentationAmount, int level, string whitespace) - { - // Strip off leading newlines; there can be an arbitrary number of these. - whitespace = whitespace.TrimStart(XDocumentNewLine); - - var indentation = new string(' ', level * indentationAmount); - - return whitespace == indentation; - } - - /// - /// Fix the whitespace in a whitespace node. - /// - /// Indentation value to use when validating leading whitespace. - /// The depth level of the desired whitespace. - /// The whitespace node to fix. - private static void FixupWhitespace(int indentationAmount, int level, XText whitespace) - { - var value = new StringBuilder(whitespace.Value.Length); - - // Keep any previous preceeding new lines. - var newlines = whitespace.Value.TakeWhile(c => c == XDocumentNewLine).Count(); - - // Ensure there is always at least one new line before the indentation. - value.Append(XDocumentNewLine, newlines == 0 ? 1 : newlines); - - whitespace.Value = value.Append(' ', level * indentationAmount).ToString(); - } - - /// - /// Removes unused namespaces from the element and its children. - /// - /// Root element to start at. - private void RemoveUnusedNamespaces(XElement root) - { - var declarations = new List(); - var namespaces = new HashSet(); - - VisitElement(root, x => - { - if (x is XAttribute a && a.IsNamespaceDeclaration) - { - declarations.Add(a); - namespaces.Add(a.Value); - } - return true; - }); - - foreach (var ns in namespaces.ToList()) - { - VisitElement(root, x => - { - if ((x is XElement e && e.Name.Namespace == ns) || - (x is XAttribute a && !a.IsNamespaceDeclaration && a.Name.Namespace == ns)) - { - namespaces.Remove(ns); - return false; - } - - return true; - }); - } - - foreach (var declaration in declarations) - { - if (namespaces.Contains(declaration.Value) && - this.OnError(ConverterTestType.RemoveUnusedNamespaces, declaration, "The namespace '{0}' is not used. Remove unused namespaces.", declaration.Value)) - { - declaration.Remove(); - } - } - } - - /// - /// Output an error message to the console. - /// - /// The type of converter test. - /// The node that caused the error. - /// Detailed error message. - /// Additional formatted string arguments. - /// Returns true indicating that action should be taken on this error, and false if it should be ignored. - private bool OnError(ConverterTestType converterTestType, XObject node, string message, params object[] args) - { - // Ignore the error if explicitly ignored or outside the range of the current operation. - if (this.IgnoreErrors.Contains(converterTestType) || - (this.Operation == ConvertOperation.Convert && converterTestType < ConverterTestType.EndIgnoreInConvert) || - (this.Operation == ConvertOperation.Format && converterTestType > ConverterTestType.BeginIgnoreInFormat)) - { - return false; - } - - // Increase the error count. - this.Errors++; - - var sourceLine = (null == node) ? new SourceLineNumber(this.SourceFile ?? "wix.exe") : new SourceLineNumber(this.SourceFile, ((IXmlLineInfo)node).LineNumber); - var warning = this.ErrorsAsWarnings.Contains(converterTestType); - var display = String.Format(CultureInfo.CurrentCulture, message, args); - - var msg = new Message(sourceLine, warning ? MessageLevel.Warning : MessageLevel.Error, (int)converterTestType, "{0} ({1})", display, converterTestType.ToString()); - - this.Messaging.Write(msg); - - return true; - } - - /// - /// Return an identifier based on passed file/directory name - /// - /// File/directory name to generate identifer from - /// A version of the name that is a legal identifier. - /// This is duplicated from WiX's Common class. - private static string GetIdentifierFromName(string name) - { - var result = IllegalIdentifierCharacters.Replace(name, "_"); // replace illegal characters with "_". - - // MSI identifiers must begin with an alphabetic character or an - // underscore. Prefix all other values with an underscore. - if (AddPrefix.IsMatch(name)) - { - result = String.Concat("_", result); - } - - return result; - } - - private static string LowercaseFirstChar(string value) - { - if (!String.IsNullOrEmpty(value)) - { - var c = Char.ToLowerInvariant(value[0]); - if (c != value[0]) - { - var remainder = value.Length > 1 ? value.Substring(1) : String.Empty; - return c + remainder; - } - } - - return value; - } - - private static string UppercaseFirstChar(string value) - { - if (!String.IsNullOrEmpty(value)) - { - var c = Char.ToUpperInvariant(value[0]); - if (c != value[0]) - { - var remainder = value.Length > 1 ? value.Substring(1) : String.Empty; - return c + remainder; - } - } - - return value; - } - - private static bool TryGetInnerText(XElement element, out string value) - { - value = null; - - var nodes = element.Nodes(); - - if (nodes.All(e => e.NodeType == XmlNodeType.Text || e.NodeType == XmlNodeType.CDATA)) - { - value = String.Join(String.Empty, nodes.Cast().Select(TrimTextValue)); - } - - return !String.IsNullOrEmpty(value); - } - - private static bool IsTextNode(XNode node, out XText text) - { - text = null; - - if (node.NodeType == XmlNodeType.Text || node.NodeType == XmlNodeType.CDATA) - { - text = (XText)node; - } - - return text != null; - } - - private static void TrimLeadingText(XDocument document) - { - while (IsTextNode(document.Nodes().FirstOrDefault(), out var text)) - { - text.Remove(); - } - } - - private static string TrimTextValue(XText text) - { - var value = text.Value; - - if (String.IsNullOrEmpty(value)) - { - return String.Empty; - } - else if (text.NodeType == XmlNodeType.CDATA && String.IsNullOrWhiteSpace(value)) - { - return " "; - } - - return value.Trim(); - } - - private static void RemoveChildren(XElement element) - { - var nodes = element.Nodes().ToList(); - foreach (var node in nodes) - { - node.Remove(); - } - } - - private static bool VisitElement(XElement element, Func visitor) - { - if (!visitor(element)) - { - return false; - } - - if (!element.Attributes().All(a => visitor(a))) - { - return false; - } - - return element.Elements().All(e => VisitElement(e, visitor)); - } - - private static bool WasImplicitlyStringTyped(string value) - { - if (value == null) - { - return false; - } - else if (value.StartsWith("v", StringComparison.OrdinalIgnoreCase)) - { - if (Int32.TryParse(value.Substring(1), NumberStyles.None, CultureInfo.InvariantCulture.NumberFormat, out var _)) - { - return false; - } - else if (Version.TryParse(value.Substring(1), out var _)) - { - return false; - } - } - else if (Int64.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture.NumberFormat, out var _)) - { - return false; - } - - return true; - } - - /// - /// Converter test types. These are used to condition error messages down to warnings. - /// - private enum ConverterTestType - { - /// - /// Internal-only: displayed when a string cannot be converted to an ConverterTestType. - /// - ConverterTestTypeUnknown, - - /// - /// Displayed when an XML loading exception has occurred. - /// - XmlException, - - /// - /// Displayed when the whitespace preceding a node is wrong. - /// - WhitespacePrecedingNodeWrong, - - /// - /// Displayed when the whitespace preceding an end element is wrong. - /// - WhitespacePrecedingEndElementWrong, - - /// Before this point, ignore errors on convert operation - EndIgnoreInConvert, - - /// - /// Displayed when the XML declaration is present in the source file. - /// - DeclarationPresent, - - /// - /// Displayed when a file cannot be accessed; typically when trying to save back a fixed file. - /// - UnauthorizedAccessException, - - /// After this point, ignore errors on format operation - BeginIgnoreInFormat, - - /// - /// Displayed when the xmlns attribute is missing from the document element. - /// - XmlnsMissing, - - /// - /// Displayed when the xmlns attribute on the document element is wrong. - /// - XmlnsValueWrong, - - /// - /// Displayed when inner text contains a deprecated $(loc.xxx) reference. - /// - DeprecatedLocalizationVariablePrefixInTextValue, - - /// - /// Displayed when an attribute value contains a deprecated $(loc.xxx) reference. - /// - DeprecatedLocalizationVariablePrefixInAttributeValue, - - /// - /// Assign an identifier to a File element when on Id attribute is specified. - /// - AssignAnonymousFileId, - - /// - /// SuppressSignatureValidation attribute is obsolete and corresponding functionality removed. - /// - BundleSignatureValidationObsolete, - - /// - /// WixCA Binary/@Id has been renamed to UtilCA. - /// - WixCABinaryIdRenamed, - - /// - /// QtExec custom actions have been renamed. - /// - QuietExecCustomActionsRenamed, - - /// - /// QtExecCmdTimeout was previously used for both CAQuietExec and CAQuietExec64. For WixQuietExec, use WixQuietExecCmdTimeout. For WixQuietExec64, use WixQuietExec64CmdTimeout. - /// - QtExecCmdTimeoutAmbiguous, - - /// - /// Directory/@ShortName may only be specified with Directory/@Name. - /// - AssignDirectoryNameFromShortName, - - /// - /// BootstrapperApplicationData attribute is deprecated and replaced with Unreal for MSI. Use BundleCustomData element for Bundles. - /// - BootstrapperApplicationDataDeprecated, - - /// - /// Inheritable is new and is now defaulted to 'yes' which is a change in behavior for all but children of CreateFolder. - /// - AssignPermissionExInheritable, - - /// - /// Column element's Category attribute is camel-case. - /// - ColumnCategoryCamelCase, - - /// - /// Column element's Modularize attribute is camel-case. - /// - ColumnModularizeCamelCase, - - /// - /// Inner text value should move to an attribute. - /// - InnerTextDeprecated, - - /// - /// Explicit auto-GUID unnecessary. - /// - AutoGuidUnnecessary, - - /// - /// The Feature Absent attribute renamed to AllowAbsent. - /// - FeatureAbsentAttributeReplaced, - - /// - /// The Feature AllowAdvertise attribute value deprecated. - /// - FeatureAllowAdvertiseValueDeprecated, - - /// - /// The Condition='1' attribute is unnecessary on Publish elements. - /// - PublishConditionOneUnnecessary, - - /// - /// DpiAwareness is new and is defaulted to 'perMonitorV2' which is a change in behavior. - /// - AssignBootstrapperApplicationDpiAwareness, - - /// - /// The string variable type was previously treated as formatted. - /// - AssignVariableTypeFormatted, - - /// - /// The CustomAction attributes have been renamed from BinaryKey and FileKey to BinaryRef and FileRef. - /// - CustomActionKeysAreNowRefs, - - /// - /// The Product and Package elements have been renamed and reorganized. - /// - ProductAndPackageRenamed, - - /// - /// The Module and Package elements have been renamed and reorganized. - /// - ModuleAndPackageRenamed, - - /// - /// A MediaTemplate with no attributes set is now provided by default. - /// - DefaultMediaTemplate, - - /// - /// util:RegistrySearch has breaking change when value is missing. - /// - UtilRegistryValueSearchBehaviorChange, - - /// - /// DisplayInternalUI can't be converted. - /// - DisplayInternalUiNotConvertable, - - /// - /// InstallerVersion has breaking change when missing. - /// - InstallerVersionBehaviorChange, - - /// - /// Verb/@Target can't be converted. - /// - VerbTargetNotConvertable, - - /// - /// The bootstrapper application dll is now specified in its own element. - /// - BootstrapperApplicationDll, - - /// - /// The new bootstrapper application dll element is required. - /// - BootstrapperApplicationDllRequired, - - /// - /// bal:UseUILanguages is deprecated, 'true' is now the standard behavior. - /// - BalUseUILanguagesDeprecated, - - /// - /// The custom elements for built-in BAs are now required. - /// - BalBootstrapperApplicationRefToElement, - - /// - /// The ExePackage elements "XxxCommand" attributes have been renamed to "XxxArguments". - /// - RenameExePackageCommandToArguments, - - /// - /// The Win64 attribute has been renamed. Use the Bitness attribute instead. - /// - Win64AttributeRenamed, - - /// - /// Breaking change: The Win64 attribute's value '{0}' cannot be converted automatically to the new Bitness attribute. - /// - Win64AttributeRenameCannotBeAutomatic, - - /// - /// The Tag element has been renamed. Use the element 'SoftwareTag' name. - /// - TagElementRenamed, - - /// - /// The Dependency namespace has been incorporated into WiX v4 namespace. - /// - IntegratedDependencyNamespace, - - /// - /// Remove unused namespaces. - /// - RemoveUnusedNamespaces, - - /// - /// The Remote element has been renamed. Use the "XxxPackagePayload" element instead. - /// - RemotePayloadRenamed, - - /// - /// The XxxPackage/@Name attribute must be specified on the child XxxPackagePayload element when using a remote payload. - /// - NameAttributeMovedToRemotePayload, - - /// - /// The XxxPackage/@Compressed attribute should not be specified when using a remote payload. - /// - CompressedAttributeUnnecessaryForRemotePayload, - - /// - /// The XxxPackage/@DownloadUrl attribute must be specified on the child XxxPackagePayload element when using a remote payload. - /// - DownloadUrlAttributeMovedToRemotePayload, - - /// - /// The hash algorithm used for bundles changed from SHA1 to SHA512. - /// - BurnHashAlgorithmChanged, - - /// - /// CustomTable elements can't always be converted. - /// - CustomTableNotAlwaysConvertable, - - /// - /// CustomTable elements that don't contain the table definition are now CustomTableRef. - /// - CustomTableRef, - - /// - /// The RegistryKey element's Action attribute is obsolete. - /// - RegistryKeyActionObsolete, - - /// - /// The TagRef element has been renamed. Use the element 'SoftwareTagRef' name. - /// - TagRefElementRenamed, - - /// - /// The SoftwareTag element's Licensed attribute is obsolete. - /// - SoftwareTagLicensedObsolete, - - /// - /// The SoftwareTag element's Type attribute is obsolete. - /// - SoftwareTagTypeObsolete, - - /// - /// TARGETDIR directory should not longer be explicitly defined. - /// - TargetDirDeprecated, - - /// - /// Standard directories should no longer be defined using the Directory element. - /// - DefiningStandardDirectoryDeprecated, - - /// - /// Naked custom action and property references replaced with WixUtilExtension elements. - /// - UtilReferencesReplaced, - } - } -} diff --git a/src/WixToolset.Converters/WixToolset.Converters.csproj b/src/WixToolset.Converters/WixToolset.Converters.csproj deleted file mode 100644 index 7dddefa5..00000000 --- a/src/WixToolset.Converters/WixToolset.Converters.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - netstandard2.0 - $(TargetFrameworks);net461;net472 - Converter - WiX Toolset Converters - embedded - true - true - - - - - - - - - - - diff --git a/src/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs b/src/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs deleted file mode 100644 index 084d3b92..00000000 --- a/src/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs +++ /dev/null @@ -1,25 +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 -{ - using WixToolset.Extensibility.Services; - - /// - /// Extension methods for adding Converters services. - /// - public static class WixToolsetCoreServiceProviderExtensions - { - /// - /// Adds Converters services. - /// - /// - /// - public static IWixToolsetCoreServiceProvider AddConverter(this IWixToolsetCoreServiceProvider coreProvider) - { - var extensionManager = coreProvider.GetService(); - extensionManager.Add(typeof(ConverterExtensionFactory).Assembly); - - return coreProvider; - } - } -} diff --git a/src/deps/wix.dll b/src/deps/wix.dll deleted file mode 100644 index 64f70f75..00000000 Binary files a/src/deps/wix.dll and /dev/null differ diff --git a/src/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs b/src/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs deleted file mode 100644 index 01213524..00000000 --- a/src/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.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, - 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/TestData/Integration/test.wixout b/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixout deleted file mode 100644 index da64b8af..00000000 Binary files a/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixout and /dev/null differ diff --git a/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj b/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj deleted file mode 100644 index d7c4e625..00000000 --- a/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - Debug - x86 - 3.10 - d59f1c1e-9238-49fa-bfa2-ec1d9c2dda1d - 2.0 - SymbolizerWixout - Package - - - bin\$(Configuration)\ - obj\$(Configuration)\ - Debug - - - bin\$(Configuration)\ - obj\$(Configuration)\ - - - - - - - $(WixExtDir)\WixUtilExtension.dll - WixUtilExtension - - - $(WixExtDir)\WixNetFxExtension.dll - WixNetFxExtension - - - - - - - - - \ No newline at end of file diff --git a/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs b/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs deleted file mode 100644 index 46d4fb43..00000000 --- a/src/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj b/src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj deleted file mode 100644 index 995d9297..00000000 --- a/src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - net461 - false - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject b/src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject deleted file mode 100644 index 18ab4f79..00000000 --- a/src/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject +++ /dev/null @@ -1,9 +0,0 @@ - - - - - WixToolsetTest.Converters.Symbolizer.ConvertSymbolsFixture.CanLoadWixoutAndConvertToIntermediate - - - - \ No newline at end of file diff --git a/src/test/WixToolsetTest.Converters/BaseConverterFixture.cs b/src/test/WixToolsetTest.Converters/BaseConverterFixture.cs deleted file mode 100644 index 2421d73b..00000000 --- a/src/test/WixToolsetTest.Converters/BaseConverterFixture.cs +++ /dev/null @@ -1,33 +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 -{ - using System; - using System.IO; - using System.Text; - using System.Xml; - using System.Xml.Linq; - using Xunit; - - public abstract class BaseConverterFixture - { - protected static string UnformattedDocumentString(XDocument document, bool omitXmlDeclaration = true) - { - var sb = new StringBuilder(); - - using (var writer = new StringWriter(sb)) - using (var xml = XmlWriter.Create(writer, new XmlWriterSettings { OmitXmlDeclaration = omitXmlDeclaration })) - { - document.Save(xml); - } - - return sb.ToString().TrimStart(); - } - - protected static string[] UnformattedDocumentLines(XDocument document, bool omitXmlDeclaration = true) - { - var unformatted = UnformattedDocumentString(document, omitXmlDeclaration); - return unformatted.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/BitnessFixture.cs b/src/test/WixToolsetTest.Converters/BitnessFixture.cs deleted file mode 100644 index e45a9388..00000000 --- a/src/test/WixToolsetTest.Converters/BitnessFixture.cs +++ /dev/null @@ -1,187 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class BitnessFixture : BaseConverterFixture - { - [Fact] - public void FixComponentBitness() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(10, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixRegistrySearchBitness() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixUtilRegistrySearchBitness() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(6, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixApprovedExeBitness() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs b/src/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs deleted file mode 100644 index 158ab3be..00000000 --- a/src/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs +++ /dev/null @@ -1,418 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class BootstrapperApplicationFixture : BaseConverterFixture - { - [Fact] - public void CantCreateBootstrapperApplicationDllFromV3PayloadGroupRef() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(2, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void ConvertDotNetCoreBootstrapperApplicationRefWithExistingElement() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(1, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void ConvertDotNetCoreBootstrapperApplicationRefWithoutExistingElement() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - "", - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(1, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void ConvertFrameworkBootstrapperApplicationRefWithExistingElement() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void ConvertFrameworkBootstrapperApplicationRefWithoutExistingElement() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - "", - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void ConvertStandardBootstrapperApplicationRefWithExistingElement() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void ConvertStandardBootstrapperApplicationRefWithoutExistingElement() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - "", - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void CreateBootstrapperApplicationDllFromV3() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - "", - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void CreateBootstrapperApplicationDllFromV3Payload() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - "", - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void DoesntSetDpiUnawareFromV4() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(0, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void KeepsDpiAwarenessFromV4() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - "", - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(1, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void RemovesBalUseUILanguages() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(5, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/ConditionFixture.cs b/src/test/WixToolsetTest.Converters/ConditionFixture.cs deleted file mode 100644 index d3f65aeb..00000000 --- a/src/test/WixToolsetTest.Converters/ConditionFixture.cs +++ /dev/null @@ -1,297 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class ConditionFixture : BaseConverterFixture - { - [Fact] - public void FixControlCondition() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " x=y", - " a<>b", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixPublishCondition() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " 1<2", - " 1", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(5, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixComponentCondition() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " 1<2", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixFeatureCondition() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " PROP = 1", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixLaunchCondition() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " 1<2", - " ", - " ", - " 1=2", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixLaunchConditionInProduct() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " 1<2", - " ", - " ", - " 1=2", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(6, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixPermissionExCondition() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " 1<2", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/ConverterFixture.cs b/src/test/WixToolsetTest.Converters/ConverterFixture.cs deleted file mode 100644 index 13df9da7..00000000 --- a/src/test/WixToolsetTest.Converters/ConverterFixture.cs +++ /dev/null @@ -1,449 +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 -{ - using System; - using System.Xml.Linq; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class ConverterFixture : BaseConverterFixture - { - private static readonly XNamespace Wix4Namespace = "http://wixtoolset.org/schemas/v4/wxs"; - - [Fact] - public void EnsuresNoDeclaration() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(1, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void EnsuresDeclarationWhenIgnored() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, ignoreErrors: new[] { "DeclarationPresent" } ); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document, omitXmlDeclaration: false); - - Assert.Equal(0, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertMainNamespace() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - //Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertNamedMainNamespace() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - Assert.Equal(Wix4Namespace, document.Root.GetNamespaceOfPrefix("w")); - } - - [Fact] - public void CanConvertNonWixDefaultNamespace() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(expected, actual); - Assert.Equal(3, errors); - Assert.Equal(Wix4Namespace, document.Root.GetNamespaceOfPrefix("w")); - Assert.Equal("http://wixtoolset.org/schemas/v4/wxs/util", document.Root.GetDefaultNamespace()); - } - - [Fact] - public void CanRemoveUnusedNamespaces() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(4, errors); - Assert.Equal(expected, actual); - Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); - } - - [Fact] - public void CanConvertMissingWixNamespace() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); - } - - [Fact] - public void CanConvertMissingIncludeNamespace() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); - } - - [Fact] - public void CanConvertAnonymousFile() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(3, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertShortNameDirectoryWithoutName() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertCatalogElement() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(1, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertSuppressSignatureValidationNo() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(1, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertSuppressSignatureValidationYes() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(1, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CantConvertVerbTarget() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertDeprecatedPrefix() - { - var parse = String.Join(Environment.NewLine, - "", - "", - "", - "", - "", - "", - "", - "", - ""); - - var expected = String.Join(Environment.NewLine, - "", - "", - "", - "", - "", - "", - "", - "", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(3, errors); - Assert.Equal(expected, actual); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs b/src/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs deleted file mode 100644 index a39f6243..00000000 --- a/src/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs +++ /dev/null @@ -1,195 +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 -{ - using System; - using System.IO; - using System.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolset.Core; - using WixToolset.Core.TestPackage; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class ConverterIntegrationFixture - { - [Fact] - public void CanConvertPermissionExFile() - { - const string beforeFileName = "v3.wxs"; - const string afterFileName = "v4_expected.wxs"; - var folder = TestData.Get(@"TestData\PermissionEx"); - - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(true); - var targetFile = Path.Combine(baseFolder, beforeFileName); - File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 4); - var errors = converter.ConvertFile(targetFile, true); - - Assert.Equal(8, errors); - - var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); - var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); - Assert.Equal(expected, actual); - - EnsureFixed(targetFile); - } - } - - [Fact] - public void CanConvertSingleFile() - { - const string beforeFileName = "SingleFile.wxs"; - const string afterFileName = "ConvertedSingleFile.wxs"; - var folder = TestData.Get(@"TestData\SingleFile"); - - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(true); - var targetFile = Path.Combine(baseFolder, beforeFileName); - File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 4); - var errors = converter.ConvertFile(targetFile, true); - - Assert.Equal(9, errors); - - var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); - var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); - Assert.Equal(expected, actual); - - EnsureFixed(targetFile); - } - } - - [Fact] - public void CanDetectReadOnlyOutputFile() - { - const string beforeFileName = "SingleFile.wxs"; - var folder = TestData.Get(@"TestData\SingleFile"); - - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(true); - var targetFile = Path.Combine(baseFolder, beforeFileName); - File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); - - var info = new FileInfo(targetFile); - info.IsReadOnly = true; - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 4); - var errors = converter.ConvertFile(targetFile, true); - - Assert.Single(messaging.Messages.Where(m => m.Id == 5/*WixConverter.ConverterTestType.UnauthorizedAccessException*/)); - } - } - - [Fact] - public void RetainsPreprocessorInstructions() - { - const string beforeFileName = "Preprocessor.wxs"; - const string afterFileName = "ConvertedPreprocessor.wxs"; - var folder = TestData.Get(@"TestData\Preprocessor"); - - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(true); - var targetFile = Path.Combine(baseFolder, beforeFileName); - File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); - - var settingsFile = Path.Combine(folder, "wixcop.settings.xml"); - - var result = RunConversion(targetFile, settingsFile: settingsFile); - Assert.Equal(9, result.ExitCode); - - var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); - var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); - Assert.Equal(expected, actual); - - EnsureFixed(targetFile); - } - } - - [Fact] - public void CanConvertQtExec() - { - const string beforeFileName = "v3.wxs"; - const string afterFileName = "v4_expected.wxs"; - var folder = TestData.Get(@"TestData\QtExec"); - - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(true); - var targetFile = Path.Combine(baseFolder, beforeFileName); - File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); - - var result = RunConversion(targetFile); - Assert.Equal(13, result.ExitCode); - - var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); - var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); - Assert.Equal(expected, actual); - - EnsureFixed(targetFile); - } - } - - [Fact] - public void DetectUnconvertableQtExecCmdTimeout() - { - const string beforeFileName = "v3.wxs"; - const string afterFileName = "v4_expected.wxs"; - var folder = TestData.Get(@"TestData\QtExec.bad"); - - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(true); - var targetFile = Path.Combine(baseFolder, beforeFileName); - File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); - - var result = RunConversion(targetFile); - - Assert.Equal(13, result.ExitCode); - Assert.Single(result.Messages.Where(message => message.ToString().EndsWith("(QtExecCmdTimeoutAmbiguous)"))); - - var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); - var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); - Assert.Equal(expected, actual); - - // still fails because QtExecCmdTimeoutAmbiguous is unfixable - var result2 = RunConversion(targetFile); - Assert.Equal(1, result2.ExitCode); - } - } - - private static WixRunnerResult RunConversion(string targetFile, bool fixErrors = true, string settingsFile = null) - { - var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider().AddConverter(); - - var exitCode = WixRunner.Execute(new[] - { - "convert", - fixErrors ? null : "--dry-run", - String.IsNullOrEmpty(settingsFile) ? null : "-set1" + settingsFile, - targetFile - }, serviceProvider, out var messages); - - return new WixRunnerResult { ExitCode = exitCode.Result, Messages = messages.ToArray() }; - } - - private static void EnsureFixed(string targetFile) - { - var messaging2 = new MockMessaging(); - var converter2 = new WixConverter(messaging2, 4); - var errors2 = converter2.ConvertFile(targetFile, true); - Assert.Equal(0, errors2); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/CustomActionFixture.cs b/src/test/WixToolsetTest.Converters/CustomActionFixture.cs deleted file mode 100644 index eafc171a..00000000 --- a/src/test/WixToolsetTest.Converters/CustomActionFixture.cs +++ /dev/null @@ -1,88 +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 -{ - using System; - using System.IO; - using System.Xml.Linq; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class CustomActionFixture : BaseConverterFixture - { - [Fact] - public void CanConvertCustomAction() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(11, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertCustomActionScript() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " function() {", - " var x = 0;", - " return x;", - " }", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expectedScript = String.Join("\n", - "function() {", - " var x = 0;", - " return x;", - " }"); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - - var script = File.ReadAllText("Foo.js"); - Assert.Equal(expectedScript, script); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/CustomTableFixture.cs b/src/test/WixToolsetTest.Converters/CustomTableFixture.cs deleted file mode 100644 index 2b81a863..00000000 --- a/src/test/WixToolsetTest.Converters/CustomTableFixture.cs +++ /dev/null @@ -1,363 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class CustomTableFixture : BaseConverterFixture - { - [Fact] - public void FixCustomTableCategoryAndModularization() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixCustomRowTextValue() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " Some value", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixCustomRowCdataValue() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixCustomRowWithoutValue() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void CanConvertBundleCustomTableBootstrapperApplicationData() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " Row1", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Bundle); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertBundleCustomTableRef() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " Row1", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Bundle); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertMsiCustomTableBootstrapperApplicationData() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " Row1", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Msi); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanConvertMsiCustomTableRef() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " Row1", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Msi); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(2, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanDetectAmbiguousCustomTableBootstrapperApplicationData() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(1, errors); - Assert.Equal(expected, actual); - } - - [Fact] - public void CanRemoveBootstrapperApplicationDataFromRealCustomTable() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(1, errors); - Assert.Equal(expected, actual); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/DependencyFixture.cs b/src/test/WixToolsetTest.Converters/DependencyFixture.cs deleted file mode 100644 index 41ded927..00000000 --- a/src/test/WixToolsetTest.Converters/DependencyFixture.cs +++ /dev/null @@ -1,178 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class DependencyFixture : BaseConverterFixture - { - [Fact] - public void FixPackageDependencyProvides() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(5, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixPackageDependencyRequires() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(7, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixPackageDependencyRequiresRef() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(7, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixBundleDependencyProvides() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(5, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/DirectoryFixture.cs b/src/test/WixToolsetTest.Converters/DirectoryFixture.cs deleted file mode 100644 index 3c906320..00000000 --- a/src/test/WixToolsetTest.Converters/DirectoryFixture.cs +++ /dev/null @@ -1,92 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class DirectoryFixture : BaseConverterFixture - { - [Fact] - public void RemoveTargetDir() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixStandardDirectory() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/ExePackageFixture.cs b/src/test/WixToolsetTest.Converters/ExePackageFixture.cs deleted file mode 100644 index 0ee8d065..00000000 --- a/src/test/WixToolsetTest.Converters/ExePackageFixture.cs +++ /dev/null @@ -1,49 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class ExePackageFixture : BaseConverterFixture - { - [Fact] - public void CanConvertExePackageCommandToArguments() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/FeatureFixture.cs b/src/test/WixToolsetTest.Converters/FeatureFixture.cs deleted file mode 100644 index 1df94a81..00000000 --- a/src/test/WixToolsetTest.Converters/FeatureFixture.cs +++ /dev/null @@ -1,110 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class FeatureFixture : BaseConverterFixture - { - [Fact] - public void FixAllowAttributes() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixDisallowAttributes() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void RemoveDeprecatedAllowAdvertiseAttributes() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs b/src/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs deleted file mode 100644 index a101019b..00000000 --- a/src/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs +++ /dev/null @@ -1,47 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class FirewallExtensionFixture : BaseConverterFixture - { - [Fact] - public void FixRemoteAddressValue() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " 127.0.0.1", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/FormatFixture.cs b/src/test/WixToolsetTest.Converters/FormatFixture.cs deleted file mode 100644 index 739fba66..00000000 --- a/src/test/WixToolsetTest.Converters/FormatFixture.cs +++ /dev/null @@ -1,117 +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 -{ - using System; - using System.Xml.Linq; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class FormatFixture : BaseConverterFixture - { - [Fact] - public void CanFixWhitespace() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 4, null, null); - - var errors = converter.FormatDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(expected, actual); - Assert.Equal(5, errors); - } - - [Fact] - public void CanPreserveNewLines() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - "", - " ", - "", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - "", - " ", - "", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 4, null, null); - - var conversions = converter.FormatDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(expected, actual); - Assert.Equal(4, conversions); - } - - [Fact] - public void CanFormatWithNewLineAtEndOfFile() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - "", - " ", - "", - " ", - "", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - "", - " ", - "", - " ", - "", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 4, null, null); - - var conversions = converter.FormatDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(expected, actual); - Assert.Equal(3, conversions); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/IncludeFixture.cs b/src/test/WixToolsetTest.Converters/IncludeFixture.cs deleted file mode 100644 index 2fd8244f..00000000 --- a/src/test/WixToolsetTest.Converters/IncludeFixture.cs +++ /dev/null @@ -1,68 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class IncludeFixture : BaseConverterFixture - { - [Fact] - public void EnsureNamespace() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = new[] - { - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(1, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixNamespace() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - ""); - - var expected = new[] - { - "", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(1, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs b/src/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs deleted file mode 100644 index b6bb8a40..00000000 --- a/src/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs +++ /dev/null @@ -1,51 +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.Mocks -{ - using System; - using System.Collections.Generic; - using WixToolset.Extensibility.Services; - - public class MockCoreServiceProvider : IWixToolsetCoreServiceProvider - { - public Dictionary, object>> CreationFunctions { get; } = new Dictionary, object>>(); - - public Dictionary Singletons { get; } = new Dictionary() - { - { typeof(IMessaging), new MockMessaging() } - }; - - public void AddService(Type serviceType, Func, object> creationFunction) => this.CreationFunctions.Add(serviceType, creationFunction); - - public void AddService(Func, T> creationFunction) where T : class => this.AddService(typeof(T), creationFunction); - - public T GetService() where T : class => this.TryGetService(typeof(T), out var obj) ? (T)obj : null; - - public object GetService(Type serviceType) => this.TryGetService(serviceType, out var service) ? service : null; - - public bool TryGetService(Type serviceType, out object service) - { - if (!this.Singletons.TryGetValue(serviceType, out service)) - { - if (this.CreationFunctions.TryGetValue(serviceType, out var creationFunction)) - { - service = creationFunction(this, this.Singletons); - } - } - - return service != null; - } - - public bool TryGetService(out T service) where T : class - { - service = null; - - if (this.TryGetService(typeof(T), out var obj)) - { - service = (T)obj; - } - - return service != null; - } - } -} \ No newline at end of file diff --git a/src/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs b/src/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs deleted file mode 100644 index 77821a1c..00000000 --- a/src/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs +++ /dev/null @@ -1,39 +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.Mocks -{ - using System; - using System.Collections.Generic; - using WixToolset.Data; - using WixToolset.Extensibility; - using WixToolset.Extensibility.Services; - - public class MockMessaging : IMessaging - { - public List Messages { get; } = new List(); - - public bool EncounteredError { get; private set; } - - public int LastErrorNumber { get; } - - public bool ShowVerboseMessages { get; set; } - - public bool SuppressAllWarnings { get; set; } - - public bool WarningsAsError { get; set; } - - public void ElevateWarningMessage(int warningNumber) => throw new NotImplementedException(); - - public void SetListener(IMessageListener listener) => throw new NotImplementedException(); - - public void SuppressWarningMessage(int warningNumber) => throw new NotImplementedException(); - - public void Write(Message message) - { - this.Messages.Add(message); - this.EncounteredError |= message.Level == MessageLevel.Error; - } - - public void Write(string message, bool verbose = false) => throw new NotImplementedException(); - } -} diff --git a/src/test/WixToolsetTest.Converters/ProductPackageFixture.cs b/src/test/WixToolsetTest.Converters/ProductPackageFixture.cs deleted file mode 100644 index e01b9789..00000000 --- a/src/test/WixToolsetTest.Converters/ProductPackageFixture.cs +++ /dev/null @@ -1,278 +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 -{ - using System; - using System.IO; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolset.Core.TestPackage; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class ProductPackageFixture : BaseConverterFixture - { - [Fact] - public void FixesCompressedWhenYes() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 4, expected); - } - - [Fact] - public void FixesCompressedWhenNo() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 4, expected); - } - - [Fact] - public void FixesCompressedWhenOmitted() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 4, expected); - } - - private static void AssertSuccess(string input, int expectedErrorCount, string[] expected) - { - var document = XDocument.Parse(input, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(expectedErrorCount, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixesInstallerVersion() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 3, expected); - } - - [Fact] - public void FixesDefaultInstallerVersion() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 3, expected); - } - - [Fact] - public void FixesImplicitInstallerVersion() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 4, expected); - } - - [Fact] - public void FixesNonDefaultInstallerVersion() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 3, expected); - } - - [Fact] - public void FixesLimitedInstallerPrivileges() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 4, expected); - } - - [Fact] - public void FixesElevatedInstallerPrivileges() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - "" - }; - - AssertSuccess(parse, 4, expected); - } - - [Fact] - public void CanDecompileAndRecompile() - { - using (var fs = new DisposableFileSystem()) - { - var baseFolder = fs.GetFolder(); - var intermediateFolder = Path.Combine(baseFolder, "obj"); - var decompiledWxsPath = Path.Combine(baseFolder, "TypicalV3.wxs"); - - var folder = TestData.Get(@"TestData\PackageSummaryInformation"); - var v3msiPath = Path.Combine(folder, "TypicalV3.msi"); - var result = WixRunner.Execute(new[] - { - "decompile", v3msiPath, - "-intermediateFolder", intermediateFolder, - "-o", decompiledWxsPath - }); - - result.AssertSuccess(); - - var v4msiPath = Path.Combine(intermediateFolder, "TypicalV4.msi"); - result = WixRunner.Execute(new[] - { - "build", decompiledWxsPath, - "-arch", "x64", - "-intermediateFolder", intermediateFolder, - "-o", v4msiPath - }); - - result.AssertSuccess(); - - Assert.True(File.Exists(v4msiPath)); - - var v3results = Query.QueryDatabase(v3msiPath, new[] { "_SummaryInformation", "Property" }); - var v4results = Query.QueryDatabase(v4msiPath, new[] { "_SummaryInformation", "Property" }); - WixAssert.CompareLineByLine(v3results, v4results); - } - } - } -} diff --git a/src/test/WixToolsetTest.Converters/PropertyFixture.cs b/src/test/WixToolsetTest.Converters/PropertyFixture.cs deleted file mode 100644 index e50a6518..00000000 --- a/src/test/WixToolsetTest.Converters/PropertyFixture.cs +++ /dev/null @@ -1,108 +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 -{ - using System; - using System.Xml.Linq; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class PropertyFixture : BaseConverterFixture - { - [Fact] - public void CanFixCdataWhitespace() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(expected, actual); - Assert.Equal(1, errors); - } - - [Fact] - public void CanFixCdataWithWhitespace() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(expected, actual); - Assert.Equal(1, errors); - } - - [Fact] - public void CanKeepCdataWithOnlyWhitespace() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - var errors = converter.ConvertDocument(document); - - var actual = UnformattedDocumentString(document); - - Assert.Equal(expected, actual); - Assert.Equal(1, errors); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/RegistryFixture.cs b/src/test/WixToolsetTest.Converters/RegistryFixture.cs deleted file mode 100644 index 405f5416..00000000 --- a/src/test/WixToolsetTest.Converters/RegistryFixture.cs +++ /dev/null @@ -1,54 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class RegistryFixture : BaseConverterFixture - { - [Fact] - public void FixRegistryKeyAction() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(5, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/RemotePayloadFixture.cs b/src/test/WixToolsetTest.Converters/RemotePayloadFixture.cs deleted file mode 100644 index b2640e13..00000000 --- a/src/test/WixToolsetTest.Converters/RemotePayloadFixture.cs +++ /dev/null @@ -1,104 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class RemotePayloadFixture : BaseConverterFixture - { - [Fact] - public void CanConvertExePackageRemotePayload() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(6, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void CanConvertMsuPackageRemotePayload() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(5, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/SequenceFixture.cs b/src/test/WixToolsetTest.Converters/SequenceFixture.cs deleted file mode 100644 index ec6c709b..00000000 --- a/src/test/WixToolsetTest.Converters/SequenceFixture.cs +++ /dev/null @@ -1,49 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class SequenceFixture : BaseConverterFixture - { - [Fact] - public void FixCondition() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " NOT Installed", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(2, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/TagFixture.cs b/src/test/WixToolsetTest.Converters/TagFixture.cs deleted file mode 100644 index 5e07c83b..00000000 --- a/src/test/WixToolsetTest.Converters/TagFixture.cs +++ /dev/null @@ -1,111 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class TagFixture : BaseConverterFixture - { - [Fact] - public void FixTagExtension() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixTagExtensionDeprecations() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(7, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixTagExtensionTagRef() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi b/src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi deleted file mode 100644 index 0d7e1b21..00000000 Binary files a/src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi and /dev/null differ diff --git a/src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs b/src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs deleted file mode 100644 index 8c5027b4..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs b/src/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs deleted file mode 100644 index 9a739052..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs b/src/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs deleted file mode 100644 index 6bf3c1ea..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs b/src/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs deleted file mode 100644 index 8188d900..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs b/src/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs deleted file mode 100644 index 2eb908c2..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml b/src/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml deleted file mode 100644 index 9d3ad496..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs b/src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs deleted file mode 100644 index b0fcf9c9..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs b/src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs deleted file mode 100644 index 95d2f618..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs b/src/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs deleted file mode 100644 index 8d81a758..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs b/src/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs deleted file mode 100644 index f24d3f8f..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs b/src/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs deleted file mode 100644 index 5bcdaf59..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs b/src/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs deleted file mode 100644 index 310ae811..00000000 --- a/src/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/WixToolsetTest.Converters/UtilExtensionFixture.cs b/src/test/WixToolsetTest.Converters/UtilExtensionFixture.cs deleted file mode 100644 index 10450c68..00000000 --- a/src/test/WixToolsetTest.Converters/UtilExtensionFixture.cs +++ /dev/null @@ -1,190 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class UtilExtensionFixture : BaseConverterFixture - { - [Fact] - public void FixCloseAppsCondition() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " a<>b", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixXmlConfigValue() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " a<>b", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void WarnsOnAllRegistryValueSearches() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(4, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - - [Fact] - public void FixXmlConfigValueCData() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " b]]>", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void FixQueryOsPropertyRefs() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(6, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/VariableFixture.cs b/src/test/WixToolsetTest.Converters/VariableFixture.cs deleted file mode 100644 index b7b7388f..00000000 --- a/src/test/WixToolsetTest.Converters/VariableFixture.cs +++ /dev/null @@ -1,86 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class VariableFixture : BaseConverterFixture - { - [Fact] - public void FixFormattedType() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(3, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - - [Fact] - public void DoesntFixFormattedTypeFromV4() - { - var parse = String.Join(Environment.NewLine, - "", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(0, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs b/src/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs deleted file mode 100644 index 16a68895..00000000 --- a/src/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs +++ /dev/null @@ -1,54 +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 -{ - using System; - using System.Xml.Linq; - using WixBuildTools.TestSupport; - using WixToolset.Converters; - using WixToolsetTest.Converters.Mocks; - using Xunit; - - public class Wix4ConversionFixture : BaseConverterFixture - { - [Fact] - public void DoesNotAddFileId() - { - var parse = String.Join(Environment.NewLine, - "", - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - ""); - - var expected = new[] - { - "", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - "" - }; - - var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); - - var messaging = new MockMessaging(); - var converter = new WixConverter(messaging, 2, null, null); - - var errors = converter.ConvertDocument(document); - Assert.Equal(1, errors); - - var actualLines = UnformattedDocumentLines(document); - WixAssert.CompareLineByLine(expected, actualLines); - } - } -} diff --git a/src/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj b/src/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj deleted file mode 100644 index 29b02b95..00000000 --- a/src/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - netcoreapp3.1 - false - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/version.json b/src/version.json new file mode 100644 index 00000000..5f857771 --- /dev/null +++ b/src/version.json @@ -0,0 +1,11 @@ +{ + "version": "4.0", + "publicReleaseRefSpec": [ + "^refs/heads/master$" + ], + "cloudBuild": { + "buildNumber": { + "enabled": true + } + } +} diff --git a/src/wix/Directory.Build.props b/src/wix/Directory.Build.props new file mode 100644 index 00000000..b3c6287c --- /dev/null +++ b/src/wix/Directory.Build.props @@ -0,0 +1,27 @@ + + + + + + Debug + false + MSB3246 + + $(MSBuildProjectName) + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\)) + $(BaseOutputPath)obj\$(ProjectName)\ + $(BaseOutputPath)$(Configuration)\ + + WiX Toolset Team + WiX Toolset + Copyright (c) .NET Foundation and contributors. All rights reserved. + MS-RL + WiX Toolset + + + + + diff --git a/src/wix/Directory.Build.targets b/src/wix/Directory.Build.targets new file mode 100644 index 00000000..2fcc765a --- /dev/null +++ b/src/wix/Directory.Build.targets @@ -0,0 +1,51 @@ + + + + + + + true + $(SolutionPath) + $(NCrunchOriginalSolutionPath) + + + + + + + $([System.IO.File]::ReadAllText($(TheSolutionPath))) + $([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) )) + (?<="[PackageName]", ")(.*)(?=", ") + + + + + + %(Identity) + $(SolutionFileContent.Contains('\%(Identity).csproj')) + + + + + $(RegexPattern.Replace('[PackageName]','%(PackageName)') ) + $([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)')) + + + + + + + + + + + + + + diff --git a/src/wix/Directory.csproj.props b/src/wix/Directory.csproj.props new file mode 100644 index 00000000..81d24ad1 --- /dev/null +++ b/src/wix/Directory.csproj.props @@ -0,0 +1,13 @@ + + + + + true + true + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk)) + false + + diff --git a/src/wix/Directory.csproj.targets b/src/wix/Directory.csproj.targets new file mode 100644 index 00000000..c3270426 --- /dev/null +++ b/src/wix/Directory.csproj.targets @@ -0,0 +1,26 @@ + + + + + false + $(OutputPath)\$(AssemblyName).xml + + + + + $(PrivateRepositoryUrl.Replace('.git','')) + + $(MSBuildProjectName).nuspec + $(OutputPath)..\ + $(NuspecProperties);Id=$(PackageId);Authors=$(Authors);Copyright=$(Copyright);Description=$(Description);Title=$(Title) + $(NuspecProperties);Version=$(PackageVersion);RepositoryCommit=$(SourceRevisionId);RepositoryType=$(RepositoryType);RepositoryUrl=$(PrivateRepositoryUrl);ProjectFolder=$(MSBuildProjectDirectory)\;ProjectUrl=$(ProjectUrl) + true + snupkg + + + + diff --git a/src/wix/README.md b/src/wix/README.md new file mode 100644 index 00000000..f031cf7c --- /dev/null +++ b/src/wix/README.md @@ -0,0 +1,2 @@ +# Converters +WixToolset.Converters, conversion related functionality diff --git a/src/wix/WixToolset.Converters.Symbolizer/ConvertSymbols.cs b/src/wix/WixToolset.Converters.Symbolizer/ConvertSymbols.cs new file mode 100644 index 00000000..6418b2a6 --- /dev/null +++ b/src/wix/WixToolset.Converters.Symbolizer/ConvertSymbols.cs @@ -0,0 +1,876 @@ +// 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; + +#pragma warning disable 1591 // TODO: add documentation + 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) +#pragma warning restore 1591 + { + var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type)); + + 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.AddSymbol(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.Global, 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.Global, 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.Global, 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": + { + var splitName = FieldAsString(row, 3)?.Split('|'); + + var symbol = new DuplicateFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) + { + ComponentRef = FieldAsString(row, 1), + FileRef = FieldAsString(row, 2), + DestinationName = splitName == null ? null : splitName.Length > 1 ? splitName[1] : splitName[0], + DestinationShortName = splitName == null ? null : splitName.Length > 1 ? splitName[0] : null, + DestinationFolder = FieldAsString(row, 4) + }; + + return symbol; + } + 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.Global, 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 splitName = FieldAsString(row, 2).Split('|'); + + var symbol = new FileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, id)) + { + ComponentRef = FieldAsString(row, 1), + Name = splitName.Length > 1 ? splitName[1] : splitName[0], + ShortName = splitName.Length > 1 ? splitName[0] : null, + 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.PatchAttributes = (PatchAttributeType)FieldAsInt(wixFileRow, 10); + } + + return symbol; + } + case "Font": + return null; + case "Icon": + return DefaultSymbolFromRow(typeof(IconSymbol), row, columnZeroIsId: true); + case "IniFile": + { + var splitName = FieldAsString(row, 1).Split('|'); + var action = FieldAsInt(row, 6); + + var symbol = new IniFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) + { + FileName = splitName.Length > 1 ? splitName[1] : splitName[0], + ShortFileName = splitName.Length > 1 ? splitName[0] : null, + DirProperty = FieldAsString(row, 2), + Section = FieldAsString(row, 3), + Key = FieldAsString(row, 4), + Value = FieldAsString(row, 5), + Action = action == 3 ? IniFileActionType.AddTag : action == 1 ? IniFileActionType.CreateLine : IniFileActionType.AddLine, + ComponentRef = FieldAsString(row, 7), + }; + + return symbol; + } + case "IniLocator": + { + var splitName = FieldAsString(row, 1).Split('|'); + + var symbol = new IniLocatorSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) + { + FileName = splitName.Length > 1 ? splitName[1] : splitName[0], + ShortFileName = splitName.Length > 1 ? splitName[0] : null, + Section = FieldAsString(row, 2), + Key = FieldAsString(row, 3), + Field = FieldAsInt(row, 4), + Type = FieldAsInt(row, 5), + }; + + return symbol; + } + 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.Global, 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.Global, 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.Global, 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.Global, 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 splitName = FieldAsString(row, 2).Split('|'); + var installMode = FieldAsInt(row, 4); + + return new RemoveFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Global, FieldAsString(row, 0))) + { + ComponentRef = FieldAsString(row, 1), + FileName = splitName.Length > 1 ? splitName[1] : splitName[0], + ShortFileName = splitName.Length > 1 ? splitName[0] : null, + DirPropertyRef = 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.Global, 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.Global, 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.Global, 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.Global, 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 new WixSuppressModularizationSymbol(SourceLineNumber4(row.SourceLineNumbers)) + { + SuppressIdentifier = FieldAsString(row, 0) + }; + } + 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 id = columnZeroIsId ? GetIdentifierForRow(row) : null; + + var createSymbol = symbolType.GetConstructor(new[] { typeof(SourceLineNumber), typeof(Identifier) }); + var symbol = (IntermediateSymbol)createSymbol.Invoke(new object[] { SourceLineNumber4(row.SourceLineNumbers), id }); + + SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); + + 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 id = columnZeroIsId ? GetIdentifierForRow(row) : null; + + var createSymbol = typeof(IntermediateSymbol).GetConstructor(new[] { typeof(IntermediateSymbolDefinition), typeof(SourceLineNumber), typeof(Identifier) }); + var symbol = (IntermediateSymbol)createSymbol.Invoke(new object[] { symbolDefinition, SourceLineNumber4(row.SourceLineNumbers), id }); + + SetSymbolFieldsFromRow(row, symbol, columnZeroIsId); + + return symbol; + } + + private static void SetSymbolFieldsFromRow(Wix3.Row row, IntermediateSymbol symbol, bool columnZeroIsId) + { + var offset = 0; + if (columnZeroIsId) + { + 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.Global, (string)row.Fields[0].Data); + case Wix3.ColumnType.Number: + return new Identifier(AccessModifier.Global, 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/wix/WixToolset.Converters.Symbolizer/WixToolset.Converters.Symbolizer.csproj b/src/wix/WixToolset.Converters.Symbolizer/WixToolset.Converters.Symbolizer.csproj new file mode 100644 index 00000000..445c3500 --- /dev/null +++ b/src/wix/WixToolset.Converters.Symbolizer/WixToolset.Converters.Symbolizer.csproj @@ -0,0 +1,32 @@ + + + + + + + netstandard2.0 + $(TargetFrameworks);net461;net472 + Symbolizer + WiX Toolset Converters Tuplizer + embedded + true + true + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/WixToolset.Converters.sln b/src/wix/WixToolset.Converters.sln new file mode 100644 index 00000000..ae8a3d92 --- /dev/null +++ b/src/wix/WixToolset.Converters.sln @@ -0,0 +1,85 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Converters", "WixToolset.Converters\WixToolset.Converters.csproj", "{6FAF6385-6598-4B89-972B-C31AFCA14538}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Converters.Symbolizer", "WixToolset.Converters.Symbolizer\WixToolset.Converters.Symbolizer.csproj", "{F051BCAF-698C-41D5-8427-164537CE5C5C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{1B16A6C1-2B5D-4F9A-9DD5-FBC89B3CE31E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Converters", "test\WixToolsetTest.Converters\WixToolsetTest.Converters.csproj", "{485C5038-97E1-4729-A54D-848CC69569FD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Converters.Symbolizer", "test\WixToolsetTest.Converters.Symbolizer\WixToolsetTest.Converters.Symbolizer.csproj", "{9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x64.ActiveCfg = Debug|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x64.Build.0 = Debug|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x86.ActiveCfg = Debug|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Debug|x86.Build.0 = Debug|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|Any CPU.Build.0 = Release|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x64.ActiveCfg = Release|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x64.Build.0 = Release|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x86.ActiveCfg = Release|Any CPU + {F051BCAF-698C-41D5-8427-164537CE5C5C}.Release|x86.Build.0 = Release|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x64.ActiveCfg = Debug|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x64.Build.0 = Debug|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x86.ActiveCfg = Debug|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Debug|x86.Build.0 = Debug|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|Any CPU.Build.0 = Release|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x64.ActiveCfg = Release|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x64.Build.0 = Release|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x86.ActiveCfg = Release|Any CPU + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C}.Release|x86.Build.0 = Release|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x64.ActiveCfg = Debug|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x64.Build.0 = Debug|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x86.ActiveCfg = Debug|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Debug|x86.Build.0 = Debug|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|Any CPU.Build.0 = Release|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x64.ActiveCfg = Release|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x64.Build.0 = Release|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x86.ActiveCfg = Release|Any CPU + {6FAF6385-6598-4B89-972B-C31AFCA14538}.Release|x86.Build.0 = Release|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x64.ActiveCfg = Debug|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x64.Build.0 = Debug|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x86.ActiveCfg = Debug|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Debug|x86.Build.0 = Debug|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Release|Any CPU.Build.0 = Release|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x64.ActiveCfg = Release|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x64.Build.0 = Release|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x86.ActiveCfg = Release|Any CPU + {485C5038-97E1-4729-A54D-848CC69569FD}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {9DB36DB1-24A1-47A7-9E57-D48A2E33C13C} = {1B16A6C1-2B5D-4F9A-9DD5-FBC89B3CE31E} + {485C5038-97E1-4729-A54D-848CC69569FD} = {1B16A6C1-2B5D-4F9A-9DD5-FBC89B3CE31E} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2E71F0EC-CF75-44DA-8353-7066EBD06564} + EndGlobalSection +EndGlobal diff --git a/src/wix/WixToolset.Converters.v3.ncrunchsolution b/src/wix/WixToolset.Converters.v3.ncrunchsolution new file mode 100644 index 00000000..f774ab93 --- /dev/null +++ b/src/wix/WixToolset.Converters.v3.ncrunchsolution @@ -0,0 +1,6 @@ + + + False + True + + \ No newline at end of file diff --git a/src/wix/WixToolset.Converters/ConvertCommand.cs b/src/wix/WixToolset.Converters/ConvertCommand.cs new file mode 100644 index 00000000..b6826f43 --- /dev/null +++ b/src/wix/WixToolset.Converters/ConvertCommand.cs @@ -0,0 +1,60 @@ +// 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 +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using WixToolset.Extensibility.Services; + + internal class ConvertCommand : FixupCommandBase + { + private const string SettingsFileDefault = "wix.convert.settings.xml"; + + public ConvertCommand(IServiceProvider serviceProvider) + { + this.Messaging = serviceProvider.GetService(); + } + + private IMessaging Messaging { get; } + + public override Task ExecuteAsync(CancellationToken cancellationToken) + { + if (this.ShowHelp) + { + DisplayHelp(); + return Task.FromResult(-1); + } + + this.ParseSettings(SettingsFileDefault); + + var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); + + var errors = base.Inspect(Inspector, cancellationToken); + + return Task.FromResult(errors); + + int Inspector(string file, bool fix) + { + return converter.ConvertFile(file, fix); + } + } + + private static void DisplayHelp() + { + Console.WriteLine(); + Console.WriteLine("Usage: wix convert [options] sourceFile [sourceFile ...]"); + Console.WriteLine(); + Console.WriteLine("Options:"); + Console.WriteLine(" -h|--help Show command line help."); + Console.WriteLine(" --nologo Suppress displaying the logo information."); + Console.WriteLine(" -n|--dry-run Only display errors, do not update files."); + Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs."); + Console.WriteLine(" -set1 Primary settings file."); + Console.WriteLine(" -set2 Secondary settings file (overrides primary)."); + Console.WriteLine(" -indent: Indentation multiple (overrides default of 4)."); + Console.WriteLine(); + Console.WriteLine(" sourceFile may use wildcards like *.wxs"); + } + } +} diff --git a/src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs b/src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs new file mode 100644 index 00000000..06d3658c --- /dev/null +++ b/src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs @@ -0,0 +1,46 @@ +// 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 +{ + using System; + using System.Collections.Generic; + using WixToolset.Extensibility; + using WixToolset.Extensibility.Data; + using WixToolset.Extensibility.Services; + + /// + /// Parses the "convert" command-line command. See ConvertCommand for + /// the bulk of the command-line processing. + /// + internal class ConverterExtensionCommandLine : BaseExtensionCommandLine + { + public ConverterExtensionCommandLine(IServiceProvider serviceProvider) + { + this.ServiceProvider = serviceProvider; + } + + private IServiceProvider ServiceProvider { get; } + + public override IReadOnlyCollection CommandLineSwitches => new ExtensionCommandLineSwitch[] + { + new ExtensionCommandLineSwitch { Switch = "convert", Description = "Convert v3 source code to v4 source code." }, + new ExtensionCommandLineSwitch { Switch = "format", Description = "Ensures consistent formatting of source code." }, + }; + + public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command) + { + command = null; + + if ("convert".Equals(argument, StringComparison.OrdinalIgnoreCase)) + { + command = new ConvertCommand(this.ServiceProvider); + } + else if ("format".Equals(argument, StringComparison.OrdinalIgnoreCase)) + { + command = new FormatCommand(this.ServiceProvider); + } + + return command != null; + } + } +} diff --git a/src/wix/WixToolset.Converters/ConverterExtensionFactory.cs b/src/wix/WixToolset.Converters/ConverterExtensionFactory.cs new file mode 100644 index 00000000..d4f480aa --- /dev/null +++ b/src/wix/WixToolset.Converters/ConverterExtensionFactory.cs @@ -0,0 +1,30 @@ +// 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 +{ + using System; + using WixToolset.Extensibility; + using WixToolset.Extensibility.Services; + + internal class ConverterExtensionFactory : IExtensionFactory + { + public ConverterExtensionFactory(IServiceProvider serviceProvider) + { + this.ServiceProvider = serviceProvider; + } + + private IServiceProvider ServiceProvider { get; } + + public bool TryCreateExtension(Type extensionType, out object extension) + { + extension = null; + + if (extensionType == typeof(IExtensionCommandLine)) + { + extension = new ConverterExtensionCommandLine(this.ServiceProvider); + } + + return extension != null; + } + } +} diff --git a/src/wix/WixToolset.Converters/FixupCommandBase.cs b/src/wix/WixToolset.Converters/FixupCommandBase.cs new file mode 100644 index 00000000..21282d07 --- /dev/null +++ b/src/wix/WixToolset.Converters/FixupCommandBase.cs @@ -0,0 +1,288 @@ +// 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 +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using System.Xml; + using WixToolset.Extensibility.Data; + using WixToolset.Extensibility.Services; + + internal abstract class FixupCommandBase : ICommandLineCommand + { + protected FixupCommandBase() + { + this.IndentationAmount = 4; // default indentation amount + this.ErrorsAsWarnings = new HashSet(); + this.ExemptFiles = new HashSet(); + this.IgnoreErrors = new HashSet(); + this.SearchPatternResults = new HashSet(); + this.SearchPatterns = new List(); + } + + public bool ShowLogo { get; private set; } + + public bool StopParsing { get; private set; } + + protected bool ShowHelp { get; set; } + + protected CustomTableTarget CustomTableSetting { get; set; } + + protected bool DryRun { get; set; } + + protected HashSet ErrorsAsWarnings { get; } + + protected HashSet IgnoreErrors { get; } + + protected HashSet ExemptFiles { get; } + + protected int IndentationAmount { get; set; } + + protected bool Recurse { get; set; } + + private HashSet SearchPatternResults { get; } + + private List SearchPatterns { get; } + + private string SettingsFile1 { get; set; } + + private string SettingsFile2 { get; set; } + + public bool TryParseArgument(ICommandLineParser parser, string argument) + { + if (!parser.IsSwitch(argument)) + { + this.SearchPatterns.Add(argument); + return true; + } + + var parameter = argument.Substring(1); + switch (parameter.ToLowerInvariant()) + { + case "?": + case "h": + case "-help": + this.ShowHelp = true; + this.ShowLogo = true; + this.StopParsing = true; + return true; + + case "-custom-table": + var customTableSetting = parser.GetNextArgumentOrError(argument); + switch (customTableSetting) + { + case "bundle": + this.CustomTableSetting = CustomTableTarget.Bundle; + break; + case "msi": + this.CustomTableSetting = CustomTableTarget.Msi; + break; + default: + parser.ReportErrorArgument(argument); + break; + } + return true; + + case "n": + case "-dry-run": + this.DryRun = true; + return true; + + case "nologo": + case "-nologo": + this.ShowLogo = false; + return true; + + case "s": + case "r": + case "-recurse": + case "-recursive": + this.Recurse = true; + return true; + + default: // other parameters + if (parameter.StartsWith("set1", StringComparison.Ordinal)) + { + this.SettingsFile1 = parameter.Substring(4); + return true; + } + else if (parameter.StartsWith("set2", StringComparison.Ordinal)) + { + this.SettingsFile2 = parameter.Substring(4); + return true; + } + else if (parameter.StartsWith("indent:", StringComparison.Ordinal)) + { + try + { + this.IndentationAmount = Convert.ToInt32(parameter.Substring(7)); + } + catch + { + parser.ReportErrorArgument(parameter); // $"Invalid numeric argument: {parameter}"; + } + return true; + } + + return false; + } + } + + public abstract Task ExecuteAsync(CancellationToken cancellationToken); + + protected void ParseSettings(string defaultSettingsFile) + { + // parse the settings if any were specified + if (null != this.SettingsFile1 || null != this.SettingsFile2) + { + this.ParseSettingsFiles(this.SettingsFile1, this.SettingsFile2); + } + else + { + if (File.Exists(defaultSettingsFile)) + { + this.ParseSettingsFiles(defaultSettingsFile, null); + } + } + } + + protected int Inspect(Func inspector, CancellationToken cancellationToken) + { + var errors = this.InspectSubDirectories(inspector, Path.GetFullPath("."), cancellationToken); + + foreach (var searchPattern in this.SearchPatterns) + { + if (!this.SearchPatternResults.Contains(searchPattern)) + { + Console.Error.WriteLine("Could not find file \"{0}\"", searchPattern); + errors++; + } + } + + return errors; + } + + /// + /// Inspect sub-directories. + /// + /// + /// The directory whose sub-directories will be inspected. + /// + /// The number of errors that were found. + private int InspectSubDirectories(Func inspector, string directory, CancellationToken cancellationToken) + { + var errors = 0; + + foreach (var searchPattern in this.SearchPatterns) + { + foreach (var sourceFilePath in GetFiles(directory, searchPattern)) + { + cancellationToken.ThrowIfCancellationRequested(); + + var file = new FileInfo(sourceFilePath); + + if (!this.ExemptFiles.Contains(file.Name.ToUpperInvariant())) + { + this.SearchPatternResults.Add(searchPattern); + errors += inspector(file.FullName, !this.DryRun); + } + } + } + + if (this.Recurse) + { + foreach (var childDirectoryPath in Directory.GetDirectories(directory)) + { + errors += this.InspectSubDirectories(inspector, childDirectoryPath, cancellationToken); + } + } + + return errors; + } + + /// + /// Parse the primary and secondary settings files. + /// + /// The primary settings file. + /// The secondary settings file. + private void ParseSettingsFiles(string localSettingsFile1, string localSettingsFile2) + { + if (null == localSettingsFile1 && null != localSettingsFile2) + { + throw new ArgumentException("Cannot specify a secondary settings file (set2) without a primary settings file (set1).", nameof(localSettingsFile2)); + } + + var settingsFile = localSettingsFile1; + while (null != settingsFile) + { + var doc = new XmlDocument(); + doc.Load(settingsFile); + + // get the types of tests that will have their errors displayed as warnings + var testsIgnoredElements = doc.SelectNodes("/Settings/IgnoreErrors/Test"); + foreach (XmlElement test in testsIgnoredElements) + { + var key = test.GetAttribute("Id"); + this.IgnoreErrors.Add(key); + } + + // get the types of tests that will have their errors displayed as warnings + var testsAsWarningsElements = doc.SelectNodes("/Settings/ErrorsAsWarnings/Test"); + foreach (XmlElement test in testsAsWarningsElements) + { + var key = test.GetAttribute("Id"); + this.ErrorsAsWarnings.Add(key); + } + + // get the exempt files + var localExemptFiles = doc.SelectNodes("/Settings/ExemptFiles/File"); + foreach (XmlElement file in localExemptFiles) + { + var key = file.GetAttribute("Name").ToUpperInvariant(); + this.ExemptFiles.Add(key); + } + + settingsFile = localSettingsFile2; + localSettingsFile2 = null; + } + } + + /// + /// Get the files that match a search path pattern. + /// + /// The base directory at which to begin the search. + /// The search path pattern. + /// The files matching the pattern. + private static string[] GetFiles(string baseDir, string searchPath) + { + // convert alternate directory separators to the standard one + var filePath = searchPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + var lastSeparator = filePath.LastIndexOf(Path.DirectorySeparatorChar); + string[] files = null; + + try + { + if (0 > lastSeparator) + { + files = Directory.GetFiles(baseDir, filePath); + } + else // found directory separator + { + var searchPattern = filePath.Substring(lastSeparator + 1); + + files = Directory.GetFiles(filePath.Substring(0, lastSeparator + 1), searchPattern); + } + } + catch (DirectoryNotFoundException) + { + // don't let this function throw the DirectoryNotFoundException. (this exception + // occurs for non-existant directories and invalid characters in the searchPattern) + } + + return files; + } + } +} diff --git a/src/wix/WixToolset.Converters/FormatCommand.cs b/src/wix/WixToolset.Converters/FormatCommand.cs new file mode 100644 index 00000000..0861fc51 --- /dev/null +++ b/src/wix/WixToolset.Converters/FormatCommand.cs @@ -0,0 +1,60 @@ +// 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 +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using WixToolset.Extensibility.Services; + + internal class FormatCommand : FixupCommandBase + { + private const string SettingsFileDefault = "wix.format.settings.xml"; + + public FormatCommand(IServiceProvider serviceProvider) + { + this.Messaging = serviceProvider.GetService(); + } + + private IMessaging Messaging { get; } + + public override Task ExecuteAsync(CancellationToken cancellationToken) + { + if (this.ShowHelp) + { + DisplayHelp(); + return Task.FromResult(-1); + } + + var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); + + this.ParseSettings(SettingsFileDefault); + + var errors = base.Inspect(Inspector, cancellationToken); + + return Task.FromResult(errors); + + int Inspector(string file, bool fix) + { + return converter.FormatFile(file, fix); + } + } + + private static void DisplayHelp() + { + Console.WriteLine(); + Console.WriteLine("Usage: wix format [options] sourceFile [sourceFile ...]"); + Console.WriteLine(); + Console.WriteLine("Options:"); + Console.WriteLine(" -h|--help Show command line help."); + Console.WriteLine(" --nologo Suppress displaying the logo information."); + Console.WriteLine(" -n|--dry-run Only display errors, do not update files."); + Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs."); + Console.WriteLine(" -set1 Primary settings file."); + Console.WriteLine(" -set2 Secondary settings file (overrides primary)."); + Console.WriteLine(" -indent: Indentation multiple (overrides default of 4)."); + Console.WriteLine(); + Console.WriteLine(" sourceFile may use wildcards like *.wxs"); + } + } +} diff --git a/src/wix/WixToolset.Converters/WixConverter.cs b/src/wix/WixToolset.Converters/WixConverter.cs new file mode 100644 index 00000000..e42d0605 --- /dev/null +++ b/src/wix/WixToolset.Converters/WixConverter.cs @@ -0,0 +1,2435 @@ +// 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 +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using System.Text.RegularExpressions; + using System.Xml; + using System.Xml.Linq; + using WixToolset.Data; + using WixToolset.Data.WindowsInstaller; + using WixToolset.Extensibility.Services; + + /// + /// How to convert CustomTable elements. + /// + public enum CustomTableTarget + { + /// + /// Ambiguous elements will be left alone. + /// + Unknown, + + /// + /// Use CustomTable, CustomTableRef, and Unreal. + /// + Msi, + + /// + /// Use BundleCustomData and BundleCustomDataRef. + /// + Bundle, + } + + /// + /// WiX source code converter. + /// + public sealed class WixConverter + { + private enum ConvertOperation + { + Convert, + Format, + } + + private static readonly Regex AddPrefix = new Regex(@"^[^a-zA-Z_]", RegexOptions.Compiled); + private static readonly Regex IllegalIdentifierCharacters = new Regex(@"[^A-Za-z0-9_\.]|\.{2,}", RegexOptions.Compiled); // non 'words' and assorted valid characters + + private const char XDocumentNewLine = '\n'; // XDocument normalizes "\r\n" to just "\n". + private static readonly XNamespace WixNamespace = "http://wixtoolset.org/schemas/v4/wxs"; + private static readonly XNamespace Wix3Namespace = "http://schemas.microsoft.com/wix/2006/wi"; + private static readonly XNamespace WixBalNamespace = "http://wixtoolset.org/schemas/v4/wxs/bal"; + private static readonly XNamespace WixDependencyNamespace = "http://wixtoolset.org/schemas/v4/wxs/dependency"; + private static readonly XNamespace WixUtilNamespace = "http://wixtoolset.org/schemas/v4/wxs/util"; + private static readonly XNamespace WixFirewallNamespace = "http://wixtoolset.org/schemas/v4/wxs/firewall"; + + private static readonly XName AdminExecuteSequenceElementName = WixNamespace + "AdminExecuteSequence"; + private static readonly XName AdminUISequenceSequenceElementName = WixNamespace + "AdminUISequence"; + private static readonly XName AdvertiseExecuteSequenceElementName = WixNamespace + "AdvertiseExecuteSequence"; + private static readonly XName InstallExecuteSequenceElementName = WixNamespace + "InstallExecuteSequence"; + private static readonly XName InstallUISequenceSequenceElementName = WixNamespace + "InstallUISequence"; + private static readonly XName BootstrapperApplicationElementName = WixNamespace + "BootstrapperApplication"; + private static readonly XName BootstrapperApplicationDllElementName = WixNamespace + "BootstrapperApplicationDll"; + private static readonly XName BootstrapperApplicationRefElementName = WixNamespace + "BootstrapperApplicationRef"; + private static readonly XName ApprovedExeForElevationElementName = WixNamespace + "ApprovedExeForElevation"; + private static readonly XName BundleAttributeElementName = WixNamespace + "BundleAttribute"; + private static readonly XName BundleAttributeDefinitionElementName = WixNamespace + "BundleAttributeDefinition"; + private static readonly XName BundleCustomDataElementName = WixNamespace + "BundleCustomData"; + private static readonly XName BundleCustomDataRefElementName = WixNamespace + "BundleCustomDataRef"; + private static readonly XName BundleElementElementName = WixNamespace + "BundleElement"; + private static readonly XName CustomTableElementName = WixNamespace + "CustomTable"; + private static readonly XName CustomTableRefElementName = WixNamespace + "CustomTableRef"; + private static readonly XName CatalogElementName = WixNamespace + "Catalog"; + private static readonly XName ColumnElementName = WixNamespace + "Column"; + private static readonly XName ComponentElementName = WixNamespace + "Component"; + private static readonly XName ControlElementName = WixNamespace + "Control"; + private static readonly XName ConditionElementName = WixNamespace + "Condition"; + private static readonly XName CreateFolderElementName = WixNamespace + "CreateFolder"; + private static readonly XName DataElementName = WixNamespace + "Data"; + private static readonly XName OldProvidesElementName = WixDependencyNamespace + "Provides"; + private static readonly XName OldRequiresElementName = WixDependencyNamespace + "Requires"; + private static readonly XName OldRequiresRefElementName = WixDependencyNamespace + "RequiresRef"; + private static readonly XName DirectoryElementName = WixNamespace + "Directory"; + private static readonly XName EmbeddedChainerElementName = WixNamespace + "EmbeddedChainer"; + private static readonly XName ErrorElementName = WixNamespace + "Error"; + private static readonly XName FeatureElementName = WixNamespace + "Feature"; + private static readonly XName FileElementName = WixNamespace + "File"; + private static readonly XName FragmentElementName = WixNamespace + "Fragment"; + private static readonly XName FirewallRemoteAddressElementName = WixFirewallNamespace + "RemoteAddress"; + private static readonly XName LaunchElementName = WixNamespace + "Launch"; + private static readonly XName LevelElementName = WixNamespace + "Level"; + private static readonly XName ExePackageElementName = WixNamespace + "ExePackage"; + private static readonly XName ExePackagePayloadElementName = WixNamespace + "ExePackagePayload"; + private static readonly XName ModuleElementName = WixNamespace + "Module"; + private static readonly XName MsiPackageElementName = WixNamespace + "MsiPackage"; + private static readonly XName MspPackageElementName = WixNamespace + "MspPackage"; + private static readonly XName MsuPackageElementName = WixNamespace + "MsuPackage"; + private static readonly XName MsuPackagePayloadElementName = WixNamespace + "MsuPackagePayload"; + private static readonly XName PackageElementName = WixNamespace + "Package"; + private static readonly XName PayloadElementName = WixNamespace + "Payload"; + private static readonly XName PermissionExElementName = WixNamespace + "PermissionEx"; + private static readonly XName ProductElementName = WixNamespace + "Product"; + private static readonly XName ProgressTextElementName = WixNamespace + "ProgressText"; + private static readonly XName PropertyRefElementName = WixNamespace + "PropertyRef"; + private static readonly XName PublishElementName = WixNamespace + "Publish"; + private static readonly XName ProvidesElementName = WixNamespace + "Provides"; + private static readonly XName RequiresElementName = WixNamespace + "Requires"; + private static readonly XName RequiresRefElementName = WixNamespace + "RequiresRef"; + private static readonly XName MultiStringValueElementName = WixNamespace + "MultiStringValue"; + private static readonly XName RemotePayloadElementName = WixNamespace + "RemotePayload"; + private static readonly XName RegistryKeyElementName = WixNamespace + "RegistryKey"; + private static readonly XName RegistrySearchElementName = WixNamespace + "RegistrySearch"; + private static readonly XName RequiredPrivilegeElementName = WixNamespace + "RequiredPrivilege"; + private static readonly XName RowElementName = WixNamespace + "Row"; + private static readonly XName ServiceArgumentElementName = WixNamespace + "ServiceArgument"; + private static readonly XName SetDirectoryElementName = WixNamespace + "SetDirectory"; + private static readonly XName SetPropertyElementName = WixNamespace + "SetProperty"; + private static readonly XName ShortcutPropertyElementName = WixNamespace + "ShortcutProperty"; + private static readonly XName SoftwareTagElementName = WixNamespace + "SoftwareTag"; + private static readonly XName SoftwareTagRefElementName = WixNamespace + "SoftwareTagRef"; + private static readonly XName StandardDirectoryElementName = WixNamespace + "StandardDirectory"; + private static readonly XName TagElementName = XNamespace.None + "Tag"; + private static readonly XName TagRefElementName = XNamespace.None + "TagRef"; + private static readonly XName TextElementName = WixNamespace + "Text"; + private static readonly XName UITextElementName = WixNamespace + "UIText"; + private static readonly XName VariableElementName = WixNamespace + "Variable"; + private static readonly XName VerbElementName = WixNamespace + "Verb"; + private static readonly XName BalUseUILanguagesName = WixBalNamespace + "UseUILanguages"; + private static readonly XName BalStandardBootstrapperApplicationName = WixBalNamespace + "WixStandardBootstrapperApplication"; + private static readonly XName BalManagedBootstrapperApplicationHostName = WixBalNamespace + "WixManagedBootstrapperApplicationHost"; + private static readonly XName BalOldDotNetCoreBootstrapperApplicationName = WixBalNamespace + "WixDotNetCoreBootstrapperApplication"; + private static readonly XName BalNewDotNetCoreBootstrapperApplicationName = WixBalNamespace + "WixDotNetCoreBootstrapperApplicationHost"; + private static readonly XName UtilCloseApplicationElementName = WixUtilNamespace + "CloseApplication"; + private static readonly XName UtilPermissionExElementName = WixUtilNamespace + "PermissionEx"; + private static readonly XName UtilRegistrySearchName = WixUtilNamespace + "RegistrySearch"; + private static readonly XName UtilXmlConfigElementName = WixUtilNamespace + "XmlConfig"; + private static readonly XName CustomActionElementName = WixNamespace + "CustomAction"; + private static readonly XName CustomActionRefElementName = WixNamespace + "CustomActionRef"; + private static readonly XName PropertyElementName = WixNamespace + "Property"; + private static readonly XName Wix4ElementName = WixNamespace + "Wix"; + private static readonly XName Wix3ElementName = Wix3Namespace + "Wix"; + private static readonly XName WixElementWithoutNamespaceName = XNamespace.None + "Wix"; + private static readonly XName Include4ElementName = WixNamespace + "Include"; + private static readonly XName Include3ElementName = Wix3Namespace + "Include"; + private static readonly XName IncludeElementWithoutNamespaceName = XNamespace.None + "Include"; + private static readonly XName SummaryInformationElementName = WixNamespace + "SummaryInformation"; + private static readonly XName MediaTemplateElementName = WixNamespace + "MediaTemplate"; + + private static readonly XName DependencyCheckAttributeName = WixDependencyNamespace + "Check"; + private static readonly XName DependencyEnforceAttributeName = WixDependencyNamespace + "Enforce"; + + private static readonly Dictionary OldToNewNamespaceMapping = new Dictionary() + { + { "http://schemas.microsoft.com/wix/BalExtension", "http://wixtoolset.org/schemas/v4/wxs/bal" }, + { "http://schemas.microsoft.com/wix/ComPlusExtension", "http://wixtoolset.org/schemas/v4/wxs/complus" }, + { "http://schemas.microsoft.com/wix/DependencyExtension", WixDependencyNamespace }, + { "http://schemas.microsoft.com/wix/DifxAppExtension", "http://wixtoolset.org/schemas/v4/wxs/difxapp" }, + { "http://schemas.microsoft.com/wix/FirewallExtension", "http://wixtoolset.org/schemas/v4/wxs/firewall" }, + { "http://schemas.microsoft.com/wix/HttpExtension", "http://wixtoolset.org/schemas/v4/wxs/http" }, + { "http://schemas.microsoft.com/wix/IIsExtension", "http://wixtoolset.org/schemas/v4/wxs/iis" }, + { "http://schemas.microsoft.com/wix/MsmqExtension", "http://wixtoolset.org/schemas/v4/wxs/msmq" }, + { "http://schemas.microsoft.com/wix/NetFxExtension", "http://wixtoolset.org/schemas/v4/wxs/netfx" }, + { "http://schemas.microsoft.com/wix/PSExtension", "http://wixtoolset.org/schemas/v4/wxs/powershell" }, + { "http://schemas.microsoft.com/wix/SqlExtension", "http://wixtoolset.org/schemas/v4/wxs/sql" }, + { "http://schemas.microsoft.com/wix/TagExtension", XNamespace.None }, + { "http://schemas.microsoft.com/wix/UtilExtension", WixUtilNamespace }, + { "http://schemas.microsoft.com/wix/VSExtension", "http://wixtoolset.org/schemas/v4/wxs/vs" }, + { "http://wixtoolset.org/schemas/thmutil/2010", "http://wixtoolset.org/schemas/v4/thmutil" }, + { "http://schemas.microsoft.com/wix/2009/Lux", "http://wixtoolset.org/schemas/v4/lux" }, + { "http://schemas.microsoft.com/wix/2006/wi", "http://wixtoolset.org/schemas/v4/wxs" }, + { "http://schemas.microsoft.com/wix/2006/localization", "http://wixtoolset.org/schemas/v4/wxl" }, + { "http://schemas.microsoft.com/wix/2006/libraries", "http://wixtoolset.org/schemas/v4/wixlib" }, + { "http://schemas.microsoft.com/wix/2006/objects", "http://wixtoolset.org/schemas/v4/wixobj" }, + { "http://schemas.microsoft.com/wix/2006/outputs", "http://wixtoolset.org/schemas/v4/wixout" }, + { "http://schemas.microsoft.com/wix/2007/pdbs", "http://wixtoolset.org/schemas/v4/wixpdb" }, + { "http://schemas.microsoft.com/wix/2003/04/actions", "http://wixtoolset.org/schemas/v4/wi/actions" }, + { "http://schemas.microsoft.com/wix/2006/tables", "http://wixtoolset.org/schemas/v4/wi/tables" }, + { "http://schemas.microsoft.com/wix/2006/WixUnit", "http://wixtoolset.org/schemas/v4/wixunit" }, + }; + + private readonly Dictionary> ConvertElementMapping; + private readonly Regex DeprecatedPrefixRegex = new Regex(@"(?<=(^|[^\$])(\$\$)*)\$(?=\(loc\.[^.].*\))", + RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture); + + /// + /// Instantiate a new Converter class. + /// + /// + /// Indentation value to use when validating leading whitespace. + /// Test errors to display as warnings. + /// Test errors to ignore. + /// How to convert CustomTable elements. + public WixConverter(IMessaging messaging, int indentationAmount, IEnumerable errorsAsWarnings = null, IEnumerable ignoreErrors = null, CustomTableTarget customTableTarget = CustomTableTarget.Unknown) + { + this.ConvertElementMapping = new Dictionary> + { + { WixConverter.AdminExecuteSequenceElementName, this.ConvertSequenceElement }, + { WixConverter.AdminUISequenceSequenceElementName, this.ConvertSequenceElement }, + { WixConverter.AdvertiseExecuteSequenceElementName, this.ConvertSequenceElement }, + { WixConverter.InstallUISequenceSequenceElementName, this.ConvertSequenceElement }, + { WixConverter.InstallExecuteSequenceElementName, this.ConvertSequenceElement }, + { WixConverter.BootstrapperApplicationElementName, this.ConvertBootstrapperApplicationElement }, + { WixConverter.BootstrapperApplicationRefElementName, this.ConvertBootstrapperApplicationRefElement }, + { WixConverter.ApprovedExeForElevationElementName, this.ConvertApprovedExeForElevationElement }, + { WixConverter.CatalogElementName, this.ConvertCatalogElement }, + { WixConverter.ColumnElementName, this.ConvertColumnElement }, + { WixConverter.ComponentElementName, this.ConvertComponentElement }, + { WixConverter.ControlElementName, this.ConvertControlElement }, + { WixConverter.CustomActionElementName, this.ConvertCustomActionElement }, + { WixConverter.CustomTableElementName, this.ConvertCustomTableElement }, + { WixConverter.DataElementName, this.ConvertDataElement }, + { WixConverter.DirectoryElementName, this.ConvertDirectoryElement }, + { WixConverter.FeatureElementName, this.ConvertFeatureElement }, + { WixConverter.FileElementName, this.ConvertFileElement }, + { WixConverter.FragmentElementName, this.ConvertFragmentElement }, + { WixConverter.FirewallRemoteAddressElementName, this.ConvertFirewallRemoteAddressElement }, + { WixConverter.EmbeddedChainerElementName, this.ConvertEmbeddedChainerElement }, + { WixConverter.ErrorElementName, this.ConvertErrorElement }, + { WixConverter.ExePackageElementName, this.ConvertExePackageElement }, + { WixConverter.ModuleElementName, this.ConvertModuleElement }, + { WixConverter.MsiPackageElementName, this.ConvertWindowsInstallerPackageElement }, + { WixConverter.MspPackageElementName, this.ConvertWindowsInstallerPackageElement }, + { WixConverter.MsuPackageElementName, this.ConvertSuppressSignatureValidation }, + { WixConverter.OldProvidesElementName, this.ConvertProvidesElement }, + { WixConverter.OldRequiresElementName, this.ConvertRequiresElement }, + { WixConverter.OldRequiresRefElementName, this.ConvertRequiresRefElement }, + { WixConverter.PayloadElementName, this.ConvertSuppressSignatureValidation }, + { WixConverter.PermissionExElementName, this.ConvertPermissionExElement }, + { WixConverter.ProductElementName, this.ConvertProductElement }, + { WixConverter.ProgressTextElementName, this.ConvertProgressTextElement }, + { WixConverter.PropertyRefElementName, this.ConvertPropertyRefElement }, + { WixConverter.PublishElementName, this.ConvertPublishElement }, + { WixConverter.MultiStringValueElementName, this.ConvertMultiStringValueElement }, + { WixConverter.RegistryKeyElementName, this.ConvertRegistryKeyElement }, + { WixConverter.RegistrySearchElementName, this.ConvertRegistrySearchElement }, + { WixConverter.RemotePayloadElementName, this.ConvertRemotePayloadElement }, + { WixConverter.RequiredPrivilegeElementName, this.ConvertRequiredPrivilegeElement }, + { WixConverter.CustomActionRefElementName, this.ConvertCustomActionRefElement }, + { WixConverter.ServiceArgumentElementName, this.ConvertServiceArgumentElement }, + { WixConverter.SetDirectoryElementName, this.ConvertSetDirectoryElement }, + { WixConverter.SetPropertyElementName, this.ConvertSetPropertyElement }, + { WixConverter.ShortcutPropertyElementName, this.ConvertShortcutPropertyElement }, + { WixConverter.TagElementName, this.ConvertTagElement }, + { WixConverter.TagRefElementName, this.ConvertTagRefElement }, + { WixConverter.TextElementName, this.ConvertTextElement }, + { WixConverter.UITextElementName, this.ConvertUITextElement }, + { WixConverter.VariableElementName, this.ConvertVariableElement }, + { WixConverter.UtilCloseApplicationElementName, this.ConvertUtilCloseApplicationElementName }, + { WixConverter.UtilPermissionExElementName, this.ConvertUtilPermissionExElement }, + { WixConverter.UtilRegistrySearchName, this.ConvertUtilRegistrySearchElement }, + { WixConverter.UtilXmlConfigElementName, this.ConvertUtilXmlConfigElement }, + { WixConverter.PropertyElementName, this.ConvertPropertyElement }, + { WixConverter.WixElementWithoutNamespaceName, this.ConvertElementWithoutNamespace }, + { WixConverter.IncludeElementWithoutNamespaceName, this.ConvertElementWithoutNamespace }, + { WixConverter.VerbElementName, this.ConvertVerbElement }, + }; + + this.Messaging = messaging; + + this.IndentationAmount = indentationAmount; + + this.ErrorsAsWarnings = new HashSet(this.YieldConverterTypes(errorsAsWarnings)); + + this.IgnoreErrors = new HashSet(this.YieldConverterTypes(ignoreErrors)); + + this.CustomTableSetting = customTableTarget; + } + + private CustomTableTarget CustomTableSetting { get; } + + private int Errors { get; set; } + + private HashSet ErrorsAsWarnings { get; set; } + + private HashSet IgnoreErrors { get; set; } + + private IMessaging Messaging { get; } + + private int IndentationAmount { get; set; } + + private ConvertOperation Operation { get; set; } + + private string SourceFile { get; set; } + + private int SourceVersion { get; set; } + + /// + /// Convert a file. + /// + /// The file to convert. + /// Option to save the converted errors that are found. + /// The number of errors found. + public int ConvertFile(string sourceFile, bool saveConvertedFile) + { + var document = this.OpenSourceFile(sourceFile); + + if (document is null) + { + return 1; + } + + this.ConvertDocument(document); + + // Fix errors if requested and necessary. + if (saveConvertedFile && 0 < this.Errors) + { + this.SaveDocument(document); + } + + return this.Errors; + } + + /// + /// Convert a document. + /// + /// The document to convert. + /// The number of errors found. + public int ConvertDocument(XDocument document) + { + // Reset the instance info. + this.Errors = 0; + this.SourceVersion = 0; + this.Operation = ConvertOperation.Convert; + + // Remove the declaration. + if (null != document.Declaration + && this.OnError(ConverterTestType.DeclarationPresent, null, "This file contains an XML declaration on the first line.")) + { + document.Declaration = null; + TrimLeadingText(document); + } + + // Start converting the nodes at the top. + this.ConvertNodes(document.Nodes(), 0); + this.RemoveUnusedNamespaces(document.Root); + + return this.Errors; + } + + /// + /// Format a file. + /// + /// The file to format. + /// Option to save the format errors that are found. + /// The number of errors found. + public int FormatFile(string sourceFile, bool saveConvertedFile) + { + var document = this.OpenSourceFile(sourceFile); + + if (document is null) + { + return 1; + } + + this.FormatDocument(document); + + // Fix errors if requested and necessary. + if (saveConvertedFile && 0 < this.Errors) + { + this.SaveDocument(document); + } + + return this.Errors; + } + + /// + /// Format a document. + /// + /// The document to format. + /// The number of errors found. + public int FormatDocument(XDocument document) + { + // Reset the instance info. + this.Errors = 0; + this.SourceVersion = 0; + this.Operation = ConvertOperation.Format; + + // Remove the declaration. + if (null != document.Declaration + && this.OnError(ConverterTestType.DeclarationPresent, null, "This file contains an XML declaration on the first line.")) + { + document.Declaration = null; + TrimLeadingText(document); + } + + // Start converting the nodes at the top. + this.ConvertNodes(document.Nodes(), 0); + this.RemoveUnusedNamespaces(document.Root); + + return this.Errors; + } + + private XDocument OpenSourceFile(string sourceFile) + { + this.SourceFile = sourceFile; + + try + { + return XDocument.Load(this.SourceFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + } + catch (XmlException e) + { + this.OnError(ConverterTestType.XmlException, null, "The xml is invalid. Detail: '{0}'", e.Message); + } + + return null; + } + + private void SaveDocument(XDocument document) + { + var ignoreDeclarationError = this.IgnoreErrors.Contains(ConverterTestType.DeclarationPresent); + + try + { + using (var writer = XmlWriter.Create(this.SourceFile, new XmlWriterSettings { OmitXmlDeclaration = !ignoreDeclarationError })) + { + document.Save(writer); + } + } + catch (UnauthorizedAccessException) + { + this.OnError(ConverterTestType.UnauthorizedAccessException, null, "Could not write to file."); + } + } + + private void ConvertNodes(IEnumerable nodes, int level) + { + // Note we operate on a copy of the node list since we may + // remove some whitespace nodes during this processing. + foreach (var node in nodes.ToList()) + { + if (node is XText text) + { + if (null != text.Value) + { + if (this.TryFixDeprecatedLocalizationPrefixes(node, text.Value, out var newValue, ConverterTestType.DeprecatedLocalizationVariablePrefixInTextValue)) + { + text.Value = newValue; + } + } + if (!String.IsNullOrWhiteSpace(text.Value)) + { + text.Value = text.Value.Trim(); + } + else if (node.NextNode is XCData cdata) + { + this.EnsurePrecedingWhitespaceRemoved(text, node, ConverterTestType.WhitespacePrecedingNodeWrong); + } + else if (node.NextNode is XElement element) + { + this.EnsurePrecedingWhitespaceCorrect(text, node, level, ConverterTestType.WhitespacePrecedingNodeWrong); + } + else if (node.NextNode is null) // this is the space before the close element + { + if (node.PreviousNode is null || node.PreviousNode is XCData) + { + this.EnsurePrecedingWhitespaceRemoved(text, node.Parent, ConverterTestType.WhitespacePrecedingEndElementWrong); + } + else if (level == 0) // root element's close tag + { + this.EnsurePrecedingWhitespaceCorrect(text, node, 0, ConverterTestType.WhitespacePrecedingEndElementWrong); + } + else + { + this.EnsurePrecedingWhitespaceCorrect(text, node, level - 1, ConverterTestType.WhitespacePrecedingEndElementWrong); + } + } + } + else if (node is XElement element) + { + this.ConvertElement(element); + + var before = element.Nodes().ToList(); + + this.ConvertNodes(before, level + 1); + + // If any nodes were added during the processing of the children, + // ensure those added children get processed as well. + var added = element.Nodes().Except(before).ToList(); + + if (added.Any()) + { + this.ConvertNodes(added, level + 1); + } + } + } + } + + private bool TryFixDeprecatedLocalizationPrefixes(XNode node, string value, out string newValue, ConverterTestType testType) + { + newValue = this.DeprecatedPrefixRegex.Replace(value, "!"); + + if (object.ReferenceEquals(newValue, value)) + { + return false; + } + + var message = testType == ConverterTestType.DeprecatedLocalizationVariablePrefixInTextValue ? "The prefix on the localization variable in the inner text is incorrect." : "The prefix on the localization variable in the attribute value is incorrect."; + + return this.OnError(testType, node, message); + } + + private void EnsurePrecedingWhitespaceCorrect(XText whitespace, XNode node, int level, ConverterTestType testType) + { + if (!WixConverter.LeadingWhitespaceValid(this.IndentationAmount, level, whitespace.Value)) + { + var message = testType == ConverterTestType.WhitespacePrecedingEndElementWrong ? "The whitespace preceding this end element is incorrect." : "The whitespace preceding this node is incorrect."; + + if (this.OnError(testType, node, message)) + { + WixConverter.FixupWhitespace(this.IndentationAmount, level, whitespace); + } + } + } + + private void EnsurePrecedingWhitespaceRemoved(XText whitespace, XNode node, ConverterTestType testType) + { + if (!String.IsNullOrEmpty(whitespace.Value) && whitespace.NodeType != XmlNodeType.CDATA) + { + var message = testType == ConverterTestType.WhitespacePrecedingEndElementWrong ? "The whitespace preceding this end element is incorrect." : "The whitespace preceding this node is incorrect."; + + if (this.OnError(testType, node, message)) + { + whitespace.Remove(); + } + } + } + + private void ConvertElement(XElement element) + { + var deprecatedToUpdatedNamespaces = new Dictionary(); + + foreach (var attribute in element.Attributes()) + { + if (attribute.IsNamespaceDeclaration) + { + // Gather any deprecated namespaces, then update this element tree based on those deprecations. + var declaration = attribute; + + if (element.Name == Wix3ElementName || element.Name == Include3ElementName) + { + this.SourceVersion = 3; + } + else if (element.Name == Wix4ElementName || element.Name == Include4ElementName) + { + this.SourceVersion = 4; + } + + if (WixConverter.OldToNewNamespaceMapping.TryGetValue(declaration.Value, out var ns)) + { + if (this.OnError(ConverterTestType.XmlnsValueWrong, declaration, "The namespace '{0}' is out of date. It must be '{1}'.", declaration.Value, ns.NamespaceName)) + { + deprecatedToUpdatedNamespaces.Add(declaration.Value, ns); + } + } + } + else + { + if (null != attribute.Value) + { + if (this.TryFixDeprecatedLocalizationPrefixes(element, attribute.Value, out var newValue, ConverterTestType.DeprecatedLocalizationVariablePrefixInAttributeValue)) + { + attribute.Value = newValue; + } + } + } + } + + if (deprecatedToUpdatedNamespaces.Any()) + { + WixConverter.UpdateElementsWithDeprecatedNamespaces(element.DescendantsAndSelf(), deprecatedToUpdatedNamespaces); + } + + // Apply any specialized conversion actions. + if (this.ConvertElementMapping.TryGetValue(element.Name, out var convert)) + { + convert(element); + } + } + + private void ConvertBootstrapperApplicationElement(XElement element) + { + var xUseUILanguages = element.Attribute(BalUseUILanguagesName); + if (xUseUILanguages != null && + this.OnError(ConverterTestType.BalUseUILanguagesDeprecated, element, "bal:UseUILanguages is deprecated, 'true' is now the standard behavior.")) + { + xUseUILanguages.Remove(); + } + + var xBADll = element.Elements(BootstrapperApplicationDllElementName).FirstOrDefault(); + if (xBADll == null) + { + xBADll = this.CreateBootstrapperApplicationDllElement(element); + + if (xBADll != null) + { + element.Add(Environment.NewLine); + element.Add(xBADll); + element.Add(Environment.NewLine); + } + } + } + + private XElement CreateBootstrapperApplicationDllElement(XElement element) + { + XElement xBADll = null; + var xSource = element.Attribute("SourceFile"); + var xDpiAwareness = element.Attribute("DpiAwareness"); + + if (xSource != null) + { + if (xBADll != null || CreateBADllElement(element, out xBADll)) + { + MoveAttribute(element, "SourceFile", xBADll); + MoveAttribute(element, "Name", xBADll); + } + } + else if (xDpiAwareness != null || this.SourceVersion < 4) // older code might be relying on old behavior of first Payload element being the BA dll. + { + var xFirstChild = element.Elements().FirstOrDefault(); + if (xFirstChild?.Name == PayloadElementName) + { + if (xBADll != null || CreateBADllElement(element, out xBADll)) + { + var attributes = xFirstChild.Attributes().ToList(); + xFirstChild.Remove(); + + foreach (var attribute in attributes) + { + xBADll.Add(attribute); + } + } + } + else + { + this.OnError(ConverterTestType.BootstrapperApplicationDllRequired, element, "The new BootstrapperApplicationDll element is required but could not be added automatically since the bootstrapper application dll was not directly specified."); + } + } + + if (xDpiAwareness != null) + { + if (xBADll != null || CreateBADllElement(element, out xBADll)) + { + MoveAttribute(element, "DpiAwareness", xBADll); + } + } + else if (this.SourceVersion < 4 && xBADll != null && + this.OnError(ConverterTestType.AssignBootstrapperApplicationDpiAwareness, element, "The BootstrapperApplicationDll DpiAwareness attribute is being set to 'unaware' to ensure it remains the same as the v3 default")) + { + xBADll.Add(new XAttribute("DpiAwareness", "unaware")); + } + + return xBADll; + + bool CreateBADllElement(XObject node, out XElement xCreatedBADll) + { + var create = this.OnError(ConverterTestType.BootstrapperApplicationDll, node, "The bootstrapper application dll is now specified in the BootstrapperApplicationDll element."); + xCreatedBADll = create ? new XElement(BootstrapperApplicationDllElementName) : null; + return create; + } + } + + private void ConvertBootstrapperApplicationRefElement(XElement element) + { + var xUseUILanguages = element.Attribute(BalUseUILanguagesName); + if (xUseUILanguages != null && + this.OnError(ConverterTestType.BalUseUILanguagesDeprecated, element, "bal:UseUILanguages is deprecated, 'true' is now the standard behavior.")) + { + xUseUILanguages.Remove(); + } + + var xId = element.Attribute("Id"); + if (xId != null) + { + XName balBAName = null; + XName oldBalBAName = null; + string theme = null; + + switch (xId.Value) + { + case "WixStandardBootstrapperApplication.RtfLicense": + balBAName = BalStandardBootstrapperApplicationName; + theme = "rtfLicense"; + break; + case "WixStandardBootstrapperApplication.RtfLargeLicense": + balBAName = BalStandardBootstrapperApplicationName; + theme = "rtfLargeLicense"; + break; + case "WixStandardBootstrapperApplication.HyperlinkLicense": + balBAName = BalStandardBootstrapperApplicationName; + theme = "hyperlinkLicense"; + break; + case "WixStandardBootstrapperApplication.HyperlinkLargeLicense": + balBAName = BalStandardBootstrapperApplicationName; + theme = "hyperlinkLargeLicense"; + break; + case "WixStandardBootstrapperApplication.HyperlinkSidebarLicense": + balBAName = BalStandardBootstrapperApplicationName; + theme = "hyperlinkSidebarLicense"; + break; + case "WixStandardBootstrapperApplication.Foundation": + balBAName = BalStandardBootstrapperApplicationName; + theme = "none"; + break; + case "ManagedBootstrapperApplicationHost": + case "ManagedBootstrapperApplicationHost.RtfLicense": + balBAName = BalManagedBootstrapperApplicationHostName; + theme = "standard"; + break; + case "ManagedBootstrapperApplicationHost.Minimal": + case "ManagedBootstrapperApplicationHost.RtfLicense.Minimal": + case "ManagedBootstrapperApplicationHost.Foundation": + balBAName = BalManagedBootstrapperApplicationHostName; + theme = "none"; + break; + case "DotNetCoreBootstrapperApplicationHost": + case "DotNetCoreBootstrapperApplicationHost.RtfLicense": + balBAName = BalNewDotNetCoreBootstrapperApplicationName; + oldBalBAName = BalOldDotNetCoreBootstrapperApplicationName; + theme = "standard"; + break; + case "DotNetCoreBootstrapperApplicationHost.Minimal": + case "DotNetCoreBootstrapperApplicationHost.RtfLicense.Minimal": + case "DotNetCoreBootstrapperApplicationHost.Foundation": + balBAName = BalNewDotNetCoreBootstrapperApplicationName; + oldBalBAName = BalOldDotNetCoreBootstrapperApplicationName; + theme = "none"; + break; + } + + if (balBAName != null && theme != null && + this.OnError(ConverterTestType.BalBootstrapperApplicationRefToElement, element, "Built-in bootstrapper applications must be referenced through their custom element")) + { + element.Name = BootstrapperApplicationElementName; + xId.Remove(); + this.ConvertBalBootstrapperApplicationRef(element, theme, balBAName, oldBalBAName); + } + } + } + + private void ConvertApprovedExeForElevationElement(XElement element) + { + this.RenameWin64ToBitness(element); + } + + private void ConvertBalBootstrapperApplicationRef(XElement element, string theme, XName balBAElementName, XName oldBalBAElementName = null) + { + var xBalBa = element.Element(oldBalBAElementName ?? balBAElementName); + if (xBalBa == null) + { + xBalBa = new XElement(balBAElementName); + element.Add(Environment.NewLine); + element.Add(xBalBa); + element.Add(Environment.NewLine); + } + else if (oldBalBAElementName != null) + { + xBalBa.Name = BalNewDotNetCoreBootstrapperApplicationName; + } + + if (theme != "standard") + { + xBalBa.Add(new XAttribute("Theme", theme)); + } + } + + private void ConvertCatalogElement(XElement element) + { + if (this.OnError(ConverterTestType.BundleSignatureValidationObsolete, element, "The Catalog element is obsolete. Signature validation is no longer supported. The element will be removed.")) + { + element.Remove(); + } + } + + private void ConvertColumnElement(XElement element) + { + var category = element.Attribute("Category"); + if (category != null) + { + var camelCaseValue = LowercaseFirstChar(category.Value); + if (category.Value != camelCaseValue && + this.OnError(ConverterTestType.ColumnCategoryCamelCase, element, "The CustomTable Category attribute contains an incorrectly cased '{0}' value. Lowercase the first character instead.", category.Name)) + { + category.Value = camelCaseValue; + } + } + + var modularization = element.Attribute("Modularize"); + if (modularization != null) + { + var camelCaseValue = LowercaseFirstChar(modularization.Value); + if (modularization.Value != camelCaseValue && + this.OnError(ConverterTestType.ColumnModularizeCamelCase, element, "The CustomTable Modularize attribute contains an incorrectly cased '{0}' value. Lowercase the first character instead.", modularization.Name)) + { + modularization.Value = camelCaseValue; + } + } + } + + private void ConvertCustomTableElement(XElement element) + { + var bootstrapperApplicationData = element.Attribute("BootstrapperApplicationData"); + if (bootstrapperApplicationData?.Value == "no") + { + if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'Unreal' attribute instead.", bootstrapperApplicationData.Name)) + { + bootstrapperApplicationData.Remove(); + } + } + else + { + if (element.Elements(ColumnElementName).Any() || bootstrapperApplicationData != null) + { + // Table definition + if (bootstrapperApplicationData != null) + { + switch (this.CustomTableSetting) + { + case CustomTableTarget.Bundle: + if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'BundleCustomData' element for Bundles.", bootstrapperApplicationData.Name)) + { + element.Name = WixConverter.BundleCustomDataElementName; + bootstrapperApplicationData.Remove(); + this.ConvertCustomTableElementToBundle(element); + } + break; + case CustomTableTarget.Msi: + if (this.OnError(ConverterTestType.BootstrapperApplicationDataDeprecated, element, "The CustomTable element contains deprecated '{0}' attribute. Use the 'Unreal' attribute instead.", bootstrapperApplicationData.Name)) + { + element.Add(new XAttribute("Unreal", bootstrapperApplicationData.Value)); + bootstrapperApplicationData.Remove(); + } + break; + default: + this.OnError(ConverterTestType.CustomTableNotAlwaysConvertable, element, "The CustomTable element contains deprecated '{0}' attribute so can't be converted. Use the 'Unreal' attribute for MSI. Use the 'BundleCustomData' element for Bundles. Use the --custom-table argument to force conversion to 'msi' or 'bundle'", bootstrapperApplicationData.Name); + break; + } + } + } + else + { + // Table ref + switch (this.CustomTableSetting) + { + case CustomTableTarget.Bundle: + if (this.OnError(ConverterTestType.CustomTableRef, element, "CustomTable elements that don't contain the table definition are now BundleCustomDataRef for Bundles.")) + { + element.Name = WixConverter.BundleCustomDataRefElementName; + this.ConvertCustomTableElementToBundle(element); + } + break; + case CustomTableTarget.Msi: + if (this.OnError(ConverterTestType.CustomTableRef, element, "CustomTable elements that don't contain the table definition are now CustomTableRef for MSI.")) + { + element.Name = WixConverter.CustomTableRefElementName; + } + break; + default: + this.OnError(ConverterTestType.CustomTableNotAlwaysConvertable, element, "The CustomTable element contains no 'Column' elements so can't be converted. Use the 'CustomTableRef' element for MSI. Use the 'BundleCustomDataRef' element for Bundles. Use the --custom-table argument to force conversion to 'msi' or 'bundle'"); + break; + } + } + } + } + + private void ConvertCustomTableElementToBundle(XElement element) + { + foreach (var xColumn in element.Elements(ColumnElementName)) + { + xColumn.Name = WixConverter.BundleAttributeDefinitionElementName; + + foreach (var xAttribute in xColumn.Attributes().ToList()) + { + if (xAttribute.Name.LocalName != "Id" && + (xAttribute.Name.Namespace == WixConverter.Wix3Namespace || + xAttribute.Name.Namespace == WixConverter.WixNamespace || + String.IsNullOrEmpty(xAttribute.Name.Namespace.NamespaceName))) + { + xAttribute.Remove(); + } + } + } + + foreach (var xRow in element.Elements(RowElementName)) + { + xRow.Name = WixConverter.BundleElementElementName; + + foreach (var xData in xRow.Elements(DataElementName)) + { + xData.Name = WixConverter.BundleAttributeElementName; + + var xColumn = xData.Attribute("Column"); + if (xColumn != null) + { + xData.Add(new XAttribute("Id", xColumn.Value)); + xColumn.Remove(); + } + + this.ConvertInnerTextToAttribute(xData, "Value"); + } + } + } + + private void ConvertControlElement(XElement element) + { + var remove = new List(); + + foreach (var xCondition in element.Elements(ConditionElementName)) + { + var action = UppercaseFirstChar(xCondition.Attribute("Action")?.Value); + if (!String.IsNullOrEmpty(action) && + TryGetInnerText(xCondition, out var text) && + this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}Condition' attribute instead.", xCondition.Name.LocalName, action)) + { + element.Add(new XAttribute(action + "Condition", text)); + remove.Add(xCondition); + } + } + + for (var i = remove.Count - 1; i >= 0; i--) + { + remove[i].Remove(); + } + } + + private void ConvertComponentElement(XElement element) + { + var guid = element.Attribute("Guid"); + if (guid != null && guid.Value == "*") + { + if (this.OnError(ConverterTestType.AutoGuidUnnecessary, element, "Using '*' for the Component Guid attribute is unnecessary. Remove the attribute to remove the redundancy.")) + { + guid.Remove(); + } + } + + var xCondition = element.Element(ConditionElementName); + if (xCondition != null) + { + if (TryGetInnerText(xCondition, out var text) && + this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) + { + element.Add(new XAttribute("Condition", text)); + xCondition.Remove(); + } + } + + this.RenameWin64ToBitness(element); + } + + private void ConvertDirectoryElement(XElement element) + { + if (null == element.Attribute("Name")) + { + var attribute = element.Attribute("ShortName"); + if (null != attribute) + { + var shortName = attribute.Value; + if (this.OnError(ConverterTestType.AssignDirectoryNameFromShortName, element, "The directory ShortName attribute is being renamed to Name since Name wasn't specified for value '{0}'", shortName)) + { + element.Add(new XAttribute("Name", shortName)); + attribute.Remove(); + } + } + } + + var id = element.Attribute("Id")?.Value; + + if (id == "TARGETDIR" && + this.OnError(ConverterTestType.TargetDirDeprecated, element, "The TARGETDIR directory should not longer be explicitly defined. Remove the Directory element with Id attribute 'TARGETDIR'.")) + { + var parentElement = element.Parent; + + element.Remove(); + + if (parentElement.FirstNode is XText text && String.IsNullOrWhiteSpace(text.Value)) + { + parentElement.FirstNode.Remove(); + } + + foreach (var child in element.Nodes()) + { + parentElement.Add(child); + } + + element.RemoveAll(); + + if (parentElement.FirstNode is XText textAgain && String.IsNullOrWhiteSpace(textAgain.Value)) + { + parentElement.FirstNode.Remove(); + } + } + else if (id != null && + WindowsInstallerStandard.IsStandardDirectory(id) && + this.OnError(ConverterTestType.DefiningStandardDirectoryDeprecated, element, "Standard directories such as '{0}' should no longer be defined using the Directory element. Use the StandardDirectory element instead.", id)) + { + element.Name = StandardDirectoryElementName; + + foreach (var attrib in element.Attributes().Where(a => a.Name.LocalName != "Id").ToList()) + { + attrib.Remove(); + } + } + } + + private void ConvertFeatureElement(XElement element) + { + var xAbsent = element.Attribute("Absent"); + if (xAbsent != null && + this.OnError(ConverterTestType.FeatureAbsentAttributeReplaced, element, "The Feature element's Absent attribute has been replaced with the AllowAbsent attribute. Use the 'AllowAbsent' attribute instead.")) + { + if (xAbsent.Value == "disallow") + { + element.Add(new XAttribute("AllowAbsent", "no")); + } + xAbsent.Remove(); + } + + var xAllowAdvertise = element.Attribute("AllowAdvertise"); + if (xAllowAdvertise != null) + { + if ((xAllowAdvertise.Value == "system" || xAllowAdvertise.Value == "allow") && + this.OnError(ConverterTestType.FeatureAllowAdvertiseValueDeprecated, element, "The AllowAdvertise attribute's '{0}' value is deprecated. Set the value to 'yes' instead.", xAllowAdvertise.Value)) + { + xAllowAdvertise.Value = "yes"; + } + else if (xAllowAdvertise.Value == "disallow" && + this.OnError(ConverterTestType.FeatureAllowAdvertiseValueDeprecated, element, "The AllowAdvertise attribute's '{0}' value is deprecated. Remove the value instead.", xAllowAdvertise.Value)) + { + xAllowAdvertise.Remove(); + } + } + + var xCondition = element.Element(ConditionElementName); + if (xCondition != null) + { + var level = xCondition.Attribute("Level")?.Value; + if (!String.IsNullOrEmpty(level) && + TryGetInnerText(xCondition, out var text) && + this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Level' element instead.", xCondition.Name.LocalName)) + { + xCondition.AddAfterSelf(new XElement(LevelElementName, + new XAttribute("Value", level), + new XAttribute("Condition", text) + )); + xCondition.Remove(); + } + } + } + + private void ConvertFileElement(XElement element) + { + if (this.SourceVersion < 4 && null == element.Attribute("Id")) + { + var attribute = element.Attribute("Name"); + + if (null == attribute) + { + attribute = element.Attribute("Source"); + } + + if (null != attribute) + { + var name = Path.GetFileName(attribute.Value); + + if (this.OnError(ConverterTestType.AssignAnonymousFileId, element, "The file id is being updated to '{0}' to ensure it remains the same as the v3 default", name)) + { + IEnumerable attributes = element.Attributes().ToList(); + element.RemoveAttributes(); + element.Add(new XAttribute("Id", GetIdentifierFromName(name))); + element.Add(attributes); + } + } + } + } + + private void ConvertFragmentElement(XElement element) + { + var remove = new List(); + + foreach (var xCondition in element.Elements(ConditionElementName)) + { + var message = xCondition.Attribute("Message")?.Value; + + if (!String.IsNullOrEmpty(message) && + TryGetInnerText(xCondition, out var text) && + this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Launch' element instead.", xCondition.Name.LocalName)) + { + xCondition.AddAfterSelf(new XElement(LaunchElementName, + new XAttribute("Condition", text), + new XAttribute("Message", message) + )); + remove.Add(xCondition); + } + } + + for (var i = remove.Count - 1; i >= 0; i--) + { + remove[i].Remove(); + } + } + + private void ConvertFirewallRemoteAddressElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + private void ConvertEmbeddedChainerElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); + + private void ConvertErrorElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Message"); + + private void ConvertExePackageElement(XElement element) + { + this.ConvertSuppressSignatureValidation(element); + + foreach (var attributeName in new[] { "InstallCommand", "RepairCommand", "UninstallCommand" }) + { + var newName = attributeName.Replace("Command", "Arguments"); + var attribute = element.Attribute(attributeName); + + if (attribute != null && + this.OnError(ConverterTestType.RenameExePackageCommandToArguments, element, "The {0} element {1} attribute has been renamed {2}.", element.Name.LocalName, attribute.Name.LocalName, newName)) + { + element.Add(new XAttribute(newName, attribute.Value)); + attribute.Remove(); + } + } + } + + private void ConvertPermissionExElement(XElement element) + { + var xCondition = element.Element(ConditionElementName); + if (xCondition != null) + { + if (TryGetInnerText(xCondition, out var text) && + this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Condition' attribute instead.", xCondition.Name.LocalName)) + { + element.Add(new XAttribute("Condition", text)); + xCondition.Remove(); + } + } + } + + private void ConvertProgressTextElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Message"); + + private void ConvertModuleElement(XElement element) + { + if (element.Attribute("Guid") == null // skip already-converted Module elements + && this.OnError(ConverterTestType.ModuleAndPackageRenamed, element, "The Module and Package elements have been renamed and reorganized for simplicity.")) + { + var xModule = element; + + var xSummaryInformation = xModule.Element(PackageElementName); + if (xSummaryInformation != null) + { + xSummaryInformation.Name = SummaryInformationElementName; + + var xInstallerVersion = xSummaryInformation.Attribute("InstallerVersion"); + if (this.SourceVersion < 4 && xInstallerVersion == null) + { + this.OnError(ConverterTestType.InstallerVersionBehaviorChange, element, "Breaking change: The default value for Package/@InstallerVersion has been changed to '500' regardless of build platform. If you need a lower version, set it manually in the Module element."); + } + + RemoveAttribute(xSummaryInformation, "AdminImage"); + RemoveAttribute(xSummaryInformation, "Comments"); + MoveAttribute(xSummaryInformation, "Id", xModule, "Guid"); + MoveAttribute(xSummaryInformation, "InstallerVersion", xModule); + RemoveAttribute(xSummaryInformation, "Languages"); + RemoveAttribute(xSummaryInformation, "Platform"); + RemoveAttribute(xSummaryInformation, "Platforms"); + RemoveAttribute(xSummaryInformation, "ReadOnly"); + MoveAttribute(xSummaryInformation, "SummaryCodepage", xSummaryInformation, "Codepage", defaultValue: "1252"); + + if (!xSummaryInformation.HasAttributes) + { + xSummaryInformation.Remove(); + } + } + } + } + + private void ConvertProductElement(XElement element) + { + var id = element.Attribute("Id"); + if (id != null && id.Value == "*") + { + if (this.OnError(ConverterTestType.AutoGuidUnnecessary, element, "Using '*' for the Product Id attribute is unnecessary. Remove the attribute to remove the redundancy.")) + { + id.Remove(); + } + } + + var xConditions = element.Elements(ConditionElementName).ToList(); + foreach (var xCondition in xConditions) + { + var message = xCondition.Attribute("Message")?.Value; + + if (!String.IsNullOrEmpty(message) && + TryGetInnerText(xCondition, out var text) && + this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the 'Launch' element instead.", xCondition.Name.LocalName)) + { + xCondition.AddAfterSelf(new XElement(LaunchElementName, + new XAttribute("Condition", text), + new XAttribute("Message", message) + )); + xCondition.Remove(); + } + } + + var xMediaTemplate = element.Element(MediaTemplateElementName); + if (xMediaTemplate?.HasAttributes == false + && this.OnError(ConverterTestType.DefaultMediaTemplate, element, "A MediaTemplate with no attributes set is now provided by default. Remove the element.")) + { + xMediaTemplate.Remove(); + } + + if (this.OnError(ConverterTestType.ProductAndPackageRenamed, element, "The Product and Package elements have been renamed and reorganized for simplicity.")) + { + var xPackage = element; + xPackage.Name = PackageElementName; + + var xSummaryInformation = xPackage.Element(PackageElementName); + if (xSummaryInformation != null) + { + xSummaryInformation.Name = SummaryInformationElementName; + + var xInstallerVersion = xSummaryInformation.Attribute("InstallerVersion"); + if (this.SourceVersion < 4 && xInstallerVersion == null) + { + this.OnError(ConverterTestType.InstallerVersionBehaviorChange, element, "Breaking change: The default value for Package/@InstallerVersion has been changed to '500' regardless of build platform. If you need a lower version, set it manually in the Package element."); + } + + if (xSummaryInformation.Attribute("Compressed") == null) + { + xPackage.SetAttributeValue("Compressed", "no"); + } + else + { + MoveAttribute(xSummaryInformation, "Compressed", xPackage, defaultValue: "yes"); + } + + RemoveAttribute(xSummaryInformation, "AdminImage"); + RemoveAttribute(xSummaryInformation, "Comments"); + RemoveAttribute(xSummaryInformation, "Id"); + MoveAttribute(xSummaryInformation, "InstallerVersion", xPackage, defaultValue: "500"); + MoveAttribute(xSummaryInformation, "InstallScope", xPackage, "Scope", defaultValue: "perMachine"); + RemoveAttribute(xSummaryInformation, "Languages"); + RemoveAttribute(xSummaryInformation, "Platform"); + RemoveAttribute(xSummaryInformation, "Platforms"); + RemoveAttribute(xSummaryInformation, "ReadOnly"); + MoveAttribute(xSummaryInformation, "ShortNames", xPackage); + MoveAttribute(xSummaryInformation, "SummaryCodepage", xSummaryInformation, "Codepage", defaultValue: "1252"); + MoveAttribute(xPackage, "Id", xPackage, "ProductCode"); + + var xInstallPrivileges = xSummaryInformation.Attribute("InstallPrivileges"); + switch (xInstallPrivileges?.Value) + { + case "limited": + xPackage.SetAttributeValue("Scope", "perUser"); + break; + case "elevated": + { + var xAllUsers = xPackage.Elements(PropertyElementName).SingleOrDefault(p => p.Attribute("Id")?.Value == "ALLUSERS"); + if (xAllUsers?.Attribute("Value")?.Value == "1") + { + xAllUsers?.Remove(); + } + } + break; + } + + xInstallPrivileges?.Remove(); + + if (!xSummaryInformation.HasAttributes) + { + xSummaryInformation.Remove(); + } + } + } + } + + private static void MoveAttribute(XElement xSource, string attributeName, XElement xDestination, string destinationAttributeName = null, string defaultValue = null) + { + var xAttribute = xSource.Attribute(attributeName); + if (xAttribute != null && (defaultValue == null || xAttribute.Value != defaultValue)) + { + xDestination.SetAttributeValue(destinationAttributeName ?? attributeName, xAttribute.Value); + } + + xAttribute?.Remove(); + } + + private static void RemoveAttribute(XElement xSummaryInformation, string attributeName) + { + var xAttribute = xSummaryInformation.Attribute(attributeName); + xAttribute?.Remove(); + } + + private void ConvertPropertyRefElement(XElement element) + { + var newElementName = String.Empty; + + var id = element.Attribute("Id"); + switch (id?.Value) + { + case "WIX_SUITE_BACKOFFICE": + case "WIX_SUITE_BLADE": + case "WIX_SUITE_COMMUNICATIONS": + case "WIX_SUITE_COMPUTE_SERVER": + case "WIX_SUITE_DATACENTER": + case "WIX_SUITE_EMBEDDED_RESTRICTED": + case "WIX_SUITE_EMBEDDEDNT": + case "WIX_SUITE_ENTERPRISE": + case "WIX_SUITE_MEDIACENTER": + case "WIX_SUITE_PERSONAL": + case "WIX_SUITE_SECURITY_APPLIANCE": + case "WIX_SUITE_SERVERR2": + case "WIX_SUITE_SINGLEUSERTS": + case "WIX_SUITE_SMALLBUSINESS": + case "WIX_SUITE_SMALLBUSINESS_RESTRICTED": + case "WIX_SUITE_STARTER": + case "WIX_SUITE_STORAGE_SERVER": + case "WIX_SUITE_TABLETPC": + case "WIX_SUITE_TERMINAL": + case "WIX_SUITE_WH_SERVER": + newElementName = "QueryWindowsSuiteInfo"; + break; + case "WIX_DIR_ADMINTOOLS": + case "WIX_DIR_ALTSTARTUP": + case "WIX_DIR_CDBURN_AREA": + case "WIX_DIR_COMMON_ADMINTOOLS": + case "WIX_DIR_COMMON_ALTSTARTUP": + case "WIX_DIR_COMMON_DOCUMENTS": + case "WIX_DIR_COMMON_FAVORITES": + case "WIX_DIR_COMMON_MUSIC": + case "WIX_DIR_COMMON_PICTURES": + case "WIX_DIR_COMMON_VIDEO": + case "WIX_DIR_COOKIES": + case "WIX_DIR_DESKTOP": + case "WIX_DIR_HISTORY": + case "WIX_DIR_INTERNET_CACHE": + case "WIX_DIR_MYMUSIC": + case "WIX_DIR_MYPICTURES": + case "WIX_DIR_MYVIDEO": + case "WIX_DIR_NETHOOD": + case "WIX_DIR_PERSONAL": + case "WIX_DIR_PRINTHOOD": + case "WIX_DIR_PROFILE": + case "WIX_DIR_RECENT": + case "WIX_DIR_RESOURCES": + newElementName = "QueryWindowsDirectories"; + break; + case "WIX_DWM_COMPOSITION_ENABLED": + case "WIX_WDDM_DRIVER_PRESENT": + newElementName = "QueryWindowsDriverInfo"; + break; + case "WIX_ACCOUNT_LOCALSYSTEM": + case "WIX_ACCOUNT_LOCALSERVICE": + case "WIX_ACCOUNT_NETWORKSERVICE": + case "WIX_ACCOUNT_ADMINISTRATORS": + case "WIX_ACCOUNT_USERS": + case "WIX_ACCOUNT_GUESTS": + case "WIX_ACCOUNT_PERFLOGUSERS": + case "WIX_ACCOUNT_PERFLOGUSERS_NODOMAIN": + newElementName = "QueryWindowsWellKnownSIDs"; + break; + } + + if (!String.IsNullOrEmpty(newElementName) + && this.OnError(ConverterTestType.UtilReferencesReplaced, element, "Custom action and property reference {0} to WixUtilExtension have been replaced with strongly-typed elements.", id)) + { + element.AddAfterSelf(new XElement(WixUtilNamespace + newElementName)); + element.Remove(); + } + } + + private void ConvertCustomActionRefElement(XElement element) + { + var newElementName = String.Empty; + + var id = element.Attribute("Id"); + switch (id?.Value) + { + case "WixBroadcastSettingChange": + case "WixBroadcastEnvironmentChange": + case "WixCheckRebootRequired": + case "WixExitEarlyWithSuccess": + case "WixFailWhenDeferred": + case "WixWaitForEvent": + case "WixWaitForEventDeferred": + newElementName = id?.Value.Substring(3); // strip leading Wix + break; + } + + if (!String.IsNullOrEmpty(newElementName) + && this.OnError(ConverterTestType.UtilReferencesReplaced, element, "Custom action and property reference {0} to WixUtilExtension have been replaced with strongly-typed elements.", id)) + { + element.AddAfterSelf(new XElement(WixUtilNamespace + newElementName)); + element.Remove(); + } + } + + private void ConvertPublishElement(XElement element) + { + this.ConvertInnerTextToAttribute(element, "Condition"); + + var xCondition = element.Attribute("Condition"); + if (xCondition?.Value == "1" && + this.OnError(ConverterTestType.PublishConditionOneUnnecessary, element, "Adding Condition='1' on {0} elements is no longer necessary. Remove the Condition attribute.", xCondition.Name.LocalName)) + { + xCondition.Remove(); + } + } + + private void ConvertMultiStringValueElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + private void ConvertRegistryKeyElement(XElement element) + { + var xAction = element.Attribute("Action"); + + if (xAction != null + && this.OnError(ConverterTestType.RegistryKeyActionObsolete, element, "The RegistryKey element's Action attribute is obsolete. Action='create' will be converted to ForceCreateOnInstall='yes'. Action='createAndRemoveOnUninstall' will be converted to ForceCreateOnInstall='yes' and ForceDeleteOnUninstall='yes'.")) + { + switch (xAction?.Value) + { + case "create": + element.SetAttributeValue("ForceCreateOnInstall", "yes"); + break; + case "createAndRemoveOnUninstall": + element.SetAttributeValue("ForceCreateOnInstall", "yes"); + element.SetAttributeValue("ForceDeleteOnUninstall", "yes"); + break; + } + + xAction.Remove(); + } + } + + private void ConvertRemotePayloadElement(XElement element) + { + var xParent = element.Parent; + + if (xParent.Name == ExePackageElementName && + this.OnError(ConverterTestType.RemotePayloadRenamed, element, "The RemotePayload element has been renamed. Use the 'ExePackagePayload' instead.")) + { + element.Name = ExePackagePayloadElementName; + } + else if (xParent.Name == MsuPackageElementName && + this.OnError(ConverterTestType.RemotePayloadRenamed, element, "The RemotePayload element has been renamed. Use the 'MsuPackagePayload' instead.")) + { + element.Name = MsuPackagePayloadElementName; + } + + var xName = xParent.Attribute("Name"); + if (xName != null && + this.OnError(ConverterTestType.NameAttributeMovedToRemotePayload, xParent, "The Name attribute must be specified on the child XxxPackagePayload element when using a remote payload.")) + { + element.SetAttributeValue("Name", xName.Value); + xName.Remove(); + } + + var xDownloadUrl = xParent.Attribute("DownloadUrl"); + if (xDownloadUrl != null && + this.OnError(ConverterTestType.DownloadUrlAttributeMovedToRemotePayload, xParent, "The DownloadUrl attribute must be specified on the child XxxPackagePayload element when using a remote payload.")) + { + element.SetAttributeValue("DownloadUrl", xDownloadUrl.Value); + xDownloadUrl.Remove(); + } + + var xCompressed = xParent.Attribute("Compressed"); + if (xCompressed != null && + this.OnError(ConverterTestType.CompressedAttributeUnnecessaryForRemotePayload, xParent, "The Compressed attribute should not be specified when using a remote payload.")) + { + xCompressed.Remove(); + } + + this.OnError(ConverterTestType.BurnHashAlgorithmChanged, element, "The hash algorithm for bundles changed from SHA1 to SHA512."); + + this.RemoveAttributeIfPresent(element, "CertificatePublicKey", ConverterTestType.BundleSignatureValidationObsolete, "The {0} element contains obsolete '{1}' attribute. Signature validation is no longer supported. The attribute will be removed."); + this.RemoveAttributeIfPresent(element, "CertificateThumbprint", ConverterTestType.BundleSignatureValidationObsolete, "The {0} element contains obsolete '{1}' attribute. Signature validation is no longer supported. The attribute will be removed."); + } + + private void ConvertRegistrySearchElement(XElement element) + { + this.RenameWin64ToBitness(element); + } + + private void ConvertRequiredPrivilegeElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Name"); + + private void ConvertDataElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + private void ConvertSequenceElement(XElement element) + { + foreach (var child in element.Elements()) + { + this.ConvertInnerTextToAttribute(child, "Condition"); + } + } + + private void ConvertServiceArgumentElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + private void ConvertSetDirectoryElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); + + private void ConvertSetPropertyElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); + + private void ConvertShortcutPropertyElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + private void ConvertProvidesElement(XElement element) + { + if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Provides element has been integrated into the WiX v4 namespace. Remove the namespace.")) + { + element.Name = ProvidesElementName; + } + + if (element.Parent.Name == ComponentElementName && + this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Provides element has been integrated into the WiX v4 namespace. Add the 'Check' attribute from the WixDependency.wixext to match v3 runtime behavior.")) + { + element.Add(new XAttribute(DependencyCheckAttributeName, "yes")); + } + } + + private void ConvertRequiresElement(XElement element) + { + if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Requires element has been integrated into the WiX v4 namespace. Remove the namespace.")) + { + element.Name = RequiresElementName; + } + + if (element.Parent.Name == ProvidesElementName && + element.Parent.Parent?.Name == ComponentElementName && + this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The Requires element has been integrated into the WiX v4 namespace. Add the 'Enforce' attribute from the WixDependency.wixext to match v3 runtime behavior.")) + { + element.Add(new XAttribute(DependencyEnforceAttributeName, "yes")); + } + } + + private void ConvertRequiresRefElement(XElement element) + { + if (this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The RequiresRef element has been integrated into the WiX v4 namespace. Remove the namespace.")) + { + element.Name = RequiresRefElementName; + } + + if (element.Parent.Name == ProvidesElementName && + element.Parent.Parent?.Name == ComponentElementName && + this.OnError(ConverterTestType.IntegratedDependencyNamespace, element, "The RequiresRef element has been integrated into the WiX v4 namespace. Add the 'Enforce' attribute from the WixDependency.wixext to match v3 runtime behavior.")) + { + element.Add(new XAttribute(DependencyEnforceAttributeName, "yes")); + } + } + + private void ConvertSuppressSignatureValidation(XElement element) + { + var suppressSignatureValidation = element.Attribute("SuppressSignatureValidation"); + + if (null != suppressSignatureValidation + && this.OnError(ConverterTestType.BundleSignatureValidationObsolete, element, "The chain package element contains obsolete '{0}' attribute. Signature validation is no longer supported. The attribute will be removed.", suppressSignatureValidation.Name)) + { + suppressSignatureValidation.Remove(); + } + } + + private void ConvertTagElement(XElement element) + { + if (this.OnError(ConverterTestType.TagElementRenamed, element, "The Tag element has been renamed. Use the 'SoftwareTag' element instead.")) + { + element.Name = SoftwareTagElementName; + } + + this.RemoveAttributeIfPresent(element, "Licensed", ConverterTestType.SoftwareTagLicensedObsolete, "The {0} element contains obsolete '{1}' attribute. The attribute will be removed."); + this.RemoveAttributeIfPresent(element, "Type", ConverterTestType.SoftwareTagLicensedObsolete, "The {0} element contains obsolete '{1}' attribute. The attribute will be removed."); + this.RenameWin64ToBitness(element); + } + + private void ConvertTagRefElement(XElement element) + { + if (this.OnError(ConverterTestType.TagRefElementRenamed, element, "The TagRef element has been renamed. Use the 'SoftwareTagRef' element instead.")) + { + element.Name = SoftwareTagRefElementName; + } + } + + private void ConvertTextElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + private void ConvertUITextElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + private void ConvertWindowsInstallerPackageElement(XElement element) + { + this.ConvertSuppressSignatureValidation(element); + + if (null != element.Attribute("DisplayInternalUI")) + { + this.OnError(ConverterTestType.DisplayInternalUiNotConvertable, element, "The DisplayInternalUI functionality has fundamentally changed and requires BootstrapperApplication support."); + } + } + + private void ConvertVerbElement(XElement element) + { + if (null != element.Attribute("Target")) + { + this.OnError(ConverterTestType.VerbTargetNotConvertable, element, "The Verb/@Target attribute has been replaced with typed @TargetFile and @TargetProperty attributes."); + } + } + + private void ConvertCustomActionElement(XElement xCustomAction) + { + var xBinaryKey = xCustomAction.Attribute("BinaryKey"); + if (xBinaryKey != null && this.OnError(ConverterTestType.CustomActionKeysAreNowRefs, xCustomAction, "The CustomAction attributes have been renamed from BinaryKey and FileKey to BinaryRef and FileRef.")) + { + xCustomAction.SetAttributeValue("BinaryRef", xBinaryKey.Value); + xBinaryKey.Remove(); + xBinaryKey = xCustomAction.Attribute("BinaryRef"); + } + + var xFileKey = xCustomAction.Attribute("FileKey"); + if (xFileKey != null && this.OnError(ConverterTestType.CustomActionKeysAreNowRefs, xCustomAction, "The CustomAction attributes have been renamed from BinaryKey and FileKey to BinaryRef and FileRef.")) + { + xCustomAction.SetAttributeValue("FileRef", xFileKey.Value); + xFileKey.Remove(); + } + + if (xBinaryKey?.Value == "WixCA" || xBinaryKey?.Value == "UtilCA") + { + if (this.OnError(ConverterTestType.WixCABinaryIdRenamed, xCustomAction, "The WixCA custom action DLL Binary table id has been renamed. Use the id 'Wix4UtilCA_X86' instead.")) + { + xBinaryKey.Value = "Wix4UtilCA_X86"; + } + } + + if (xBinaryKey?.Value == "WixCA_x64" || xBinaryKey?.Value == "UtilCA_x64") + { + if (this.OnError(ConverterTestType.WixCABinaryIdRenamed, xCustomAction, "The WixCA_x64 custom action DLL Binary table id has been renamed. Use the id 'Wix4UtilCA_X64' instead.")) + { + xBinaryKey.Value = "Wix4UtilCA_X64"; + } + } + + var xDllEntry = xCustomAction.Attribute("DllEntry"); + + if (xDllEntry?.Value == "CAQuietExec" || xDllEntry?.Value == "CAQuietExec64") + { + if (this.OnError(ConverterTestType.QuietExecCustomActionsRenamed, xCustomAction, "The CAQuietExec and CAQuietExec64 custom action ids have been renamed. Use the ids 'WixQuietExec' and 'WixQuietExec64' instead.")) + { + xDllEntry.Value = xDllEntry.Value.Replace("CAQuietExec", "WixQuietExec"); + } + } + + var xProperty = xCustomAction.Attribute("Property"); + + if (xProperty?.Value == "QtExecCmdLine" || xProperty?.Value == "QtExec64CmdLine") + { + if (this.OnError(ConverterTestType.QuietExecCustomActionsRenamed, xCustomAction, "The QtExecCmdLine and QtExec64CmdLine property ids have been renamed. Use the ids 'WixQuietExecCmdLine' and 'WixQuietExec64CmdLine' instead.")) + { + xProperty.Value = xProperty.Value.Replace("QtExec", "WixQuietExec"); + } + } + + var xScript = xCustomAction.Attribute("Script"); + + if (xScript != null && TryGetInnerText(xCustomAction, out var scriptText)) + { + if (this.OnError(ConverterTestType.InnerTextDeprecated, xCustomAction, "Using {0} element text is deprecated. Extract the text to a file and use the 'ScriptSourceFile' attribute to reference it.", xCustomAction.Name.LocalName)) + { + var scriptFolder = Path.GetDirectoryName(this.SourceFile) ?? String.Empty; + var id = xCustomAction.Attribute("Id")?.Value ?? Guid.NewGuid().ToString("N"); + var ext = (xScript.Value == "jscript") ? ".js" : (xScript.Value == "vbscript") ? ".vbs" : ".txt"; + + var scriptFile = Path.Combine(scriptFolder, id + ext); + File.WriteAllText(scriptFile, scriptText); + + RemoveChildren(xCustomAction); + xCustomAction.Add(new XAttribute("ScriptSourceFile", scriptFile)); + } + } + } + + private void ConvertVariableElement(XElement xVariable) + { + var xType = xVariable.Attribute("Type"); + var xValue = xVariable.Attribute("Value"); + if (this.SourceVersion < 4) + { + if (xType == null) + { + if (WasImplicitlyStringTyped(xValue?.Value) && + this.OnError(ConverterTestType.AssignVariableTypeFormatted, xVariable, "The \"string\" variable type now denotes a literal string. Use \"formatted\" to keep the previous behavior.")) + { + xVariable.Add(new XAttribute("Type", "formatted")); + } + } + else if (xType.Value == "string" && + this.OnError(ConverterTestType.AssignVariableTypeFormatted, xVariable, "The \"string\" variable type now denotes a literal string. Use \"formatted\" to keep the previous behavior.")) + { + xType.Value = "formatted"; + } + } + } + + private void ConvertPropertyElement(XElement xProperty) + { + var xId = xProperty.Attribute("Id"); + + if (xId.Value == "QtExecCmdTimeout") + { + this.OnError(ConverterTestType.QtExecCmdTimeoutAmbiguous, xProperty, "QtExecCmdTimeout was previously used for both CAQuietExec and CAQuietExec64. For WixQuietExec, use WixQuietExecCmdTimeout. For WixQuietExec64, use WixQuietExec64CmdTimeout."); + } + + this.ConvertInnerTextToAttribute(xProperty, "Value"); + } + + private void ConvertUtilCloseApplicationElementName(XElement element) => this.ConvertInnerTextToAttribute(element, "Condition"); + + private void ConvertUtilPermissionExElement(XElement element) + { + if (this.SourceVersion < 4 && null == element.Attribute("Inheritable")) + { + var inheritable = element.Parent.Name == CreateFolderElementName; + if (!inheritable) + { + if (this.OnError(ConverterTestType.AssignPermissionExInheritable, element, "The PermissionEx Inheritable attribute is being set to 'no' to ensure it remains the same as the v3 default.")) + { + element.Add(new XAttribute("Inheritable", "no")); + } + } + } + } + + private void ConvertUtilRegistrySearchElement(XElement element) + { + this.RenameWin64ToBitness(element); + + if (this.SourceVersion < 4) + { + var result = element.Attribute("Result")?.Value; + if (result == null || result == "value") + { + this.OnError(ConverterTestType.UtilRegistryValueSearchBehaviorChange, element, "Breaking change: util:RegistrySearch for a value no longer clears the variable when the key or value is missing."); + } + } + } + + private void ConvertUtilXmlConfigElement(XElement element) => this.ConvertInnerTextToAttribute(element, "Value"); + + /// + /// Converts a Wix element. + /// + /// The Wix element to convert. + /// The converted element. + private void ConvertElementWithoutNamespace(XElement element) + { + if (this.OnError(ConverterTestType.XmlnsMissing, element, "The xmlns attribute is missing. It must be present with a value of '{0}'.", WixNamespace.NamespaceName)) + { + element.Name = WixNamespace.GetName(element.Name.LocalName); + + element.Add(new XAttribute("xmlns", WixNamespace.NamespaceName)); // set the default namespace. + + foreach (var elementWithoutNamespace in element.DescendantsAndSelf().Where(e => XNamespace.None == e.Name.Namespace)) + { + elementWithoutNamespace.Name = WixNamespace.GetName(elementWithoutNamespace.Name.LocalName); + } + } + } + + private void ConvertInnerTextToAttribute(XElement element, string attributeName) + { + if (TryGetInnerText(element, out var text) && + this.OnError(ConverterTestType.InnerTextDeprecated, element, "Using {0} element text is deprecated. Use the '{1}' attribute instead.", element.Name.LocalName, attributeName)) + { + element.Add(new XAttribute(attributeName, text)); + RemoveChildren(element); + } + } + + void RemoveAttributeIfPresent(XElement element, string attributeName, ConverterTestType type, string format) + { + var xAttribute = element.Attribute(attributeName); + if (null != xAttribute && this.OnError(type, element, format, element.Name.LocalName, xAttribute.Name)) + { + xAttribute.Remove(); + } + } + + private void RenameWin64ToBitness(XElement element) + { + var win64 = element.Attribute("Win64"); + if (win64 != null && this.OnError(ConverterTestType.Win64AttributeRenamed, element, "The {0} element's Win64 attribute has been renamed. Use the Bitness attribute instead.", element.Name.LocalName)) + { + var value = this.UpdateWin64ValueToBitnessValue(win64); + element.Add(new XAttribute("Bitness", value)); + win64.Remove(); + } + } + + private string UpdateWin64ValueToBitnessValue(XAttribute xWin64Attribute) + { + var value = xWin64Attribute.Value ?? String.Empty; + switch (value) + { + case "yes": + return "always64"; + case "no": + return "always32"; + default: + this.OnError(ConverterTestType.Win64AttributeRenameCannotBeAutomatic, xWin64Attribute, "Breaking change: The Win64 attribute's value '{0}' cannot be converted automatically to the new Bitness attribute.", value); + return value; + } + } + + private IEnumerable YieldConverterTypes(IEnumerable types) + { + if (null != types) + { + foreach (var type in types) + { + if (Enum.TryParse(type, true, out var itt)) + { + yield return itt; + } + else // not a known ConverterTestType + { + this.OnError(ConverterTestType.ConverterTestTypeUnknown, null, "Unknown error type: '{0}'.", type); + } + } + } + } + + private static void UpdateElementsWithDeprecatedNamespaces(IEnumerable elements, Dictionary deprecatedToUpdatedNamespaces) + { + foreach (var element in elements) + { + if (deprecatedToUpdatedNamespaces.TryGetValue(element.Name.Namespace, out var ns)) + { + element.Name = ns.GetName(element.Name.LocalName); + } + + // Remove all the attributes and add them back to with their namespace updated (as necessary). + IEnumerable attributes = element.Attributes().ToList(); + element.RemoveAttributes(); + + foreach (var attribute in attributes) + { + var convertedAttribute = attribute; + + if (attribute.IsNamespaceDeclaration) + { + if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Value, out ns)) + { + if (ns == XNamespace.None) + { + continue; + } + + convertedAttribute = ("xmlns" == attribute.Name.LocalName) ? new XAttribute(attribute.Name.LocalName, ns.NamespaceName) : new XAttribute(XNamespace.Xmlns + attribute.Name.LocalName, ns.NamespaceName); + } + } + else if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Name.Namespace, out ns)) + { + convertedAttribute = new XAttribute(ns.GetName(attribute.Name.LocalName), attribute.Value); + } + + element.Add(convertedAttribute); + } + } + } + + /// + /// Determine if the whitespace preceding a node is appropriate for its depth level. + /// + /// Indentation value to use when validating leading whitespace. + /// The depth level that should match this whitespace. + /// The whitespace to validate. + /// true if the whitespace is legal; false otherwise. + private static bool LeadingWhitespaceValid(int indentationAmount, int level, string whitespace) + { + // Strip off leading newlines; there can be an arbitrary number of these. + whitespace = whitespace.TrimStart(XDocumentNewLine); + + var indentation = new string(' ', level * indentationAmount); + + return whitespace == indentation; + } + + /// + /// Fix the whitespace in a whitespace node. + /// + /// Indentation value to use when validating leading whitespace. + /// The depth level of the desired whitespace. + /// The whitespace node to fix. + private static void FixupWhitespace(int indentationAmount, int level, XText whitespace) + { + var value = new StringBuilder(whitespace.Value.Length); + + // Keep any previous preceeding new lines. + var newlines = whitespace.Value.TakeWhile(c => c == XDocumentNewLine).Count(); + + // Ensure there is always at least one new line before the indentation. + value.Append(XDocumentNewLine, newlines == 0 ? 1 : newlines); + + whitespace.Value = value.Append(' ', level * indentationAmount).ToString(); + } + + /// + /// Removes unused namespaces from the element and its children. + /// + /// Root element to start at. + private void RemoveUnusedNamespaces(XElement root) + { + var declarations = new List(); + var namespaces = new HashSet(); + + VisitElement(root, x => + { + if (x is XAttribute a && a.IsNamespaceDeclaration) + { + declarations.Add(a); + namespaces.Add(a.Value); + } + return true; + }); + + foreach (var ns in namespaces.ToList()) + { + VisitElement(root, x => + { + if ((x is XElement e && e.Name.Namespace == ns) || + (x is XAttribute a && !a.IsNamespaceDeclaration && a.Name.Namespace == ns)) + { + namespaces.Remove(ns); + return false; + } + + return true; + }); + } + + foreach (var declaration in declarations) + { + if (namespaces.Contains(declaration.Value) && + this.OnError(ConverterTestType.RemoveUnusedNamespaces, declaration, "The namespace '{0}' is not used. Remove unused namespaces.", declaration.Value)) + { + declaration.Remove(); + } + } + } + + /// + /// Output an error message to the console. + /// + /// The type of converter test. + /// The node that caused the error. + /// Detailed error message. + /// Additional formatted string arguments. + /// Returns true indicating that action should be taken on this error, and false if it should be ignored. + private bool OnError(ConverterTestType converterTestType, XObject node, string message, params object[] args) + { + // Ignore the error if explicitly ignored or outside the range of the current operation. + if (this.IgnoreErrors.Contains(converterTestType) || + (this.Operation == ConvertOperation.Convert && converterTestType < ConverterTestType.EndIgnoreInConvert) || + (this.Operation == ConvertOperation.Format && converterTestType > ConverterTestType.BeginIgnoreInFormat)) + { + return false; + } + + // Increase the error count. + this.Errors++; + + var sourceLine = (null == node) ? new SourceLineNumber(this.SourceFile ?? "wix.exe") : new SourceLineNumber(this.SourceFile, ((IXmlLineInfo)node).LineNumber); + var warning = this.ErrorsAsWarnings.Contains(converterTestType); + var display = String.Format(CultureInfo.CurrentCulture, message, args); + + var msg = new Message(sourceLine, warning ? MessageLevel.Warning : MessageLevel.Error, (int)converterTestType, "{0} ({1})", display, converterTestType.ToString()); + + this.Messaging.Write(msg); + + return true; + } + + /// + /// Return an identifier based on passed file/directory name + /// + /// File/directory name to generate identifer from + /// A version of the name that is a legal identifier. + /// This is duplicated from WiX's Common class. + private static string GetIdentifierFromName(string name) + { + var result = IllegalIdentifierCharacters.Replace(name, "_"); // replace illegal characters with "_". + + // MSI identifiers must begin with an alphabetic character or an + // underscore. Prefix all other values with an underscore. + if (AddPrefix.IsMatch(name)) + { + result = String.Concat("_", result); + } + + return result; + } + + private static string LowercaseFirstChar(string value) + { + if (!String.IsNullOrEmpty(value)) + { + var c = Char.ToLowerInvariant(value[0]); + if (c != value[0]) + { + var remainder = value.Length > 1 ? value.Substring(1) : String.Empty; + return c + remainder; + } + } + + return value; + } + + private static string UppercaseFirstChar(string value) + { + if (!String.IsNullOrEmpty(value)) + { + var c = Char.ToUpperInvariant(value[0]); + if (c != value[0]) + { + var remainder = value.Length > 1 ? value.Substring(1) : String.Empty; + return c + remainder; + } + } + + return value; + } + + private static bool TryGetInnerText(XElement element, out string value) + { + value = null; + + var nodes = element.Nodes(); + + if (nodes.All(e => e.NodeType == XmlNodeType.Text || e.NodeType == XmlNodeType.CDATA)) + { + value = String.Join(String.Empty, nodes.Cast().Select(TrimTextValue)); + } + + return !String.IsNullOrEmpty(value); + } + + private static bool IsTextNode(XNode node, out XText text) + { + text = null; + + if (node.NodeType == XmlNodeType.Text || node.NodeType == XmlNodeType.CDATA) + { + text = (XText)node; + } + + return text != null; + } + + private static void TrimLeadingText(XDocument document) + { + while (IsTextNode(document.Nodes().FirstOrDefault(), out var text)) + { + text.Remove(); + } + } + + private static string TrimTextValue(XText text) + { + var value = text.Value; + + if (String.IsNullOrEmpty(value)) + { + return String.Empty; + } + else if (text.NodeType == XmlNodeType.CDATA && String.IsNullOrWhiteSpace(value)) + { + return " "; + } + + return value.Trim(); + } + + private static void RemoveChildren(XElement element) + { + var nodes = element.Nodes().ToList(); + foreach (var node in nodes) + { + node.Remove(); + } + } + + private static bool VisitElement(XElement element, Func visitor) + { + if (!visitor(element)) + { + return false; + } + + if (!element.Attributes().All(a => visitor(a))) + { + return false; + } + + return element.Elements().All(e => VisitElement(e, visitor)); + } + + private static bool WasImplicitlyStringTyped(string value) + { + if (value == null) + { + return false; + } + else if (value.StartsWith("v", StringComparison.OrdinalIgnoreCase)) + { + if (Int32.TryParse(value.Substring(1), NumberStyles.None, CultureInfo.InvariantCulture.NumberFormat, out var _)) + { + return false; + } + else if (Version.TryParse(value.Substring(1), out var _)) + { + return false; + } + } + else if (Int64.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture.NumberFormat, out var _)) + { + return false; + } + + return true; + } + + /// + /// Converter test types. These are used to condition error messages down to warnings. + /// + private enum ConverterTestType + { + /// + /// Internal-only: displayed when a string cannot be converted to an ConverterTestType. + /// + ConverterTestTypeUnknown, + + /// + /// Displayed when an XML loading exception has occurred. + /// + XmlException, + + /// + /// Displayed when the whitespace preceding a node is wrong. + /// + WhitespacePrecedingNodeWrong, + + /// + /// Displayed when the whitespace preceding an end element is wrong. + /// + WhitespacePrecedingEndElementWrong, + + /// Before this point, ignore errors on convert operation + EndIgnoreInConvert, + + /// + /// Displayed when the XML declaration is present in the source file. + /// + DeclarationPresent, + + /// + /// Displayed when a file cannot be accessed; typically when trying to save back a fixed file. + /// + UnauthorizedAccessException, + + /// After this point, ignore errors on format operation + BeginIgnoreInFormat, + + /// + /// Displayed when the xmlns attribute is missing from the document element. + /// + XmlnsMissing, + + /// + /// Displayed when the xmlns attribute on the document element is wrong. + /// + XmlnsValueWrong, + + /// + /// Displayed when inner text contains a deprecated $(loc.xxx) reference. + /// + DeprecatedLocalizationVariablePrefixInTextValue, + + /// + /// Displayed when an attribute value contains a deprecated $(loc.xxx) reference. + /// + DeprecatedLocalizationVariablePrefixInAttributeValue, + + /// + /// Assign an identifier to a File element when on Id attribute is specified. + /// + AssignAnonymousFileId, + + /// + /// SuppressSignatureValidation attribute is obsolete and corresponding functionality removed. + /// + BundleSignatureValidationObsolete, + + /// + /// WixCA Binary/@Id has been renamed to UtilCA. + /// + WixCABinaryIdRenamed, + + /// + /// QtExec custom actions have been renamed. + /// + QuietExecCustomActionsRenamed, + + /// + /// QtExecCmdTimeout was previously used for both CAQuietExec and CAQuietExec64. For WixQuietExec, use WixQuietExecCmdTimeout. For WixQuietExec64, use WixQuietExec64CmdTimeout. + /// + QtExecCmdTimeoutAmbiguous, + + /// + /// Directory/@ShortName may only be specified with Directory/@Name. + /// + AssignDirectoryNameFromShortName, + + /// + /// BootstrapperApplicationData attribute is deprecated and replaced with Unreal for MSI. Use BundleCustomData element for Bundles. + /// + BootstrapperApplicationDataDeprecated, + + /// + /// Inheritable is new and is now defaulted to 'yes' which is a change in behavior for all but children of CreateFolder. + /// + AssignPermissionExInheritable, + + /// + /// Column element's Category attribute is camel-case. + /// + ColumnCategoryCamelCase, + + /// + /// Column element's Modularize attribute is camel-case. + /// + ColumnModularizeCamelCase, + + /// + /// Inner text value should move to an attribute. + /// + InnerTextDeprecated, + + /// + /// Explicit auto-GUID unnecessary. + /// + AutoGuidUnnecessary, + + /// + /// The Feature Absent attribute renamed to AllowAbsent. + /// + FeatureAbsentAttributeReplaced, + + /// + /// The Feature AllowAdvertise attribute value deprecated. + /// + FeatureAllowAdvertiseValueDeprecated, + + /// + /// The Condition='1' attribute is unnecessary on Publish elements. + /// + PublishConditionOneUnnecessary, + + /// + /// DpiAwareness is new and is defaulted to 'perMonitorV2' which is a change in behavior. + /// + AssignBootstrapperApplicationDpiAwareness, + + /// + /// The string variable type was previously treated as formatted. + /// + AssignVariableTypeFormatted, + + /// + /// The CustomAction attributes have been renamed from BinaryKey and FileKey to BinaryRef and FileRef. + /// + CustomActionKeysAreNowRefs, + + /// + /// The Product and Package elements have been renamed and reorganized. + /// + ProductAndPackageRenamed, + + /// + /// The Module and Package elements have been renamed and reorganized. + /// + ModuleAndPackageRenamed, + + /// + /// A MediaTemplate with no attributes set is now provided by default. + /// + DefaultMediaTemplate, + + /// + /// util:RegistrySearch has breaking change when value is missing. + /// + UtilRegistryValueSearchBehaviorChange, + + /// + /// DisplayInternalUI can't be converted. + /// + DisplayInternalUiNotConvertable, + + /// + /// InstallerVersion has breaking change when missing. + /// + InstallerVersionBehaviorChange, + + /// + /// Verb/@Target can't be converted. + /// + VerbTargetNotConvertable, + + /// + /// The bootstrapper application dll is now specified in its own element. + /// + BootstrapperApplicationDll, + + /// + /// The new bootstrapper application dll element is required. + /// + BootstrapperApplicationDllRequired, + + /// + /// bal:UseUILanguages is deprecated, 'true' is now the standard behavior. + /// + BalUseUILanguagesDeprecated, + + /// + /// The custom elements for built-in BAs are now required. + /// + BalBootstrapperApplicationRefToElement, + + /// + /// The ExePackage elements "XxxCommand" attributes have been renamed to "XxxArguments". + /// + RenameExePackageCommandToArguments, + + /// + /// The Win64 attribute has been renamed. Use the Bitness attribute instead. + /// + Win64AttributeRenamed, + + /// + /// Breaking change: The Win64 attribute's value '{0}' cannot be converted automatically to the new Bitness attribute. + /// + Win64AttributeRenameCannotBeAutomatic, + + /// + /// The Tag element has been renamed. Use the element 'SoftwareTag' name. + /// + TagElementRenamed, + + /// + /// The Dependency namespace has been incorporated into WiX v4 namespace. + /// + IntegratedDependencyNamespace, + + /// + /// Remove unused namespaces. + /// + RemoveUnusedNamespaces, + + /// + /// The Remote element has been renamed. Use the "XxxPackagePayload" element instead. + /// + RemotePayloadRenamed, + + /// + /// The XxxPackage/@Name attribute must be specified on the child XxxPackagePayload element when using a remote payload. + /// + NameAttributeMovedToRemotePayload, + + /// + /// The XxxPackage/@Compressed attribute should not be specified when using a remote payload. + /// + CompressedAttributeUnnecessaryForRemotePayload, + + /// + /// The XxxPackage/@DownloadUrl attribute must be specified on the child XxxPackagePayload element when using a remote payload. + /// + DownloadUrlAttributeMovedToRemotePayload, + + /// + /// The hash algorithm used for bundles changed from SHA1 to SHA512. + /// + BurnHashAlgorithmChanged, + + /// + /// CustomTable elements can't always be converted. + /// + CustomTableNotAlwaysConvertable, + + /// + /// CustomTable elements that don't contain the table definition are now CustomTableRef. + /// + CustomTableRef, + + /// + /// The RegistryKey element's Action attribute is obsolete. + /// + RegistryKeyActionObsolete, + + /// + /// The TagRef element has been renamed. Use the element 'SoftwareTagRef' name. + /// + TagRefElementRenamed, + + /// + /// The SoftwareTag element's Licensed attribute is obsolete. + /// + SoftwareTagLicensedObsolete, + + /// + /// The SoftwareTag element's Type attribute is obsolete. + /// + SoftwareTagTypeObsolete, + + /// + /// TARGETDIR directory should not longer be explicitly defined. + /// + TargetDirDeprecated, + + /// + /// Standard directories should no longer be defined using the Directory element. + /// + DefiningStandardDirectoryDeprecated, + + /// + /// Naked custom action and property references replaced with WixUtilExtension elements. + /// + UtilReferencesReplaced, + } + } +} diff --git a/src/wix/WixToolset.Converters/WixToolset.Converters.csproj b/src/wix/WixToolset.Converters/WixToolset.Converters.csproj new file mode 100644 index 00000000..7dddefa5 --- /dev/null +++ b/src/wix/WixToolset.Converters/WixToolset.Converters.csproj @@ -0,0 +1,24 @@ + + + + + + + netstandard2.0 + $(TargetFrameworks);net461;net472 + Converter + WiX Toolset Converters + embedded + true + true + + + + + + + + + + + diff --git a/src/wix/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs b/src/wix/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs new file mode 100644 index 00000000..084d3b92 --- /dev/null +++ b/src/wix/WixToolset.Converters/WixToolsetCoreServiceProviderExtensions.cs @@ -0,0 +1,25 @@ +// 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 +{ + using WixToolset.Extensibility.Services; + + /// + /// Extension methods for adding Converters services. + /// + public static class WixToolsetCoreServiceProviderExtensions + { + /// + /// Adds Converters services. + /// + /// + /// + public static IWixToolsetCoreServiceProvider AddConverter(this IWixToolsetCoreServiceProvider coreProvider) + { + var extensionManager = coreProvider.GetService(); + extensionManager.Add(typeof(ConverterExtensionFactory).Assembly); + + return coreProvider; + } + } +} diff --git a/src/wix/appveyor.cmd b/src/wix/appveyor.cmd new file mode 100644 index 00000000..02db695b --- /dev/null +++ b/src/wix/appveyor.cmd @@ -0,0 +1,20 @@ +@setlocal +@pushd %~dp0 +@set _P=%~dp0build\Release\publish +@set _C=Release +@if /i "%1"=="debug" set _C=Debug + +:: Restore +msbuild -p:Configuration=%_C% -t:Restore || exit /b + +:: Build +msbuild -p:Configuration=%_C% || exit /b + +:: Test +dotnet test -c %_C% --no-build || exit /b + +:: Pack +msbuild -p:Configuration=%_C% -p:NoBuild=true -t:Pack || exit /b + +@popd +@endlocal diff --git a/src/wix/appveyor.yml b/src/wix/appveyor.yml new file mode 100644 index 00000000..364569cf --- /dev/null +++ b/src/wix/appveyor.yml @@ -0,0 +1,44 @@ +# Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. +# +# Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml +# then update all of the repos. + +branches: + only: + - master + - develop + +image: Visual Studio 2019 + +version: 0.0.0.{build} +configuration: Release + +environment: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + NUGET_XMLDOC_MODE: skip + +build_script: + - appveyor.cmd + +test: off + +pull_requests: + do_not_increment_build_number: true + +nuget: + disable_publish_on_pr: true + +skip_branch_with_pr: true +skip_tags: true + +artifacts: +- path: build\Release\**\*.nupkg + name: nuget +- path: build\Release\**\*.snupkg + name: snupkg + +notifications: +- provider: Slack + incoming_webhook: + secure: p5xuu+4x2JHfwGDMDe5KcG1k7gZxqYc4jWVwvyNZv5cvkubPD2waJs5yXMAXZNN7Z63/3PWHb7q4KoY/99AjauYa1nZ4c5qYqRPFRBKTHfA= diff --git a/src/wix/deps/wix.dll b/src/wix/deps/wix.dll new file mode 100644 index 00000000..64f70f75 Binary files /dev/null and b/src/wix/deps/wix.dll differ diff --git a/src/wix/nuget.config b/src/wix/nuget.config new file mode 100644 index 00000000..31435a21 --- /dev/null +++ b/src/wix/nuget.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/wix/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs b/src/wix/test/WixToolsetTest.Converters.Symbolizer/ConvertSymbolsFixture.cs new file mode 100644 index 00000000..01213524 --- /dev/null +++ b/src/wix/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, + 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/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixout b/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixout new file mode 100644 index 00000000..da64b8af Binary files /dev/null and b/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixout differ diff --git a/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj b/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj new file mode 100644 index 00000000..d7c4e625 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wixproj @@ -0,0 +1,47 @@ + + + + Debug + x86 + 3.10 + d59f1c1e-9238-49fa-bfa2-ec1d9c2dda1d + 2.0 + SymbolizerWixout + Package + + + bin\$(Configuration)\ + obj\$(Configuration)\ + Debug + + + bin\$(Configuration)\ + obj\$(Configuration)\ + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixNetFxExtension.dll + WixNetFxExtension + + + + + + + + + \ No newline at end of file diff --git a/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs b/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs new file mode 100644 index 00000000..46d4fb43 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters.Symbolizer/TestData/Integration/test.wxs @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj b/src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj new file mode 100644 index 00000000..995d9297 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.csproj @@ -0,0 +1,33 @@ + + + + + + + net461 + false + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject b/src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject new file mode 100644 index 00000000..18ab4f79 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters.Symbolizer/WixToolsetTest.Converters.Symbolizer.v3.ncrunchproject @@ -0,0 +1,9 @@ + + + + + WixToolsetTest.Converters.Symbolizer.ConvertSymbolsFixture.CanLoadWixoutAndConvertToIntermediate + + + + \ No newline at end of file diff --git a/src/wix/test/WixToolsetTest.Converters/BaseConverterFixture.cs b/src/wix/test/WixToolsetTest.Converters/BaseConverterFixture.cs new file mode 100644 index 00000000..2421d73b --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/BaseConverterFixture.cs @@ -0,0 +1,33 @@ +// 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 +{ + using System; + using System.IO; + using System.Text; + using System.Xml; + using System.Xml.Linq; + using Xunit; + + public abstract class BaseConverterFixture + { + protected static string UnformattedDocumentString(XDocument document, bool omitXmlDeclaration = true) + { + var sb = new StringBuilder(); + + using (var writer = new StringWriter(sb)) + using (var xml = XmlWriter.Create(writer, new XmlWriterSettings { OmitXmlDeclaration = omitXmlDeclaration })) + { + document.Save(xml); + } + + return sb.ToString().TrimStart(); + } + + protected static string[] UnformattedDocumentLines(XDocument document, bool omitXmlDeclaration = true) + { + var unformatted = UnformattedDocumentString(document, omitXmlDeclaration); + return unformatted.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/BitnessFixture.cs b/src/wix/test/WixToolsetTest.Converters/BitnessFixture.cs new file mode 100644 index 00000000..e45a9388 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/BitnessFixture.cs @@ -0,0 +1,187 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class BitnessFixture : BaseConverterFixture + { + [Fact] + public void FixComponentBitness() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(10, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixRegistrySearchBitness() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixUtilRegistrySearchBitness() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(6, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixApprovedExeBitness() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs b/src/wix/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs new file mode 100644 index 00000000..158ab3be --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/BootstrapperApplicationFixture.cs @@ -0,0 +1,418 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class BootstrapperApplicationFixture : BaseConverterFixture + { + [Fact] + public void CantCreateBootstrapperApplicationDllFromV3PayloadGroupRef() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(2, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void ConvertDotNetCoreBootstrapperApplicationRefWithExistingElement() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(1, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void ConvertDotNetCoreBootstrapperApplicationRefWithoutExistingElement() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + "", + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(1, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void ConvertFrameworkBootstrapperApplicationRefWithExistingElement() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void ConvertFrameworkBootstrapperApplicationRefWithoutExistingElement() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + "", + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void ConvertStandardBootstrapperApplicationRefWithExistingElement() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void ConvertStandardBootstrapperApplicationRefWithoutExistingElement() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + "", + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void CreateBootstrapperApplicationDllFromV3() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + "", + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void CreateBootstrapperApplicationDllFromV3Payload() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + "", + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void DoesntSetDpiUnawareFromV4() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(0, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void KeepsDpiAwarenessFromV4() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + "", + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(1, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void RemovesBalUseUILanguages() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(5, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs b/src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs new file mode 100644 index 00000000..d3f65aeb --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/ConditionFixture.cs @@ -0,0 +1,297 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class ConditionFixture : BaseConverterFixture + { + [Fact] + public void FixControlCondition() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " x=y", + " a<>b", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixPublishCondition() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " 1<2", + " 1", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(5, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixComponentCondition() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " 1<2", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixFeatureCondition() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " PROP = 1", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixLaunchCondition() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " 1<2", + " ", + " ", + " 1=2", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixLaunchConditionInProduct() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " 1<2", + " ", + " ", + " 1=2", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(6, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixPermissionExCondition() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " 1<2", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs b/src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs new file mode 100644 index 00000000..13df9da7 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs @@ -0,0 +1,449 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class ConverterFixture : BaseConverterFixture + { + private static readonly XNamespace Wix4Namespace = "http://wixtoolset.org/schemas/v4/wxs"; + + [Fact] + public void EnsuresNoDeclaration() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(1, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void EnsuresDeclarationWhenIgnored() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, ignoreErrors: new[] { "DeclarationPresent" } ); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document, omitXmlDeclaration: false); + + Assert.Equal(0, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertMainNamespace() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + //Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertNamedMainNamespace() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + Assert.Equal(Wix4Namespace, document.Root.GetNamespaceOfPrefix("w")); + } + + [Fact] + public void CanConvertNonWixDefaultNamespace() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(expected, actual); + Assert.Equal(3, errors); + Assert.Equal(Wix4Namespace, document.Root.GetNamespaceOfPrefix("w")); + Assert.Equal("http://wixtoolset.org/schemas/v4/wxs/util", document.Root.GetDefaultNamespace()); + } + + [Fact] + public void CanRemoveUnusedNamespaces() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(4, errors); + Assert.Equal(expected, actual); + Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); + } + + [Fact] + public void CanConvertMissingWixNamespace() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); + } + + [Fact] + public void CanConvertMissingIncludeNamespace() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + Assert.Equal(Wix4Namespace, document.Root.GetDefaultNamespace()); + } + + [Fact] + public void CanConvertAnonymousFile() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(3, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertShortNameDirectoryWithoutName() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertCatalogElement() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(1, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertSuppressSignatureValidationNo() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(1, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertSuppressSignatureValidationYes() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(1, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CantConvertVerbTarget() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertDeprecatedPrefix() + { + var parse = String.Join(Environment.NewLine, + "", + "", + "", + "", + "", + "", + "", + "", + ""); + + var expected = String.Join(Environment.NewLine, + "", + "", + "", + "", + "", + "", + "", + "", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(3, errors); + Assert.Equal(expected, actual); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs b/src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs new file mode 100644 index 00000000..a39f6243 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/ConverterIntegrationFixture.cs @@ -0,0 +1,195 @@ +// 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 +{ + using System; + using System.IO; + using System.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolset.Core; + using WixToolset.Core.TestPackage; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class ConverterIntegrationFixture + { + [Fact] + public void CanConvertPermissionExFile() + { + const string beforeFileName = "v3.wxs"; + const string afterFileName = "v4_expected.wxs"; + var folder = TestData.Get(@"TestData\PermissionEx"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(true); + var targetFile = Path.Combine(baseFolder, beforeFileName); + File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 4); + var errors = converter.ConvertFile(targetFile, true); + + Assert.Equal(8, errors); + + var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); + var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); + Assert.Equal(expected, actual); + + EnsureFixed(targetFile); + } + } + + [Fact] + public void CanConvertSingleFile() + { + const string beforeFileName = "SingleFile.wxs"; + const string afterFileName = "ConvertedSingleFile.wxs"; + var folder = TestData.Get(@"TestData\SingleFile"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(true); + var targetFile = Path.Combine(baseFolder, beforeFileName); + File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 4); + var errors = converter.ConvertFile(targetFile, true); + + Assert.Equal(9, errors); + + var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); + var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); + Assert.Equal(expected, actual); + + EnsureFixed(targetFile); + } + } + + [Fact] + public void CanDetectReadOnlyOutputFile() + { + const string beforeFileName = "SingleFile.wxs"; + var folder = TestData.Get(@"TestData\SingleFile"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(true); + var targetFile = Path.Combine(baseFolder, beforeFileName); + File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); + + var info = new FileInfo(targetFile); + info.IsReadOnly = true; + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 4); + var errors = converter.ConvertFile(targetFile, true); + + Assert.Single(messaging.Messages.Where(m => m.Id == 5/*WixConverter.ConverterTestType.UnauthorizedAccessException*/)); + } + } + + [Fact] + public void RetainsPreprocessorInstructions() + { + const string beforeFileName = "Preprocessor.wxs"; + const string afterFileName = "ConvertedPreprocessor.wxs"; + var folder = TestData.Get(@"TestData\Preprocessor"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(true); + var targetFile = Path.Combine(baseFolder, beforeFileName); + File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); + + var settingsFile = Path.Combine(folder, "wixcop.settings.xml"); + + var result = RunConversion(targetFile, settingsFile: settingsFile); + Assert.Equal(9, result.ExitCode); + + var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); + var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); + Assert.Equal(expected, actual); + + EnsureFixed(targetFile); + } + } + + [Fact] + public void CanConvertQtExec() + { + const string beforeFileName = "v3.wxs"; + const string afterFileName = "v4_expected.wxs"; + var folder = TestData.Get(@"TestData\QtExec"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(true); + var targetFile = Path.Combine(baseFolder, beforeFileName); + File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); + + var result = RunConversion(targetFile); + Assert.Equal(13, result.ExitCode); + + var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); + var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); + Assert.Equal(expected, actual); + + EnsureFixed(targetFile); + } + } + + [Fact] + public void DetectUnconvertableQtExecCmdTimeout() + { + const string beforeFileName = "v3.wxs"; + const string afterFileName = "v4_expected.wxs"; + var folder = TestData.Get(@"TestData\QtExec.bad"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(true); + var targetFile = Path.Combine(baseFolder, beforeFileName); + File.Copy(Path.Combine(folder, beforeFileName), Path.Combine(baseFolder, beforeFileName)); + + var result = RunConversion(targetFile); + + Assert.Equal(13, result.ExitCode); + Assert.Single(result.Messages.Where(message => message.ToString().EndsWith("(QtExecCmdTimeoutAmbiguous)"))); + + var expected = File.ReadAllText(Path.Combine(folder, afterFileName)).Replace("\r\n", "\n"); + var actual = File.ReadAllText(targetFile).Replace("\r\n", "\n"); + Assert.Equal(expected, actual); + + // still fails because QtExecCmdTimeoutAmbiguous is unfixable + var result2 = RunConversion(targetFile); + Assert.Equal(1, result2.ExitCode); + } + } + + private static WixRunnerResult RunConversion(string targetFile, bool fixErrors = true, string settingsFile = null) + { + var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider().AddConverter(); + + var exitCode = WixRunner.Execute(new[] + { + "convert", + fixErrors ? null : "--dry-run", + String.IsNullOrEmpty(settingsFile) ? null : "-set1" + settingsFile, + targetFile + }, serviceProvider, out var messages); + + return new WixRunnerResult { ExitCode = exitCode.Result, Messages = messages.ToArray() }; + } + + private static void EnsureFixed(string targetFile) + { + var messaging2 = new MockMessaging(); + var converter2 = new WixConverter(messaging2, 4); + var errors2 = converter2.ConvertFile(targetFile, true); + Assert.Equal(0, errors2); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/CustomActionFixture.cs b/src/wix/test/WixToolsetTest.Converters/CustomActionFixture.cs new file mode 100644 index 00000000..eafc171a --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/CustomActionFixture.cs @@ -0,0 +1,88 @@ +// 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 +{ + using System; + using System.IO; + using System.Xml.Linq; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class CustomActionFixture : BaseConverterFixture + { + [Fact] + public void CanConvertCustomAction() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(11, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertCustomActionScript() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " function() {", + " var x = 0;", + " return x;", + " }", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expectedScript = String.Join("\n", + "function() {", + " var x = 0;", + " return x;", + " }"); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + + var script = File.ReadAllText("Foo.js"); + Assert.Equal(expectedScript, script); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/CustomTableFixture.cs b/src/wix/test/WixToolsetTest.Converters/CustomTableFixture.cs new file mode 100644 index 00000000..2b81a863 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/CustomTableFixture.cs @@ -0,0 +1,363 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class CustomTableFixture : BaseConverterFixture + { + [Fact] + public void FixCustomTableCategoryAndModularization() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixCustomRowTextValue() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " Some value", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixCustomRowCdataValue() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixCustomRowWithoutValue() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void CanConvertBundleCustomTableBootstrapperApplicationData() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " Row1", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Bundle); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertBundleCustomTableRef() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " Row1", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Bundle); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertMsiCustomTableBootstrapperApplicationData() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " Row1", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Msi); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanConvertMsiCustomTableRef() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " Row1", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, customTableTarget: CustomTableTarget.Msi); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(2, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanDetectAmbiguousCustomTableBootstrapperApplicationData() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(1, errors); + Assert.Equal(expected, actual); + } + + [Fact] + public void CanRemoveBootstrapperApplicationDataFromRealCustomTable() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(1, errors); + Assert.Equal(expected, actual); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/DependencyFixture.cs b/src/wix/test/WixToolsetTest.Converters/DependencyFixture.cs new file mode 100644 index 00000000..41ded927 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/DependencyFixture.cs @@ -0,0 +1,178 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class DependencyFixture : BaseConverterFixture + { + [Fact] + public void FixPackageDependencyProvides() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(5, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixPackageDependencyRequires() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(7, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixPackageDependencyRequiresRef() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(7, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixBundleDependencyProvides() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(5, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/DirectoryFixture.cs b/src/wix/test/WixToolsetTest.Converters/DirectoryFixture.cs new file mode 100644 index 00000000..3c906320 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/DirectoryFixture.cs @@ -0,0 +1,92 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class DirectoryFixture : BaseConverterFixture + { + [Fact] + public void RemoveTargetDir() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixStandardDirectory() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/ExePackageFixture.cs b/src/wix/test/WixToolsetTest.Converters/ExePackageFixture.cs new file mode 100644 index 00000000..0ee8d065 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/ExePackageFixture.cs @@ -0,0 +1,49 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class ExePackageFixture : BaseConverterFixture + { + [Fact] + public void CanConvertExePackageCommandToArguments() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/FeatureFixture.cs b/src/wix/test/WixToolsetTest.Converters/FeatureFixture.cs new file mode 100644 index 00000000..1df94a81 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/FeatureFixture.cs @@ -0,0 +1,110 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class FeatureFixture : BaseConverterFixture + { + [Fact] + public void FixAllowAttributes() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixDisallowAttributes() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void RemoveDeprecatedAllowAdvertiseAttributes() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs b/src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs new file mode 100644 index 00000000..a101019b --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs @@ -0,0 +1,47 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class FirewallExtensionFixture : BaseConverterFixture + { + [Fact] + public void FixRemoteAddressValue() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " 127.0.0.1", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/FormatFixture.cs b/src/wix/test/WixToolsetTest.Converters/FormatFixture.cs new file mode 100644 index 00000000..739fba66 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/FormatFixture.cs @@ -0,0 +1,117 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class FormatFixture : BaseConverterFixture + { + [Fact] + public void CanFixWhitespace() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 4, null, null); + + var errors = converter.FormatDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(expected, actual); + Assert.Equal(5, errors); + } + + [Fact] + public void CanPreserveNewLines() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + "", + " ", + "", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + "", + " ", + "", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 4, null, null); + + var conversions = converter.FormatDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(expected, actual); + Assert.Equal(4, conversions); + } + + [Fact] + public void CanFormatWithNewLineAtEndOfFile() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + "", + " ", + "", + " ", + "", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + "", + " ", + "", + " ", + "", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 4, null, null); + + var conversions = converter.FormatDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(expected, actual); + Assert.Equal(3, conversions); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/IncludeFixture.cs b/src/wix/test/WixToolsetTest.Converters/IncludeFixture.cs new file mode 100644 index 00000000..2fd8244f --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/IncludeFixture.cs @@ -0,0 +1,68 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class IncludeFixture : BaseConverterFixture + { + [Fact] + public void EnsureNamespace() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = new[] + { + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(1, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixNamespace() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + ""); + + var expected = new[] + { + "", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(1, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs b/src/wix/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs new file mode 100644 index 00000000..b6bb8a40 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/Mocks/MockCoreServiceProvider.cs @@ -0,0 +1,51 @@ +// 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.Mocks +{ + using System; + using System.Collections.Generic; + using WixToolset.Extensibility.Services; + + public class MockCoreServiceProvider : IWixToolsetCoreServiceProvider + { + public Dictionary, object>> CreationFunctions { get; } = new Dictionary, object>>(); + + public Dictionary Singletons { get; } = new Dictionary() + { + { typeof(IMessaging), new MockMessaging() } + }; + + public void AddService(Type serviceType, Func, object> creationFunction) => this.CreationFunctions.Add(serviceType, creationFunction); + + public void AddService(Func, T> creationFunction) where T : class => this.AddService(typeof(T), creationFunction); + + public T GetService() where T : class => this.TryGetService(typeof(T), out var obj) ? (T)obj : null; + + public object GetService(Type serviceType) => this.TryGetService(serviceType, out var service) ? service : null; + + public bool TryGetService(Type serviceType, out object service) + { + if (!this.Singletons.TryGetValue(serviceType, out service)) + { + if (this.CreationFunctions.TryGetValue(serviceType, out var creationFunction)) + { + service = creationFunction(this, this.Singletons); + } + } + + return service != null; + } + + public bool TryGetService(out T service) where T : class + { + service = null; + + if (this.TryGetService(typeof(T), out var obj)) + { + service = (T)obj; + } + + return service != null; + } + } +} \ No newline at end of file diff --git a/src/wix/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs b/src/wix/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs new file mode 100644 index 00000000..77821a1c --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/Mocks/MockMessaging.cs @@ -0,0 +1,39 @@ +// 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.Mocks +{ + using System; + using System.Collections.Generic; + using WixToolset.Data; + using WixToolset.Extensibility; + using WixToolset.Extensibility.Services; + + public class MockMessaging : IMessaging + { + public List Messages { get; } = new List(); + + public bool EncounteredError { get; private set; } + + public int LastErrorNumber { get; } + + public bool ShowVerboseMessages { get; set; } + + public bool SuppressAllWarnings { get; set; } + + public bool WarningsAsError { get; set; } + + public void ElevateWarningMessage(int warningNumber) => throw new NotImplementedException(); + + public void SetListener(IMessageListener listener) => throw new NotImplementedException(); + + public void SuppressWarningMessage(int warningNumber) => throw new NotImplementedException(); + + public void Write(Message message) + { + this.Messages.Add(message); + this.EncounteredError |= message.Level == MessageLevel.Error; + } + + public void Write(string message, bool verbose = false) => throw new NotImplementedException(); + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/ProductPackageFixture.cs b/src/wix/test/WixToolsetTest.Converters/ProductPackageFixture.cs new file mode 100644 index 00000000..e01b9789 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/ProductPackageFixture.cs @@ -0,0 +1,278 @@ +// 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 +{ + using System; + using System.IO; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolset.Core.TestPackage; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class ProductPackageFixture : BaseConverterFixture + { + [Fact] + public void FixesCompressedWhenYes() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 4, expected); + } + + [Fact] + public void FixesCompressedWhenNo() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 4, expected); + } + + [Fact] + public void FixesCompressedWhenOmitted() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 4, expected); + } + + private static void AssertSuccess(string input, int expectedErrorCount, string[] expected) + { + var document = XDocument.Parse(input, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(expectedErrorCount, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixesInstallerVersion() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 3, expected); + } + + [Fact] + public void FixesDefaultInstallerVersion() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 3, expected); + } + + [Fact] + public void FixesImplicitInstallerVersion() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 4, expected); + } + + [Fact] + public void FixesNonDefaultInstallerVersion() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 3, expected); + } + + [Fact] + public void FixesLimitedInstallerPrivileges() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 4, expected); + } + + [Fact] + public void FixesElevatedInstallerPrivileges() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + "" + }; + + AssertSuccess(parse, 4, expected); + } + + [Fact] + public void CanDecompileAndRecompile() + { + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var decompiledWxsPath = Path.Combine(baseFolder, "TypicalV3.wxs"); + + var folder = TestData.Get(@"TestData\PackageSummaryInformation"); + var v3msiPath = Path.Combine(folder, "TypicalV3.msi"); + var result = WixRunner.Execute(new[] + { + "decompile", v3msiPath, + "-intermediateFolder", intermediateFolder, + "-o", decompiledWxsPath + }); + + result.AssertSuccess(); + + var v4msiPath = Path.Combine(intermediateFolder, "TypicalV4.msi"); + result = WixRunner.Execute(new[] + { + "build", decompiledWxsPath, + "-arch", "x64", + "-intermediateFolder", intermediateFolder, + "-o", v4msiPath + }); + + result.AssertSuccess(); + + Assert.True(File.Exists(v4msiPath)); + + var v3results = Query.QueryDatabase(v3msiPath, new[] { "_SummaryInformation", "Property" }); + var v4results = Query.QueryDatabase(v4msiPath, new[] { "_SummaryInformation", "Property" }); + WixAssert.CompareLineByLine(v3results, v4results); + } + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/PropertyFixture.cs b/src/wix/test/WixToolsetTest.Converters/PropertyFixture.cs new file mode 100644 index 00000000..e50a6518 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/PropertyFixture.cs @@ -0,0 +1,108 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class PropertyFixture : BaseConverterFixture + { + [Fact] + public void CanFixCdataWhitespace() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(expected, actual); + Assert.Equal(1, errors); + } + + [Fact] + public void CanFixCdataWithWhitespace() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(expected, actual); + Assert.Equal(1, errors); + } + + [Fact] + public void CanKeepCdataWithOnlyWhitespace() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + var errors = converter.ConvertDocument(document); + + var actual = UnformattedDocumentString(document); + + Assert.Equal(expected, actual); + Assert.Equal(1, errors); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/RegistryFixture.cs b/src/wix/test/WixToolsetTest.Converters/RegistryFixture.cs new file mode 100644 index 00000000..405f5416 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/RegistryFixture.cs @@ -0,0 +1,54 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class RegistryFixture : BaseConverterFixture + { + [Fact] + public void FixRegistryKeyAction() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(5, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/RemotePayloadFixture.cs b/src/wix/test/WixToolsetTest.Converters/RemotePayloadFixture.cs new file mode 100644 index 00000000..b2640e13 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/RemotePayloadFixture.cs @@ -0,0 +1,104 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class RemotePayloadFixture : BaseConverterFixture + { + [Fact] + public void CanConvertExePackageRemotePayload() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(6, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void CanConvertMsuPackageRemotePayload() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(5, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/SequenceFixture.cs b/src/wix/test/WixToolsetTest.Converters/SequenceFixture.cs new file mode 100644 index 00000000..ec6c709b --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/SequenceFixture.cs @@ -0,0 +1,49 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class SequenceFixture : BaseConverterFixture + { + [Fact] + public void FixCondition() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " NOT Installed", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(2, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/TagFixture.cs b/src/wix/test/WixToolsetTest.Converters/TagFixture.cs new file mode 100644 index 00000000..5e07c83b --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TagFixture.cs @@ -0,0 +1,111 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class TagFixture : BaseConverterFixture + { + [Fact] + public void FixTagExtension() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixTagExtensionDeprecations() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(7, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixTagExtensionTagRef() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi b/src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi new file mode 100644 index 00000000..0d7e1b21 Binary files /dev/null and b/src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.msi differ diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs new file mode 100644 index 00000000..8c5027b4 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/PackageSummaryInformation/TypicalV3.wxs @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs new file mode 100644 index 00000000..9a739052 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v3.wxs @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs new file mode 100644 index 00000000..6bf3c1ea --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/PermissionEx/v4_expected.wxs @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs new file mode 100644 index 00000000..8188d900 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/ConvertedPreprocessor.wxs @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs new file mode 100644 index 00000000..2eb908c2 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/Preprocessor.wxs @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml b/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml new file mode 100644 index 00000000..9d3ad496 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/Preprocessor/wixcop.settings.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs new file mode 100644 index 00000000..b0fcf9c9 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v3.wxs @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs new file mode 100644 index 00000000..95d2f618 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec.bad/v4_expected.wxs @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs new file mode 100644 index 00000000..8d81a758 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v3.wxs @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs new file mode 100644 index 00000000..f24d3f8f --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/QtExec/v4_expected.wxs @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs new file mode 100644 index 00000000..5bcdaf59 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/ConvertedSingleFile.wxs @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs b/src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs new file mode 100644 index 00000000..310ae811 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/TestData/SingleFile/SingleFile.wxs @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.Converters/UtilExtensionFixture.cs b/src/wix/test/WixToolsetTest.Converters/UtilExtensionFixture.cs new file mode 100644 index 00000000..10450c68 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/UtilExtensionFixture.cs @@ -0,0 +1,190 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class UtilExtensionFixture : BaseConverterFixture + { + [Fact] + public void FixCloseAppsCondition() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " a<>b", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixXmlConfigValue() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " a<>b", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void WarnsOnAllRegistryValueSearches() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(4, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + + [Fact] + public void FixXmlConfigValueCData() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " b]]>", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void FixQueryOsPropertyRefs() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(6, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/VariableFixture.cs b/src/wix/test/WixToolsetTest.Converters/VariableFixture.cs new file mode 100644 index 00000000..b7b7388f --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/VariableFixture.cs @@ -0,0 +1,86 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class VariableFixture : BaseConverterFixture + { + [Fact] + public void FixFormattedType() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(3, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + + [Fact] + public void DoesntFixFormattedTypeFromV4() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(0, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs b/src/wix/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs new file mode 100644 index 00000000..16a68895 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/Wix4ConversionFixture.cs @@ -0,0 +1,54 @@ +// 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 +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class Wix4ConversionFixture : BaseConverterFixture + { + [Fact] + public void DoesNotAddFileId() + { + var parse = String.Join(Environment.NewLine, + "", + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(1, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} diff --git a/src/wix/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj b/src/wix/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj new file mode 100644 index 00000000..29b02b95 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/WixToolsetTest.Converters.csproj @@ -0,0 +1,31 @@ + + + + + + netcoreapp3.1 + false + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/version.json b/version.json deleted file mode 100644 index 5f857771..00000000 --- a/version.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "4.0", - "publicReleaseRefSpec": [ - "^refs/heads/master$" - ], - "cloudBuild": { - "buildNumber": { - "enabled": true - } - } -} -- cgit v1.2.3-55-g6feb