diff options
| author | Rob Mensching <rob@firegiant.com> | 2017-11-11 01:45:59 -0800 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2017-11-11 01:45:59 -0800 |
| commit | 9f8cb5374481b6c8a06eb2739858332350f72666 (patch) | |
| tree | 4b09b90d8a516cb5e7d8203759bd2489b6a5d20c /src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | |
| parent | 2bb37beda887d120a0ddabf874ad25357101faa1 (diff) | |
| download | wix-9f8cb5374481b6c8a06eb2739858332350f72666.tar.gz wix-9f8cb5374481b6c8a06eb2739858332350f72666.tar.bz2 wix-9f8cb5374481b6c8a06eb2739858332350f72666.zip | |
Additional IR updates
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 | } |
