From 4449fcc5b8d104817c67135229682c66c3d892ca Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Fri, 2 Apr 2021 14:41:49 -0700 Subject: Enable codepages and languages to be set via .wxl files Fixes wixtoolset/issues#5801 --- .../WixToolset.Core.Burn.csproj | 1 - .../Bind/AttachPatchTransformsCommand.cs | 26 ++-- .../Bind/BindDatabaseCommand.cs | 127 +++++++++-------- .../Bind/BindSummaryInfoCommand.cs | 61 ++++++-- .../Bind/BindTransformCommand.cs | 2 +- .../Bind/CreateDeltaPatchesCommand.cs | 4 +- .../Bind/CreateIdtFileCommand.cs | 42 +++--- .../CreateWindowsInstallerDataFromIRCommand.cs | 32 ++++- .../Bind/GenerateDatabaseCommand.cs | 11 +- .../Bind/GenerateTransformCommand.cs | 1 - .../Bind/ProcessPropertiesCommand.cs | 101 ++++++++++++++ .../Unbind/UnbindTranformCommand.cs | 2 +- .../WixToolset.Core.WindowsInstaller.csproj | 1 + src/WixToolset.Core/BindContext.cs | 8 +- src/WixToolset.Core/CommandLine/BuildCommand.cs | 4 +- src/WixToolset.Core/Compiler.cs | 4 +- src/WixToolset.Core/CompilerCore.cs | 18 ++- src/WixToolset.Core/Compiler_Bundle.cs | 2 +- src/WixToolset.Core/Compiler_Module.cs | 20 +-- src/WixToolset.Core/Compiler_Package.cs | 46 +++--- src/WixToolset.Core/Compiler_Patch.cs | 9 +- src/WixToolset.Core/Compiler_PatchCreation.cs | 2 +- src/WixToolset.Core/IResolver.cs | 9 +- .../Link/CollateLocalizationsCommand.cs | 4 +- src/WixToolset.Core/Linker.cs | 2 +- src/WixToolset.Core/LocalizationParser.cs | 20 +-- src/WixToolset.Core/ResolveResult.cs | 6 +- src/WixToolset.Core/Resolver.cs | 81 ++++++----- .../LanguageFixture.cs | 155 +++++++++++++++++++++ .../LinkerFixture.cs | 4 +- .../WixToolsetTest.CoreIntegration/ParseFixture.cs | 2 +- .../TestData/Language/Package.en-us.wxl | 7 + .../TestData/Language/Package.ja-jp.wxl | 7 + .../TestData/Language/Package.wxl | 7 + .../TestData/Language/Package.wxs | 16 +++ .../Language/PackageWithEnSummaryInfo.ja-jp.wxl | 7 + .../TestData/Language/data/test.txt | 1 + .../VariableResolverFixture.cs | 2 +- 38 files changed, 619 insertions(+), 235 deletions(-) create mode 100644 src/WixToolset.Core.WindowsInstaller/Bind/ProcessPropertiesCommand.cs create mode 100644 src/test/WixToolsetTest.CoreIntegration/LanguageFixture.cs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.en-us.wxl create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.ja-jp.wxl create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxl create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Language/PackageWithEnSummaryInfo.ja-jp.wxl create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Language/data/test.txt (limited to 'src') diff --git a/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj b/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj index 2e828eae..85bfae69 100644 --- a/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj +++ b/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj @@ -22,7 +22,6 @@ - diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AttachPatchTransformsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AttachPatchTransformsCommand.cs index 5f8df92c..76bcd532 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/AttachPatchTransformsCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/AttachPatchTransformsCommand.cs @@ -91,15 +91,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind var symbols = this.Intermediate.Sections.SelectMany(s => s.Symbols).ToList(); // Get the patch id from the WixPatchId symbol. - var patchIdSymbol = symbols.OfType().FirstOrDefault(); + var patchSymbol = symbols.OfType().FirstOrDefault(); - if (String.IsNullOrEmpty(patchIdSymbol.Id?.Id)) + if (String.IsNullOrEmpty(patchSymbol.Id?.Id)) { this.Messaging.Write(ErrorMessages.ExpectedPatchIdInWixMsp()); return subStorages; } - if (String.IsNullOrEmpty(patchIdSymbol.ClientPatchId)) + if (String.IsNullOrEmpty(patchSymbol.ClientPatchId)) { this.Messaging.Write(ErrorMessages.ExpectedClientPatchIdInWixMsp()); return subStorages; @@ -115,7 +115,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind } // populate MSP summary information - var patchMetadata = this.PopulateSummaryInformation(summaryInfo, symbols, patchIdSymbol, section.Codepage); + var patchMetadata = this.PopulateSummaryInformation(summaryInfo, symbols, patchSymbol); // enumerate transforms var productCodes = new SortedSet(); @@ -168,7 +168,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind mainTransform.Transform.Tables.Remove("Media"); mainTransform.Transform.Tables.Remove("MsiDigitalSignature"); - var pairedTransform = this.BuildPairedTransform(summaryInfo, patchMetadata, patchIdSymbol, mainTransform.Transform, mediaSymbol, baselineSymbol, out var productCode); + var pairedTransform = this.BuildPairedTransform(summaryInfo, patchMetadata, patchSymbol, mainTransform.Transform, mediaSymbol, baselineSymbol, out var productCode); productCode = productCode.ToUpperInvariant(); productCodes.Add(productCode); @@ -211,14 +211,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind productCodes = FinalizePatchProductCodes(symbols, productCodes); // Semicolon delimited list of the product codes that can accept the patch. - summaryInfo.Add(SummaryInformationType.PatchProductCodes, new SummaryInformationSymbol(patchIdSymbol.SourceLineNumbers) + summaryInfo.Add(SummaryInformationType.PatchProductCodes, new SummaryInformationSymbol(patchSymbol.SourceLineNumbers) { PropertyId = SummaryInformationType.PatchProductCodes, Value = String.Join(";", productCodes) }); // Semicolon delimited list of transform substorage names in the order they are applied. - summaryInfo.Add(SummaryInformationType.TransformNames, new SummaryInformationSymbol(patchIdSymbol.SourceLineNumbers) + summaryInfo.Add(SummaryInformationType.TransformNames, new SummaryInformationSymbol(patchSymbol.SourceLineNumbers) { PropertyId = SummaryInformationType.TransformNames, Value = String.Join(";", transformNames) @@ -262,25 +262,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind return result; } - private Dictionary PopulateSummaryInformation(Dictionary summaryInfo, List symbols, WixPatchIdSymbol patchIdSymbol, int codepage) + private Dictionary PopulateSummaryInformation(Dictionary summaryInfo, List symbols, WixPatchSymbol patchSymbol) { // PID_CODEPAGE if (!summaryInfo.ContainsKey(SummaryInformationType.Codepage)) { // Set the code page by default to the same code page for the // string pool in the database. - AddSummaryInformation(SummaryInformationType.Codepage, codepage.ToString(CultureInfo.InvariantCulture), patchIdSymbol.SourceLineNumbers); + AddSummaryInformation(SummaryInformationType.Codepage, patchSymbol.Codepage?.ToString(CultureInfo.InvariantCulture) ?? "0", patchSymbol.SourceLineNumbers); } // GUID patch code for the patch. - AddSummaryInformation(SummaryInformationType.PatchCode, patchIdSymbol.Id.Id, patchIdSymbol.SourceLineNumbers); + AddSummaryInformation(SummaryInformationType.PatchCode, patchSymbol.Id.Id, patchSymbol.SourceLineNumbers); // Indicates the minimum Windows Installer version that is required to install the patch. - AddSummaryInformation(SummaryInformationType.PatchInstallerRequirement, ((int)SummaryInformation.InstallerRequirement.Version31).ToString(CultureInfo.InvariantCulture), patchIdSymbol.SourceLineNumbers); + AddSummaryInformation(SummaryInformationType.PatchInstallerRequirement, ((int)SummaryInformation.InstallerRequirement.Version31).ToString(CultureInfo.InvariantCulture), patchSymbol.SourceLineNumbers); if (!summaryInfo.ContainsKey(SummaryInformationType.Security)) { - AddSummaryInformation(SummaryInformationType.Security, "4", patchIdSymbol.SourceLineNumbers); // Read-only enforced; + AddSummaryInformation(SummaryInformationType.Security, "4", patchSymbol.SourceLineNumbers); // Read-only enforced; } // Use authored comments or default to display name. @@ -1090,7 +1090,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind /// /// Create the #transform for the given main transform. /// - private WindowsInstallerData BuildPairedTransform(Dictionary summaryInfo, Dictionary patchMetadata, WixPatchIdSymbol patchIdSymbol, WindowsInstallerData mainTransform, MediaSymbol mediaSymbol, WixPatchBaselineSymbol baselineSymbol, out string productCode) + private WindowsInstallerData BuildPairedTransform(Dictionary summaryInfo, Dictionary patchMetadata, WixPatchSymbol patchIdSymbol, WindowsInstallerData mainTransform, MediaSymbol mediaSymbol, WixPatchBaselineSymbol baselineSymbol, out string productCode) { productCode = null; diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index fb5d7b83..06b51ba1 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs @@ -37,7 +37,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind this.CabbingThreadCount = context.CabbingThreadCount; this.CabCachePath = context.CabCachePath; - this.Codepage = context.Codepage; this.DefaultCompressionLevel = context.DefaultCompressionLevel; this.DelayedFields = context.DelayedFields; this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles; @@ -47,6 +46,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind this.OutputPath = context.OutputPath; this.OutputPdbPath = context.PdbPath; this.PdbType = context.PdbType; + this.ResolvedCodepage = context.ResolvedCodepage; + this.ResolvedSummaryInformationCodepage = context.ResolvedSummaryInformationCodepage; + this.ResolvedLcid = context.ResolvedLcid; this.SuppressLayout = context.SuppressLayout; this.SubStorages = subStorages; @@ -67,8 +69,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind private IPathResolver PathResolver { get; } - private int Codepage { get; } - private int CabbingThreadCount { get; } private string CabCachePath { get; } @@ -95,6 +95,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind private string OutputPdbPath { get; } + private int? ResolvedCodepage { get; } + + private int? ResolvedSummaryInformationCodepage { get; } + + private int? ResolvedLcid { get; } + private bool SuppressAddingValidationRows { get; } private bool SuppressLayout { get; } @@ -111,21 +117,22 @@ namespace WixToolset.Core.WindowsInstaller.Bind public IBindResult Execute() { - if (!this.Intermediate.HasLevel(Data.IntermediateLevels.Linked) && !this.Intermediate.HasLevel(Data.IntermediateLevels.Resolved)) + if (!this.Intermediate.HasLevel(Data.IntermediateLevels.Linked) || !this.Intermediate.HasLevel(Data.IntermediateLevels.Resolved)) { this.Messaging.Write(ErrorMessages.IntermediatesMustBeResolved(this.Intermediate.Id)); } var section = this.Intermediate.Sections.Single(); + var packageSymbol = (section.Type == SectionType.Product) ? this.GetSingleSymbol(section) : null; + var moduleSymbol = (section.Type == SectionType.Module) ? this.GetSingleSymbol(section) : null; + var patchSymbol = (section.Type == SectionType.Patch) ? this.GetSingleSymbol(section) : null; + var fileTransfers = new List(); var trackedFiles = new List(); var containsMergeModules = false; - // If there are any fields to resolve later, create the cache to populate during bind. - var variableCache = this.DelayedFields.Any() ? new Dictionary(StringComparer.InvariantCultureIgnoreCase) : null; - // Load standard tables, authored custom tables, and extension custom tables. TableDefinitionCollection tableDefinitions; { @@ -135,7 +142,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind tableDefinitions = command.TableDefinitions; } - // Process the summary information table before the other tables. + // Calculate codepage + var codepage = this.CalculateCodepage(packageSymbol, moduleSymbol, patchSymbol); + + // Process properties and create the delayed variable cache if needed. + Dictionary variableCache = null; + string productLanguage = null; + { + var command = new ProcessPropertiesCommand(section, packageSymbol, this.ResolvedLcid ?? 0, this.DelayedFields.Any(), this.WindowsInstallerBackendHelper); + command.Execute(); + + variableCache = command.DelayedVariablesCache; + productLanguage = command.ProductLanguage; + } + + // Process the summary information table after properties are processed. bool compressed; bool longNames; int installerVersion; @@ -144,7 +165,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind { var branding = this.ServiceProvider.GetService(); - var command = new BindSummaryInfoCommand(section, this.WindowsInstallerBackendHelper, branding); + var command = new BindSummaryInfoCommand(section, this.ResolvedSummaryInformationCodepage, productLanguage, this.WindowsInstallerBackendHelper, branding); command.Execute(); compressed = command.Compressed; @@ -154,49 +175,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind modularizationSuffix = command.ModularizationSuffix; } - // Add binder variables for all properties. - if (SectionType.Product == section.Type || variableCache != null) - { - foreach (var propertyRow in section.Symbols.OfType()) - { - // Set the ProductCode if it is to be generated. - if ("ProductCode".Equals(propertyRow.Id.Id, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) - { - propertyRow.Value = this.WindowsInstallerBackendHelper.CreateGuid(); - -#if TODO_PATCHING // Is this still necessary? - - // Update the target ProductCode in any instance transforms. - foreach (SubStorage subStorage in this.Output.SubStorages) - { - Output subStorageOutput = subStorage.Data; - if (OutputType.Transform != subStorageOutput.Type) - { - continue; - } - - Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; - foreach (Row row in instanceSummaryInformationTable.Rows) - { - if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) - { - row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); - break; - } - } - } -#endif - } - - // Add the property name and value to the variableCache. - if (variableCache != null) - { - var key = String.Concat("property.", propertyRow.Id.Id); - variableCache[key] = propertyRow.Value; - } - } - } - // Sequence all the actions. { var command = new SequenceActionsCommand(this.Messaging, section); @@ -415,7 +393,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind // Time to create the WindowsInstallerData object. Try to put as much above here as possible, updating the IR is better. WindowsInstallerData data; { - var command = new CreateWindowsInstallerDataFromIRCommand(this.Messaging, section, tableDefinitions, this.BackendExtensions, this.WindowsInstallerBackendHelper); + var command = new CreateWindowsInstallerDataFromIRCommand(this.Messaging, section, tableDefinitions, codepage, this.BackendExtensions, this.WindowsInstallerBackendHelper); data = command.Execute(); } @@ -450,7 +428,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind if (SectionType.Patch == section.Type && this.DeltaBinaryPatch) { - var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Symbols.OfType().FirstOrDefault()); + var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Symbols.OfType().FirstOrDefault()); command.Execute(); } @@ -508,7 +486,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind var trackMsi = this.WindowsInstallerBackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final); trackedFiles.Add(trackMsi); - var command = new GenerateDatabaseCommand(this.Messaging, this.WindowsInstallerBackendHelper, this.FileSystemManager, data, trackMsi.Path, tableDefinitions, this.IntermediateFolder, this.Codepage, keepAddedColumns: false, this.SuppressAddingValidationRows, useSubdirectory: false); + var command = new GenerateDatabaseCommand(this.Messaging, this.WindowsInstallerBackendHelper, this.FileSystemManager, data, trackMsi.Path, tableDefinitions, this.IntermediateFolder, keepAddedColumns: false, this.SuppressAddingValidationRows, useSubdirectory: false); command.Execute(); trackedFiles.AddRange(command.GeneratedTemporaryFiles); @@ -532,7 +510,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind if (this.Messaging.EncounteredError) { return null; - } + } // Validate the output if there are CUBe files and we're not explicitly suppressing validation. if (this.CubeFiles != null && !this.SuppressValidation) @@ -575,6 +553,43 @@ namespace WixToolset.Core.WindowsInstaller.Bind return result; } + private int CalculateCodepage(WixPackageSymbol packageSymbol, WixModuleSymbol moduleSymbol, WixPatchSymbol patchSymbol) + { + var codepage = packageSymbol?.Codepage ?? moduleSymbol?.Codepage ?? patchSymbol?.Codepage; + + if (String.IsNullOrEmpty(codepage)) + { + codepage = this.ResolvedCodepage?.ToString() ?? "65001"; + + if (packageSymbol != null) + { + packageSymbol.Codepage = codepage; + } + else if (moduleSymbol != null) + { + moduleSymbol.Codepage = codepage; + } + else if (patchSymbol != null) + { + patchSymbol.Codepage = codepage; + } + } + + return this.WindowsInstallerBackendHelper.GetValidCodePage(codepage); + } + + private T GetSingleSymbol(IntermediateSection section) where T : IntermediateSymbol + { + var symbols = section.Symbols.OfType().ToList(); + + if (1 != symbols.Count) + { + throw new WixException(ErrorMessages.MissingBundleInformation(nameof(T))); + } + + return symbols[0]; + } + private WixOutput CreateWixout(List trackedFiles, Intermediate intermediate, WindowsInstallerData data) { WixOutput wixout; diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs index babe0c1b..41da2a13 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs @@ -14,15 +14,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind /// internal class BindSummaryInfoCommand { - public BindSummaryInfoCommand(IntermediateSection section, IBackendHelper backendHelper, IWixBranding branding) + public BindSummaryInfoCommand(IntermediateSection section, int? summaryInformationCodepage, string productLanguage, IBackendHelper backendHelper, IWixBranding branding) { this.Section = section; + this.SummaryInformationCodepage = summaryInformationCodepage; + this.ProductLanguage = productLanguage; this.BackendHelper = backendHelper; this.Branding = branding; } private IntermediateSection Section { get; } + private int? SummaryInformationCodepage { get; } + + private string ProductLanguage { get; } + private IBackendHelper BackendHelper { get; } private IWixBranding Branding { get; } @@ -53,6 +59,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind this.InstallerVersion = 0; this.ModularizationSuffix = null; + SummaryInformationSymbol summaryInformationCodepageSymbol = null; + SummaryInformationSymbol platformAndLanguageSymbol = null; var foundCreateDateTime = false; var foundLastSaveDataTime = false; var foundCreatingApplication = false; @@ -64,20 +72,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind switch (summaryInformationSymbol.PropertyId) { case SummaryInformationType.Codepage: // PID_CODEPAGE - // make sure the code page is an int and not a web name or null - var codepage = summaryInformationSymbol.Value; - - if (String.IsNullOrEmpty(codepage)) - { - codepage = "0"; - } - else - { - summaryInformationSymbol.Value = this.BackendHelper.GetValidCodePage(codepage, false, false, summaryInformationSymbol.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); - } + summaryInformationCodepageSymbol = summaryInformationSymbol; break; + case SummaryInformationType.PlatformAndLanguage: - this.Platform = GetPlatformFromSummaryInformation(summaryInformationSymbol.Value); + platformAndLanguageSymbol = summaryInformationSymbol; break; case SummaryInformationType.PackageCode: // PID_REVNUMBER @@ -117,7 +116,31 @@ namespace WixToolset.Core.WindowsInstaller.Bind } } - // set the revision number (package/patch code) if it should be automatically generated + // Ensure the codepage is set properly. + if (summaryInformationCodepageSymbol == null) + { + summaryInformationCodepageSymbol = this.Section.AddSymbol(new SummaryInformationSymbol(null) + { + PropertyId = SummaryInformationType.Codepage + }); + } + + var codepage = summaryInformationCodepageSymbol.Value; + + if (String.IsNullOrEmpty(codepage)) + { + codepage = this.SummaryInformationCodepage?.ToString(CultureInfo.InvariantCulture) ?? "1252"; + } + + summaryInformationCodepageSymbol.Value = this.BackendHelper.GetValidCodePage(codepage, onlyAnsi: true).ToString(CultureInfo.InvariantCulture); + + // Ensure the language is set properly and figure out what platform we are targeting. + if (platformAndLanguageSymbol != null) + { + this.Platform = EnsureLanguageAndGetPlatformFromSummaryInformation(platformAndLanguageSymbol, this.ProductLanguage); + } + + // Set the revision number (package/patch code) if it should be automatically generated. if (!foundPackageCode) { this.Section.AddSymbol(new SummaryInformationSymbol(null) @@ -158,11 +181,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind } } - private static Platform GetPlatformFromSummaryInformation(string value) + private static Platform EnsureLanguageAndGetPlatformFromSummaryInformation(SummaryInformationSymbol symbol, string language) { + var value = symbol.Value; var separatorIndex = value.IndexOf(';'); var platformValue = separatorIndex > 0 ? value.Substring(0, separatorIndex) : value; + // If the language was provided and there was language value after the separator + // (or the separator was absent) then use the provided language. + if (!String.IsNullOrEmpty(language) && (separatorIndex < 0 || separatorIndex + 1 == value.Length)) + { + symbol.Value = platformValue + ';' + language; + } + switch (platformValue) { case "x64": diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs index 3a9bd545..3379ec5d 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs @@ -438,7 +438,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind private void GenerateDatabase(WindowsInstallerData output, string outputPath, bool keepAddedColumns) { - var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, output, outputPath, this.TableDefinitions, this.IntermediateFolder, codepage: -1, keepAddedColumns, suppressAddingValidationRows: true, useSubdirectory: true); + var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, output, outputPath, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns, suppressAddingValidationRows: true, useSubdirectory: true); command.Execute(); } } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs index b587e6d9..47d8399f 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs @@ -15,7 +15,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind /// internal class CreateDeltaPatchesCommand { - public CreateDeltaPatchesCommand(List fileFacades, string intermediateFolder, WixPatchIdSymbol wixPatchId) + public CreateDeltaPatchesCommand(List fileFacades, string intermediateFolder, WixPatchSymbol wixPatchId) { this.FileFacades = fileFacades; this.IntermediateFolder = intermediateFolder; @@ -24,7 +24,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind private IEnumerable FileFacades { get; } - private WixPatchIdSymbol WixPatchId { get; } + private WixPatchSymbol WixPatchId { get; } private string IntermediateFolder { get; } diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs index f09a2e47..ff03413c 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs @@ -36,23 +36,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind public void Execute() { // write out the table to an IDT file - Encoding encoding; - - // If UTF8 encoding, use the UTF8-specific constructor to avoid writing - // the byte order mark at the beginning of the file - if (this.Codepage == Encoding.UTF8.CodePage) - { - encoding = new UTF8Encoding(false, true); - } - else - { - if (this.Codepage == 0) - { - this.Codepage = Encoding.ASCII.CodePage; - } - - encoding = Encoding.GetEncoding(this.Codepage, new EncoderExceptionFallback(), new DecoderExceptionFallback()); - } + var encoding = GetCodepageEncoding(this.Codepage); this.IdtPath = Path.Combine(this.IntermediateFolder, String.Concat(this.Table.Name, ".idt")); @@ -209,6 +193,30 @@ namespace WixToolset.Core.WindowsInstaller.Bind .Replace('\n', '\x19'); } + private static Encoding GetCodepageEncoding(int codepage) + { + Encoding encoding; + + // If UTF8 encoding, use the UTF8-specific constructor to avoid writing + // the byte order mark at the beginning of the file + if (codepage == Encoding.UTF8.CodePage) + { + encoding = new UTF8Encoding(false, true); + } + else + { + if (codepage == 0) + { + codepage = Encoding.ASCII.CodePage; + } + + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + + encoding = Encoding.GetEncoding(codepage, new EncoderExceptionFallback(), new DecoderExceptionFallback()); + } + + return encoding; + } /// /// Gets the type of the column in IDT format. diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs index bc95fd4c..1bd00900 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs @@ -18,11 +18,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind internal class CreateWindowsInstallerDataFromIRCommand { - public CreateWindowsInstallerDataFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable backendExtensions, IWindowsInstallerBackendHelper backendHelper) + public CreateWindowsInstallerDataFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, int codepage, IEnumerable backendExtensions, IWindowsInstallerBackendHelper backendHelper) { this.Messaging = messaging; this.Section = section; this.TableDefinitions = tableDefinitions; + this.Codepage = codepage; this.BackendExtensions = backendExtensions; this.BackendHelper = backendHelper; this.GeneratedShortNames = new Dictionary>(); @@ -36,6 +37,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind private TableDefinitionCollection TableDefinitions { get; } + private int Codepage { get; } + private IntermediateSection Section { get; } private Dictionary> GeneratedShortNames { get; } @@ -46,7 +49,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind { this.Data = new WindowsInstallerData(this.Section.Symbols.First().SourceLineNumbers) { - Codepage = this.Section.Codepage, + Codepage = this.Codepage, Type = SectionTypeToOutputType(this.Section.Type) }; @@ -219,6 +222,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind this.AddWixEnsureTableSymbol((WixEnsureTableSymbol)symbol); break; + case SymbolDefinitionType.WixPackage: + this.AddWixPackageSymbol((WixPackageSymbol)symbol); + break; + // Symbols used internally and are not added to the output. case SymbolDefinitionType.WixBuildInfo: case SymbolDefinitionType.WixBindUpdatedFiles: @@ -237,7 +244,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind case SymbolDefinitionType.WixOrdering: case SymbolDefinitionType.WixPatchBaseline: case SymbolDefinitionType.WixPatchFamilyGroup: - case SymbolDefinitionType.WixPatchId: + case SymbolDefinitionType.WixPatch: case SymbolDefinitionType.WixPatchRef: case SymbolDefinitionType.WixPatchTarget: case SymbolDefinitionType.WixProperty: @@ -1214,6 +1221,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind this.Data.EnsureTable(tableDefinition); } + private void AddWixPackageSymbol(WixPackageSymbol symbol) + { + // TODO: Remove the following from the compiler and do it here instead. + //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "Manufacturer"), manufacturer, false, false, false, true); + //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductCode"), productCode, false, false, false, true); + //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductLanguage"), productLanguage, false, false, false, true); + //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductName"), this.activeName, false, false, false, true); + //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductVersion"), version, false, false, false, true); + //if (null != upgradeCode) + //{ + // this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "UpgradeCode"), upgradeCode, false, false, false, true); + //} + + //if (isPerMachine) + //{ + // this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ALLUSERS"), "1", false, false, false, false); + //} + } + private bool AddSymbolFromExtension(IntermediateSymbol symbol) { foreach (var extension in this.BackendExtensions) diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs index f125f497..b8cca752 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs @@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind { private const string IdtsSubFolder = "_idts"; - public GenerateDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, FileSystemManager fileSystemManager, WindowsInstallerData data, string outputPath, TableDefinitionCollection tableDefinitions, string intermediateFolder, int codepage, bool keepAddedColumns, bool suppressAddingValidationRows, bool useSubdirectory) + public GenerateDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, FileSystemManager fileSystemManager, WindowsInstallerData data, string outputPath, TableDefinitionCollection tableDefinitions, string intermediateFolder, bool keepAddedColumns, bool suppressAddingValidationRows, bool useSubdirectory) { this.Messaging = messaging; this.BackendHelper = backendHelper; @@ -27,14 +27,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind this.OutputPath = outputPath; this.TableDefinitions = tableDefinitions; this.IntermediateFolder = intermediateFolder; - this.Codepage = codepage; this.KeepAddedColumns = keepAddedColumns; this.SuppressAddingValidationRows = suppressAddingValidationRows; this.UseSubDirectory = useSubdirectory; } - private int Codepage { get; } - private IBackendHelper BackendHelper { get; } private FileSystemManager FileSystemManager { get; } @@ -88,12 +85,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind type |= OpenDatabase.OpenPatchFile; } - // Localize the codepage if a value was specified directly. - if (-1 != this.Codepage) - { - this.Data.Codepage = this.Codepage; - } - try { Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath)); diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs index ef141795..faa03762 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs @@ -9,7 +9,6 @@ namespace WixToolset.Core.WindowsInstaller using WixToolset.Data; using WixToolset.Data.Symbols; using WixToolset.Data.WindowsInstaller; - using WixToolset.Data.WindowsInstaller.Rows; using WixToolset.Extensibility.Services; /// diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessPropertiesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessPropertiesCommand.cs new file mode 100644 index 00000000..217609be --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessPropertiesCommand.cs @@ -0,0 +1,101 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core.WindowsInstaller.Bind +{ + using System; + using System.Collections.Generic; + using System.Linq; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using WixToolset.Extensibility.Services; + + internal class ProcessPropertiesCommand + { + public ProcessPropertiesCommand(IntermediateSection section, WixPackageSymbol packageSymbol, int fallbackLcid, bool populateDelayedVariables, IBackendHelper backendHelper) + { + this.Section = section; + this.PackageSymbol = packageSymbol; + this.FallbackLcid = fallbackLcid; + this.PopulateDelayedVariables = populateDelayedVariables; + this.BackendHelper = backendHelper; + } + + private IntermediateSection Section { get; } + + private WixPackageSymbol PackageSymbol { get; } + + private int FallbackLcid { get; } + + private bool PopulateDelayedVariables { get; } + + private IBackendHelper BackendHelper { get; } + + public Dictionary DelayedVariablesCache { get; private set; } + + public string ProductLanguage { get; private set; } + + public void Execute() + { + PropertySymbol languageSymbol = null; + var variableCache = this.PopulateDelayedVariables ? new Dictionary(StringComparer.OrdinalIgnoreCase) : null; + + if (SectionType.Product == this.Section.Type || variableCache != null) + { + foreach (var propertySymbol in this.Section.Symbols.OfType()) + { + // Set the ProductCode if it is to be generated. + if ("ProductCode" == propertySymbol.Id.Id && "*".Equals(propertySymbol.Value, StringComparison.Ordinal)) + { + propertySymbol.Value = this.BackendHelper.CreateGuid(); + +#if TODO_PATCHING // Is this still necessary? + // Update the target ProductCode in any instance transforms. + foreach (SubStorage subStorage in this.Output.SubStorages) + { + Output subStorageOutput = subStorage.Data; + if (OutputType.Transform != subStorageOutput.Type) + { + continue; + } + + Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; + foreach (Row row in instanceSummaryInformationTable.Rows) + { + if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) + { + row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); + break; + } + } + } +#endif + } + else if ("ProductLanguage" == propertySymbol.Id.Id) + { + languageSymbol = propertySymbol; + } + + // Add the property name and value to the variableCache. + if (variableCache != null) + { + variableCache[$"property.{propertySymbol.Id.Id}"] = propertySymbol.Value; + } + } + + if (this.Section.Type == SectionType.Product && String.IsNullOrEmpty(languageSymbol?.Value)) + { + if (languageSymbol == null) + { + languageSymbol = this.Section.AddSymbol(new PropertySymbol(this.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, "ProductLanguage"))); + } + + this.PackageSymbol.Language = this.FallbackLcid.ToString(); + languageSymbol.Value = this.FallbackLcid.ToString(); + } + } + + this.DelayedVariablesCache = variableCache; + this.ProductLanguage = languageSymbol?.Value; + } + } +} diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs index 9f649435..f40aed4e 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs @@ -302,7 +302,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind private void GenerateDatabase(WindowsInstallerData output, string databaseFile) { - var command = new GenerateDatabaseCommand(this.Messaging, null, null, output, databaseFile, this.TableDefinitions, this.IntermediateFolder, codepage: -1, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false); + var command = new GenerateDatabaseCommand(this.Messaging, null, null, output, databaseFile, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false); command.Execute(); } } diff --git a/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj b/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj index 56262373..b08f337f 100644 --- a/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj +++ b/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj @@ -20,6 +20,7 @@ + diff --git a/src/WixToolset.Core/BindContext.cs b/src/WixToolset.Core/BindContext.cs index 6b0a09a2..09454824 100644 --- a/src/WixToolset.Core/BindContext.cs +++ b/src/WixToolset.Core/BindContext.cs @@ -26,8 +26,6 @@ namespace WixToolset.Core public string CabCachePath { get; set; } - public int Codepage { get; set; } - public CompressionLevel? DefaultCompressionLevel { get; set; } public IEnumerable DelayedFields { get; set; } @@ -50,6 +48,12 @@ namespace WixToolset.Core public string PdbPath { get; set; } + public int? ResolvedCodepage { get; set; } + + public int? ResolvedSummaryInformationCodepage { get; set; } + + public int? ResolvedLcid { get; set; } + public IEnumerable SuppressIces { get; set; } public bool SuppressValidation { get; set; } diff --git a/src/WixToolset.Core/CommandLine/BuildCommand.cs b/src/WixToolset.Core/CommandLine/BuildCommand.cs index 9efef830..59aa2f1f 100644 --- a/src/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/WixToolset.Core/CommandLine/BuildCommand.cs @@ -338,7 +338,9 @@ namespace WixToolset.Core.CommandLine var context = this.ServiceProvider.GetService(); //context.CabbingThreadCount = this.CabbingThreadCount; context.CabCachePath = cabCachePath; - context.Codepage = resolveResult.Codepage; + context.ResolvedCodepage = resolveResult.Codepage; + context.ResolvedSummaryInformationCodepage = resolveResult.SummaryInformationCodepage; + context.ResolvedLcid = resolveResult.PackageLcid; context.DefaultCompressionLevel = this.DefaultCompressionLevel; context.DelayedFields = resolveResult.DelayedFields; context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles; diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index c2783481..926a46c5 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs @@ -384,7 +384,7 @@ namespace WixToolset.Core { var id = String.Concat(this.Core.ActiveSection.Id, ".", propertyId.Id); - section = this.Core.CreateSection(id, SectionType.Fragment, this.Core.ActiveSection.Codepage, this.Context.CompilationId); + section = this.Core.CreateSection(id, SectionType.Fragment, this.Context.CompilationId); // Reference the property in the active section. this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Property, propertyId.Id); @@ -6159,7 +6159,7 @@ namespace WixToolset.Core // NOTE: Id is not required for Fragments, this is a departure from the normal run of the mill processing. - this.Core.CreateActiveSection(id?.Id, SectionType.Fragment, 0, this.Context.CompilationId); + this.Core.CreateActiveSection(id?.Id, SectionType.Fragment, this.Context.CompilationId); var featureDisplay = 0; foreach (var child in node.Elements()) diff --git a/src/WixToolset.Core/CompilerCore.cs b/src/WixToolset.Core/CompilerCore.cs index 0bc63d79..df532d74 100644 --- a/src/WixToolset.Core/CompilerCore.cs +++ b/src/WixToolset.Core/CompilerCore.cs @@ -680,7 +680,7 @@ namespace WixToolset.Core Debug.Assert(minimum > CompilerConstants.IntegerNotSet && minimum > CompilerConstants.IllegalInteger, "The legal values for this attribute collide with at least one sentinel used during parsing."); - string value = this.GetAttributeValue(sourceLineNumbers, attribute); + var value = this.GetAttributeValue(sourceLineNumbers, attribute); if (0 < value.Length) { @@ -692,7 +692,7 @@ namespace WixToolset.Core { try { - int integer = Convert.ToInt32(value, CultureInfo.InvariantCulture.NumberFormat); + var integer = Convert.ToInt32(value, CultureInfo.InvariantCulture.NumberFormat); if (CompilerConstants.IntegerNotSet == integer || CompilerConstants.IllegalInteger == integer) { @@ -1036,12 +1036,11 @@ namespace WixToolset.Core /// /// Unique identifier for the section. /// Type of section to create. - /// Codepage for the resulting database for this ection. - /// + /// Unique identifier for the compilation. /// New section. - internal IntermediateSection CreateActiveSection(string id, SectionType type, int codepage, string compilationId) + internal IntermediateSection CreateActiveSection(string id, SectionType type, string compilationId) { - this.ActiveSection = this.CreateSection(id, type, codepage, compilationId); + this.ActiveSection = this.CreateSection(id, type, compilationId); this.activeSectionCachedInlinedDirectoryIds = new Dictionary(); this.activeSectionSimpleReferences = new HashSet(); @@ -1054,12 +1053,11 @@ namespace WixToolset.Core /// /// Unique identifier for the section. /// Type of section to create. - /// Codepage for the resulting database for this ection. - /// + /// Unique identifier for the compilation. /// New section. - internal IntermediateSection CreateSection(string id, SectionType type, int codepage, string compilationId) + internal IntermediateSection CreateSection(string id, SectionType type, string compilationId) { - var section = new IntermediateSection(id, type, codepage, compilationId); + var section = new IntermediateSection(id, type, compilationId); this.intermediate.Sections.Add(section); diff --git a/src/WixToolset.Core/Compiler_Bundle.cs b/src/WixToolset.Core/Compiler_Bundle.cs index 7e07532e..779ad376 100644 --- a/src/WixToolset.Core/Compiler_Bundle.cs +++ b/src/WixToolset.Core/Compiler_Bundle.cs @@ -259,7 +259,7 @@ namespace WixToolset.Core } this.activeName = String.IsNullOrEmpty(name) ? Common.GenerateGuid() : name; - this.Core.CreateActiveSection(this.activeName, SectionType.Bundle, 0, this.Context.CompilationId); + this.Core.CreateActiveSection(this.activeName, SectionType.Bundle, this.Context.CompilationId); // Now that the active section is initialized, process only extension attributes and the special ProviderKey attribute. foreach (var attrib in node.Attributes()) diff --git a/src/WixToolset.Core/Compiler_Module.cs b/src/WixToolset.Core/Compiler_Module.cs index 597bc25c..59fe9164 100644 --- a/src/WixToolset.Core/Compiler_Module.cs +++ b/src/WixToolset.Core/Compiler_Module.cs @@ -104,7 +104,7 @@ namespace WixToolset.Core try { this.compilingModule = true; // notice that we are actually building a Merge Module here - this.Core.CreateActiveSection(this.activeName, SectionType.Module, codepage, this.Context.CompilationId); + this.Core.CreateActiveSection(this.activeName, SectionType.Module, this.Context.CompilationId); foreach (var child in node.Elements()) { @@ -232,15 +232,6 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - if (!setCodepage) - { - this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers) - { - PropertyId = SummaryInformationType.Codepage, - Value = "1252" - }); - } - if (!setPackageName) { this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers) @@ -259,21 +250,20 @@ namespace WixToolset.Core }); } - var symbol = this.Core.AddSymbol(new ModuleSignatureSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, this.activeName, this.activeLanguage)) + var symbol = this.Core.AddSymbol(new WixModuleSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, this.activeName, this.activeLanguage)) { - ModuleID = this.activeName, + ModuleId = this.activeName, + Language = this.activeLanguage, Version = version }); - symbol.Set((int)ModuleSignatureSymbolFields.Language, this.activeLanguage); - this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers) { PropertyId = SummaryInformationType.PackageCode, Value = moduleId }); - this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform); + this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform, this.activeLanguage); } } finally diff --git a/src/WixToolset.Core/Compiler_Package.cs b/src/WixToolset.Core/Compiler_Package.cs index fed08001..afe02f08 100644 --- a/src/WixToolset.Core/Compiler_Package.cs +++ b/src/WixToolset.Core/Compiler_Package.cs @@ -5,7 +5,6 @@ namespace WixToolset.Core using System; using System.Collections; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Xml.Linq; @@ -28,10 +27,10 @@ namespace WixToolset.Core var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); var compressed = YesNoDefaultType.Default; var sourceBits = 0; - var codepage = 65001; + string codepage = null; var productCode = "*"; + string productLanguage = null; var isPerMachine = true; - string installScope = null; string upgradeCode = null; string manufacturer = null; string version = null; @@ -53,7 +52,7 @@ namespace WixToolset.Core switch (attrib.Name.LocalName) { case "Codepage": - codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); + codepage = this.Core.GetAttributeLocalizableCodePageValue(sourceLineNumbers, attrib); break; case "Compressed": compressed = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); @@ -62,7 +61,7 @@ namespace WixToolset.Core msiVersion = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue); break; case "Language": - this.activeLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); + productLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); break; case "Manufacturer": manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters); @@ -82,7 +81,7 @@ namespace WixToolset.Core productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); break; case "Scope": - installScope = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + var installScope = this.Core.GetAttributeValue(sourceLineNumbers, attrib); switch (installScope) { case "perMachine": @@ -129,11 +128,6 @@ namespace WixToolset.Core this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); } - if (null == this.activeLanguage) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Language")); - } - if (null == manufacturer) { this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer")); @@ -171,11 +165,11 @@ namespace WixToolset.Core try { this.compilingProduct = true; - this.Core.CreateActiveSection(productCode, SectionType.Product, codepage, this.Context.CompilationId); + this.Core.CreateActiveSection(productCode, SectionType.Product, this.Context.CompilationId); this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "Manufacturer"), manufacturer, false, false, false, true); this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductCode"), productCode, false, false, false, true); - this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductLanguage"), this.activeLanguage, false, false, false, true); + this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductLanguage"), productLanguage, false, false, false, true); this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductName"), this.activeName, false, false, false, true); this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductVersion"), version, false, false, false, true); if (null != upgradeCode) @@ -188,7 +182,7 @@ namespace WixToolset.Core this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ALLUSERS"), "1", false, false, false, false); } - this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform); + this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform, productLanguage); this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers) { @@ -198,7 +192,7 @@ namespace WixToolset.Core var contextValues = new Dictionary { - ["ProductLanguage"] = this.activeLanguage, + ["ProductLanguage"] = productLanguage, ["ProductVersion"] = version, ["UpgradeCode"] = upgradeCode }; @@ -360,14 +354,17 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - if (!isCodepageSet) + this.Core.AddSymbol(new WixPackageSymbol(sourceLineNumbers) { - this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers) - { - PropertyId = SummaryInformationType.Codepage, - Value = "1252" - }); - } + PackageId = productCode, + UpgradeCode = upgradeCode, + Name = this.activeName, + Language = productLanguage, + Version = version, + Manufacturer = manufacturer, + Attributes = isPerMachine ? WixPackageAttributes.PerMachine : WixPackageAttributes.None, + Codepage = codepage, + }); if (!isPackageNameSet) { @@ -435,7 +432,7 @@ namespace WixToolset.Core } } - private void ValidateAndAddCommonSummaryInformationSymbols(SourceLineNumber sourceLineNumbers, int msiVersion, string platform) + private void ValidateAndAddCommonSummaryInformationSymbols(SourceLineNumber sourceLineNumbers, int msiVersion, string platform, string language) { if (String.Equals(platform, "X64", StringComparison.OrdinalIgnoreCase) && 200 > msiVersion) { @@ -464,7 +461,7 @@ namespace WixToolset.Core this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers) { PropertyId = SummaryInformationType.PlatformAndLanguage, - Value = String.Format(CultureInfo.InvariantCulture, "{0};{1}", platform, this.activeLanguage) + Value = $"{platform};{language}" }); this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers) @@ -478,7 +475,6 @@ namespace WixToolset.Core PropertyId = SummaryInformationType.Security, Value = "2" }); - } /// diff --git a/src/WixToolset.Core/Compiler_Patch.cs b/src/WixToolset.Core/Compiler_Patch.cs index a2cadd67..c9cae183 100644 --- a/src/WixToolset.Core/Compiler_Patch.cs +++ b/src/WixToolset.Core/Compiler_Patch.cs @@ -24,7 +24,7 @@ namespace WixToolset.Core { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string patchId = null; - var codepage = 0; + string codepage = null; ////bool versionMismatches = false; ////bool productMismatches = false; var allowRemoval = false; @@ -53,7 +53,7 @@ namespace WixToolset.Core patchId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); break; case "Codepage": - codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); + codepage = this.Core.GetAttributeLocalizableCodePageValue(sourceLineNumbers, attrib); break; case "AllowMajorVersionMismatches": ////versionMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); @@ -149,7 +149,7 @@ namespace WixToolset.Core this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer")); } - this.Core.CreateActiveSection(this.activeName, SectionType.Patch, codepage, this.Context.CompilationId); + this.Core.CreateActiveSection(this.activeName, SectionType.Patch, this.Context.CompilationId); foreach (var child in node.Elements()) { @@ -197,8 +197,9 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - this.Core.AddSymbol(new WixPatchIdSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, patchId)) + this.Core.AddSymbol(new WixPatchSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, patchId)) { + Codepage = codepage, ClientPatchId = clientPatchId, OptimizePatchSizeForLargeFiles = optimizePatchSizeForLargeFiles, ApiPatchingSymbolFlags = apiPatchingSymbolFlags, diff --git a/src/WixToolset.Core/Compiler_PatchCreation.cs b/src/WixToolset.Core/Compiler_PatchCreation.cs index 7675a5c0..81ae4121 100644 --- a/src/WixToolset.Core/Compiler_PatchCreation.cs +++ b/src/WixToolset.Core/Compiler_PatchCreation.cs @@ -82,7 +82,7 @@ namespace WixToolset.Core this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); } - this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, codepage, this.Context.CompilationId); + this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, this.Context.CompilationId); foreach (var child in node.Elements()) { diff --git a/src/WixToolset.Core/IResolver.cs b/src/WixToolset.Core/IResolver.cs index 3004ad2c..db25edbe 100644 --- a/src/WixToolset.Core/IResolver.cs +++ b/src/WixToolset.Core/IResolver.cs @@ -4,9 +4,16 @@ namespace WixToolset.Core { using WixToolset.Extensibility.Data; -#pragma warning disable 1591 // TODO: add documentation + /// + /// Resolves localization and bind variables. + /// public interface IResolver { + /// + /// Resolve localization and bind variables. + /// + /// Resolve context. + /// Resolve result. IResolveResult Resolve(IResolveContext context); } } diff --git a/src/WixToolset.Core/Link/CollateLocalizationsCommand.cs b/src/WixToolset.Core/Link/CollateLocalizationsCommand.cs index ffa66210..d5c69838 100644 --- a/src/WixToolset.Core/Link/CollateLocalizationsCommand.cs +++ b/src/WixToolset.Core/Link/CollateLocalizationsCommand.cs @@ -1,4 +1,4 @@ -// 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. +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixToolset.Core.Link { @@ -65,7 +65,7 @@ namespace WixToolset.Core.Link } } - return new Localization(existingLocalization.Codepage, existingLocalization.Culture, variables, controls); + return new Localization(existingLocalization.Codepage ?? localization.Codepage, existingLocalization.SummaryInformationCodepage ?? localization.SummaryInformationCodepage, existingLocalization.Culture, variables, controls); } } } diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index 320f7d1f..2c8508a8 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs @@ -180,7 +180,7 @@ namespace WixToolset.Core // Create a new section to hold the linked content. Start with the entry section's // metadata. - var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type, find.EntrySection.Codepage); + var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type); var sectionCount = 0; diff --git a/src/WixToolset.Core/LocalizationParser.cs b/src/WixToolset.Core/LocalizationParser.cs index dd5144ca..d6113fc6 100644 --- a/src/WixToolset.Core/LocalizationParser.cs +++ b/src/WixToolset.Core/LocalizationParser.cs @@ -86,7 +86,8 @@ namespace WixToolset.Core private static Localization ParseWixLocalizationElement(IMessaging messaging, XElement node) { var sourceLineNumbers = SourceLineNumber.CreateFromXObject(node); - var codepage = -1; + int? codepage = null; + int? summaryInformationCodepage = null; string culture = null; foreach (var attrib in node.Attributes()) @@ -98,6 +99,9 @@ namespace WixToolset.Core case "Codepage": codepage = Common.GetValidCodePage(attrib.Value, true, false, sourceLineNumbers); break; + case "SummaryInformationCodepage": + summaryInformationCodepage = Common.GetValidCodePage(attrib.Value, true, false, sourceLineNumbers); + break; case "Culture": culture = attrib.Value; break; @@ -143,7 +147,7 @@ namespace WixToolset.Core } } - return messaging.EncounteredError ? null : new Localization(codepage, culture, variables, localizedControls); + return messaging.EncounteredError ? null : new Localization(codepage, summaryInformationCodepage, culture, variables, localizedControls); } /// @@ -254,24 +258,12 @@ namespace WixToolset.Core break; case "RightToLeft": rightToLeft = YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib); - //if (YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib)) - //{ - // attribs |= MsiInterop.MsidbControlAttributesRTLRO; - //} break; case "RightAligned": rightAligned = YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib); - //if (YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib)) - //{ - // attribs |= MsiInterop.MsidbControlAttributesRightAligned; - //} break; case "LeftScroll": leftScroll = YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib); - //if (YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib)) - //{ - // attribs |= MsiInterop.MsidbControlAttributesLeftScroll; - //} break; default: Common.UnexpectedAttribute(messaging, sourceLineNumbers, attrib); diff --git a/src/WixToolset.Core/ResolveResult.cs b/src/WixToolset.Core/ResolveResult.cs index 6b6bc7c4..38b432b0 100644 --- a/src/WixToolset.Core/ResolveResult.cs +++ b/src/WixToolset.Core/ResolveResult.cs @@ -8,7 +8,11 @@ namespace WixToolset.Core internal class ResolveResult : IResolveResult { - public int Codepage { get; set; } + public int? Codepage { get; set; } + + public int? SummaryInformationCodepage { get; set; } + + public int? PackageLcid { get; set; } public IEnumerable DelayedFields { get; set; } diff --git a/src/WixToolset.Core/Resolver.cs b/src/WixToolset.Core/Resolver.cs index 92c2a9c9..f4cb2fd6 100644 --- a/src/WixToolset.Core/Resolver.cs +++ b/src/WixToolset.Core/Resolver.cs @@ -4,6 +4,7 @@ namespace WixToolset.Core { using System; using System.Collections.Generic; + using System.Globalization; using System.Linq; using WixToolset.Core.Bind; using WixToolset.Data; @@ -22,26 +23,12 @@ namespace WixToolset.Core this.ServiceProvider = serviceProvider; this.Messaging = serviceProvider.GetService(); - - this.VariableResolver = serviceProvider.GetService(); } private IServiceProvider ServiceProvider { get; } private IMessaging Messaging { get; } - private IVariableResolver VariableResolver { get; set; } - - public IEnumerable BindPaths { get; set; } - - public string IntermediateFolder { get; set; } - - public Intermediate IntermediateRepresentation { get; set; } - - public IEnumerable Localizations { get; set; } - - public IEnumerable FilterCultures { get; set; } - public IResolveResult Resolve(IResolveContext context) { foreach (var extension in context.Extensions) @@ -52,11 +39,26 @@ namespace WixToolset.Core ResolveResult resolveResult = null; try { - var codepage = this.PopulateVariableResolver(context); + var filteredLocalizations = FilterLocalizations(context); + + var variableResolver = this.CreateVariableResolver(context, filteredLocalizations); + + this.LocalizeUI(variableResolver, context.IntermediateRepresentation); + + resolveResult = this.DoResolve(context, variableResolver); + + var primaryLocalization = filteredLocalizations.FirstOrDefault(); + + if (primaryLocalization != null) + { + this.TryGetCultureInfo(primaryLocalization.Culture, out var cultureInfo); - this.LocalizeUI(context); + resolveResult.Codepage = primaryLocalization.Codepage ?? cultureInfo?.TextInfo.ANSICodePage; - resolveResult = this.DoResolve(context, codepage); + resolveResult.SummaryInformationCodepage = primaryLocalization.SummaryInformationCodepage ?? primaryLocalization.Codepage ?? cultureInfo?.TextInfo.ANSICodePage; + + resolveResult.PackageLcid = cultureInfo?.LCID; + } } finally { @@ -69,7 +71,7 @@ namespace WixToolset.Core return resolveResult; } - private ResolveResult DoResolve(IResolveContext context, int? codepage) + private ResolveResult DoResolve(IResolveContext context, IVariableResolver variableResolver) { var buildingPatch = context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch); @@ -80,7 +82,7 @@ namespace WixToolset.Core var command = new ResolveFieldsCommand(); command.Messaging = this.Messaging; command.BuildingPatch = buildingPatch; - command.VariableResolver = this.VariableResolver; + command.VariableResolver = variableResolver; command.BindPaths = context.BindPaths; command.Extensions = context.Extensions; command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles; @@ -118,7 +120,6 @@ namespace WixToolset.Core return new ResolveResult { - Codepage = codepage.HasValue ? codepage.Value : -1, ExpectedEmbeddedFiles = expectedEmbeddedFiles, DelayedFields = delayedFields, IntermediateRepresentation = context.IntermediateRepresentation @@ -128,13 +129,13 @@ namespace WixToolset.Core /// /// Localize dialogs and controls. /// - private void LocalizeUI(IResolveContext context) + private void LocalizeUI(IVariableResolver variableResolver, Intermediate intermediate) { - foreach (var section in context.IntermediateRepresentation.Sections) + foreach (var section in intermediate.Sections) { foreach (var symbol in section.Symbols.OfType()) { - if (this.VariableResolver.TryGetLocalizedControl(symbol.Id.Id, null, out var localizedControl)) + if (variableResolver.TryGetLocalizedControl(symbol.Id.Id, null, out var localizedControl)) { if (CompilerConstants.IntegerNotSet != localizedControl.X) { @@ -169,7 +170,7 @@ namespace WixToolset.Core foreach (var symbol in section.Symbols.OfType()) { - if (this.VariableResolver.TryGetLocalizedControl(symbol.DialogRef, symbol.Control, out var localizedControl)) + if (variableResolver.TryGetLocalizedControl(symbol.DialogRef, symbol.Control, out var localizedControl)) { if (CompilerConstants.IntegerNotSet != localizedControl.X) { @@ -204,24 +205,42 @@ namespace WixToolset.Core } } - private int? PopulateVariableResolver(IResolveContext context) + private IVariableResolver CreateVariableResolver(IResolveContext context, IEnumerable filteredLocalizations) { - var localizations = FilterLocalizations(context); - var codepage = localizations.FirstOrDefault()?.Codepage; + var variableResolver = this.ServiceProvider.GetService(); - foreach (var localization in localizations) + foreach (var localization in filteredLocalizations) { - this.VariableResolver.AddLocalization(localization); + variableResolver.AddLocalization(localization); } // Gather all the wix variables. var wixVariableSymbols = context.IntermediateRepresentation.Sections.SelectMany(s => s.Symbols).OfType(); foreach (var symbol in wixVariableSymbols) { - this.VariableResolver.AddVariable(symbol.SourceLineNumbers, symbol.Id.Id, symbol.Value, symbol.Overridable); + variableResolver.AddVariable(symbol.SourceLineNumbers, symbol.Id.Id, symbol.Value, symbol.Overridable); + } + + return variableResolver; + } + + private bool TryGetCultureInfo(string culture, out CultureInfo cultureInfo) + { + cultureInfo = null; + + if (!String.IsNullOrEmpty(culture)) + { + try + { + cultureInfo = new CultureInfo(culture, useUserOverride: false); + } + catch + { + this.Messaging.Write(""); + } } - return codepage; + return cultureInfo != null; } private static IEnumerable FilterLocalizations(IResolveContext context) diff --git a/src/test/WixToolsetTest.CoreIntegration/LanguageFixture.cs b/src/test/WixToolsetTest.CoreIntegration/LanguageFixture.cs new file mode 100644 index 00000000..319b0788 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/LanguageFixture.cs @@ -0,0 +1,155 @@ +// 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.CoreIntegration +{ + using System.IO; + using System.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Core.TestPackage; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using Xunit; + + public class LanguageFixture + { + [Fact] + public void CanBuildWithDefaultProductLanguage() + { + var folder = TestData.Get(@"TestData", "Language"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "Package.wxs"), + "-loc", Path.Combine(folder, "Package.wxl"), + "-bindpath", Path.Combine(folder, "data"), + "-intermediateFolder", Path.Combine(baseFolder, "obj"), + "-o", Path.Combine(baseFolder, @"bin\test.msi") + }); + + result.AssertSuccess(); + + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); + var section = intermediate.Sections.Single(); + + var propertySymbol = section.Symbols.OfType().Single(p => p.Id.Id == "ProductLanguage"); + Assert.Equal("0", propertySymbol.Value); + + var summaryPlatform = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage); + Assert.Equal("Intel;0", summaryPlatform.Value); + + var summaryCodepage = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.Codepage); + Assert.Equal("1252", summaryCodepage.Value); + } + } + + [Fact] + public void CanBuildEnuWxl() + { + var folder = TestData.Get(@"TestData", "Language"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "Package.wxs"), + "-loc", Path.Combine(folder, "Package.en-us.wxl"), + "-bindpath", Path.Combine(folder, "data"), + "-intermediateFolder", Path.Combine(baseFolder, "obj"), + "-o", Path.Combine(baseFolder, @"bin\test.msi") + }); + + result.AssertSuccess(); + + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); + var section = intermediate.Sections.Single(); + + var propertySymbol = section.Symbols.OfType().Single(p => p.Id.Id == "ProductLanguage"); + Assert.Equal("1033", propertySymbol.Value); + + var summaryPlatform = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage); + Assert.Equal("Intel;1033", summaryPlatform.Value); + + var summaryCodepage = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.Codepage); + Assert.Equal("1252", summaryCodepage.Value); + } + } + + [Fact] + public void CanBuildJpnWxl() + { + var folder = TestData.Get(@"TestData", "Language"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "Package.wxs"), + "-loc", Path.Combine(folder, "Package.ja-jp.wxl"), + "-bindpath", Path.Combine(folder, "data"), + "-intermediateFolder", Path.Combine(baseFolder, "obj"), + "-o", Path.Combine(baseFolder, @"bin\test.msi") + }); + + result.AssertSuccess(); + + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); + var section = intermediate.Sections.Single(); + + var propertySymbol = section.Symbols.OfType().Single(p => p.Id.Id == "ProductLanguage"); + Assert.Equal("1041", propertySymbol.Value); + + var summaryPlatform = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage); + Assert.Equal("Intel;1041", summaryPlatform.Value); + + var summaryCodepage = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.Codepage); + Assert.Equal("932", summaryCodepage.Value); + } + } + + [Fact] + public void CanBuildJpnWxlWithEnuSummaryInfo() + { + var folder = TestData.Get(@"TestData", "Language"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "Package.wxs"), + "-loc", Path.Combine(folder, "PackageWithEnSummaryInfo.ja-jp.wxl"), + "-bindpath", Path.Combine(folder, "data"), + "-intermediateFolder", Path.Combine(baseFolder, "obj"), + "-o", Path.Combine(baseFolder, @"bin\test.msi") + }); + + result.AssertSuccess(); + + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb")); + var section = intermediate.Sections.Single(); + + var propertySymbol = section.Symbols.OfType().Single(p => p.Id.Id == "ProductLanguage"); + Assert.Equal("1041", propertySymbol.Value); + + var summaryPlatform = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage); + Assert.Equal("Intel;1041", summaryPlatform.Value); + + var summaryCodepage = section.Symbols.OfType().Single(s => s.PropertyId == SummaryInformationType.Codepage); + Assert.Equal("1252", summaryCodepage.Value); + } + } + } +} diff --git a/src/test/WixToolsetTest.CoreIntegration/LinkerFixture.cs b/src/test/WixToolsetTest.CoreIntegration/LinkerFixture.cs index 41c1d773..f73a57d0 100644 --- a/src/test/WixToolsetTest.CoreIntegration/LinkerFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/LinkerFixture.cs @@ -19,8 +19,8 @@ namespace WixToolsetTest.CoreIntegration [Fact] public void MustCompileBeforeLinking() { - var intermediate1 = new Intermediate("TestIntermediate1", new[] { new IntermediateSection("test1", SectionType.Product, 65001) }, null); - var intermediate2 = new Intermediate("TestIntermediate2", new[] { new IntermediateSection("test2", SectionType.Fragment, 65001) }, null); + var intermediate1 = new Intermediate("TestIntermediate1", new[] { new IntermediateSection("test1", SectionType.Product) }, null); + var intermediate2 = new Intermediate("TestIntermediate2", new[] { new IntermediateSection("test2", SectionType.Fragment) }, null); var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider(); var listener = new TestMessageListener(); diff --git a/src/test/WixToolsetTest.CoreIntegration/ParseFixture.cs b/src/test/WixToolsetTest.CoreIntegration/ParseFixture.cs index 2d98a66c..cdba85de 100644 --- a/src/test/WixToolsetTest.CoreIntegration/ParseFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/ParseFixture.cs @@ -16,7 +16,7 @@ namespace WixToolsetTest.CoreIntegration public void GeneratesCorrectCustomActionIdentifiers() { var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider(); - var section = new IntermediateSection("section", SectionType.Fragment, 0); + var section = new IntermediateSection("section", SectionType.Fragment); var parseHelper = serviceProvider.GetService(); parseHelper.CreateCustomActionReference(null, section, "CustomAction32", Platform.X86, CustomActionPlatforms.X86); diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.en-us.wxl b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.en-us.wxl new file mode 100644 index 00000000..f7453566 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.en-us.wxl @@ -0,0 +1,7 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.ja-jp.wxl b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.ja-jp.wxl new file mode 100644 index 00000000..ef287da7 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.ja-jp.wxl @@ -0,0 +1,7 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxl b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxl new file mode 100644 index 00000000..10ebf2c5 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxl @@ -0,0 +1,7 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxs new file mode 100644 index 00000000..2bbc14f9 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Language/PackageWithEnSummaryInfo.ja-jp.wxl b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/PackageWithEnSummaryInfo.ja-jp.wxl new file mode 100644 index 00000000..596ee077 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/PackageWithEnSummaryInfo.ja-jp.wxl @@ -0,0 +1,7 @@ + + + + A newer version of [ProductName] is already installed. + MsiPackage + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Language/data/test.txt b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/data/test.txt new file mode 100644 index 00000000..cd0db0e1 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Language/data/test.txt @@ -0,0 +1 @@ +This is test.txt. \ No newline at end of file diff --git a/src/test/WixToolsetTest.CoreIntegration/VariableResolverFixture.cs b/src/test/WixToolsetTest.CoreIntegration/VariableResolverFixture.cs index 28c68e99..15e5d334 100644 --- a/src/test/WixToolsetTest.CoreIntegration/VariableResolverFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/VariableResolverFixture.cs @@ -25,7 +25,7 @@ namespace WixToolsetTest.CoreIntegration { "ProductNameEditionVersion", new BindVariable() { Id = "ProductNameEditionVersion", Value = "!(loc.ProductNameEdition) v1.2.3" } }, }; - var localization = new Localization(0, "x-none", variables, new Dictionary()); + var localization = new Localization(0, null, "x-none", variables, new Dictionary()); variableResolver.AddLocalization(localization); -- cgit v1.2.3-55-g6feb