diff options
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs')
-rw-r--r-- | src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | 739 |
1 files changed, 224 insertions, 515 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index 5a61b63c..30a19a4b 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | |||
@@ -3,21 +3,15 @@ | |||
3 | namespace WixToolset.Core.WindowsInstaller.Bind | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | ||
7 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
8 | using System.Diagnostics; | ||
9 | using System.Globalization; | ||
10 | using System.IO; | 7 | using System.IO; |
11 | using System.Linq; | 8 | using System.Linq; |
12 | using WixToolset.Bind; | ||
13 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
14 | using WixToolset.Core.WindowsInstaller.Databases; | ||
15 | using WixToolset.Data; | 10 | using WixToolset.Data; |
16 | using WixToolset.Data.Bind; | 11 | using WixToolset.Data.Bind; |
17 | using WixToolset.Data.Rows; | 12 | using WixToolset.Data.Tuples; |
18 | using WixToolset.Extensibility; | 13 | using WixToolset.Extensibility; |
19 | using WixToolset.Extensibility.Services; | 14 | using WixToolset.Extensibility.Services; |
20 | using WixToolset.Msi; | ||
21 | 15 | ||
22 | /// <summary> | 16 | /// <summary> |
23 | /// Binds a databse. | 17 | /// Binds a databse. |
@@ -25,11 +19,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
25 | internal class BindDatabaseCommand | 19 | internal class BindDatabaseCommand |
26 | { | 20 | { |
27 | // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. | 21 | // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. |
28 | private static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); | 22 | internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); |
29 | 23 | ||
30 | public BindDatabaseCommand(IBindContext context, Validator validator) | 24 | public BindDatabaseCommand(IBindContext context, Validator validator) |
31 | { | 25 | { |
32 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 26 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
33 | 27 | ||
34 | this.BindPaths = context.BindPaths; | 28 | this.BindPaths = context.BindPaths; |
35 | this.CabbingThreadCount = context.CabbingThreadCount; | 29 | this.CabbingThreadCount = context.CabbingThreadCount; |
@@ -73,8 +67,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
73 | 67 | ||
74 | private Intermediate Intermediate { get; } | 68 | private Intermediate Intermediate { get; } |
75 | 69 | ||
76 | private Output Output { get; } | ||
77 | |||
78 | private string OutputPath { get; } | 70 | private string OutputPath { get; } |
79 | 71 | ||
80 | private bool SuppressAddingValidationRows { get; } | 72 | private bool SuppressAddingValidationRows { get; } |
@@ -95,22 +87,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
95 | 87 | ||
96 | public void Execute() | 88 | public void Execute() |
97 | { | 89 | { |
98 | this.Intermediate.Save(this.OutputPath); | 90 | var section = this.Intermediate.Sections.Single(); |
99 | #if FINISH | ||
100 | List<FileTransfer> fileTransfers = new List<FileTransfer>(); | ||
101 | 91 | ||
102 | HashSet<string> suppressedTableNames = new HashSet<string>(); | 92 | var fileTransfers = new List<FileTransfer>(); |
103 | 93 | ||
104 | // If there are any fields to resolve later, create the cache to populate during bind. | 94 | var suppressedTableNames = new HashSet<string>(); |
105 | IDictionary<string, string> variableCache = null; | ||
106 | if (this.DelayedFields.Any()) | ||
107 | { | ||
108 | variableCache = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); | ||
109 | } | ||
110 | 95 | ||
111 | this.LocalizeUI(this.Output.Tables); | 96 | // If there are any fields to resolve later, create the cache to populate during bind. |
97 | var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null; | ||
112 | 98 | ||
113 | this.Output = CreateOutputFromIR(this.Intermediate); | 99 | this.LocalizeUI(section); |
114 | 100 | ||
115 | // Process the summary information table before the other tables. | 101 | // Process the summary information table before the other tables. |
116 | bool compressed; | 102 | bool compressed; |
@@ -118,8 +104,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
118 | int installerVersion; | 104 | int installerVersion; |
119 | string modularizationGuid; | 105 | string modularizationGuid; |
120 | { | 106 | { |
121 | BindSummaryInfoCommand command = new BindSummaryInfoCommand(); | 107 | var command = new BindSummaryInfoCommand(section); |
122 | command.Output = this.Output; | ||
123 | command.Execute(); | 108 | command.Execute(); |
124 | 109 | ||
125 | compressed = command.Compressed; | 110 | compressed = command.Compressed; |
@@ -128,42 +113,61 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
128 | modularizationGuid = command.ModularizationGuid; | 113 | modularizationGuid = command.ModularizationGuid; |
129 | } | 114 | } |
130 | 115 | ||
131 | // Stop processing if an error previously occurred. | 116 | // Add binder variables for all properties. |
132 | if (Messaging.Instance.EncounteredError) | 117 | if (SectionType.Product == section.Type || variableCache != null) |
133 | { | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | // Modularize identifiers and add tables with real streams to the import tables. | ||
138 | if (OutputType.Module == this.Output.Type) | ||
139 | { | 118 | { |
140 | // Gather all the suppress modularization identifiers | 119 | foreach (var propertyRow in section.Tuples.OfType<PropertyTuple>()) |
141 | HashSet<string> suppressModularizationIdentifiers = null; | ||
142 | Table wixSuppressModularizationTable = this.Output.Tables["WixSuppressModularization"]; | ||
143 | if (null != wixSuppressModularizationTable) | ||
144 | { | 120 | { |
145 | suppressModularizationIdentifiers = new HashSet<string>(wixSuppressModularizationTable.Rows.Select(row => (string)row[0])); | 121 | // Set the ProductCode if it is to be generated. |
146 | } | 122 | if ("ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) |
123 | { | ||
124 | propertyRow.Value = Common.GenerateGuid(); | ||
147 | 125 | ||
148 | foreach (Table table in this.Output.Tables) | 126 | #if TODO_FIX_INSTANCE_TRANSFORM |
149 | { | 127 | // Update the target ProductCode in any instance transforms. |
150 | table.Modularize(modularizationGuid, suppressModularizationIdentifiers); | 128 | foreach (SubStorage subStorage in this.Output.SubStorages) |
129 | { | ||
130 | Output subStorageOutput = subStorage.Data; | ||
131 | if (OutputType.Transform != subStorageOutput.Type) | ||
132 | { | ||
133 | continue; | ||
134 | } | ||
135 | |||
136 | Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; | ||
137 | foreach (Row row in instanceSummaryInformationTable.Rows) | ||
138 | { | ||
139 | if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) | ||
140 | { | ||
141 | row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | #endif | ||
147 | } | ||
148 | |||
149 | // Add the property name and value to the variableCache. | ||
150 | if (variableCache != null) | ||
151 | { | ||
152 | var key = String.Concat("property.", propertyRow.Property); | ||
153 | variableCache[key] = propertyRow.Value; | ||
154 | } | ||
151 | } | 155 | } |
152 | } | 156 | } |
153 | 157 | ||
154 | // This must occur after all variables and source paths have been resolved and after modularization. | 158 | // Sequence all the actions. |
155 | List<FileFacade> fileFacades; | ||
156 | { | 159 | { |
157 | GetFileFacadesCommand command = new GetFileFacadesCommand(); | 160 | var command = new SequenceActionsCommand(section); |
158 | command.FileTable = this.Output.Tables["File"]; | 161 | command.Messaging = Messaging.Instance; |
159 | command.WixFileTable = this.Output.Tables["WixFile"]; | ||
160 | command.WixDeltaPatchFileTable = this.Output.Tables["WixDeltaPatchFile"]; | ||
161 | command.WixDeltaPatchSymbolPathsTable = this.Output.Tables["WixDeltaPatchSymbolPaths"]; | ||
162 | command.Execute(); | 162 | command.Execute(); |
163 | } | ||
163 | 164 | ||
164 | fileFacades = command.FileFacades; | 165 | { |
166 | var command = new CreateSpecialPropertiesCommand(section); | ||
167 | command.Execute(); | ||
165 | } | 168 | } |
166 | 169 | ||
170 | #if TODO_FINISH_PATCH | ||
167 | ////if (OutputType.Patch == this.Output.Type) | 171 | ////if (OutputType.Patch == this.Output.Type) |
168 | ////{ | 172 | ////{ |
169 | //// foreach (SubStorage substorage in this.Output.SubStorages) | 173 | //// foreach (SubStorage substorage in this.Output.SubStorages) |
@@ -183,87 +187,72 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
183 | //// this.MergeUnrealTables(transform.Tables); | 187 | //// this.MergeUnrealTables(transform.Tables); |
184 | //// } | 188 | //// } |
185 | ////} | 189 | ////} |
186 | 190 | #endif | |
187 | { | ||
188 | CreateSpecialPropertiesCommand command = new CreateSpecialPropertiesCommand(); | ||
189 | command.PropertyTable = this.Output.Tables["Property"]; | ||
190 | command.WixPropertyTable = this.Output.Tables["WixProperty"]; | ||
191 | command.Execute(); | ||
192 | } | ||
193 | 191 | ||
194 | if (Messaging.Instance.EncounteredError) | 192 | if (Messaging.Instance.EncounteredError) |
195 | { | 193 | { |
196 | return; | 194 | return; |
197 | } | 195 | } |
198 | 196 | ||
199 | // Add binder variables for all properties. | 197 | Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); |
200 | Table propertyTable = this.Output.Tables["Property"]; | 198 | |
201 | if (null != propertyTable) | 199 | // This must occur after all variables and source paths have been resolved. |
200 | List<FileFacade> fileFacades; | ||
202 | { | 201 | { |
203 | foreach (PropertyRow propertyRow in propertyTable.Rows) | 202 | var command = new GetFileFacadesCommand(section); |
204 | { | 203 | command.Execute(); |
205 | // Set the ProductCode if it is to be generated. | ||
206 | if (OutputType.Product == this.Output.Type && "ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) | ||
207 | { | ||
208 | propertyRow.Value = Common.GenerateGuid(); | ||
209 | 204 | ||
210 | // Update the target ProductCode in any instance transforms. | 205 | fileFacades = command.FileFacades; |
211 | foreach (SubStorage subStorage in this.Output.SubStorages) | 206 | } |
212 | { | ||
213 | Output subStorageOutput = subStorage.Data; | ||
214 | if (OutputType.Transform != subStorageOutput.Type) | ||
215 | { | ||
216 | continue; | ||
217 | } | ||
218 | 207 | ||
219 | Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; | 208 | // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules). |
220 | foreach (Row row in instanceSummaryInformationTable.Rows) | 209 | { |
221 | { | 210 | var command = new ExtractEmbeddedFilesCommand(this.ExpectedEmbeddedFiles); |
222 | if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) | 211 | command.Execute(); |
223 | { | 212 | } |
224 | row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | 213 | ||
231 | // Add the property name and value to the variableCache. | 214 | // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table). |
232 | if (null != variableCache) | 215 | { |
233 | { | 216 | var command = new UpdateFileFacadesCommand(section); |
234 | string key = String.Concat("property.", Common.Demodularize(this.Output.Type, modularizationGuid, propertyRow.Property)); | 217 | command.FileFacades = fileFacades; |
235 | variableCache[key] = propertyRow.Value; | 218 | command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); |
236 | } | 219 | command.OverwriteHash = true; |
237 | } | 220 | command.TableDefinitions = this.TableDefinitions; |
221 | command.VariableCache = variableCache; | ||
222 | command.Execute(); | ||
238 | } | 223 | } |
239 | 224 | ||
240 | // Extract files that come from cabinet files (this does not extract files from merge modules). | 225 | // Now that the variable cache is populated, resolve any delayed fields. |
226 | if (this.DelayedFields.Any()) | ||
241 | { | 227 | { |
242 | ExtractEmbeddedFilesCommand command = new ExtractEmbeddedFilesCommand(); | 228 | var command = new ResolveDelayedFieldsCommand(this.DelayedFields, variableCache); |
243 | command.FilesWithEmbeddedFiles = this.ExpectedEmbeddedFiles; | ||
244 | command.Execute(); | 229 | command.Execute(); |
245 | } | 230 | } |
246 | 231 | ||
247 | if (OutputType.Product == this.Output.Type) | 232 | // Set generated component guids. |
233 | { | ||
234 | var command = new CalculateComponentGuids(section); | ||
235 | command.Execute(); | ||
236 | } | ||
237 | |||
238 | if (SectionType.Product == section.Type) | ||
248 | { | 239 | { |
249 | // Retrieve files and their information from merge modules. | 240 | // Retrieve files and their information from merge modules. |
250 | Table wixMergeTable = this.Output.Tables["WixMerge"]; | 241 | var wixMergeTuples = section.Tuples.OfType<WixMergeTuple>().ToList(); |
251 | 242 | ||
252 | if (null != wixMergeTable) | 243 | if (wixMergeTuples.Any()) |
253 | { | 244 | { |
254 | ExtractMergeModuleFilesCommand command = new ExtractMergeModuleFilesCommand(); | 245 | var command = new ExtractMergeModuleFilesCommand(section, wixMergeTuples); |
255 | command.FileFacades = fileFacades; | 246 | command.FileFacades = fileFacades; |
256 | command.FileTable = this.Output.Tables["File"]; | ||
257 | command.WixFileTable = this.Output.Tables["WixFile"]; | ||
258 | command.WixMergeTable = wixMergeTable; | ||
259 | command.OutputInstallerVersion = installerVersion; | 247 | command.OutputInstallerVersion = installerVersion; |
260 | command.SuppressLayout = this.SuppressLayout; | 248 | command.SuppressLayout = this.SuppressLayout; |
261 | command.TempFilesLocation = this.IntermediateFolder; | 249 | command.IntermediateFolder = this.IntermediateFolder; |
262 | command.Execute(); | 250 | command.Execute(); |
263 | 251 | ||
264 | fileFacades.AddRange(command.MergeModulesFileFacades); | 252 | fileFacades.AddRange(command.MergeModulesFileFacades); |
265 | } | 253 | } |
266 | } | 254 | } |
255 | #if TODO_FINISH_PATCH | ||
267 | else if (OutputType.Patch == this.Output.Type) | 256 | else if (OutputType.Patch == this.Output.Type) |
268 | { | 257 | { |
269 | // Merge transform data into the output object. | 258 | // Merge transform data into the output object. |
@@ -271,6 +260,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
271 | 260 | ||
272 | fileFacades.AddRange(filesFromTransform); | 261 | fileFacades.AddRange(filesFromTransform); |
273 | } | 262 | } |
263 | #endif | ||
274 | 264 | ||
275 | // stop processing if an error previously occurred | 265 | // stop processing if an error previously occurred |
276 | if (Messaging.Instance.EncounteredError) | 266 | if (Messaging.Instance.EncounteredError) |
@@ -278,51 +268,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
278 | return; | 268 | return; |
279 | } | 269 | } |
280 | 270 | ||
281 | Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); | 271 | #if TODO_FIX_INSTANCE_TRANSFORM |
282 | |||
283 | // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table). | ||
284 | { | ||
285 | UpdateFileFacadesCommand command = new UpdateFileFacadesCommand(); | ||
286 | command.FileFacades = fileFacades; | ||
287 | command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); | ||
288 | command.ModularizationGuid = modularizationGuid; | ||
289 | command.Output = this.Output; | ||
290 | command.OverwriteHash = true; | ||
291 | command.TableDefinitions = this.TableDefinitions; | ||
292 | command.VariableCache = variableCache; | ||
293 | command.Execute(); | ||
294 | } | ||
295 | |||
296 | // Set generated component guids. | ||
297 | this.SetComponentGuids(this.Output); | ||
298 | |||
299 | // With the Component Guids set now we can create instance transforms. | 272 | // With the Component Guids set now we can create instance transforms. |
300 | this.CreateInstanceTransforms(this.Output); | 273 | this.CreateInstanceTransforms(this.Output); |
301 | 274 | #endif | |
302 | this.ValidateComponentGuids(this.Output); | ||
303 | |||
304 | this.UpdateControlText(this.Output); | ||
305 | |||
306 | if (this.DelayedFields.Any()) | ||
307 | { | ||
308 | ResolveDelayedFieldsCommand command = new ResolveDelayedFieldsCommand(); | ||
309 | command.OutputType = this.Output.Type; | ||
310 | command.DelayedFields = this.DelayedFields; | ||
311 | command.ModularizationGuid = null; | ||
312 | command.VariableCache = variableCache; | ||
313 | command.Execute(); | ||
314 | } | ||
315 | 275 | ||
316 | // Assign files to media. | 276 | // Assign files to media. |
317 | RowDictionary<MediaRow> assignedMediaRows; | 277 | Dictionary<int, MediaTuple> assignedMediaRows; |
318 | Dictionary<MediaRow, IEnumerable<FileFacade>> filesByCabinetMedia; | 278 | Dictionary<MediaTuple, IEnumerable<FileFacade>> filesByCabinetMedia; |
319 | IEnumerable<FileFacade> uncompressedFiles; | 279 | IEnumerable<FileFacade> uncompressedFiles; |
320 | { | 280 | { |
321 | AssignMediaCommand command = new AssignMediaCommand(); | 281 | var command = new AssignMediaCommand(section); |
322 | command.FilesCompressed = compressed; | ||
323 | command.FileFacades = fileFacades; | 282 | command.FileFacades = fileFacades; |
324 | command.Output = this.Output; | 283 | command.FilesCompressed = compressed; |
325 | command.TableDefinitions = this.TableDefinitions; | ||
326 | command.Execute(); | 284 | command.Execute(); |
327 | 285 | ||
328 | assignedMediaRows = command.MediaRows; | 286 | assignedMediaRows = command.MediaRows; |
@@ -330,15 +288,40 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
330 | uncompressedFiles = command.UncompressedFileFacades; | 288 | uncompressedFiles = command.UncompressedFileFacades; |
331 | } | 289 | } |
332 | 290 | ||
333 | // Update file sequence. | ||
334 | this.UpdateMediaSequences(this.Output.Type, fileFacades, assignedMediaRows); | ||
335 | |||
336 | // stop processing if an error previously occurred | 291 | // stop processing if an error previously occurred |
337 | if (Messaging.Instance.EncounteredError) | 292 | if (Messaging.Instance.EncounteredError) |
338 | { | 293 | { |
339 | return; | 294 | return; |
340 | } | 295 | } |
341 | 296 | ||
297 | // Try to put as much above here as possible, updating the IR is better. | ||
298 | Output output; | ||
299 | { | ||
300 | var command = new CreateOutputFromIRCommand(section, this.TableDefinitions); | ||
301 | command.Execute(); | ||
302 | |||
303 | output = command.Output; | ||
304 | } | ||
305 | |||
306 | // Update file sequence. | ||
307 | { | ||
308 | var command = new UpdateMediaSequencesCommand(output, fileFacades, assignedMediaRows); | ||
309 | command.Execute(); | ||
310 | } | ||
311 | |||
312 | // Modularize identifiers and add tables with real streams to the import tables. | ||
313 | if (OutputType.Module == output.Type) | ||
314 | { | ||
315 | // Gather all the suppress modularization identifiers | ||
316 | var suppressModularizationIdentifiers = new HashSet<string>(section.Tuples.OfType<WixSuppressModularizationTuple>().Select(s => s.WixSuppressModularization)); | ||
317 | |||
318 | foreach (var table in output.Tables) | ||
319 | { | ||
320 | table.Modularize(modularizationGuid, suppressModularizationIdentifiers); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | #if TODO_FINISH_UPDATE | ||
342 | // Extended binder extensions can be called now that fields are resolved. | 325 | // Extended binder extensions can be called now that fields are resolved. |
343 | { | 326 | { |
344 | Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]); | 327 | Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]); |
@@ -372,27 +355,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
372 | command.Execute(); | 355 | command.Execute(); |
373 | } | 356 | } |
374 | } | 357 | } |
358 | #endif | ||
375 | 359 | ||
376 | // stop processing if an error previously occurred | 360 | // Stop processing if an error previously occurred. |
377 | if (Messaging.Instance.EncounteredError) | 361 | if (Messaging.Instance.EncounteredError) |
378 | { | 362 | { |
379 | return; | 363 | return; |
380 | } | 364 | } |
381 | 365 | ||
366 | // Ensure the intermediate folder is created since delta patches will be | ||
367 | // created there. | ||
382 | Directory.CreateDirectory(this.IntermediateFolder); | 368 | Directory.CreateDirectory(this.IntermediateFolder); |
383 | 369 | ||
384 | if (OutputType.Patch == this.Output.Type && this.DeltaBinaryPatch) | 370 | if (SectionType.Patch == section.Type && this.DeltaBinaryPatch) |
385 | { | 371 | { |
386 | CreateDeltaPatchesCommand command = new CreateDeltaPatchesCommand(); | 372 | var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Tuples.OfType<WixPatchIdTuple>().FirstOrDefault()); |
387 | command.FileFacades = fileFacades; | ||
388 | command.WixPatchIdTable = this.Output.Tables["WixPatchId"]; | ||
389 | command.TempFilesLocation = this.IntermediateFolder; | ||
390 | command.Execute(); | 373 | command.Execute(); |
391 | } | 374 | } |
392 | 375 | ||
393 | // create cabinet files and process uncompressed files | 376 | // create cabinet files and process uncompressed files |
394 | string layoutDirectory = Path.GetDirectoryName(this.OutputPath); | 377 | string layoutDirectory = Path.GetDirectoryName(this.OutputPath); |
395 | if (!this.SuppressLayout || OutputType.Module == this.Output.Type) | 378 | if (!this.SuppressLayout || OutputType.Module == output.Type) |
396 | { | 379 | { |
397 | Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles()); | 380 | Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles()); |
398 | 381 | ||
@@ -400,7 +383,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
400 | command.CabbingThreadCount = this.CabbingThreadCount; | 383 | command.CabbingThreadCount = this.CabbingThreadCount; |
401 | command.CabCachePath = this.CabCachePath; | 384 | command.CabCachePath = this.CabCachePath; |
402 | command.DefaultCompressionLevel = this.DefaultCompressionLevel; | 385 | command.DefaultCompressionLevel = this.DefaultCompressionLevel; |
403 | command.Output = this.Output; | 386 | command.Output = output; |
404 | command.BackendExtensions = this.BackendExtensions; | 387 | command.BackendExtensions = this.BackendExtensions; |
405 | command.LayoutDirectory = layoutDirectory; | 388 | command.LayoutDirectory = layoutDirectory; |
406 | command.Compressed = compressed; | 389 | command.Compressed = compressed; |
@@ -408,39 +391,35 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
408 | command.ResolveMedia = this.ResolveMedia; | 391 | command.ResolveMedia = this.ResolveMedia; |
409 | command.TableDefinitions = this.TableDefinitions; | 392 | command.TableDefinitions = this.TableDefinitions; |
410 | command.TempFilesLocation = this.IntermediateFolder; | 393 | command.TempFilesLocation = this.IntermediateFolder; |
411 | command.WixMediaTable = this.Output.Tables["WixMedia"]; | 394 | command.WixMediaTable = output.Tables["WixMedia"]; |
412 | command.Execute(); | 395 | command.Execute(); |
413 | 396 | ||
414 | fileTransfers.AddRange(command.FileTransfers); | 397 | fileTransfers.AddRange(command.FileTransfers); |
415 | } | 398 | } |
416 | 399 | ||
400 | #if TODO_FINISH_PATCH | ||
417 | if (OutputType.Patch == this.Output.Type) | 401 | if (OutputType.Patch == this.Output.Type) |
418 | { | 402 | { |
419 | // copy output data back into the transforms | 403 | // copy output data back into the transforms |
420 | this.CopyToTransformData(this.Output); | 404 | this.CopyToTransformData(this.Output); |
421 | } | 405 | } |
406 | #endif | ||
422 | 407 | ||
423 | // stop processing if an error previously occurred | 408 | // Add back suppressed tables which must be present prior to merging in modules. |
424 | if (Messaging.Instance.EncounteredError) | 409 | if (OutputType.Product == output.Type) |
425 | { | ||
426 | return; | ||
427 | } | ||
428 | |||
429 | // add back suppressed tables which must be present prior to merging in modules | ||
430 | if (OutputType.Product == this.Output.Type) | ||
431 | { | 410 | { |
432 | Table wixMergeTable = this.Output.Tables["WixMerge"]; | 411 | Table wixMergeTable = output.Tables["WixMerge"]; |
433 | 412 | ||
434 | if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count) | 413 | if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count) |
435 | { | 414 | { |
436 | foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable))) | 415 | foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable))) |
437 | { | 416 | { |
438 | string sequenceTableName = sequence.ToString(); | 417 | string sequenceTableName = sequence.ToString(); |
439 | Table sequenceTable = this.Output.Tables[sequenceTableName]; | 418 | Table sequenceTable = output.Tables[sequenceTableName]; |
440 | 419 | ||
441 | if (null == sequenceTable) | 420 | if (null == sequenceTable) |
442 | { | 421 | { |
443 | sequenceTable = this.Output.EnsureTable(this.TableDefinitions[sequenceTableName]); | 422 | sequenceTable = output.EnsureTable(this.TableDefinitions[sequenceTableName]); |
444 | } | 423 | } |
445 | 424 | ||
446 | if (0 == sequenceTable.Rows.Count) | 425 | if (0 == sequenceTable.Rows.Count) |
@@ -456,67 +435,59 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
456 | // extension.PostBind(this.Context); | 435 | // extension.PostBind(this.Context); |
457 | //} | 436 | //} |
458 | 437 | ||
459 | // generate database file | 438 | this.ValidateComponentGuids(output); |
439 | |||
440 | // stop processing if an error previously occurred | ||
441 | if (Messaging.Instance.EncounteredError) | ||
442 | { | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | // Generate database file. | ||
460 | Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase()); | 447 | Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase()); |
461 | string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); | 448 | string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); |
462 | this.GenerateDatabase(this.Output, tempDatabaseFile, false, false); | 449 | this.GenerateDatabase(output, tempDatabaseFile, false, false); |
463 | 450 | ||
464 | FileTransfer transfer; | 451 | if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, output.Type.ToString(), null, out var transfer)) // note where this database needs to move in the future |
465 | if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, this.Output.Type.ToString(), null, out transfer)) // note where this database needs to move in the future | ||
466 | { | 452 | { |
467 | transfer.Built = true; | 453 | transfer.Built = true; |
468 | fileTransfers.Add(transfer); | 454 | fileTransfers.Add(transfer); |
469 | } | 455 | } |
470 | 456 | ||
471 | // stop processing if an error previously occurred | 457 | // Stop processing if an error previously occurred. |
472 | if (Messaging.Instance.EncounteredError) | 458 | if (Messaging.Instance.EncounteredError) |
473 | { | 459 | { |
474 | return; | 460 | return; |
475 | } | 461 | } |
476 | 462 | ||
477 | // Output the output to a file | 463 | // Output the output to a file. |
478 | Pdb pdb = new Pdb(); | 464 | Pdb pdb = new Pdb(); |
479 | pdb.Output = this.Output; | 465 | pdb.Output = output; |
480 | if (!String.IsNullOrEmpty(this.PdbFile)) | 466 | if (!String.IsNullOrEmpty(this.PdbFile)) |
481 | { | 467 | { |
482 | pdb.Save(this.PdbFile); | 468 | pdb.Save(this.PdbFile); |
483 | } | 469 | } |
484 | 470 | ||
485 | // Merge modules. | 471 | // Merge modules. |
486 | if (OutputType.Product == this.Output.Type) | 472 | if (OutputType.Product == output.Type) |
487 | { | 473 | { |
488 | Messaging.Instance.OnMessage(WixVerboses.MergingModules()); | 474 | Messaging.Instance.OnMessage(WixVerboses.MergingModules()); |
489 | 475 | ||
490 | MergeModulesCommand command = new MergeModulesCommand(); | 476 | var command = new MergeModulesCommand(); |
491 | command.FileFacades = fileFacades; | 477 | command.FileFacades = fileFacades; |
492 | command.Output = this.Output; | 478 | command.Output = output; |
493 | command.OutputPath = tempDatabaseFile; | 479 | command.OutputPath = tempDatabaseFile; |
494 | command.SuppressedTableNames = suppressedTableNames; | 480 | command.SuppressedTableNames = suppressedTableNames; |
495 | command.Execute(); | 481 | command.Execute(); |
496 | |||
497 | // stop processing if an error previously occurred | ||
498 | if (Messaging.Instance.EncounteredError) | ||
499 | { | ||
500 | return; | ||
501 | } | ||
502 | } | 482 | } |
503 | 483 | ||
504 | // inspect the MSI prior to running ICEs | ||
505 | //InspectorCore inspectorCore = new InspectorCore(); | ||
506 | //foreach (InspectorExtension inspectorExtension in this.InspectorExtensions) | ||
507 | //{ | ||
508 | // inspectorExtension.Core = inspectorCore; | ||
509 | // inspectorExtension.InspectDatabase(tempDatabaseFile, pdb); | ||
510 | |||
511 | // inspectorExtension.Core = null; // reset. | ||
512 | //} | ||
513 | |||
514 | if (Messaging.Instance.EncounteredError) | 484 | if (Messaging.Instance.EncounteredError) |
515 | { | 485 | { |
516 | return; | 486 | return; |
517 | } | 487 | } |
518 | 488 | ||
519 | // validate the output if there is an MSI validator | 489 | #if TODO_FINISH_VALIDATION |
490 | // Validate the output if there is an MSI validator. | ||
520 | if (null != this.Validator) | 491 | if (null != this.Validator) |
521 | { | 492 | { |
522 | Stopwatch stopwatch = Stopwatch.StartNew(); | 493 | Stopwatch stopwatch = Stopwatch.StartNew(); |
@@ -537,19 +508,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
537 | return; | 508 | return; |
538 | } | 509 | } |
539 | } | 510 | } |
511 | #endif | ||
540 | 512 | ||
541 | // Process uncompressed files. | 513 | // Process uncompressed files. |
542 | if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) | 514 | if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) |
543 | { | 515 | { |
544 | var command = new ProcessUncompressedFilesCommand(); | 516 | var command = new ProcessUncompressedFilesCommand(section); |
545 | command.Compressed = compressed; | 517 | command.Compressed = compressed; |
546 | command.FileFacades = uncompressedFiles; | 518 | command.FileFacades = uncompressedFiles; |
547 | command.LayoutDirectory = layoutDirectory; | 519 | command.LayoutDirectory = layoutDirectory; |
548 | command.LongNamesInImage = longNames; | 520 | command.LongNamesInImage = longNames; |
549 | command.MediaRows = assignedMediaRows; | ||
550 | command.ResolveMedia = this.ResolveMedia; | 521 | command.ResolveMedia = this.ResolveMedia; |
551 | command.DatabasePath = tempDatabaseFile; | 522 | command.DatabasePath = tempDatabaseFile; |
552 | command.WixMediaTable = this.Output.Tables["WixMedia"]; | ||
553 | command.Execute(); | 523 | command.Execute(); |
554 | 524 | ||
555 | fileTransfers.AddRange(command.FileTransfers); | 525 | fileTransfers.AddRange(command.FileTransfers); |
@@ -557,94 +527,92 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
557 | 527 | ||
558 | this.FileTransfers = fileTransfers; | 528 | this.FileTransfers = fileTransfers; |
559 | this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList(); | 529 | this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList(); |
530 | |||
531 | // TODO: Eventually this gets removed | ||
532 | var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths); | ||
533 | intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir")); | ||
560 | } | 534 | } |
561 | 535 | ||
562 | /// <summary> | 536 | /// <summary> |
563 | /// Localize dialogs and controls. | 537 | /// Localize dialogs and controls. |
564 | /// </summary> | 538 | /// </summary> |
565 | /// <param name="tables">The tables to localize.</param> | 539 | /// <param name="tables">The tables to localize.</param> |
566 | private void LocalizeUI(TableIndexedCollection tables) | 540 | private void LocalizeUI(IntermediateSection section) |
567 | { | 541 | { |
568 | Table dialogTable = tables["Dialog"]; | 542 | foreach (var row in section.Tuples.OfType<DialogTuple>()) |
569 | if (null != dialogTable) | ||
570 | { | 543 | { |
571 | foreach (Row row in dialogTable.Rows) | 544 | string dialog = row.Dialog; |
572 | { | ||
573 | string dialog = (string)row[0]; | ||
574 | 545 | ||
575 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) | 546 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) |
547 | { | ||
548 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
576 | { | 549 | { |
577 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | 550 | row.HCentering = localizedControl.X; |
578 | { | 551 | } |
579 | row[1] = localizedControl.X; | ||
580 | } | ||
581 | 552 | ||
582 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | 553 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) |
583 | { | 554 | { |
584 | row[2] = localizedControl.Y; | 555 | row.VCentering = localizedControl.Y; |
585 | } | 556 | } |
586 | 557 | ||
587 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | 558 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) |
588 | { | 559 | { |
589 | row[3] = localizedControl.Width; | 560 | row.Width = localizedControl.Width; |
590 | } | 561 | } |
591 | 562 | ||
592 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | 563 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) |
593 | { | 564 | { |
594 | row[4] = localizedControl.Height; | 565 | row.Height = localizedControl.Height; |
595 | } | 566 | } |
596 | 567 | ||
597 | row[5] = (int)row[5] | localizedControl.Attributes; | 568 | row.Attributes = row.Attributes | localizedControl.Attributes; |
598 | 569 | ||
599 | if (!String.IsNullOrEmpty(localizedControl.Text)) | 570 | if (!String.IsNullOrEmpty(localizedControl.Text)) |
600 | { | 571 | { |
601 | row[6] = localizedControl.Text; | 572 | row.Title = localizedControl.Text; |
602 | } | ||
603 | } | 573 | } |
604 | } | 574 | } |
605 | } | 575 | } |
606 | 576 | ||
607 | Table controlTable = tables["Control"]; | 577 | |
608 | if (null != controlTable) | 578 | foreach (var row in section.Tuples.OfType<ControlTuple>()) |
609 | { | 579 | { |
610 | foreach (Row row in controlTable.Rows) | 580 | string dialog = row.Dialog_; |
611 | { | 581 | string control = row.Control; |
612 | string dialog = (string)row[0]; | ||
613 | string control = (string)row[1]; | ||
614 | 582 | ||
615 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) | 583 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) |
584 | { | ||
585 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
616 | { | 586 | { |
617 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | 587 | row.X = localizedControl.X; |
618 | { | 588 | } |
619 | row[3] = localizedControl.X.ToString(); | ||
620 | } | ||
621 | 589 | ||
622 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | 590 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) |
623 | { | 591 | { |
624 | row[4] = localizedControl.Y.ToString(); | 592 | row.Y = localizedControl.Y; |
625 | } | 593 | } |
626 | 594 | ||
627 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | 595 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) |
628 | { | 596 | { |
629 | row[5] = localizedControl.Width.ToString(); | 597 | row.Width = localizedControl.Width; |
630 | } | 598 | } |
631 | 599 | ||
632 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | 600 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) |
633 | { | 601 | { |
634 | row[6] = localizedControl.Height.ToString(); | 602 | row.Height = localizedControl.Height; |
635 | } | 603 | } |
636 | 604 | ||
637 | row[7] = (int)row[7] | localizedControl.Attributes; | 605 | row.Attributes = row.Attributes | localizedControl.Attributes; |
638 | 606 | ||
639 | if (!String.IsNullOrEmpty(localizedControl.Text)) | 607 | if (!String.IsNullOrEmpty(localizedControl.Text)) |
640 | { | 608 | { |
641 | row[9] = localizedControl.Text; | 609 | row.Text = localizedControl.Text; |
642 | } | ||
643 | } | 610 | } |
644 | } | 611 | } |
645 | } | 612 | } |
646 | } | 613 | } |
647 | 614 | ||
615 | #if TODO_FINISH_PATCH | ||
648 | /// <summary> | 616 | /// <summary> |
649 | /// Copy file data between transform substorages and the patch output object | 617 | /// Copy file data between transform substorages and the patch output object |
650 | /// </summary> | 618 | /// </summary> |
@@ -674,269 +642,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
674 | command.TableDefinitions = this.TableDefinitions; | 642 | command.TableDefinitions = this.TableDefinitions; |
675 | command.Execute(); | 643 | command.Execute(); |
676 | } | 644 | } |
645 | #endif | ||
677 | 646 | ||
678 | private void UpdateMediaSequences(OutputType outputType, IEnumerable<FileFacade> fileFacades, RowDictionary<MediaRow> mediaRows) | ||
679 | { | ||
680 | // Calculate sequence numbers and media disk id layout for all file media information objects. | ||
681 | if (OutputType.Module == outputType) | ||
682 | { | ||
683 | int lastSequence = 0; | ||
684 | foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI. | ||
685 | { | ||
686 | facade.File.Sequence = ++lastSequence; | ||
687 | } | ||
688 | } | ||
689 | else | ||
690 | { | ||
691 | int lastSequence = 0; | ||
692 | MediaRow mediaRow = null; | ||
693 | Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>(); | ||
694 | |||
695 | // sequence the non-patch-added files | ||
696 | foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI. | ||
697 | { | ||
698 | if (null == mediaRow) | ||
699 | { | ||
700 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
701 | if (OutputType.Patch == outputType) | ||
702 | { | ||
703 | // patch Media cannot start at zero | ||
704 | lastSequence = mediaRow.LastSequence; | ||
705 | } | ||
706 | } | ||
707 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
708 | { | ||
709 | mediaRow.LastSequence = lastSequence; | ||
710 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
711 | } | ||
712 | |||
713 | if (0 < facade.WixFile.PatchGroup) | ||
714 | { | ||
715 | List<FileFacade> patchGroup = patchGroups[facade.WixFile.PatchGroup]; | ||
716 | |||
717 | if (null == patchGroup) | ||
718 | { | ||
719 | patchGroup = new List<FileFacade>(); | ||
720 | patchGroups.Add(facade.WixFile.PatchGroup, patchGroup); | ||
721 | } | ||
722 | |||
723 | patchGroup.Add(facade); | ||
724 | } | ||
725 | else | ||
726 | { | ||
727 | facade.File.Sequence = ++lastSequence; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | if (null != mediaRow) | ||
732 | { | ||
733 | mediaRow.LastSequence = lastSequence; | ||
734 | mediaRow = null; | ||
735 | } | ||
736 | |||
737 | // sequence the patch-added files | ||
738 | foreach (List<FileFacade> patchGroup in patchGroups.Values) | ||
739 | { | ||
740 | foreach (FileFacade facade in patchGroup) | ||
741 | { | ||
742 | if (null == mediaRow) | ||
743 | { | ||
744 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
745 | } | ||
746 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
747 | { | ||
748 | mediaRow.LastSequence = lastSequence; | ||
749 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
750 | } | ||
751 | |||
752 | facade.File.Sequence = ++lastSequence; | ||
753 | } | ||
754 | } | ||
755 | |||
756 | if (null != mediaRow) | ||
757 | { | ||
758 | mediaRow.LastSequence = lastSequence; | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | |||
763 | /// <summary> | ||
764 | /// Set the guids for components with generatable guids. | ||
765 | /// </summary> | ||
766 | /// <param name="output">Internal representation of the database to operate on.</param> | ||
767 | private void SetComponentGuids(Output output) | ||
768 | { | ||
769 | Table componentTable = output.Tables["Component"]; | ||
770 | if (null != componentTable) | ||
771 | { | ||
772 | Hashtable registryKeyRows = null; | ||
773 | Hashtable directories = null; | ||
774 | Hashtable componentIdGenSeeds = null; | ||
775 | Dictionary<string, List<FileRow>> fileRows = null; | ||
776 | |||
777 | // find components with generatable guids | ||
778 | foreach (ComponentRow componentRow in componentTable.Rows) | ||
779 | { | ||
780 | // component guid will be generated | ||
781 | if ("*" == componentRow.Guid) | ||
782 | { | ||
783 | if (null == componentRow.KeyPath || componentRow.IsOdbcDataSourceKeyPath) | ||
784 | { | ||
785 | Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers)); | ||
786 | } | ||
787 | else if (componentRow.IsRegistryKeyPath) | ||
788 | { | ||
789 | if (null == registryKeyRows) | ||
790 | { | ||
791 | Table registryTable = output.Tables["Registry"]; | ||
792 | |||
793 | registryKeyRows = new Hashtable(registryTable.Rows.Count); | ||
794 | |||
795 | foreach (Row registryRow in registryTable.Rows) | ||
796 | { | ||
797 | registryKeyRows.Add((string)registryRow[0], registryRow); | ||
798 | } | ||
799 | } | ||
800 | |||
801 | Row foundRow = registryKeyRows[componentRow.KeyPath] as Row; | ||
802 | |||
803 | string bitness = componentRow.Is64Bit ? "64" : String.Empty; | ||
804 | if (null != foundRow) | ||
805 | { | ||
806 | string regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]); | ||
807 | componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant(); | ||
808 | } | ||
809 | } | ||
810 | else // must be a File KeyPath | ||
811 | { | ||
812 | // if the directory table hasn't been loaded into an indexed hash | ||
813 | // of directory ids to target names do that now. | ||
814 | if (null == directories) | ||
815 | { | ||
816 | Table directoryTable = output.Tables["Directory"]; | ||
817 | |||
818 | int numDirectoryTableRows = (null != directoryTable) ? directoryTable.Rows.Count : 0; | ||
819 | |||
820 | directories = new Hashtable(numDirectoryTableRows); | ||
821 | |||
822 | // get the target paths for all directories | ||
823 | if (null != directoryTable) | ||
824 | { | ||
825 | foreach (Row row in directoryTable.Rows) | ||
826 | { | ||
827 | // if the directory Id already exists, we will skip it here since | ||
828 | // checking for duplicate primary keys is done later when importing tables | ||
829 | // into database | ||
830 | if (directories.ContainsKey(row[0])) | ||
831 | { | ||
832 | continue; | ||
833 | } | ||
834 | |||
835 | string targetName = Common.GetName((string)row[2], false, true); | ||
836 | directories.Add(row[0], new ResolvedDirectory((string)row[1], targetName)); | ||
837 | } | ||
838 | } | ||
839 | } | ||
840 | |||
841 | // if the component id generation seeds have not been indexed | ||
842 | // from the WixDirectory table do that now. | ||
843 | if (null == componentIdGenSeeds) | ||
844 | { | ||
845 | Table wixDirectoryTable = output.Tables["WixDirectory"]; | ||
846 | |||
847 | int numWixDirectoryRows = (null != wixDirectoryTable) ? wixDirectoryTable.Rows.Count : 0; | ||
848 | |||
849 | componentIdGenSeeds = new Hashtable(numWixDirectoryRows); | ||
850 | |||
851 | // if there are any WixDirectory rows, build up the Component Guid | ||
852 | // generation seeds indexed by Directory/@Id. | ||
853 | if (null != wixDirectoryTable) | ||
854 | { | ||
855 | foreach (Row row in wixDirectoryTable.Rows) | ||
856 | { | ||
857 | componentIdGenSeeds.Add(row[0], (string)row[1]); | ||
858 | } | ||
859 | } | ||
860 | } | ||
861 | |||
862 | // if the file rows have not been indexed by File.Component yet | ||
863 | // then do that now | ||
864 | if (null == fileRows) | ||
865 | { | ||
866 | Table fileTable = output.Tables["File"]; | ||
867 | |||
868 | int numFileRows = (null != fileTable) ? fileTable.Rows.Count : 0; | ||
869 | |||
870 | fileRows = new Dictionary<string, List<FileRow>>(numFileRows); | ||
871 | |||
872 | if (null != fileTable) | ||
873 | { | ||
874 | foreach (FileRow file in fileTable.Rows) | ||
875 | { | ||
876 | List<FileRow> files; | ||
877 | if (!fileRows.TryGetValue(file.Component, out files)) | ||
878 | { | ||
879 | files = new List<FileRow>(); | ||
880 | fileRows.Add(file.Component, files); | ||
881 | } | ||
882 | |||
883 | files.Add(file); | ||
884 | } | ||
885 | } | ||
886 | } | ||
887 | |||
888 | // validate component meets all the conditions to have a generated guid | ||
889 | List<FileRow> currentComponentFiles = fileRows[componentRow.Component]; | ||
890 | int numFilesInComponent = currentComponentFiles.Count; | ||
891 | string path = null; | ||
892 | |||
893 | foreach (FileRow fileRow in currentComponentFiles) | ||
894 | { | ||
895 | if (fileRow.File == componentRow.KeyPath) | ||
896 | { | ||
897 | // calculate the key file's canonical target path | ||
898 | string directoryPath = Binder.GetDirectoryPath(directories, componentIdGenSeeds, componentRow.Directory, true); | ||
899 | string fileName = Common.GetName(fileRow.FileName, false, true).ToLower(CultureInfo.InvariantCulture); | ||
900 | path = Path.Combine(directoryPath, fileName); | ||
901 | |||
902 | // find paths that are not canonicalized | ||
903 | if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) || | ||
904 | path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) || | ||
905 | path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) || | ||
906 | path.StartsWith("TARGETDIR", StringComparison.Ordinal) || | ||
907 | path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) || | ||
908 | path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal)) | ||
909 | { | ||
910 | Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component, path)); | ||
911 | } | ||
912 | |||
913 | // if component has more than one file, the key path must be versioned | ||
914 | if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version)) | ||
915 | { | ||
916 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers)); | ||
917 | } | ||
918 | } | ||
919 | else | ||
920 | { | ||
921 | // not a key path, so it must be an unversioned file if component has more than one file | ||
922 | if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version)) | ||
923 | { | ||
924 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers)); | ||
925 | } | ||
926 | } | ||
927 | } | ||
928 | |||
929 | // if the rules were followed, reward with a generated guid | ||
930 | if (!Messaging.Instance.EncounteredError) | ||
931 | { | ||
932 | componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant(); | ||
933 | } | ||
934 | } | ||
935 | } | ||
936 | } | ||
937 | } | ||
938 | } | ||
939 | 647 | ||
648 | #if TODO_FIX_INSTANCE_TRANSFORM | ||
940 | /// <summary> | 649 | /// <summary> |
941 | /// Creates instance transform substorages in the output. | 650 | /// Creates instance transform substorages in the output. |
942 | /// </summary> | 651 | /// </summary> |
@@ -1171,6 +880,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1171 | } | 880 | } |
1172 | } | 881 | } |
1173 | } | 882 | } |
883 | #endif | ||
1174 | 884 | ||
1175 | /// <summary> | 885 | /// <summary> |
1176 | /// Validate that there are no duplicate GUIDs in the output. | 886 | /// Validate that there are no duplicate GUIDs in the output. |
@@ -1186,7 +896,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1186 | { | 896 | { |
1187 | Dictionary<string, bool> componentGuidConditions = new Dictionary<string, bool>(componentTable.Rows.Count); | 897 | Dictionary<string, bool> componentGuidConditions = new Dictionary<string, bool>(componentTable.Rows.Count); |
1188 | 898 | ||
1189 | foreach (ComponentRow row in componentTable.Rows) | 899 | foreach (Data.Rows.ComponentRow row in componentTable.Rows) |
1190 | { | 900 | { |
1191 | // we don't care about unmanaged components and if there's a * GUID remaining, | 901 | // we don't care about unmanaged components and if there's a * GUID remaining, |
1192 | // there's already an error that prevented it from being replaced with a real GUID. | 902 | // there's already an error that prevented it from being replaced with a real GUID. |
@@ -1221,7 +931,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1221 | /// <param name="output">Internal representation of the msi database to operate upon.</param> | 931 | /// <param name="output">Internal representation of the msi database to operate upon.</param> |
1222 | private void UpdateControlText(Output output) | 932 | private void UpdateControlText(Output output) |
1223 | { | 933 | { |
1224 | UpdateControlTextCommand command = new UpdateControlTextCommand(); | 934 | var command = new UpdateControlTextCommand(); |
1225 | command.BBControlTable = output.Tables["BBControl"]; | 935 | command.BBControlTable = output.Tables["BBControl"]; |
1226 | command.WixBBControlTable = output.Tables["WixBBControl"]; | 936 | command.WixBBControlTable = output.Tables["WixBBControl"]; |
1227 | command.ControlTable = output.Tables["Control"]; | 937 | command.ControlTable = output.Tables["Control"]; |
@@ -1229,7 +939,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1229 | command.Execute(); | 939 | command.Execute(); |
1230 | } | 940 | } |
1231 | 941 | ||
1232 | private string ResolveMedia(MediaRow mediaRow, string mediaLayoutDirectory, string layoutDirectory) | 942 | private string ResolveMedia(MediaTuple mediaRow, string mediaLayoutDirectory, string layoutDirectory) |
1233 | { | 943 | { |
1234 | string layout = null; | 944 | string layout = null; |
1235 | 945 | ||
@@ -1282,7 +992,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1282 | command.TempFilesLocation = this.IntermediateFolder; | 992 | command.TempFilesLocation = this.IntermediateFolder; |
1283 | command.Codepage = this.Codepage; | 993 | command.Codepage = this.Codepage; |
1284 | command.Execute(); | 994 | command.Execute(); |
1285 | #endif | ||
1286 | } | 995 | } |
1287 | } | 996 | } |
1288 | } | 997 | } |