aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-04-02 14:41:49 -0700
committerRob Mensching <rob@firegiant.com>2021-04-02 14:58:00 -0700
commit4449fcc5b8d104817c67135229682c66c3d892ca (patch)
tree327f617de2e296ddb4e62c50bf07ec8b5dcf0a3e /src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
parent9cca339473d77c7036035f949239f5231c325968 (diff)
downloadwix-4449fcc5b8d104817c67135229682c66c3d892ca.tar.gz
wix-4449fcc5b8d104817c67135229682c66c3d892ca.tar.bz2
wix-4449fcc5b8d104817c67135229682c66c3d892ca.zip
Enable codepages and languages to be set via .wxl files
Fixes wixtoolset/issues#5801
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs127
1 files changed, 71 insertions, 56 deletions
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
37 37
38 this.CabbingThreadCount = context.CabbingThreadCount; 38 this.CabbingThreadCount = context.CabbingThreadCount;
39 this.CabCachePath = context.CabCachePath; 39 this.CabCachePath = context.CabCachePath;
40 this.Codepage = context.Codepage;
41 this.DefaultCompressionLevel = context.DefaultCompressionLevel; 40 this.DefaultCompressionLevel = context.DefaultCompressionLevel;
42 this.DelayedFields = context.DelayedFields; 41 this.DelayedFields = context.DelayedFields;
43 this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles; 42 this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles;
@@ -47,6 +46,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
47 this.OutputPath = context.OutputPath; 46 this.OutputPath = context.OutputPath;
48 this.OutputPdbPath = context.PdbPath; 47 this.OutputPdbPath = context.PdbPath;
49 this.PdbType = context.PdbType; 48 this.PdbType = context.PdbType;
49 this.ResolvedCodepage = context.ResolvedCodepage;
50 this.ResolvedSummaryInformationCodepage = context.ResolvedSummaryInformationCodepage;
51 this.ResolvedLcid = context.ResolvedLcid;
50 this.SuppressLayout = context.SuppressLayout; 52 this.SuppressLayout = context.SuppressLayout;
51 53
52 this.SubStorages = subStorages; 54 this.SubStorages = subStorages;
@@ -67,8 +69,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
67 69
68 private IPathResolver PathResolver { get; } 70 private IPathResolver PathResolver { get; }
69 71
70 private int Codepage { get; }
71
72 private int CabbingThreadCount { get; } 72 private int CabbingThreadCount { get; }
73 73
74 private string CabCachePath { get; } 74 private string CabCachePath { get; }
@@ -95,6 +95,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
95 95
96 private string OutputPdbPath { get; } 96 private string OutputPdbPath { get; }
97 97
98 private int? ResolvedCodepage { get; }
99
100 private int? ResolvedSummaryInformationCodepage { get; }
101
102 private int? ResolvedLcid { get; }
103
98 private bool SuppressAddingValidationRows { get; } 104 private bool SuppressAddingValidationRows { get; }
99 105
100 private bool SuppressLayout { get; } 106 private bool SuppressLayout { get; }
@@ -111,21 +117,22 @@ namespace WixToolset.Core.WindowsInstaller.Bind
111 117
112 public IBindResult Execute() 118 public IBindResult Execute()
113 { 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))
115 { 121 {
116 this.Messaging.Write(ErrorMessages.IntermediatesMustBeResolved(this.Intermediate.Id)); 122 this.Messaging.Write(ErrorMessages.IntermediatesMustBeResolved(this.Intermediate.Id));
117 } 123 }
118 124
119 var section = this.Intermediate.Sections.Single(); 125 var section = this.Intermediate.Sections.Single();
120 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
121 var fileTransfers = new List<IFileTransfer>(); 131 var fileTransfers = new List<IFileTransfer>();
122 var trackedFiles = new List<ITrackedFile>(); 132 var trackedFiles = new List<ITrackedFile>();
123 133
124 var containsMergeModules = false; 134 var containsMergeModules = false;
125 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
129 // Load standard tables, authored custom tables, and extension custom tables. 136 // Load standard tables, authored custom tables, and extension custom tables.
130 TableDefinitionCollection tableDefinitions; 137 TableDefinitionCollection tableDefinitions;
131 { 138 {
@@ -135,7 +142,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
135 tableDefinitions = command.TableDefinitions; 142 tableDefinitions = command.TableDefinitions;
136 } 143 }
137 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.
139 bool compressed; 160 bool compressed;
140 bool longNames; 161 bool longNames;
141 int installerVersion; 162 int installerVersion;
@@ -144,7 +165,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
144 { 165 {
145 var branding = this.ServiceProvider.GetService<IWixBranding>(); 166 var branding = this.ServiceProvider.GetService<IWixBranding>();
146 167
147 var command = new BindSummaryInfoCommand(section, this.WindowsInstallerBackendHelper, branding); 168 var command = new BindSummaryInfoCommand(section, this.ResolvedSummaryInformationCodepage, productLanguage, this.WindowsInstallerBackendHelper, branding);
148 command.Execute(); 169 command.Execute();
149 170
150 compressed = command.Compressed; 171 compressed = command.Compressed;
@@ -154,49 +175,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
154 modularizationSuffix = command.ModularizationSuffix; 175 modularizationSuffix = command.ModularizationSuffix;
155 } 176 }
156 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
200 // Sequence all the actions. 178 // Sequence all the actions.
201 { 179 {
202 var command = new SequenceActionsCommand(this.Messaging, section); 180 var command = new SequenceActionsCommand(this.Messaging, section);
@@ -415,7 +393,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
415 // Time to create the WindowsInstallerData object. Try to put as much above here as possible, updating the IR is better. 393 // Time to create the WindowsInstallerData object. Try to put as much above here as possible, updating the IR is better.
416 WindowsInstallerData data; 394 WindowsInstallerData data;
417 { 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);
419 data = command.Execute(); 397 data = command.Execute();
420 } 398 }
421 399
@@ -450,7 +428,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
450 428
451 if (SectionType.Patch == section.Type && this.DeltaBinaryPatch) 429 if (SectionType.Patch == section.Type && this.DeltaBinaryPatch)
452 { 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());
454 command.Execute(); 432 command.Execute();
455 } 433 }
456 434
@@ -508,7 +486,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
508 var trackMsi = this.WindowsInstallerBackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final); 486 var trackMsi = this.WindowsInstallerBackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final);
509 trackedFiles.Add(trackMsi); 487 trackedFiles.Add(trackMsi);
510 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);
512 command.Execute(); 490 command.Execute();
513 491
514 trackedFiles.AddRange(command.GeneratedTemporaryFiles); 492 trackedFiles.AddRange(command.GeneratedTemporaryFiles);
@@ -532,7 +510,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
532 if (this.Messaging.EncounteredError) 510 if (this.Messaging.EncounteredError)
533 { 511 {
534 return null; 512 return null;
535 } 513 }
536 514
537 // Validate the output if there are CUBe files and we're not explicitly suppressing validation. 515 // Validate the output if there are CUBe files and we're not explicitly suppressing validation.
538 if (this.CubeFiles != null && !this.SuppressValidation) 516 if (this.CubeFiles != null && !this.SuppressValidation)
@@ -575,6 +553,43 @@ namespace WixToolset.Core.WindowsInstaller.Bind
575 return result; 553 return result;
576 } 554 }
577 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
578 private WixOutput CreateWixout(List<ITrackedFile> trackedFiles, Intermediate intermediate, WindowsInstallerData data) 593 private WixOutput CreateWixout(List<ITrackedFile> trackedFiles, Intermediate intermediate, WindowsInstallerData data)
579 { 594 {
580 WixOutput wixout; 595 WixOutput wixout;