Enable codepages and languages to be set via .wxl files
Fixes wixtoolset/issues#5801
Rob Mensching committed
Apr 2, 2021 at 14:41 UTC
4449fcc5b8d104817c67135229682c66c3d892ca
38 files changed
+619
-235
src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj
-1
@@ -22,7 +22,6 @@
22
</ItemGroup>
23
24
<ItemGroup>
25
- <PackageReference Include="System.Security.Permissions" Version="4.6.0" />
25
<PackageReference Include="WixToolset.Burn" Version="4.0.*" />
26
<PackageReference Include="WixToolset.Core.Native" Version="4.0.*" />
27
<PackageReference Include="WixToolset.Data" Version="4.0.*" />
src/WixToolset.Core.WindowsInstaller/Bind/AttachPatchTransformsCommand.cs
+13
-13
@@ -91,15 +91,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
91
var symbols = this.Intermediate.Sections.SelectMany(s => s.Symbols).ToList();
92
93
// Get the patch id from the WixPatchId symbol.
94
- var patchIdSymbol = symbols.OfType<WixPatchIdSymbol>().FirstOrDefault();
94
+ var patchSymbol = symbols.OfType<WixPatchSymbol>().FirstOrDefault();
95
96
- if (String.IsNullOrEmpty(patchIdSymbol.Id?.Id))
96
+ if (String.IsNullOrEmpty(patchSymbol.Id?.Id))
97
{
98
this.Messaging.Write(ErrorMessages.ExpectedPatchIdInWixMsp());
99
return subStorages;
100
}
101
102
- if (String.IsNullOrEmpty(patchIdSymbol.ClientPatchId))
102
+ if (String.IsNullOrEmpty(patchSymbol.ClientPatchId))
103
{
104
this.Messaging.Write(ErrorMessages.ExpectedClientPatchIdInWixMsp());
105
return subStorages;
@@ -115,7 +115,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
115
}
116
117
// populate MSP summary information
118
- var patchMetadata = this.PopulateSummaryInformation(summaryInfo, symbols, patchIdSymbol, section.Codepage);
118
+ var patchMetadata = this.PopulateSummaryInformation(summaryInfo, symbols, patchSymbol);
119
120
// enumerate transforms
121
var productCodes = new SortedSet<string>();
@@ -168,7 +168,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
168
mainTransform.Transform.Tables.Remove("Media");
169
mainTransform.Transform.Tables.Remove("MsiDigitalSignature");
170
171
- var pairedTransform = this.BuildPairedTransform(summaryInfo, patchMetadata, patchIdSymbol, mainTransform.Transform, mediaSymbol, baselineSymbol, out var productCode);
171
+ var pairedTransform = this.BuildPairedTransform(summaryInfo, patchMetadata, patchSymbol, mainTransform.Transform, mediaSymbol, baselineSymbol, out var productCode);
172
173
productCode = productCode.ToUpperInvariant();
174
productCodes.Add(productCode);
@@ -211,14 +211,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
211
productCodes = FinalizePatchProductCodes(symbols, productCodes);
212
213
// Semicolon delimited list of the product codes that can accept the patch.
214
- summaryInfo.Add(SummaryInformationType.PatchProductCodes, new SummaryInformationSymbol(patchIdSymbol.SourceLineNumbers)
214
+ summaryInfo.Add(SummaryInformationType.PatchProductCodes, new SummaryInformationSymbol(patchSymbol.SourceLineNumbers)
215
{
216
PropertyId = SummaryInformationType.PatchProductCodes,
217
Value = String.Join(";", productCodes)
218
});
219
220
// Semicolon delimited list of transform substorage names in the order they are applied.
221
- summaryInfo.Add(SummaryInformationType.TransformNames, new SummaryInformationSymbol(patchIdSymbol.SourceLineNumbers)
221
+ summaryInfo.Add(SummaryInformationType.TransformNames, new SummaryInformationSymbol(patchSymbol.SourceLineNumbers)
222
{
223
PropertyId = SummaryInformationType.TransformNames,
224
Value = String.Join(";", transformNames)
@@ -262,25 +262,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind
262
return result;
263
}
264
265
- private Dictionary<string, MsiPatchMetadataSymbol> PopulateSummaryInformation(Dictionary<SummaryInformationType, SummaryInformationSymbol> summaryInfo, List<IntermediateSymbol> symbols, WixPatchIdSymbol patchIdSymbol, int codepage)
265
+ private Dictionary<string, MsiPatchMetadataSymbol> PopulateSummaryInformation(Dictionary<SummaryInformationType, SummaryInformationSymbol> summaryInfo, List<IntermediateSymbol> symbols, WixPatchSymbol patchSymbol)
266
{
267
// PID_CODEPAGE
268
if (!summaryInfo.ContainsKey(SummaryInformationType.Codepage))
269
{
270
// Set the code page by default to the same code page for the
271
// string pool in the database.
272
- AddSummaryInformation(SummaryInformationType.Codepage, codepage.ToString(CultureInfo.InvariantCulture), patchIdSymbol.SourceLineNumbers);
272
+ AddSummaryInformation(SummaryInformationType.Codepage, patchSymbol.Codepage?.ToString(CultureInfo.InvariantCulture) ?? "0", patchSymbol.SourceLineNumbers);
273
}
274
275
// GUID patch code for the patch.
276
- AddSummaryInformation(SummaryInformationType.PatchCode, patchIdSymbol.Id.Id, patchIdSymbol.SourceLineNumbers);
276
+ AddSummaryInformation(SummaryInformationType.PatchCode, patchSymbol.Id.Id, patchSymbol.SourceLineNumbers);
277
278
// Indicates the minimum Windows Installer version that is required to install the patch.
279
- AddSummaryInformation(SummaryInformationType.PatchInstallerRequirement, ((int)SummaryInformation.InstallerRequirement.Version31).ToString(CultureInfo.InvariantCulture), patchIdSymbol.SourceLineNumbers);
279
+ AddSummaryInformation(SummaryInformationType.PatchInstallerRequirement, ((int)SummaryInformation.InstallerRequirement.Version31).ToString(CultureInfo.InvariantCulture), patchSymbol.SourceLineNumbers);
280
281
if (!summaryInfo.ContainsKey(SummaryInformationType.Security))
282
{
283
- AddSummaryInformation(SummaryInformationType.Security, "4", patchIdSymbol.SourceLineNumbers); // Read-only enforced;
283
+ AddSummaryInformation(SummaryInformationType.Security, "4", patchSymbol.SourceLineNumbers); // Read-only enforced;
284
}
285
286
// Use authored comments or default to display name.
@@ -1090,7 +1090,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1090
/// <summary>
1091
/// Create the #transform for the given main transform.
1092
/// </summary>
1093
- private WindowsInstallerData BuildPairedTransform(Dictionary<SummaryInformationType, SummaryInformationSymbol> summaryInfo, Dictionary<string, MsiPatchMetadataSymbol> patchMetadata, WixPatchIdSymbol patchIdSymbol, WindowsInstallerData mainTransform, MediaSymbol mediaSymbol, WixPatchBaselineSymbol baselineSymbol, out string productCode)
1093
+ private WindowsInstallerData BuildPairedTransform(Dictionary<SummaryInformationType, SummaryInformationSymbol> summaryInfo, Dictionary<string, MsiPatchMetadataSymbol> patchMetadata, WixPatchSymbol patchIdSymbol, WindowsInstallerData mainTransform, MediaSymbol mediaSymbol, WixPatchBaselineSymbol baselineSymbol, out string productCode)
1094
{
1095
productCode = null;
1096
src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+71
-56
@@ -37,7 +37,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
37
38
this.CabbingThreadCount = context.CabbingThreadCount;
39
this.CabCachePath = context.CabCachePath;
40
- this.Codepage = context.Codepage;
40
this.DefaultCompressionLevel = context.DefaultCompressionLevel;
41
this.DelayedFields = context.DelayedFields;
42
this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles;
@@ -47,6 +46,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
46
this.OutputPath = context.OutputPath;
47
this.OutputPdbPath = context.PdbPath;
48
this.PdbType = context.PdbType;
49
+ this.ResolvedCodepage = context.ResolvedCodepage;
50
+ this.ResolvedSummaryInformationCodepage = context.ResolvedSummaryInformationCodepage;
51
+ this.ResolvedLcid = context.ResolvedLcid;
52
this.SuppressLayout = context.SuppressLayout;
53
54
this.SubStorages = subStorages;
@@ -67,8 +69,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
69
70
private IPathResolver PathResolver { get; }
71
70
- private int Codepage { get; }
71
-
72
private int CabbingThreadCount { get; }
73
74
private string CabCachePath { get; }
@@ -95,6 +95,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
95
96
private string OutputPdbPath { get; }
97
98
+ private int? ResolvedCodepage { get; }
99
+
100
+ private int? ResolvedSummaryInformationCodepage { get; }
101
+
102
+ private int? ResolvedLcid { get; }
103
+
104
private bool SuppressAddingValidationRows { get; }
105
106
private bool SuppressLayout { get; }
@@ -111,21 +117,22 @@ namespace WixToolset.Core.WindowsInstaller.Bind
117
118
public IBindResult Execute()
119
{
114
- if (!this.Intermediate.HasLevel(Data.IntermediateLevels.Linked) && !this.Intermediate.HasLevel(Data.IntermediateLevels.Resolved))
120
+ if (!this.Intermediate.HasLevel(Data.IntermediateLevels.Linked) || !this.Intermediate.HasLevel(Data.IntermediateLevels.Resolved))
121
{
122
this.Messaging.Write(ErrorMessages.IntermediatesMustBeResolved(this.Intermediate.Id));
123
}
124
125
var section = this.Intermediate.Sections.Single();
126
127
+ var packageSymbol = (section.Type == SectionType.Product) ? this.GetSingleSymbol<WixPackageSymbol>(section) : null;
128
+ var moduleSymbol = (section.Type == SectionType.Module) ? this.GetSingleSymbol<WixModuleSymbol>(section) : null;
129
+ var patchSymbol = (section.Type == SectionType.Patch) ? this.GetSingleSymbol<WixPatchSymbol>(section) : null;
130
+
131
var fileTransfers = new List<IFileTransfer>();
132
var trackedFiles = new List<ITrackedFile>();
133
134
var containsMergeModules = false;
135
126
- // If there are any fields to resolve later, create the cache to populate during bind.
127
- var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null;
128
-
136
// Load standard tables, authored custom tables, and extension custom tables.
137
TableDefinitionCollection tableDefinitions;
138
{
@@ -135,7 +142,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
142
tableDefinitions = command.TableDefinitions;
143
}
144
138
- // Process the summary information table before the other tables.
145
+ // Calculate codepage
146
+ var codepage = this.CalculateCodepage(packageSymbol, moduleSymbol, patchSymbol);
147
+
148
+ // Process properties and create the delayed variable cache if needed.
149
+ Dictionary<string, string> variableCache = null;
150
+ string productLanguage = null;
151
+ {
152
+ var command = new ProcessPropertiesCommand(section, packageSymbol, this.ResolvedLcid ?? 0, this.DelayedFields.Any(), this.WindowsInstallerBackendHelper);
153
+ command.Execute();
154
+
155
+ variableCache = command.DelayedVariablesCache;
156
+ productLanguage = command.ProductLanguage;
157
+ }
158
+
159
+ // Process the summary information table after properties are processed.
160
bool compressed;
161
bool longNames;
162
int installerVersion;
@@ -144,7 +165,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
165
{
166
var branding = this.ServiceProvider.GetService<IWixBranding>();
167
147
- var command = new BindSummaryInfoCommand(section, this.WindowsInstallerBackendHelper, branding);
168
+ var command = new BindSummaryInfoCommand(section, this.ResolvedSummaryInformationCodepage, productLanguage, this.WindowsInstallerBackendHelper, branding);
169
command.Execute();
170
171
compressed = command.Compressed;
@@ -154,49 +175,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
175
modularizationSuffix = command.ModularizationSuffix;
176
}
177
157
- // Add binder variables for all properties.
158
- if (SectionType.Product == section.Type || variableCache != null)
159
- {
160
- foreach (var propertyRow in section.Symbols.OfType<PropertySymbol>())
161
- {
162
- // Set the ProductCode if it is to be generated.
163
- if ("ProductCode".Equals(propertyRow.Id.Id, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal))
164
- {
165
- propertyRow.Value = this.WindowsInstallerBackendHelper.CreateGuid();
166
-
167
-#if TODO_PATCHING // Is this still necessary?
168
-
169
- // Update the target ProductCode in any instance transforms.
170
- foreach (SubStorage subStorage in this.Output.SubStorages)
171
- {
172
- Output subStorageOutput = subStorage.Data;
173
- if (OutputType.Transform != subStorageOutput.Type)
174
- {
175
- continue;
176
- }
177
-
178
- Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"];
179
- foreach (Row row in instanceSummaryInformationTable.Rows)
180
- {
181
- if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0))
182
- {
183
- row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value);
184
- break;
185
- }
186
- }
187
- }
188
-#endif
189
- }
190
-
191
- // Add the property name and value to the variableCache.
192
- if (variableCache != null)
193
- {
194
- var key = String.Concat("property.", propertyRow.Id.Id);
195
- variableCache[key] = propertyRow.Value;
196
- }
197
- }
198
- }
199
-
178
// Sequence all the actions.
179
{
180
var command = new SequenceActionsCommand(this.Messaging, section);
@@ -415,7 +393,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
393
// Time to create the WindowsInstallerData object. Try to put as much above here as possible, updating the IR is better.
394
WindowsInstallerData data;
395
{
418
- var command = new CreateWindowsInstallerDataFromIRCommand(this.Messaging, section, tableDefinitions, this.BackendExtensions, this.WindowsInstallerBackendHelper);
396
+ var command = new CreateWindowsInstallerDataFromIRCommand(this.Messaging, section, tableDefinitions, codepage, this.BackendExtensions, this.WindowsInstallerBackendHelper);
397
data = command.Execute();
398
}
399
@@ -450,7 +428,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
428
429
if (SectionType.Patch == section.Type && this.DeltaBinaryPatch)
430
{
453
- var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Symbols.OfType<WixPatchIdSymbol>().FirstOrDefault());
431
+ var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Symbols.OfType<WixPatchSymbol>().FirstOrDefault());
432
command.Execute();
433
}
434
@@ -508,7 +486,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
486
var trackMsi = this.WindowsInstallerBackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final);
487
trackedFiles.Add(trackMsi);
488
511
- var command = new GenerateDatabaseCommand(this.Messaging, this.WindowsInstallerBackendHelper, this.FileSystemManager, data, trackMsi.Path, tableDefinitions, this.IntermediateFolder, this.Codepage, keepAddedColumns: false, this.SuppressAddingValidationRows, useSubdirectory: false);
489
+ var command = new GenerateDatabaseCommand(this.Messaging, this.WindowsInstallerBackendHelper, this.FileSystemManager, data, trackMsi.Path, tableDefinitions, this.IntermediateFolder, keepAddedColumns: false, this.SuppressAddingValidationRows, useSubdirectory: false);
490
command.Execute();
491
492
trackedFiles.AddRange(command.GeneratedTemporaryFiles);
@@ -532,7 +510,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
510
if (this.Messaging.EncounteredError)
511
{
512
return null;
535
- }
513
+ }
514
515
// Validate the output if there are CUBe files and we're not explicitly suppressing validation.
516
if (this.CubeFiles != null && !this.SuppressValidation)
@@ -575,6 +553,43 @@ namespace WixToolset.Core.WindowsInstaller.Bind
553
return result;
554
}
555
556
+ private int CalculateCodepage(WixPackageSymbol packageSymbol, WixModuleSymbol moduleSymbol, WixPatchSymbol patchSymbol)
557
+ {
558
+ var codepage = packageSymbol?.Codepage ?? moduleSymbol?.Codepage ?? patchSymbol?.Codepage;
559
+
560
+ if (String.IsNullOrEmpty(codepage))
561
+ {
562
+ codepage = this.ResolvedCodepage?.ToString() ?? "65001";
563
+
564
+ if (packageSymbol != null)
565
+ {
566
+ packageSymbol.Codepage = codepage;
567
+ }
568
+ else if (moduleSymbol != null)
569
+ {
570
+ moduleSymbol.Codepage = codepage;
571
+ }
572
+ else if (patchSymbol != null)
573
+ {
574
+ patchSymbol.Codepage = codepage;
575
+ }
576
+ }
577
+
578
+ return this.WindowsInstallerBackendHelper.GetValidCodePage(codepage);
579
+ }
580
+
581
+ private T GetSingleSymbol<T>(IntermediateSection section) where T : IntermediateSymbol
582
+ {
583
+ var symbols = section.Symbols.OfType<T>().ToList();
584
+
585
+ if (1 != symbols.Count)
586
+ {
587
+ throw new WixException(ErrorMessages.MissingBundleInformation(nameof(T)));
588
+ }
589
+
590
+ return symbols[0];
591
+ }
592
+
593
private WixOutput CreateWixout(List<ITrackedFile> trackedFiles, Intermediate intermediate, WindowsInstallerData data)
594
{
595
WixOutput wixout;
src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs
+46
-15
@@ -14,15 +14,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
14
/// </summary>
15
internal class BindSummaryInfoCommand
16
{
17
- public BindSummaryInfoCommand(IntermediateSection section, IBackendHelper backendHelper, IWixBranding branding)
17
+ public BindSummaryInfoCommand(IntermediateSection section, int? summaryInformationCodepage, string productLanguage, IBackendHelper backendHelper, IWixBranding branding)
18
{
19
this.Section = section;
20
+ this.SummaryInformationCodepage = summaryInformationCodepage;
21
+ this.ProductLanguage = productLanguage;
22
this.BackendHelper = backendHelper;
23
this.Branding = branding;
24
}
25
26
private IntermediateSection Section { get; }
27
28
+ private int? SummaryInformationCodepage { get; }
29
+
30
+ private string ProductLanguage { get; }
31
+
32
private IBackendHelper BackendHelper { get; }
33
34
private IWixBranding Branding { get; }
@@ -53,6 +59,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
59
this.InstallerVersion = 0;
60
this.ModularizationSuffix = null;
61
62
+ SummaryInformationSymbol summaryInformationCodepageSymbol = null;
63
+ SummaryInformationSymbol platformAndLanguageSymbol = null;
64
var foundCreateDateTime = false;
65
var foundLastSaveDataTime = false;
66
var foundCreatingApplication = false;
@@ -64,20 +72,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
72
switch (summaryInformationSymbol.PropertyId)
73
{
74
case SummaryInformationType.Codepage: // PID_CODEPAGE
67
- // make sure the code page is an int and not a web name or null
68
- var codepage = summaryInformationSymbol.Value;
69
-
70
- if (String.IsNullOrEmpty(codepage))
71
- {
72
- codepage = "0";
73
- }
74
- else
75
- {
76
- summaryInformationSymbol.Value = this.BackendHelper.GetValidCodePage(codepage, false, false, summaryInformationSymbol.SourceLineNumbers).ToString(CultureInfo.InvariantCulture);
77
- }
75
+ summaryInformationCodepageSymbol = summaryInformationSymbol;
76
break;
77
+
78
case SummaryInformationType.PlatformAndLanguage:
80
- this.Platform = GetPlatformFromSummaryInformation(summaryInformationSymbol.Value);
79
+ platformAndLanguageSymbol = summaryInformationSymbol;
80
break;
81
82
case SummaryInformationType.PackageCode: // PID_REVNUMBER
@@ -117,7 +116,31 @@ namespace WixToolset.Core.WindowsInstaller.Bind
116
}
117
}
118
120
- // set the revision number (package/patch code) if it should be automatically generated
119
+ // Ensure the codepage is set properly.
120
+ if (summaryInformationCodepageSymbol == null)
121
+ {
122
+ summaryInformationCodepageSymbol = this.Section.AddSymbol(new SummaryInformationSymbol(null)
123
+ {
124
+ PropertyId = SummaryInformationType.Codepage
125
+ });
126
+ }
127
+
128
+ var codepage = summaryInformationCodepageSymbol.Value;
129
+
130
+ if (String.IsNullOrEmpty(codepage))
131
+ {
132
+ codepage = this.SummaryInformationCodepage?.ToString(CultureInfo.InvariantCulture) ?? "1252";
133
+ }
134
+
135
+ summaryInformationCodepageSymbol.Value = this.BackendHelper.GetValidCodePage(codepage, onlyAnsi: true).ToString(CultureInfo.InvariantCulture);
136
+
137
+ // Ensure the language is set properly and figure out what platform we are targeting.
138
+ if (platformAndLanguageSymbol != null)
139
+ {
140
+ this.Platform = EnsureLanguageAndGetPlatformFromSummaryInformation(platformAndLanguageSymbol, this.ProductLanguage);
141
+ }
142
+
143
+ // Set the revision number (package/patch code) if it should be automatically generated.
144
if (!foundPackageCode)
145
{
146
this.Section.AddSymbol(new SummaryInformationSymbol(null)
@@ -158,11 +181,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
181
}
182
}
183
161
- private static Platform GetPlatformFromSummaryInformation(string value)
184
+ private static Platform EnsureLanguageAndGetPlatformFromSummaryInformation(SummaryInformationSymbol symbol, string language)
185
{
186
+ var value = symbol.Value;
187
var separatorIndex = value.IndexOf(';');
188
var platformValue = separatorIndex > 0 ? value.Substring(0, separatorIndex) : value;
189
190
+ // If the language was provided and there was language value after the separator
191
+ // (or the separator was absent) then use the provided language.
192
+ if (!String.IsNullOrEmpty(language) && (separatorIndex < 0 || separatorIndex + 1 == value.Length))
193
+ {
194
+ symbol.Value = platformValue + ';' + language;
195
+ }
196
+
197
switch (platformValue)
198
{
199
case "x64":
src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+1
-1
@@ -438,7 +438,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
438
439
private void GenerateDatabase(WindowsInstallerData output, string outputPath, bool keepAddedColumns)
440
{
441
- var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, output, outputPath, this.TableDefinitions, this.IntermediateFolder, codepage: -1, keepAddedColumns, suppressAddingValidationRows: true, useSubdirectory: true);
441
+ var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, output, outputPath, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns, suppressAddingValidationRows: true, useSubdirectory: true);
442
command.Execute();
443
}
444
}
src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs
+2
-2
@@ -15,7 +15,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
15
/// </summary>
16
internal class CreateDeltaPatchesCommand
17
{
18
- public CreateDeltaPatchesCommand(List<IFileFacade> fileFacades, string intermediateFolder, WixPatchIdSymbol wixPatchId)
18
+ public CreateDeltaPatchesCommand(List<IFileFacade> fileFacades, string intermediateFolder, WixPatchSymbol wixPatchId)
19
{
20
this.FileFacades = fileFacades;
21
this.IntermediateFolder = intermediateFolder;
@@ -24,7 +24,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
24
25
private IEnumerable<IFileFacade> FileFacades { get; }
26
27
- private WixPatchIdSymbol WixPatchId { get; }
27
+ private WixPatchSymbol WixPatchId { get; }
28
29
private string IntermediateFolder { get; }
30
src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs
+25
-17
@@ -36,23 +36,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
36
public void Execute()
37
{
38
// write out the table to an IDT file
39
- Encoding encoding;
40
-
41
- // If UTF8 encoding, use the UTF8-specific constructor to avoid writing
42
- // the byte order mark at the beginning of the file
43
- if (this.Codepage == Encoding.UTF8.CodePage)
44
- {
45
- encoding = new UTF8Encoding(false, true);
46
- }
47
- else
48
- {
49
- if (this.Codepage == 0)
50
- {
51
- this.Codepage = Encoding.ASCII.CodePage;
52
- }
53
-
54
- encoding = Encoding.GetEncoding(this.Codepage, new EncoderExceptionFallback(), new DecoderExceptionFallback());
55
- }
39
+ var encoding = GetCodepageEncoding(this.Codepage);
40
41
this.IdtPath = Path.Combine(this.IntermediateFolder, String.Concat(this.Table.Name, ".idt"));
42
@@ -209,6 +193,30 @@ namespace WixToolset.Core.WindowsInstaller.Bind
193
.Replace('\n', '\x19');
194
}
195
196
+ private static Encoding GetCodepageEncoding(int codepage)
197
+ {
198
+ Encoding encoding;
199
+
200
+ // If UTF8 encoding, use the UTF8-specific constructor to avoid writing
201
+ // the byte order mark at the beginning of the file
202
+ if (codepage == Encoding.UTF8.CodePage)
203
+ {
204
+ encoding = new UTF8Encoding(false, true);
205
+ }
206
+ else
207
+ {
208
+ if (codepage == 0)
209
+ {
210
+ codepage = Encoding.ASCII.CodePage;
211
+ }
212
+
213
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
214
+
215
+ encoding = Encoding.GetEncoding(codepage, new EncoderExceptionFallback(), new DecoderExceptionFallback());
216
+ }
217
+
218
+ return encoding;
219
+ }
220
221
/// <summary>
222
/// Gets the type of the column in IDT format.
src/WixToolset.Core.WindowsInstaller/Bind/CreateWindowsInstallerDataFromIRCommand.cs
+29
-3
@@ -18,11 +18,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
18
19
internal class CreateWindowsInstallerDataFromIRCommand
20
{
21
- public CreateWindowsInstallerDataFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions, IWindowsInstallerBackendHelper backendHelper)
21
+ public CreateWindowsInstallerDataFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, int codepage, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions, IWindowsInstallerBackendHelper backendHelper)
22
{
23
this.Messaging = messaging;
24
this.Section = section;
25
this.TableDefinitions = tableDefinitions;
26
+ this.Codepage = codepage;
27
this.BackendExtensions = backendExtensions;
28
this.BackendHelper = backendHelper;
29
this.GeneratedShortNames = new Dictionary<string, List<FileSymbol>>();
@@ -36,6 +37,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
37
38
private TableDefinitionCollection TableDefinitions { get; }
39
40
+ private int Codepage { get; }
41
+
42
private IntermediateSection Section { get; }
43
44
private Dictionary<string, List<FileSymbol>> GeneratedShortNames { get; }
@@ -46,7 +49,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
49
{
50
this.Data = new WindowsInstallerData(this.Section.Symbols.First().SourceLineNumbers)
51
{
49
- Codepage = this.Section.Codepage,
52
+ Codepage = this.Codepage,
53
Type = SectionTypeToOutputType(this.Section.Type)
54
};
55
@@ -219,6 +222,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
222
this.AddWixEnsureTableSymbol((WixEnsureTableSymbol)symbol);
223
break;
224
225
+ case SymbolDefinitionType.WixPackage:
226
+ this.AddWixPackageSymbol((WixPackageSymbol)symbol);
227
+ break;
228
+
229
// Symbols used internally and are not added to the output.
230
case SymbolDefinitionType.WixBuildInfo:
231
case SymbolDefinitionType.WixBindUpdatedFiles:
@@ -237,7 +244,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
244
case SymbolDefinitionType.WixOrdering:
245
case SymbolDefinitionType.WixPatchBaseline:
246
case SymbolDefinitionType.WixPatchFamilyGroup:
240
- case SymbolDefinitionType.WixPatchId:
247
+ case SymbolDefinitionType.WixPatch:
248
case SymbolDefinitionType.WixPatchRef:
249
case SymbolDefinitionType.WixPatchTarget:
250
case SymbolDefinitionType.WixProperty:
@@ -1214,6 +1221,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1221
this.Data.EnsureTable(tableDefinition);
1222
}
1223
1224
+ private void AddWixPackageSymbol(WixPackageSymbol symbol)
1225
+ {
1226
+ // TODO: Remove the following from the compiler and do it here instead.
1227
+ //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "Manufacturer"), manufacturer, false, false, false, true);
1228
+ //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductCode"), productCode, false, false, false, true);
1229
+ //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductLanguage"), productLanguage, false, false, false, true);
1230
+ //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductName"), this.activeName, false, false, false, true);
1231
+ //this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductVersion"), version, false, false, false, true);
1232
+ //if (null != upgradeCode)
1233
+ //{
1234
+ // this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "UpgradeCode"), upgradeCode, false, false, false, true);
1235
+ //}
1236
+
1237
+ //if (isPerMachine)
1238
+ //{
1239
+ // this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ALLUSERS"), "1", false, false, false, false);
1240
+ //}
1241
+ }
1242
+
1243
private bool AddSymbolFromExtension(IntermediateSymbol symbol)
1244
{
1245
foreach (var extension in this.BackendExtensions)
src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
+1
-10
@@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
18
{
19
private const string IdtsSubFolder = "_idts";
20
21
- public GenerateDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, FileSystemManager fileSystemManager, WindowsInstallerData data, string outputPath, TableDefinitionCollection tableDefinitions, string intermediateFolder, int codepage, bool keepAddedColumns, bool suppressAddingValidationRows, bool useSubdirectory)
21
+ public GenerateDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, FileSystemManager fileSystemManager, WindowsInstallerData data, string outputPath, TableDefinitionCollection tableDefinitions, string intermediateFolder, bool keepAddedColumns, bool suppressAddingValidationRows, bool useSubdirectory)
22
{
23
this.Messaging = messaging;
24
this.BackendHelper = backendHelper;
@@ -27,14 +27,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
27
this.OutputPath = outputPath;
28
this.TableDefinitions = tableDefinitions;
29
this.IntermediateFolder = intermediateFolder;
30
- this.Codepage = codepage;
30
this.KeepAddedColumns = keepAddedColumns;
31
this.SuppressAddingValidationRows = suppressAddingValidationRows;
32
this.UseSubDirectory = useSubdirectory;
33
}
34
36
- private int Codepage { get; }
37
-
35
private IBackendHelper BackendHelper { get; }
36
37
private FileSystemManager FileSystemManager { get; }
@@ -88,12 +85,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
85
type |= OpenDatabase.OpenPatchFile;
86
}
87
91
- // Localize the codepage if a value was specified directly.
92
- if (-1 != this.Codepage)
93
- {
94
- this.Data.Codepage = this.Codepage;
95
- }
96
-
88
try
89
{
90
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath));
src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs
-1
@@ -9,7 +9,6 @@ namespace WixToolset.Core.WindowsInstaller
9
using WixToolset.Data;
10
using WixToolset.Data.Symbols;
11
using WixToolset.Data.WindowsInstaller;
12
- using WixToolset.Data.WindowsInstaller.Rows;
12
using WixToolset.Extensibility.Services;
13
14
/// <summary>
src/WixToolset.Core.WindowsInstaller/Bind/ProcessPropertiesCommand.cs
new
+101
@@ -0,0 +1,101 @@
1
+// 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.
2
+
3
+namespace WixToolset.Core.WindowsInstaller.Bind
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.Linq;
8
+ using WixToolset.Data;
9
+ using WixToolset.Data.Symbols;
10
+ using WixToolset.Extensibility.Services;
11
+
12
+ internal class ProcessPropertiesCommand
13
+ {
14
+ public ProcessPropertiesCommand(IntermediateSection section, WixPackageSymbol packageSymbol, int fallbackLcid, bool populateDelayedVariables, IBackendHelper backendHelper)
15
+ {
16
+ this.Section = section;
17
+ this.PackageSymbol = packageSymbol;
18
+ this.FallbackLcid = fallbackLcid;
19
+ this.PopulateDelayedVariables = populateDelayedVariables;
20
+ this.BackendHelper = backendHelper;
21
+ }
22
+
23
+ private IntermediateSection Section { get; }
24
+
25
+ private WixPackageSymbol PackageSymbol { get; }
26
+
27
+ private int FallbackLcid { get; }
28
+
29
+ private bool PopulateDelayedVariables { get; }
30
+
31
+ private IBackendHelper BackendHelper { get; }
32
+
33
+ public Dictionary<string, string> DelayedVariablesCache { get; private set; }
34
+
35
+ public string ProductLanguage { get; private set; }
36
+
37
+ public void Execute()
38
+ {
39
+ PropertySymbol languageSymbol = null;
40
+ var variableCache = this.PopulateDelayedVariables ? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) : null;
41
+
42
+ if (SectionType.Product == this.Section.Type || variableCache != null)
43
+ {
44
+ foreach (var propertySymbol in this.Section.Symbols.OfType<PropertySymbol>())
45
+ {
46
+ // Set the ProductCode if it is to be generated.
47
+ if ("ProductCode" == propertySymbol.Id.Id && "*".Equals(propertySymbol.Value, StringComparison.Ordinal))
48
+ {
49
+ propertySymbol.Value = this.BackendHelper.CreateGuid();
50
+
51
+#if TODO_PATCHING // Is this still necessary?
52
+ // Update the target ProductCode in any instance transforms.
53
+ foreach (SubStorage subStorage in this.Output.SubStorages)
54
+ {
55
+ Output subStorageOutput = subStorage.Data;
56
+ if (OutputType.Transform != subStorageOutput.Type)
57
+ {
58
+ continue;
59
+ }
60
+
61
+ Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"];
62
+ foreach (Row row in instanceSummaryInformationTable.Rows)
63
+ {
64
+ if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0))
65
+ {
66
+ row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value);
67
+ break;
68
+ }
69
+ }
70
+ }
71
+#endif
72
+ }
73
+ else if ("ProductLanguage" == propertySymbol.Id.Id)
74
+ {
75
+ languageSymbol = propertySymbol;
76
+ }
77
+
78
+ // Add the property name and value to the variableCache.
79
+ if (variableCache != null)
80
+ {
81
+ variableCache[$"property.{propertySymbol.Id.Id}"] = propertySymbol.Value;
82
+ }
83
+ }
84
+
85
+ if (this.Section.Type == SectionType.Product && String.IsNullOrEmpty(languageSymbol?.Value))
86
+ {
87
+ if (languageSymbol == null)
88
+ {
89
+ languageSymbol = this.Section.AddSymbol(new PropertySymbol(this.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, "ProductLanguage")));
90
+ }
91
+
92
+ this.PackageSymbol.Language = this.FallbackLcid.ToString();
93
+ languageSymbol.Value = this.FallbackLcid.ToString();
94
+ }
95
+ }
96
+
97
+ this.DelayedVariablesCache = variableCache;
98
+ this.ProductLanguage = languageSymbol?.Value;
99
+ }
100
+ }
101
+}
src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
+1
-1
@@ -302,7 +302,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
302
303
private void GenerateDatabase(WindowsInstallerData output, string databaseFile)
304
{
305
- var command = new GenerateDatabaseCommand(this.Messaging, null, null, output, databaseFile, this.TableDefinitions, this.IntermediateFolder, codepage: -1, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false);
305
+ var command = new GenerateDatabaseCommand(this.Messaging, null, null, output, databaseFile, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false);
306
command.Execute();
307
}
308
}
src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj
+1
@@ -20,6 +20,7 @@
20
21
<ItemGroup>
22
<PackageReference Include="System.Reflection.Metadata" Version="1.6.0" />
23
+ <PackageReference Include="System.Text.Encoding.CodePages" Version="4.6.0" />
24
</ItemGroup>
25
26
<ItemGroup>
src/WixToolset.Core/BindContext.cs
+6
-2
@@ -26,8 +26,6 @@ namespace WixToolset.Core
26
27
public string CabCachePath { get; set; }
28
29
- public int Codepage { get; set; }
30
-
29
public CompressionLevel? DefaultCompressionLevel { get; set; }
30
31
public IEnumerable<IDelayedField> DelayedFields { get; set; }
@@ -50,6 +48,12 @@ namespace WixToolset.Core
48
49
public string PdbPath { get; set; }
50
51
+ public int? ResolvedCodepage { get; set; }
52
+
53
+ public int? ResolvedSummaryInformationCodepage { get; set; }
54
+
55
+ public int? ResolvedLcid { get; set; }
56
+
57
public IEnumerable<string> SuppressIces { get; set; }
58
59
public bool SuppressValidation { get; set; }
src/WixToolset.Core/CommandLine/BuildCommand.cs
+3
-1
@@ -338,7 +338,9 @@ namespace WixToolset.Core.CommandLine
338
var context = this.ServiceProvider.GetService<IBindContext>();
339
//context.CabbingThreadCount = this.CabbingThreadCount;
340
context.CabCachePath = cabCachePath;
341
- context.Codepage = resolveResult.Codepage;
341
+ context.ResolvedCodepage = resolveResult.Codepage;
342
+ context.ResolvedSummaryInformationCodepage = resolveResult.SummaryInformationCodepage;
343
+ context.ResolvedLcid = resolveResult.PackageLcid;
344
context.DefaultCompressionLevel = this.DefaultCompressionLevel;
345
context.DelayedFields = resolveResult.DelayedFields;
346
context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles;
src/WixToolset.Core/Compiler.cs
+2
-2
@@ -384,7 +384,7 @@ namespace WixToolset.Core
384
{
385
var id = String.Concat(this.Core.ActiveSection.Id, ".", propertyId.Id);
386
387
- section = this.Core.CreateSection(id, SectionType.Fragment, this.Core.ActiveSection.Codepage, this.Context.CompilationId);
387
+ section = this.Core.CreateSection(id, SectionType.Fragment, this.Context.CompilationId);
388
389
// Reference the property in the active section.
390
this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Property, propertyId.Id);
@@ -6159,7 +6159,7 @@ namespace WixToolset.Core
6159
6160
// NOTE: Id is not required for Fragments, this is a departure from the normal run of the mill processing.
6161
6162
- this.Core.CreateActiveSection(id?.Id, SectionType.Fragment, 0, this.Context.CompilationId);
6162
+ this.Core.CreateActiveSection(id?.Id, SectionType.Fragment, this.Context.CompilationId);
6163
6164
var featureDisplay = 0;
6165
foreach (var child in node.Elements())
src/WixToolset.Core/CompilerCore.cs
+8
-10
@@ -680,7 +680,7 @@ namespace WixToolset.Core
680
681
Debug.Assert(minimum > CompilerConstants.IntegerNotSet && minimum > CompilerConstants.IllegalInteger, "The legal values for this attribute collide with at least one sentinel used during parsing.");
682
683
- string value = this.GetAttributeValue(sourceLineNumbers, attribute);
683
+ var value = this.GetAttributeValue(sourceLineNumbers, attribute);
684
685
if (0 < value.Length)
686
{
@@ -692,7 +692,7 @@ namespace WixToolset.Core
692
{
693
try
694
{
695
- int integer = Convert.ToInt32(value, CultureInfo.InvariantCulture.NumberFormat);
695
+ var integer = Convert.ToInt32(value, CultureInfo.InvariantCulture.NumberFormat);
696
697
if (CompilerConstants.IntegerNotSet == integer || CompilerConstants.IllegalInteger == integer)
698
{
@@ -1036,12 +1036,11 @@ namespace WixToolset.Core
1036
/// </summary>
1037
/// <param name="id">Unique identifier for the section.</param>
1038
/// <param name="type">Type of section to create.</param>
1039
- /// <param name="codepage">Codepage for the resulting database for this ection.</param>
1040
- /// <param name="compilationId"></param>
1039
+ /// <param name="compilationId">Unique identifier for the compilation.</param>
1040
/// <returns>New section.</returns>
1042
- internal IntermediateSection CreateActiveSection(string id, SectionType type, int codepage, string compilationId)
1041
+ internal IntermediateSection CreateActiveSection(string id, SectionType type, string compilationId)
1042
{
1044
- this.ActiveSection = this.CreateSection(id, type, codepage, compilationId);
1043
+ this.ActiveSection = this.CreateSection(id, type, compilationId);
1044
1045
this.activeSectionCachedInlinedDirectoryIds = new Dictionary<string, string>();
1046
this.activeSectionSimpleReferences = new HashSet<string>();
@@ -1054,12 +1053,11 @@ namespace WixToolset.Core
1053
/// </summary>
1054
/// <param name="id">Unique identifier for the section.</param>
1055
/// <param name="type">Type of section to create.</param>
1057
- /// <param name="codepage">Codepage for the resulting database for this ection.</param>
1058
- /// <param name="compilationId"></param>
1056
+ /// <param name="compilationId">Unique identifier for the compilation.</param>
1057
/// <returns>New section.</returns>
1060
- internal IntermediateSection CreateSection(string id, SectionType type, int codepage, string compilationId)
1058
+ internal IntermediateSection CreateSection(string id, SectionType type, string compilationId)
1059
{
1062
- var section = new IntermediateSection(id, type, codepage, compilationId);
1060
+ var section = new IntermediateSection(id, type, compilationId);
1061
1062
this.intermediate.Sections.Add(section);
1063
src/WixToolset.Core/Compiler_Bundle.cs
+1
-1
@@ -259,7 +259,7 @@ namespace WixToolset.Core
259
}
260
261
this.activeName = String.IsNullOrEmpty(name) ? Common.GenerateGuid() : name;
262
- this.Core.CreateActiveSection(this.activeName, SectionType.Bundle, 0, this.Context.CompilationId);
262
+ this.Core.CreateActiveSection(this.activeName, SectionType.Bundle, this.Context.CompilationId);
263
264
// Now that the active section is initialized, process only extension attributes and the special ProviderKey attribute.
265
foreach (var attrib in node.Attributes())
src/WixToolset.Core/Compiler_Module.cs
+5
-15
@@ -104,7 +104,7 @@ namespace WixToolset.Core
104
try
105
{
106
this.compilingModule = true; // notice that we are actually building a Merge Module here
107
- this.Core.CreateActiveSection(this.activeName, SectionType.Module, codepage, this.Context.CompilationId);
107
+ this.Core.CreateActiveSection(this.activeName, SectionType.Module, this.Context.CompilationId);
108
109
foreach (var child in node.Elements())
110
{
@@ -232,15 +232,6 @@ namespace WixToolset.Core
232
233
if (!this.Core.EncounteredError)
234
{
235
- if (!setCodepage)
236
- {
237
- this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers)
238
- {
239
- PropertyId = SummaryInformationType.Codepage,
240
- Value = "1252"
241
- });
242
- }
243
-
235
if (!setPackageName)
236
{
237
this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers)
@@ -259,21 +250,20 @@ namespace WixToolset.Core
250
});
251
}
252
262
- var symbol = this.Core.AddSymbol(new ModuleSignatureSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, this.activeName, this.activeLanguage))
253
+ var symbol = this.Core.AddSymbol(new WixModuleSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, this.activeName, this.activeLanguage))
254
{
264
- ModuleID = this.activeName,
255
+ ModuleId = this.activeName,
256
+ Language = this.activeLanguage,
257
Version = version
258
});
259
268
- symbol.Set((int)ModuleSignatureSymbolFields.Language, this.activeLanguage);
269
-
260
this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers)
261
{
262
PropertyId = SummaryInformationType.PackageCode,
263
Value = moduleId
264
});
265
276
- this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform);
266
+ this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform, this.activeLanguage);
267
}
268
}
269
finally
src/WixToolset.Core/Compiler_Package.cs
+21
-25
@@ -5,7 +5,6 @@ namespace WixToolset.Core
5
using System;
6
using System.Collections;
7
using System.Collections.Generic;
8
- using System.Diagnostics.CodeAnalysis;
8
using System.Globalization;
9
using System.IO;
10
using System.Xml.Linq;
@@ -28,10 +27,10 @@ namespace WixToolset.Core
27
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
28
var compressed = YesNoDefaultType.Default;
29
var sourceBits = 0;
31
- var codepage = 65001;
30
+ string codepage = null;
31
var productCode = "*";
32
+ string productLanguage = null;
33
var isPerMachine = true;
34
- string installScope = null;
34
string upgradeCode = null;
35
string manufacturer = null;
36
string version = null;
@@ -53,7 +52,7 @@ namespace WixToolset.Core
52
switch (attrib.Name.LocalName)
53
{
54
case "Codepage":
56
- codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
55
+ codepage = this.Core.GetAttributeLocalizableCodePageValue(sourceLineNumbers, attrib);
56
break;
57
case "Compressed":
58
compressed = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
@@ -62,7 +61,7 @@ namespace WixToolset.Core
61
msiVersion = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int32.MaxValue);
62
break;
63
case "Language":
65
- this.activeLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
64
+ productLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
65
break;
66
case "Manufacturer":
67
manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters);
@@ -82,7 +81,7 @@ namespace WixToolset.Core
81
productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true);
82
break;
83
case "Scope":
85
- installScope = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
84
+ var installScope = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
85
switch (installScope)
86
{
87
case "perMachine":
@@ -129,11 +128,6 @@ namespace WixToolset.Core
128
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
129
}
130
132
- if (null == this.activeLanguage)
133
- {
134
- this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Language"));
135
- }
136
-
131
if (null == manufacturer)
132
{
133
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer"));
@@ -171,11 +165,11 @@ namespace WixToolset.Core
165
try
166
{
167
this.compilingProduct = true;
174
- this.Core.CreateActiveSection(productCode, SectionType.Product, codepage, this.Context.CompilationId);
168
+ this.Core.CreateActiveSection(productCode, SectionType.Product, this.Context.CompilationId);
169
170
this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "Manufacturer"), manufacturer, false, false, false, true);
171
this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductCode"), productCode, false, false, false, true);
178
- this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductLanguage"), this.activeLanguage, false, false, false, true);
172
+ this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductLanguage"), productLanguage, false, false, false, true);
173
this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductName"), this.activeName, false, false, false, true);
174
this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ProductVersion"), version, false, false, false, true);
175
if (null != upgradeCode)
@@ -188,7 +182,7 @@ namespace WixToolset.Core
182
this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Global, "ALLUSERS"), "1", false, false, false, false);
183
}
184
191
- this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform);
185
+ this.ValidateAndAddCommonSummaryInformationSymbols(sourceLineNumbers, msiVersion, platform, productLanguage);
186
187
this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers)
188
{
@@ -198,7 +192,7 @@ namespace WixToolset.Core
192
193
var contextValues = new Dictionary<string, string>
194
{
201
- ["ProductLanguage"] = this.activeLanguage,
195
+ ["ProductLanguage"] = productLanguage,
196
["ProductVersion"] = version,
197
["UpgradeCode"] = upgradeCode
198
};
@@ -360,14 +354,17 @@ namespace WixToolset.Core
354
355
if (!this.Core.EncounteredError)
356
{
363
- if (!isCodepageSet)
357
+ this.Core.AddSymbol(new WixPackageSymbol(sourceLineNumbers)
358
{
365
- this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers)
366
- {
367
- PropertyId = SummaryInformationType.Codepage,
368
- Value = "1252"
369
- });
370
- }
359
+ PackageId = productCode,
360
+ UpgradeCode = upgradeCode,
361
+ Name = this.activeName,
362
+ Language = productLanguage,
363
+ Version = version,
364
+ Manufacturer = manufacturer,
365
+ Attributes = isPerMachine ? WixPackageAttributes.PerMachine : WixPackageAttributes.None,
366
+ Codepage = codepage,
367
+ });
368
369
if (!isPackageNameSet)
370
{
@@ -435,7 +432,7 @@ namespace WixToolset.Core
432
}
433
}
434
438
- private void ValidateAndAddCommonSummaryInformationSymbols(SourceLineNumber sourceLineNumbers, int msiVersion, string platform)
435
+ private void ValidateAndAddCommonSummaryInformationSymbols(SourceLineNumber sourceLineNumbers, int msiVersion, string platform, string language)
436
{
437
if (String.Equals(platform, "X64", StringComparison.OrdinalIgnoreCase) && 200 > msiVersion)
438
{
@@ -464,7 +461,7 @@ namespace WixToolset.Core
461
this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers)
462
{
463
PropertyId = SummaryInformationType.PlatformAndLanguage,
467
- Value = String.Format(CultureInfo.InvariantCulture, "{0};{1}", platform, this.activeLanguage)
464
+ Value = $"{platform};{language}"
465
});
466
467
this.Core.AddSymbol(new SummaryInformationSymbol(sourceLineNumbers)
@@ -478,7 +475,6 @@ namespace WixToolset.Core
475
PropertyId = SummaryInformationType.Security,
476
Value = "2"
477
});
481
-
478
}
479
480
/// <summary>
src/WixToolset.Core/Compiler_Patch.cs
+5
-4
@@ -24,7 +24,7 @@ namespace WixToolset.Core
24
{
25
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
26
string patchId = null;
27
- var codepage = 0;
27
+ string codepage = null;
28
////bool versionMismatches = false;
29
////bool productMismatches = false;
30
var allowRemoval = false;
@@ -53,7 +53,7 @@ namespace WixToolset.Core
53
patchId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true);
54
break;
55
case "Codepage":
56
- codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
56
+ codepage = this.Core.GetAttributeLocalizableCodePageValue(sourceLineNumbers, attrib);
57
break;
58
case "AllowMajorVersionMismatches":
59
////versionMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
@@ -149,7 +149,7 @@ namespace WixToolset.Core
149
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer"));
150
}
151
152
- this.Core.CreateActiveSection(this.activeName, SectionType.Patch, codepage, this.Context.CompilationId);
152
+ this.Core.CreateActiveSection(this.activeName, SectionType.Patch, this.Context.CompilationId);
153
154
foreach (var child in node.Elements())
155
{
@@ -197,8 +197,9 @@ namespace WixToolset.Core
197
198
if (!this.Core.EncounteredError)
199
{
200
- this.Core.AddSymbol(new WixPatchIdSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, patchId))
200
+ this.Core.AddSymbol(new WixPatchSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, patchId))
201
{
202
+ Codepage = codepage,
203
ClientPatchId = clientPatchId,
204
OptimizePatchSizeForLargeFiles = optimizePatchSizeForLargeFiles,
205
ApiPatchingSymbolFlags = apiPatchingSymbolFlags,
src/WixToolset.Core/Compiler_PatchCreation.cs
+1
-1
@@ -82,7 +82,7 @@ namespace WixToolset.Core
82
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
83
}
84
85
- this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, codepage, this.Context.CompilationId);
85
+ this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, this.Context.CompilationId);
86
87
foreach (var child in node.Elements())
88
{
src/WixToolset.Core/IResolver.cs
+8
-1
@@ -4,9 +4,16 @@ namespace WixToolset.Core
4
{
5
using WixToolset.Extensibility.Data;
6
7
-#pragma warning disable 1591 // TODO: add documentation
7
+ /// <summary>
8
+ /// Resolves localization and bind variables.
9
+ /// </summary>
10
public interface IResolver
11
{
12
+ /// <summary>
13
+ /// Resolve localization and bind variables.
14
+ /// </summary>
15
+ /// <param name="context">Resolve context.</param>
16
+ /// <returns>Resolve result.</returns>
17
IResolveResult Resolve(IResolveContext context);
18
}
19
}
src/WixToolset.Core/Link/CollateLocalizationsCommand.cs
+2
-2
@@ -1,4 +1,4 @@
1
-// 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.
1
+// 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.
2
3
namespace WixToolset.Core.Link
4
{
@@ -65,7 +65,7 @@ namespace WixToolset.Core.Link
65
}
66
}
67
68
- return new Localization(existingLocalization.Codepage, existingLocalization.Culture, variables, controls);
68
+ return new Localization(existingLocalization.Codepage ?? localization.Codepage, existingLocalization.SummaryInformationCodepage ?? localization.SummaryInformationCodepage, existingLocalization.Culture, variables, controls);
69
}
70
}
71
}
src/WixToolset.Core/Linker.cs
+1
-1
@@ -180,7 +180,7 @@ namespace WixToolset.Core
180
181
// Create a new section to hold the linked content. Start with the entry section's
182
// metadata.
183
- var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type, find.EntrySection.Codepage);
183
+ var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type);
184
185
var sectionCount = 0;
186
src/WixToolset.Core/LocalizationParser.cs
+6
-14
@@ -86,7 +86,8 @@ namespace WixToolset.Core
86
private static Localization ParseWixLocalizationElement(IMessaging messaging, XElement node)
87
{
88
var sourceLineNumbers = SourceLineNumber.CreateFromXObject(node);
89
- var codepage = -1;
89
+ int? codepage = null;
90
+ int? summaryInformationCodepage = null;
91
string culture = null;
92
93
foreach (var attrib in node.Attributes())
@@ -98,6 +99,9 @@ namespace WixToolset.Core
99
case "Codepage":
100
codepage = Common.GetValidCodePage(attrib.Value, true, false, sourceLineNumbers);
101
break;
102
+ case "SummaryInformationCodepage":
103
+ summaryInformationCodepage = Common.GetValidCodePage(attrib.Value, true, false, sourceLineNumbers);
104
+ break;
105
case "Culture":
106
culture = attrib.Value;
107
break;
@@ -143,7 +147,7 @@ namespace WixToolset.Core
147
}
148
}
149
146
- return messaging.EncounteredError ? null : new Localization(codepage, culture, variables, localizedControls);
150
+ return messaging.EncounteredError ? null : new Localization(codepage, summaryInformationCodepage, culture, variables, localizedControls);
151
}
152
153
/// <summary>
@@ -254,24 +258,12 @@ namespace WixToolset.Core
258
break;
259
case "RightToLeft":
260
rightToLeft = YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib);
257
- //if (YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib))
258
- //{
259
- // attribs |= MsiInterop.MsidbControlAttributesRTLRO;
260
- //}
261
break;
262
case "RightAligned":
263
rightAligned = YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib);
264
- //if (YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib))
265
- //{
266
- // attribs |= MsiInterop.MsidbControlAttributesRightAligned;
267
- //}
264
break;
265
case "LeftScroll":
266
leftScroll = YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib);
271
- //if (YesNoType.Yes == Common.GetAttributeYesNoValue(messaging, sourceLineNumbers, attrib))
272
- //{
273
- // attribs |= MsiInterop.MsidbControlAttributesLeftScroll;
274
- //}
267
break;
268
default:
269
Common.UnexpectedAttribute(messaging, sourceLineNumbers, attrib);
src/WixToolset.Core/ResolveResult.cs
+5
-1
@@ -8,7 +8,11 @@ namespace WixToolset.Core
8
9
internal class ResolveResult : IResolveResult
10
{
11
- public int Codepage { get; set; }
11
+ public int? Codepage { get; set; }
12
+
13
+ public int? SummaryInformationCodepage { get; set; }
14
+
15
+ public int? PackageLcid { get; set; }
16
17
public IEnumerable<IDelayedField> DelayedFields { get; set; }
18
src/WixToolset.Core/Resolver.cs
+50
-31
@@ -4,6 +4,7 @@ namespace WixToolset.Core
4
{
5
using System;
6
using System.Collections.Generic;
7
+ using System.Globalization;
8
using System.Linq;
9
using WixToolset.Core.Bind;
10
using WixToolset.Data;
@@ -22,26 +23,12 @@ namespace WixToolset.Core
23
this.ServiceProvider = serviceProvider;
24
25
this.Messaging = serviceProvider.GetService<IMessaging>();
25
-
26
- this.VariableResolver = serviceProvider.GetService<IVariableResolver>();
26
}
27
28
private IServiceProvider ServiceProvider { get; }
29
30
private IMessaging Messaging { get; }
31
33
- private IVariableResolver VariableResolver { get; set; }
34
-
35
- public IEnumerable<IBindPath> BindPaths { get; set; }
36
-
37
- public string IntermediateFolder { get; set; }
38
-
39
- public Intermediate IntermediateRepresentation { get; set; }
40
-
41
- public IEnumerable<Localization> Localizations { get; set; }
42
-
43
- public IEnumerable<string> FilterCultures { get; set; }
44
-
32
public IResolveResult Resolve(IResolveContext context)
33
{
34
foreach (var extension in context.Extensions)
@@ -52,11 +39,26 @@ namespace WixToolset.Core
39
ResolveResult resolveResult = null;
40
try
41
{
55
- var codepage = this.PopulateVariableResolver(context);
42
+ var filteredLocalizations = FilterLocalizations(context);
43
+
44
+ var variableResolver = this.CreateVariableResolver(context, filteredLocalizations);
45
+
46
+ this.LocalizeUI(variableResolver, context.IntermediateRepresentation);
47
+
48
+ resolveResult = this.DoResolve(context, variableResolver);
49
+
50
+ var primaryLocalization = filteredLocalizations.FirstOrDefault();
51
+
52
+ if (primaryLocalization != null)
53
+ {
54
+ this.TryGetCultureInfo(primaryLocalization.Culture, out var cultureInfo);
55
57
- this.LocalizeUI(context);
56
+ resolveResult.Codepage = primaryLocalization.Codepage ?? cultureInfo?.TextInfo.ANSICodePage;
57
59
- resolveResult = this.DoResolve(context, codepage);
58
+ resolveResult.SummaryInformationCodepage = primaryLocalization.SummaryInformationCodepage ?? primaryLocalization.Codepage ?? cultureInfo?.TextInfo.ANSICodePage;
59
+
60
+ resolveResult.PackageLcid = cultureInfo?.LCID;
61
+ }
62
}
63
finally
64
{
@@ -69,7 +71,7 @@ namespace WixToolset.Core
71
return resolveResult;
72
}
73
72
- private ResolveResult DoResolve(IResolveContext context, int? codepage)
74
+ private ResolveResult DoResolve(IResolveContext context, IVariableResolver variableResolver)
75
{
76
var buildingPatch = context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch);
77
@@ -80,7 +82,7 @@ namespace WixToolset.Core
82
var command = new ResolveFieldsCommand();
83
command.Messaging = this.Messaging;
84
command.BuildingPatch = buildingPatch;
83
- command.VariableResolver = this.VariableResolver;
85
+ command.VariableResolver = variableResolver;
86
command.BindPaths = context.BindPaths;
87
command.Extensions = context.Extensions;
88
command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
@@ -118,7 +120,6 @@ namespace WixToolset.Core
120
121
return new ResolveResult
122
{
121
- Codepage = codepage.HasValue ? codepage.Value : -1,
123
ExpectedEmbeddedFiles = expectedEmbeddedFiles,
124
DelayedFields = delayedFields,
125
IntermediateRepresentation = context.IntermediateRepresentation
@@ -128,13 +129,13 @@ namespace WixToolset.Core
129
/// <summary>
130
/// Localize dialogs and controls.
131
/// </summary>
131
- private void LocalizeUI(IResolveContext context)
132
+ private void LocalizeUI(IVariableResolver variableResolver, Intermediate intermediate)
133
{
133
- foreach (var section in context.IntermediateRepresentation.Sections)
134
+ foreach (var section in intermediate.Sections)
135
{
136
foreach (var symbol in section.Symbols.OfType<DialogSymbol>())
137
{
137
- if (this.VariableResolver.TryGetLocalizedControl(symbol.Id.Id, null, out var localizedControl))
138
+ if (variableResolver.TryGetLocalizedControl(symbol.Id.Id, null, out var localizedControl))
139
{
140
if (CompilerConstants.IntegerNotSet != localizedControl.X)
141
{
@@ -169,7 +170,7 @@ namespace WixToolset.Core
170
171
foreach (var symbol in section.Symbols.OfType<ControlSymbol>())
172
{
172
- if (this.VariableResolver.TryGetLocalizedControl(symbol.DialogRef, symbol.Control, out var localizedControl))
173
+ if (variableResolver.TryGetLocalizedControl(symbol.DialogRef, symbol.Control, out var localizedControl))
174
{
175
if (CompilerConstants.IntegerNotSet != localizedControl.X)
176
{
@@ -204,24 +205,42 @@ namespace WixToolset.Core
205
}
206
}
207
207
- private int? PopulateVariableResolver(IResolveContext context)
208
+ private IVariableResolver CreateVariableResolver(IResolveContext context, IEnumerable<Localization> filteredLocalizations)
209
{
209
- var localizations = FilterLocalizations(context);
210
- var codepage = localizations.FirstOrDefault()?.Codepage;
210
+ var variableResolver = this.ServiceProvider.GetService<IVariableResolver>();
211
212
- foreach (var localization in localizations)
212
+ foreach (var localization in filteredLocalizations)
213
{
214
- this.VariableResolver.AddLocalization(localization);
214
+ variableResolver.AddLocalization(localization);
215
}
216
217
// Gather all the wix variables.
218
var wixVariableSymbols = context.IntermediateRepresentation.Sections.SelectMany(s => s.Symbols).OfType<WixVariableSymbol>();
219
foreach (var symbol in wixVariableSymbols)
220
{
221
- this.VariableResolver.AddVariable(symbol.SourceLineNumbers, symbol.Id.Id, symbol.Value, symbol.Overridable);
221
+ variableResolver.AddVariable(symbol.SourceLineNumbers, symbol.Id.Id, symbol.Value, symbol.Overridable);
222
+ }
223
+
224
+ return variableResolver;
225
+ }
226
+
227
+ private bool TryGetCultureInfo(string culture, out CultureInfo cultureInfo)
228
+ {
229
+ cultureInfo = null;
230
+
231
+ if (!String.IsNullOrEmpty(culture))
232
+ {
233
+ try
234
+ {
235
+ cultureInfo = new CultureInfo(culture, useUserOverride: false);
236
+ }
237
+ catch
238
+ {
239
+ this.Messaging.Write("");
240
+ }
241
}
242
224
- return codepage;
243
+ return cultureInfo != null;
244
}
245
246
private static IEnumerable<Localization> FilterLocalizations(IResolveContext context)
src/test/WixToolsetTest.CoreIntegration/LanguageFixture.cs
new
+155
@@ -0,0 +1,155 @@
1
+// 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.
2
+
3
+namespace WixToolsetTest.CoreIntegration
4
+{
5
+ using System.IO;
6
+ using System.Linq;
7
+ using WixBuildTools.TestSupport;
8
+ using WixToolset.Core.TestPackage;
9
+ using WixToolset.Data;
10
+ using WixToolset.Data.Symbols;
11
+ using Xunit;
12
+
13
+ public class LanguageFixture
14
+ {
15
+ [Fact]
16
+ public void CanBuildWithDefaultProductLanguage()
17
+ {
18
+ var folder = TestData.Get(@"TestData", "Language");
19
+
20
+ using (var fs = new DisposableFileSystem())
21
+ {
22
+ var baseFolder = fs.GetFolder();
23
+
24
+ var result = WixRunner.Execute(new[]
25
+ {
26
+ "build",
27
+ Path.Combine(folder, "Package.wxs"),
28
+ "-loc", Path.Combine(folder, "Package.wxl"),
29
+ "-bindpath", Path.Combine(folder, "data"),
30
+ "-intermediateFolder", Path.Combine(baseFolder, "obj"),
31
+ "-o", Path.Combine(baseFolder, @"bin\test.msi")
32
+ });
33
+
34
+ result.AssertSuccess();
35
+
36
+ var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
37
+ var section = intermediate.Sections.Single();
38
+
39
+ var propertySymbol = section.Symbols.OfType<PropertySymbol>().Single(p => p.Id.Id == "ProductLanguage");
40
+ Assert.Equal("0", propertySymbol.Value);
41
+
42
+ var summaryPlatform = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage);
43
+ Assert.Equal("Intel;0", summaryPlatform.Value);
44
+
45
+ var summaryCodepage = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.Codepage);
46
+ Assert.Equal("1252", summaryCodepage.Value);
47
+ }
48
+ }
49
+
50
+ [Fact]
51
+ public void CanBuildEnuWxl()
52
+ {
53
+ var folder = TestData.Get(@"TestData", "Language");
54
+
55
+ using (var fs = new DisposableFileSystem())
56
+ {
57
+ var baseFolder = fs.GetFolder();
58
+
59
+ var result = WixRunner.Execute(new[]
60
+ {
61
+ "build",
62
+ Path.Combine(folder, "Package.wxs"),
63
+ "-loc", Path.Combine(folder, "Package.en-us.wxl"),
64
+ "-bindpath", Path.Combine(folder, "data"),
65
+ "-intermediateFolder", Path.Combine(baseFolder, "obj"),
66
+ "-o", Path.Combine(baseFolder, @"bin\test.msi")
67
+ });
68
+
69
+ result.AssertSuccess();
70
+
71
+ var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
72
+ var section = intermediate.Sections.Single();
73
+
74
+ var propertySymbol = section.Symbols.OfType<PropertySymbol>().Single(p => p.Id.Id == "ProductLanguage");
75
+ Assert.Equal("1033", propertySymbol.Value);
76
+
77
+ var summaryPlatform = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage);
78
+ Assert.Equal("Intel;1033", summaryPlatform.Value);
79
+
80
+ var summaryCodepage = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.Codepage);
81
+ Assert.Equal("1252", summaryCodepage.Value);
82
+ }
83
+ }
84
+
85
+ [Fact]
86
+ public void CanBuildJpnWxl()
87
+ {
88
+ var folder = TestData.Get(@"TestData", "Language");
89
+
90
+ using (var fs = new DisposableFileSystem())
91
+ {
92
+ var baseFolder = fs.GetFolder();
93
+
94
+ var result = WixRunner.Execute(new[]
95
+ {
96
+ "build",
97
+ Path.Combine(folder, "Package.wxs"),
98
+ "-loc", Path.Combine(folder, "Package.ja-jp.wxl"),
99
+ "-bindpath", Path.Combine(folder, "data"),
100
+ "-intermediateFolder", Path.Combine(baseFolder, "obj"),
101
+ "-o", Path.Combine(baseFolder, @"bin\test.msi")
102
+ });
103
+
104
+ result.AssertSuccess();
105
+
106
+ var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
107
+ var section = intermediate.Sections.Single();
108
+
109
+ var propertySymbol = section.Symbols.OfType<PropertySymbol>().Single(p => p.Id.Id == "ProductLanguage");
110
+ Assert.Equal("1041", propertySymbol.Value);
111
+
112
+ var summaryPlatform = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage);
113
+ Assert.Equal("Intel;1041", summaryPlatform.Value);
114
+
115
+ var summaryCodepage = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.Codepage);
116
+ Assert.Equal("932", summaryCodepage.Value);
117
+ }
118
+ }
119
+
120
+ [Fact]
121
+ public void CanBuildJpnWxlWithEnuSummaryInfo()
122
+ {
123
+ var folder = TestData.Get(@"TestData", "Language");
124
+
125
+ using (var fs = new DisposableFileSystem())
126
+ {
127
+ var baseFolder = fs.GetFolder();
128
+
129
+ var result = WixRunner.Execute(new[]
130
+ {
131
+ "build",
132
+ Path.Combine(folder, "Package.wxs"),
133
+ "-loc", Path.Combine(folder, "PackageWithEnSummaryInfo.ja-jp.wxl"),
134
+ "-bindpath", Path.Combine(folder, "data"),
135
+ "-intermediateFolder", Path.Combine(baseFolder, "obj"),
136
+ "-o", Path.Combine(baseFolder, @"bin\test.msi")
137
+ });
138
+
139
+ result.AssertSuccess();
140
+
141
+ var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wixpdb"));
142
+ var section = intermediate.Sections.Single();
143
+
144
+ var propertySymbol = section.Symbols.OfType<PropertySymbol>().Single(p => p.Id.Id == "ProductLanguage");
145
+ Assert.Equal("1041", propertySymbol.Value);
146
+
147
+ var summaryPlatform = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage);
148
+ Assert.Equal("Intel;1041", summaryPlatform.Value);
149
+
150
+ var summaryCodepage = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.Codepage);
151
+ Assert.Equal("1252", summaryCodepage.Value);
152
+ }
153
+ }
154
+ }
155
+}
src/test/WixToolsetTest.CoreIntegration/LinkerFixture.cs
+2
-2
@@ -19,8 +19,8 @@ namespace WixToolsetTest.CoreIntegration
19
[Fact]
20
public void MustCompileBeforeLinking()
21
{
22
- var intermediate1 = new Intermediate("TestIntermediate1", new[] { new IntermediateSection("test1", SectionType.Product, 65001) }, null);
23
- var intermediate2 = new Intermediate("TestIntermediate2", new[] { new IntermediateSection("test2", SectionType.Fragment, 65001) }, null);
22
+ var intermediate1 = new Intermediate("TestIntermediate1", new[] { new IntermediateSection("test1", SectionType.Product) }, null);
23
+ var intermediate2 = new Intermediate("TestIntermediate2", new[] { new IntermediateSection("test2", SectionType.Fragment) }, null);
24
var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider();
25
26
var listener = new TestMessageListener();
src/test/WixToolsetTest.CoreIntegration/ParseFixture.cs
+1
-1
@@ -16,7 +16,7 @@ namespace WixToolsetTest.CoreIntegration
16
public void GeneratesCorrectCustomActionIdentifiers()
17
{
18
var serviceProvider = WixToolsetServiceProviderFactory.CreateServiceProvider();
19
- var section = new IntermediateSection("section", SectionType.Fragment, 0);
19
+ var section = new IntermediateSection("section", SectionType.Fragment);
20
var parseHelper = serviceProvider.GetService<IParseHelper>();
21
22
parseHelper.CreateCustomActionReference(null, section, "CustomAction32", Platform.X86, CustomActionPlatforms.X86);
src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.en-us.wxl
new
+7
@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
3
+
4
+ <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
5
+ <String Id="FeatureTitle">MsiPackage</String>
6
+
7
+</WixLocalization>
src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.ja-jp.wxl
new
+7
@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="ja-JP">
3
+
4
+ <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
5
+ <String Id="FeatureTitle">MsiPackage</String>
6
+
7
+</WixLocalization>
src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxl
new
+7
@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl">
3
+
4
+ <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
5
+ <String Id="FeatureTitle">MsiPackage</String>
6
+
7
+</WixLocalization>
src/test/WixToolsetTest.CoreIntegration/TestData/Language/Package.wxs
new
+16
@@ -0,0 +1,16 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2
+ <Package Name="~DefaultLanguagePackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+
4
+ <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
5
+
6
+ <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
7
+ <Component Directory="INSTALLFOLDER">
8
+ <File Source="test.txt" />
9
+ </Component>
10
+ </Feature>
11
+ </Package>
12
+
13
+ <Fragment>
14
+ <Directory Id="INSTALLFOLDER" Name="ProgramFilesFolder:\MsiPackage" />
15
+ </Fragment>
16
+</Wix>
src/test/WixToolsetTest.CoreIntegration/TestData/Language/PackageWithEnSummaryInfo.ja-jp.wxl
new
+7
@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" SummaryInformationCodepage="1252" Culture="ja-JP">
3
+
4
+ <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
5
+ <String Id="FeatureTitle">MsiPackage</String>
6
+
7
+</WixLocalization>
src/test/WixToolsetTest.CoreIntegration/TestData/Language/data/test.txt
new
+1
@@ -0,0 +1 @@
1
+This is test.txt.
\ No newline at end of file
src/test/WixToolsetTest.CoreIntegration/VariableResolverFixture.cs
+1
-1
@@ -25,7 +25,7 @@ namespace WixToolsetTest.CoreIntegration
25
{ "ProductNameEditionVersion", new BindVariable() { Id = "ProductNameEditionVersion", Value = "!(loc.ProductNameEdition) v1.2.3" } },
26
};
27
28
- var localization = new Localization(0, "x-none", variables, new Dictionary<string,LocalizedControl>());
28
+ var localization = new Localization(0, null, "x-none", variables, new Dictionary<string,LocalizedControl>());
29
30
variableResolver.AddLocalization(localization);
31