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 | |
| 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')
27 files changed, 1830 insertions, 956 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs index 74e2cdb5..f426b96d 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs | |||
| @@ -1,43 +1,44 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Globalization; | 7 | using System.Globalization; |
| 8 | using System.Linq; | ||
| 8 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
| 9 | using WixToolset.Data; | 10 | using WixToolset.Data; |
| 10 | using WixToolset.Data.Rows; | 11 | using WixToolset.Data.Rows; |
| 12 | using WixToolset.Data.Tuples; | ||
| 11 | 13 | ||
| 12 | /// <summary> | 14 | /// <summary> |
| 13 | /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows. | 15 | /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows. |
| 14 | /// </summary> | 16 | /// </summary> |
| 15 | public class AssignMediaCommand | 17 | internal class AssignMediaCommand |
| 16 | { | 18 | { |
| 17 | public AssignMediaCommand() | 19 | public AssignMediaCommand(IntermediateSection section) |
| 18 | { | 20 | { |
| 19 | this.CabinetNameTemplate = "Cab{0}.cab"; | 21 | this.CabinetNameTemplate = "Cab{0}.cab"; |
| 22 | this.Section = section; | ||
| 20 | } | 23 | } |
| 21 | 24 | ||
| 22 | public Output Output { private get; set; } | 25 | private IntermediateSection Section { get; } |
| 26 | |||
| 27 | public IEnumerable<FileFacade> FileFacades { private get; set; } | ||
| 23 | 28 | ||
| 24 | public bool FilesCompressed { private get; set; } | 29 | public bool FilesCompressed { private get; set; } |
| 25 | 30 | ||
| 26 | public string CabinetNameTemplate { private get; set; } | 31 | public string CabinetNameTemplate { private get; set; } |
| 27 | 32 | ||
| 28 | public IEnumerable<FileFacade> FileFacades { private get; set; } | ||
| 29 | |||
| 30 | public TableDefinitionCollection TableDefinitions { private get; set; } | ||
| 31 | |||
| 32 | /// <summary> | 33 | /// <summary> |
| 33 | /// Gets cabinets with their file rows. | 34 | /// Gets cabinets with their file rows. |
| 34 | /// </summary> | 35 | /// </summary> |
| 35 | public Dictionary<MediaRow, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; } | 36 | public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; } |
| 36 | 37 | ||
| 37 | /// <summary> | 38 | /// <summary> |
| 38 | /// Get media rows. | 39 | /// Get media rows. |
| 39 | /// </summary> | 40 | /// </summary> |
| 40 | public RowDictionary<MediaRow> MediaRows { get; private set; } | 41 | public Dictionary<int, MediaTuple> MediaRows { get; private set; } |
| 41 | 42 | ||
| 42 | /// <summary> | 43 | /// <summary> |
| 43 | /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no. | 44 | /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no. |
| @@ -47,42 +48,41 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 47 | 48 | ||
| 48 | public void Execute() | 49 | public void Execute() |
| 49 | { | 50 | { |
| 50 | Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia = new Dictionary<MediaRow, List<FileFacade>>(); | 51 | var filesByCabinetMedia = new Dictionary<MediaTuple, List<FileFacade>>(); |
| 51 | 52 | ||
| 52 | RowDictionary<MediaRow> mediaRows = new RowDictionary<MediaRow>(); | 53 | var mediaRows = new Dictionary<int, MediaTuple>(); |
| 53 | 54 | ||
| 54 | List<FileFacade> uncompressedFiles = new List<FileFacade>(); | 55 | List<FileFacade> uncompressedFiles = new List<FileFacade>(); |
| 55 | 56 | ||
| 56 | MediaRow mergeModuleMediaRow = null; | 57 | var mediaTable = this.Section.Tuples.OfType<MediaTuple>().ToList(); |
| 57 | Table mediaTable = this.Output.Tables["Media"]; | 58 | var mediaTemplateTable = this.Section.Tuples.OfType<WixMediaTemplateTuple>().ToList(); |
| 58 | Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"]; | ||
| 59 | 59 | ||
| 60 | // If both tables are authored, it is an error. | 60 | // If both tables are authored, it is an error. |
| 61 | if ((mediaTemplateTable != null && mediaTemplateTable.Rows.Count > 0) && (mediaTable != null && mediaTable.Rows.Count > 1)) | 61 | if ((mediaTemplateTable != null && mediaTemplateTable.Count > 0) && (mediaTable != null && mediaTable.Count > 1)) |
| 62 | { | 62 | { |
| 63 | throw new WixException(WixErrors.MediaTableCollision(null)); | 63 | throw new WixException(WixErrors.MediaTableCollision(null)); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | // When building merge module, all the files go to "#MergeModule.CABinet". | 66 | // When building merge module, all the files go to "#MergeModule.CABinet". |
| 67 | if (OutputType.Module == this.Output.Type) | 67 | if (SectionType.Module == this.Section.Type) |
| 68 | { | 68 | { |
| 69 | Table mergeModuleMediaTable = new Table(this.TableDefinitions["Media"]); | 69 | var mergeModuleMediaRow = new MediaTuple(); |
| 70 | mergeModuleMediaRow = (MediaRow)mergeModuleMediaTable.CreateRow(null); | ||
| 71 | mergeModuleMediaRow.Cabinet = "#MergeModule.CABinet"; | 70 | mergeModuleMediaRow.Cabinet = "#MergeModule.CABinet"; |
| 72 | 71 | ||
| 73 | filesByCabinetMedia.Add(mergeModuleMediaRow, new List<FileFacade>()); | 72 | this.Section.Tuples.Add(mergeModuleMediaRow); |
| 74 | } | ||
| 75 | 73 | ||
| 76 | if (OutputType.Module == this.Output.Type || null == mediaTemplateTable) | 74 | filesByCabinetMedia.Add(mergeModuleMediaRow, new List<FileFacade>(this.FileFacades)); |
| 75 | } | ||
| 76 | else if (null == mediaTemplateTable) | ||
| 77 | { | 77 | { |
| 78 | this.ManuallyAssignFiles(mediaTable, mergeModuleMediaRow, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); | 78 | this.ManuallyAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); |
| 79 | } | 79 | } |
| 80 | else | 80 | else |
| 81 | { | 81 | { |
| 82 | this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); | 82 | this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | this.FileFacadesByCabinetMedia = new Dictionary<MediaRow, IEnumerable<FileFacade>>(); | 85 | this.FileFacadesByCabinetMedia = new Dictionary<MediaTuple, IEnumerable<FileFacade>>(); |
| 86 | 86 | ||
| 87 | foreach (var mediaRowWithFiles in filesByCabinetMedia) | 87 | foreach (var mediaRowWithFiles in filesByCabinetMedia) |
| 88 | { | 88 | { |
| @@ -98,7 +98,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 98 | /// Assign files to cabinets based on MediaTemplate authoring. | 98 | /// Assign files to cabinets based on MediaTemplate authoring. |
| 99 | /// </summary> | 99 | /// </summary> |
| 100 | /// <param name="fileFacades">FileRowCollection</param> | 100 | /// <param name="fileFacades">FileRowCollection</param> |
| 101 | private void AutoAssignFiles(Table mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia, RowDictionary<MediaRow> mediaRows, List<FileFacade> uncompressedFiles) | 101 | private void AutoAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles) |
| 102 | { | 102 | { |
| 103 | const int MaxCabIndex = 999; | 103 | const int MaxCabIndex = 999; |
| 104 | 104 | ||
| @@ -107,13 +107,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 107 | int maxPreCabSizeInMB = 0; | 107 | int maxPreCabSizeInMB = 0; |
| 108 | int currentCabIndex = 0; | 108 | int currentCabIndex = 0; |
| 109 | 109 | ||
| 110 | MediaRow currentMediaRow = null; | 110 | MediaTuple currentMediaRow = null; |
| 111 | 111 | ||
| 112 | Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"]; | 112 | var mediaTemplateTable = this.Section.Tuples.OfType<WixMediaTemplateTuple>(); |
| 113 | |||
| 114 | // Remove all previous media tuples since they will be replaced with | ||
| 115 | // media template. | ||
| 116 | foreach (var mediaTuple in mediaTable) | ||
| 117 | { | ||
| 118 | this.Section.Tuples.Remove(mediaTuple); | ||
| 119 | } | ||
| 113 | 120 | ||
| 114 | // Auto assign files to cabinets based on maximum uncompressed media size | 121 | // Auto assign files to cabinets based on maximum uncompressed media size |
| 115 | mediaTable.Rows.Clear(); | 122 | var mediaTemplateRow = mediaTemplateTable.Single(); |
| 116 | WixMediaTemplateRow mediaTemplateRow = (WixMediaTemplateRow)mediaTemplateTable.Rows[0]; | ||
| 117 | 123 | ||
| 118 | if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) | 124 | if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) |
| 119 | { | 125 | { |
| @@ -149,9 +155,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 149 | { | 155 | { |
| 150 | // When building a product, if the current file is not to be compressed or if | 156 | // When building a product, if the current file is not to be compressed or if |
| 151 | // the package set not to be compressed, don't cab it. | 157 | // the package set not to be compressed, don't cab it. |
| 152 | if (OutputType.Product == this.Output.Type && | 158 | if (SectionType.Product == this.Section.Type && |
| 153 | (!facade.File.Compressed.Value || | 159 | ((facade.File.Compressed.HasValue && !facade.File.Compressed.Value) || |
| 154 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) | 160 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) |
| 155 | { | 161 | { |
| 156 | uncompressedFiles.Add(facade); | 162 | uncompressedFiles.Add(facade); |
| 157 | continue; | 163 | continue; |
| @@ -172,8 +178,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 172 | if (currentPreCabSize > maxPreCabSizeInBytes) | 178 | if (currentPreCabSize > maxPreCabSizeInBytes) |
| 173 | { | 179 | { |
| 174 | // Overflow due to current file | 180 | // Overflow due to current file |
| 175 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex); | 181 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); |
| 176 | mediaRows.Add(currentMediaRow); | 182 | mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); |
| 177 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); | 183 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); |
| 178 | 184 | ||
| 179 | List<FileFacade> cabinetFileRows = filesByCabinetMedia[currentMediaRow]; | 185 | List<FileFacade> cabinetFileRows = filesByCabinetMedia[currentMediaRow]; |
| @@ -188,8 +194,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 188 | if (currentMediaRow == null) | 194 | if (currentMediaRow == null) |
| 189 | { | 195 | { |
| 190 | // Create new cab and MediaRow | 196 | // Create new cab and MediaRow |
| 191 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex); | 197 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); |
| 192 | mediaRows.Add(currentMediaRow); | 198 | mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); |
| 193 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); | 199 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); |
| 194 | } | 200 | } |
| 195 | 201 | ||
| @@ -201,11 +207,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 201 | } | 207 | } |
| 202 | 208 | ||
| 203 | // If there are uncompressed files and no MediaRow, create a default one. | 209 | // If there are uncompressed files and no MediaRow, create a default one. |
| 204 | if (uncompressedFiles.Count > 0 && mediaTable.Rows.Count == 0) | 210 | if (uncompressedFiles.Count > 0 && !this.Section.Tuples.OfType<MediaTuple>().Any()) |
| 205 | { | 211 | { |
| 206 | MediaRow defaultMediaRow = (MediaRow)mediaTable.CreateRow(null); | 212 | var defaultMediaRow = new MediaTuple(null, new Identifier(1, AccessModifier.Private)); |
| 207 | defaultMediaRow.DiskId = 1; | 213 | defaultMediaRow.DiskId = 1; |
| 208 | mediaRows.Add(defaultMediaRow); | 214 | |
| 215 | mediaRows.Add(1, defaultMediaRow); | ||
| 216 | this.Section.Tuples.Add(defaultMediaRow); | ||
| 209 | } | 217 | } |
| 210 | } | 218 | } |
| 211 | 219 | ||
| @@ -213,79 +221,65 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 213 | /// Assign files to cabinets based on Media authoring. | 221 | /// Assign files to cabinets based on Media authoring. |
| 214 | /// </summary> | 222 | /// </summary> |
| 215 | /// <param name="mediaTable"></param> | 223 | /// <param name="mediaTable"></param> |
| 216 | /// <param name="mergeModuleMediaRow"></param> | ||
| 217 | /// <param name="fileFacades"></param> | 224 | /// <param name="fileFacades"></param> |
| 218 | private void ManuallyAssignFiles(Table mediaTable, MediaRow mergeModuleMediaRow, IEnumerable<FileFacade> fileFacades, Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia, RowDictionary<MediaRow> mediaRows, List<FileFacade> uncompressedFiles) | 225 | private void ManuallyAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles) |
| 219 | { | 226 | { |
| 220 | if (OutputType.Module != this.Output.Type) | 227 | if (mediaTable.Any()) |
| 221 | { | 228 | { |
| 222 | if (null != mediaTable) | 229 | var cabinetMediaRows = new Dictionary<string, MediaTuple>(StringComparer.OrdinalIgnoreCase); |
| 230 | foreach (var mediaRow in mediaTable) | ||
| 223 | { | 231 | { |
| 224 | Dictionary<string, MediaRow> cabinetMediaRows = new Dictionary<string, MediaRow>(StringComparer.InvariantCultureIgnoreCase); | 232 | // If the Media row has a cabinet, make sure it is unique across all Media rows. |
| 225 | foreach (MediaRow mediaRow in mediaTable.Rows) | 233 | if (!String.IsNullOrEmpty(mediaRow.Cabinet)) |
| 226 | { | 234 | { |
| 227 | // If the Media row has a cabinet, make sure it is unique across all Media rows. | 235 | if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out var existingRow)) |
| 228 | if (!String.IsNullOrEmpty(mediaRow.Cabinet)) | ||
| 229 | { | 236 | { |
| 230 | MediaRow existingRow; | 237 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); |
| 231 | if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out existingRow)) | 238 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); |
| 232 | { | 239 | } |
| 233 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); | 240 | else |
| 234 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); | 241 | { |
| 235 | } | 242 | cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); |
| 236 | else | ||
| 237 | { | ||
| 238 | cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); | ||
| 239 | } | ||
| 240 | } | 243 | } |
| 241 | |||
| 242 | mediaRows.Add(mediaRow); | ||
| 243 | } | 244 | } |
| 245 | |||
| 246 | mediaRows.Add(mediaRow.DiskId, mediaRow); | ||
| 244 | } | 247 | } |
| 248 | } | ||
| 245 | 249 | ||
| 246 | foreach (MediaRow mediaRow in mediaRows.Values) | 250 | foreach (var mediaRow in mediaRows.Values) |
| 251 | { | ||
| 252 | if (null != mediaRow.Cabinet) | ||
| 247 | { | 253 | { |
| 248 | if (null != mediaRow.Cabinet) | 254 | filesByCabinetMedia.Add(mediaRow, new List<FileFacade>()); |
| 249 | { | ||
| 250 | filesByCabinetMedia.Add(mediaRow, new List<FileFacade>()); | ||
| 251 | } | ||
| 252 | } | 255 | } |
| 253 | } | 256 | } |
| 254 | 257 | ||
| 255 | foreach (FileFacade facade in fileFacades) | 258 | foreach (FileFacade facade in fileFacades) |
| 256 | { | 259 | { |
| 257 | if (OutputType.Module == this.Output.Type) | 260 | if (!mediaRows.TryGetValue(facade.WixFile.DiskId, out var mediaRow)) |
| 258 | { | 261 | { |
| 259 | filesByCabinetMedia[mergeModuleMediaRow].Add(facade); | 262 | Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); |
| 263 | continue; | ||
| 260 | } | 264 | } |
| 261 | else | ||
| 262 | { | ||
| 263 | MediaRow mediaRow; | ||
| 264 | if (!mediaRows.TryGetValue(facade.WixFile.DiskId.ToString(CultureInfo.InvariantCulture), out mediaRow)) | ||
| 265 | { | ||
| 266 | Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); | ||
| 267 | continue; | ||
| 268 | } | ||
| 269 | 265 | ||
| 270 | // When building a product, if the current file is not to be compressed or if | 266 | // When building a product, if the current file is not to be compressed or if |
| 271 | // the package set not to be compressed, don't cab it. | 267 | // the package set not to be compressed, don't cab it. |
| 272 | if (OutputType.Product == this.Output.Type && | 268 | if (SectionType.Product == this.Section.Type && |
| 273 | (!facade.File.Compressed.Value || | 269 | (!facade.File.Compressed.Value || |
| 274 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) | 270 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) |
| 271 | { | ||
| 272 | uncompressedFiles.Add(facade); | ||
| 273 | } | ||
| 274 | else // file is marked compressed. | ||
| 275 | { | ||
| 276 | if (filesByCabinetMedia.TryGetValue(mediaRow, out var cabinetFiles)) | ||
| 275 | { | 277 | { |
| 276 | uncompressedFiles.Add(facade); | 278 | cabinetFiles.Add(facade); |
| 277 | } | 279 | } |
| 278 | else // file is marked compressed. | 280 | else |
| 279 | { | 281 | { |
| 280 | List<FileFacade> cabinetFiles; | 282 | Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); |
| 281 | if (filesByCabinetMedia.TryGetValue(mediaRow, out cabinetFiles)) | ||
| 282 | { | ||
| 283 | cabinetFiles.Add(facade); | ||
| 284 | } | ||
| 285 | else | ||
| 286 | { | ||
| 287 | Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); | ||
| 288 | } | ||
| 289 | } | 283 | } |
| 290 | } | 284 | } |
| 291 | } | 285 | } |
| @@ -297,17 +291,20 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 297 | /// <param name="mediaTable"></param> | 291 | /// <param name="mediaTable"></param> |
| 298 | /// <param name="cabIndex"></param> | 292 | /// <param name="cabIndex"></param> |
| 299 | /// <returns></returns> | 293 | /// <returns></returns> |
| 300 | private MediaRow AddMediaRow(WixMediaTemplateRow mediaTemplateRow, Table mediaTable, int cabIndex) | 294 | private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateRow, int cabIndex) |
| 301 | { | 295 | { |
| 302 | MediaRow currentMediaRow = (MediaRow)mediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers); | 296 | var currentMediaRow = new MediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); |
| 303 | currentMediaRow.DiskId = cabIndex; | 297 | currentMediaRow.DiskId = cabIndex; |
| 304 | currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex); | 298 | currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex); |
| 305 | 299 | ||
| 306 | Table wixMediaTable = this.Output.EnsureTable(this.TableDefinitions["WixMedia"]); | 300 | this.Section.Tuples.Add(currentMediaRow); |
| 307 | WixMediaRow row = (WixMediaRow)wixMediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers); | 301 | |
| 308 | row.DiskId = cabIndex; | 302 | var row = new WixMediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); |
| 303 | row.DiskId_ = cabIndex; | ||
| 309 | row.CompressionLevel = mediaTemplateRow.CompressionLevel; | 304 | row.CompressionLevel = mediaTemplateRow.CompressionLevel; |
| 310 | 305 | ||
| 306 | this.Section.Tuples.Add(row); | ||
| 307 | |||
| 311 | return currentMediaRow; | 308 | return currentMediaRow; |
| 312 | } | 309 | } |
| 313 | } | 310 | } |
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 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs index 5471792d..c9286a38 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs | |||
| @@ -1,20 +1,24 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Globalization; | 6 | using System.Globalization; |
| 7 | using System.Linq; | ||
| 7 | using WixToolset.Data; | 8 | using WixToolset.Data; |
| 9 | using WixToolset.Data.Tuples; | ||
| 8 | 10 | ||
| 9 | /// <summary> | 11 | /// <summary> |
| 10 | /// Binds the summary information table of a database. | 12 | /// Binds the summary information table of a database. |
| 11 | /// </summary> | 13 | /// </summary> |
| 12 | internal class BindSummaryInfoCommand | 14 | internal class BindSummaryInfoCommand |
| 13 | { | 15 | { |
| 14 | /// <summary> | 16 | public BindSummaryInfoCommand(IntermediateSection section) |
| 15 | /// The output to bind. | 17 | { |
| 16 | /// </summary> | 18 | this.Section = section; |
| 17 | public Output Output { private get; set; } | 19 | } |
| 20 | |||
| 21 | private IntermediateSection Section { get; } | ||
| 18 | 22 | ||
| 19 | /// <summary> | 23 | /// <summary> |
| 20 | /// Returns a flag indicating if files are compressed by default. | 24 | /// Returns a flag indicating if files are compressed by default. |
| @@ -40,95 +44,97 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 40 | this.InstallerVersion = 0; | 44 | this.InstallerVersion = 0; |
| 41 | this.ModularizationGuid = null; | 45 | this.ModularizationGuid = null; |
| 42 | 46 | ||
| 43 | Table summaryInformationTable = this.Output.Tables["_SummaryInformation"]; | 47 | bool foundCreateDataTime = false; |
| 48 | bool foundLastSaveDataTime = false; | ||
| 49 | bool foundCreatingApplication = false; | ||
| 50 | string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); | ||
| 44 | 51 | ||
| 45 | if (null != summaryInformationTable) | 52 | foreach (var summaryInformationRow in this.Section.Tuples.OfType<_SummaryInformationTuple>()) |
| 46 | { | 53 | { |
| 47 | bool foundCreateDataTime = false; | 54 | switch (summaryInformationRow.PropertyId) |
| 48 | bool foundLastSaveDataTime = false; | ||
| 49 | bool foundCreatingApplication = false; | ||
| 50 | string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); | ||
| 51 | |||
| 52 | foreach (Row summaryInformationRow in summaryInformationTable.Rows) | ||
| 53 | { | 55 | { |
| 54 | switch (summaryInformationRow.FieldAsInteger(0)) | 56 | case 1: // PID_CODEPAGE |
| 55 | { | ||
| 56 | case 1: // PID_CODEPAGE | ||
| 57 | // make sure the code page is an int and not a web name or null | 57 | // make sure the code page is an int and not a web name or null |
| 58 | string codepage = summaryInformationRow.FieldAsString(1); | 58 | var codepage = summaryInformationRow.Value; |
| 59 | |||
| 60 | if (null == codepage) | ||
| 61 | { | ||
| 62 | codepage = "0"; | ||
| 63 | } | ||
| 64 | else | ||
| 65 | { | ||
| 66 | summaryInformationRow[1] = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); | ||
| 67 | } | ||
| 68 | break; | ||
| 69 | case 9: // PID_REVNUMBER | ||
| 70 | string packageCode = (string)summaryInformationRow[1]; | ||
| 71 | |||
| 72 | if (OutputType.Module == this.Output.Type) | ||
| 73 | { | ||
| 74 | this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_'); | ||
| 75 | } | ||
| 76 | else if ("*" == packageCode) | ||
| 77 | { | ||
| 78 | // set the revision number (package/patch code) if it should be automatically generated | ||
| 79 | summaryInformationRow[1] = Common.GenerateGuid(); | ||
| 80 | } | ||
| 81 | break; | ||
| 82 | case 12: // PID_CREATE_DTM | ||
| 83 | foundCreateDataTime = true; | ||
| 84 | break; | ||
| 85 | case 13: // PID_LASTSAVE_DTM | ||
| 86 | foundLastSaveDataTime = true; | ||
| 87 | break; | ||
| 88 | case 14: | ||
| 89 | this.InstallerVersion = summaryInformationRow.FieldAsInteger(1); | ||
| 90 | break; | ||
| 91 | case 15: // PID_WORDCOUNT | ||
| 92 | if (OutputType.Patch == this.Output.Type) | ||
| 93 | { | ||
| 94 | this.LongNames = true; | ||
| 95 | this.Compressed = true; | ||
| 96 | } | ||
| 97 | else | ||
| 98 | { | ||
| 99 | this.LongNames = (0 == (summaryInformationRow.FieldAsInteger(1) & 1)); | ||
| 100 | this.Compressed = (2 == (summaryInformationRow.FieldAsInteger(1) & 2)); | ||
| 101 | } | ||
| 102 | break; | ||
| 103 | case 18: // PID_APPNAME | ||
| 104 | foundCreatingApplication = true; | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | 59 | ||
| 109 | // add a summary information row for the create time/date property if its not already set | 60 | if (String.IsNullOrEmpty(codepage)) |
| 110 | if (!foundCreateDataTime) | 61 | { |
| 111 | { | 62 | codepage = "0"; |
| 112 | Row createTimeDateRow = summaryInformationTable.CreateRow(null); | 63 | } |
| 113 | createTimeDateRow[0] = 12; | 64 | else |
| 114 | createTimeDateRow[1] = now; | 65 | { |
| 115 | } | 66 | summaryInformationRow.Value = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); |
| 67 | } | ||
| 68 | break; | ||
| 69 | case 9: // PID_REVNUMBER | ||
| 70 | var packageCode = summaryInformationRow.Value; | ||
| 116 | 71 | ||
| 117 | // add a summary information row for the last save time/date property if its not already set | 72 | if (SectionType.Module == this.Section.Type) |
| 118 | if (!foundLastSaveDataTime) | 73 | { |
| 119 | { | 74 | this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_'); |
| 120 | Row lastSaveTimeDateRow = summaryInformationTable.CreateRow(null); | 75 | } |
| 121 | lastSaveTimeDateRow[0] = 13; | 76 | else if ("*" == packageCode) |
| 122 | lastSaveTimeDateRow[1] = now; | 77 | { |
| 78 | // set the revision number (package/patch code) if it should be automatically generated | ||
| 79 | summaryInformationRow.Value = Common.GenerateGuid(); | ||
| 80 | } | ||
| 81 | break; | ||
| 82 | case 12: // PID_CREATE_DTM | ||
| 83 | foundCreateDataTime = true; | ||
| 84 | break; | ||
| 85 | case 13: // PID_LASTSAVE_DTM | ||
| 86 | foundLastSaveDataTime = true; | ||
| 87 | break; | ||
| 88 | case 14: | ||
| 89 | this.InstallerVersion = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); | ||
| 90 | break; | ||
| 91 | case 15: // PID_WORDCOUNT | ||
| 92 | if (SectionType.Patch == this.Section.Type) | ||
| 93 | { | ||
| 94 | this.LongNames = true; | ||
| 95 | this.Compressed = true; | ||
| 96 | } | ||
| 97 | else | ||
| 98 | { | ||
| 99 | var attributes = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); | ||
| 100 | this.LongNames = (0 == (attributes & 1)); | ||
| 101 | this.Compressed = (2 == (attributes & 2)); | ||
| 102 | } | ||
| 103 | break; | ||
| 104 | case 18: // PID_APPNAME | ||
| 105 | foundCreatingApplication = true; | ||
| 106 | break; | ||
| 123 | } | 107 | } |
| 108 | } | ||
| 124 | 109 | ||
| 125 | // add a summary information row for the creating application property if its not already set | 110 | // add a summary information row for the create time/date property if its not already set |
| 126 | if (!foundCreatingApplication) | 111 | if (!foundCreateDataTime) |
| 127 | { | 112 | { |
| 128 | Row creatingApplicationRow = summaryInformationTable.CreateRow(null); | 113 | var createTimeDateRow = new _SummaryInformationTuple(null, new Identifier(12, AccessModifier.Private)); |
| 129 | creatingApplicationRow[0] = 18; | 114 | createTimeDateRow.PropertyId = 12; |
| 130 | creatingApplicationRow[1] = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString()); | 115 | createTimeDateRow.Value = now; |
| 131 | } | 116 | |
| 117 | this.Section.Tuples.Add(createTimeDateRow); | ||
| 118 | } | ||
| 119 | |||
| 120 | // add a summary information row for the last save time/date property if its not already set | ||
| 121 | if (!foundLastSaveDataTime) | ||
| 122 | { | ||
| 123 | var lastSaveTimeDateRow = new _SummaryInformationTuple(null, new Identifier(13, AccessModifier.Private)); | ||
| 124 | lastSaveTimeDateRow.PropertyId = 13; | ||
| 125 | lastSaveTimeDateRow.Value = now; | ||
| 126 | |||
| 127 | this.Section.Tuples.Add(lastSaveTimeDateRow); | ||
| 128 | } | ||
| 129 | |||
| 130 | // add a summary information row for the creating application property if its not already set | ||
| 131 | if (!foundCreatingApplication) | ||
| 132 | { | ||
| 133 | var creatingApplicationRow = new _SummaryInformationTuple(null, new Identifier(18, AccessModifier.Private)); | ||
| 134 | creatingApplicationRow.PropertyId = 18; | ||
| 135 | creatingApplicationRow.Value = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString()); | ||
| 136 | |||
| 137 | this.Section.Tuples.Add(creatingApplicationRow); | ||
| 132 | } | 138 | } |
| 133 | } | 139 | } |
| 134 | } | 140 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs index 425d1f9c..b4027834 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs index b2cc76fc..c25a497e 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections; | 6 | using System.Collections; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs index dcafcd36..405b840b 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs | |||
| @@ -1,11 +1,10 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System.Collections.Generic; | 5 | using System.Collections.Generic; |
| 6 | using WixToolset.Core.Bind; | 6 | using WixToolset.Core.Bind; |
| 7 | using WixToolset.Data; | 7 | using WixToolset.Data; |
| 8 | using WixToolset.Data.Rows; | ||
| 9 | 8 | ||
| 10 | /// <summary> | 9 | /// <summary> |
| 11 | /// A cabinet builder work item. | 10 | /// A cabinet builder work item. |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs new file mode 100644 index 00000000..0c0aea1f --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.IO; | ||
| 8 | using System.Linq; | ||
| 9 | using WixToolset.Bind; | ||
| 10 | using WixToolset.Core.Native; | ||
| 11 | using WixToolset.Data; | ||
| 12 | using WixToolset.Data.Tuples; | ||
| 13 | |||
| 14 | /// <summary> | ||
| 15 | /// Set the guids for components with generatable guids. | ||
| 16 | /// </summary> | ||
| 17 | internal class CalculateComponentGuids | ||
| 18 | { | ||
| 19 | public CalculateComponentGuids(IntermediateSection section) | ||
| 20 | { | ||
| 21 | this.Section = section; | ||
| 22 | } | ||
| 23 | |||
| 24 | private IntermediateSection Section { get; } | ||
| 25 | |||
| 26 | public void Execute() | ||
| 27 | { | ||
| 28 | Dictionary<string, RegistryTuple> registryKeyRows = null; | ||
| 29 | Dictionary<string, ResolvedDirectory> targetPathsByDirectoryId = null; | ||
| 30 | Dictionary<string, string> componentIdGenSeeds = null; | ||
| 31 | Dictionary<string, List<FileTuple>> filesByComponentId = null; | ||
| 32 | |||
| 33 | // Find components with generatable guids. | ||
| 34 | foreach (var componentRow in this.Section.Tuples.OfType<ComponentTuple>()) | ||
| 35 | { | ||
| 36 | // Skip components that do not specify generate guid. | ||
| 37 | if (componentRow.ComponentId != "*") | ||
| 38 | { | ||
| 39 | continue; | ||
| 40 | } | ||
| 41 | |||
| 42 | var odbcDataSourceKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesODBCDataSource) != 0; | ||
| 43 | |||
| 44 | if (String.IsNullOrEmpty(componentRow.KeyPath) || odbcDataSourceKeyPath) | ||
| 45 | { | ||
| 46 | Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers)); | ||
| 47 | continue; | ||
| 48 | } | ||
| 49 | |||
| 50 | var registryKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesRegistryKeyPath) != 0; | ||
| 51 | |||
| 52 | if (registryKeyPath) | ||
| 53 | { | ||
| 54 | if (registryKeyRows is null) | ||
| 55 | { | ||
| 56 | registryKeyRows = this.Section.Tuples.OfType<RegistryTuple>().ToDictionary(t => t.Registry); | ||
| 57 | } | ||
| 58 | |||
| 59 | if (registryKeyRows.TryGetValue(componentRow.KeyPath, out var foundRow)) | ||
| 60 | { | ||
| 61 | var is64Bit = (componentRow.Attributes & MsiInterop.MsidbComponentAttributes64bit) != 0; | ||
| 62 | var bitness = is64Bit ? "64" : String.Empty; | ||
| 63 | var regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]); | ||
| 64 | componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant(); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | else // must be a File KeyPath. | ||
| 68 | { | ||
| 69 | // If the directory table hasn't been loaded into an indexed hash | ||
| 70 | // of directory ids to target names do that now. | ||
| 71 | if (targetPathsByDirectoryId is null) | ||
| 72 | { | ||
| 73 | var directories = this.Section.Tuples.OfType<DirectoryTuple>().ToList(); | ||
| 74 | |||
| 75 | targetPathsByDirectoryId = new Dictionary<string, ResolvedDirectory>(directories.Count); | ||
| 76 | |||
| 77 | // Get the target paths for all directories. | ||
| 78 | foreach (var row in directories) | ||
| 79 | { | ||
| 80 | // If the directory Id already exists, we will skip it here since | ||
| 81 | // checking for duplicate primary keys is done later when importing tables | ||
| 82 | // into database | ||
| 83 | if (targetPathsByDirectoryId.ContainsKey(row.Directory)) | ||
| 84 | { | ||
| 85 | continue; | ||
| 86 | } | ||
| 87 | |||
| 88 | var targetName = Common.GetName(row.DefaultDir, false, true); | ||
| 89 | targetPathsByDirectoryId.Add(row.Directory, new ResolvedDirectory(row.Directory_Parent, targetName)); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | // If the component id generation seeds have not been indexed | ||
| 94 | // from the WixDirectory table do that now. | ||
| 95 | if (componentIdGenSeeds is null) | ||
| 96 | { | ||
| 97 | // If there are any WixDirectory rows, build up the Component Guid | ||
| 98 | // generation seeds indexed by Directory/@Id. | ||
| 99 | componentIdGenSeeds = this.Section.Tuples.OfType<WixDirectoryTuple>() | ||
| 100 | .Where(t => !String.IsNullOrEmpty(t.ComponentGuidGenerationSeed)) | ||
| 101 | .ToDictionary(t => t.Directory_, t => t.ComponentGuidGenerationSeed); | ||
| 102 | } | ||
| 103 | |||
| 104 | // if the file rows have not been indexed by File.Component yet | ||
| 105 | // then do that now | ||
| 106 | if (filesByComponentId is null) | ||
| 107 | { | ||
| 108 | var files = this.Section.Tuples.OfType<FileTuple>().ToList(); | ||
| 109 | |||
| 110 | filesByComponentId = new Dictionary<string, List<FileTuple>>(files.Count); | ||
| 111 | |||
| 112 | foreach (var file in files) | ||
| 113 | { | ||
| 114 | if (!filesByComponentId.TryGetValue(file.Component_, out var componentFiles)) | ||
| 115 | { | ||
| 116 | componentFiles = new List<FileTuple>(); | ||
| 117 | filesByComponentId.Add(file.Component_, componentFiles); | ||
| 118 | } | ||
| 119 | |||
| 120 | componentFiles.Add(file); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | // validate component meets all the conditions to have a generated guid | ||
| 125 | var currentComponentFiles = filesByComponentId[componentRow.Component]; | ||
| 126 | var numFilesInComponent = currentComponentFiles.Count; | ||
| 127 | string path = null; | ||
| 128 | |||
| 129 | foreach (var fileRow in currentComponentFiles) | ||
| 130 | { | ||
| 131 | if (fileRow.File == componentRow.KeyPath) | ||
| 132 | { | ||
| 133 | // calculate the key file's canonical target path | ||
| 134 | string directoryPath = Binder.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentRow.Directory_, true); | ||
| 135 | string fileName = Common.GetName(fileRow.LongFileName, false, true).ToLowerInvariant(); | ||
| 136 | path = Path.Combine(directoryPath, fileName); | ||
| 137 | |||
| 138 | // find paths that are not canonicalized | ||
| 139 | if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) || | ||
| 140 | path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) || | ||
| 141 | path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) || | ||
| 142 | path.StartsWith("TARGETDIR", StringComparison.Ordinal) || | ||
| 143 | path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) || | ||
| 144 | path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal)) | ||
| 145 | { | ||
| 146 | Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component_, path)); | ||
| 147 | } | ||
| 148 | |||
| 149 | // if component has more than one file, the key path must be versioned | ||
| 150 | if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version)) | ||
| 151 | { | ||
| 152 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers)); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | else | ||
| 156 | { | ||
| 157 | // not a key path, so it must be an unversioned file if component has more than one file | ||
| 158 | if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version)) | ||
| 159 | { | ||
| 160 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers)); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | // if the rules were followed, reward with a generated guid | ||
| 166 | if (!Messaging.Instance.EncounteredError) | ||
| 167 | { | ||
| 168 | componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant(); | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } | ||
| 172 | } | ||
| 173 | } | ||
| 174 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs index d4d3799f..9a8e2bba 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections; | 6 | using System.Collections; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs index 6388a352..0dcddb99 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| @@ -10,6 +10,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 10 | using WixToolset.Extensibility; | 10 | using WixToolset.Extensibility; |
| 11 | using WixToolset.Core.Native; | 11 | using WixToolset.Core.Native; |
| 12 | using WixToolset.Core.Bind; | 12 | using WixToolset.Core.Bind; |
| 13 | using WixToolset.Data.Tuples; | ||
| 13 | 14 | ||
| 14 | internal class CopyTransformDataCommand | 15 | internal class CopyTransformDataCommand |
| 15 | { | 16 | { |
| @@ -29,7 +30,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 29 | 30 | ||
| 30 | List<FileFacade> allFileRows = this.CopyOutFileRows ? new List<FileFacade>() : null; | 31 | List<FileFacade> allFileRows = this.CopyOutFileRows ? new List<FileFacade>() : null; |
| 31 | 32 | ||
| 32 | #if false // TODO: Fix this patching related code to work correctly with FileFacades. | 33 | #if REVISIT_FOR_PATCHING // TODO: Fix this patching related code to work correctly with FileFacades. |
| 33 | bool copyToPatch = (allFileRows != null); | 34 | bool copyToPatch = (allFileRows != null); |
| 34 | bool copyFromPatch = !copyToPatch; | 35 | bool copyFromPatch = !copyToPatch; |
| 35 | 36 | ||
| @@ -454,7 +455,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 454 | } | 455 | } |
| 455 | 456 | ||
| 456 | Row patchAction = iesTable.CreateRow(null); | 457 | Row patchAction = iesTable.CreateRow(null); |
| 457 | WixActionRow wixPatchAction = WindowsInstallerStandard.GetStandardActions()[table, "PatchFiles"]; | 458 | WixActionRow wixPatchAction = WindowsInstallerStandardInternal.GetStandardActionRows()[table, "PatchFiles"]; |
| 458 | int sequence = wixPatchAction.Sequence; | 459 | int sequence = wixPatchAction.Sequence; |
| 459 | // Test for default sequence value's appropriateness | 460 | // Test for default sequence value's appropriateness |
| 460 | if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence)) | 461 | if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence)) |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs index 02015744..b5a436c5 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| @@ -10,10 +10,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 10 | using System.Runtime.InteropServices; | 10 | using System.Runtime.InteropServices; |
| 11 | using System.Threading; | 11 | using System.Threading; |
| 12 | using WixToolset.Core.Bind; | 12 | using WixToolset.Core.Bind; |
| 13 | using WixToolset.Core.WindowsInstaller.Bind; | ||
| 14 | using WixToolset.Data; | 13 | using WixToolset.Data; |
| 15 | using WixToolset.Data.Bind; | 14 | using WixToolset.Data.Bind; |
| 16 | using WixToolset.Data.Rows; | 15 | using WixToolset.Data.Rows; |
| 16 | using WixToolset.Data.Tuples; | ||
| 17 | using WixToolset.Extensibility; | 17 | using WixToolset.Extensibility; |
| 18 | 18 | ||
| 19 | /// <summary> | 19 | /// <summary> |
| @@ -60,9 +60,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 60 | 60 | ||
| 61 | public bool Compressed { private get; set; } | 61 | public bool Compressed { private get; set; } |
| 62 | 62 | ||
| 63 | public Dictionary<MediaRow, IEnumerable<FileFacade>> FileRowsByCabinet { private get; set; } | 63 | public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileRowsByCabinet { private get; set; } |
| 64 | 64 | ||
| 65 | public Func<MediaRow, string, string, string> ResolveMedia { private get; set; } | 65 | public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; } |
| 66 | 66 | ||
| 67 | public TableDefinitionCollection TableDefinitions { private get; set; } | 67 | public TableDefinitionCollection TableDefinitions { private get; set; } |
| 68 | 68 | ||
| @@ -77,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 77 | /// <returns>The uncompressed file rows.</returns> | 77 | /// <returns>The uncompressed file rows.</returns> |
| 78 | public void Execute() | 78 | public void Execute() |
| 79 | { | 79 | { |
| 80 | RowDictionary<WixMediaRow> wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable); | 80 | var wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable); |
| 81 | 81 | ||
| 82 | this.lastCabinetAddedToMediaTable = new Dictionary<string, string>(); | 82 | this.lastCabinetAddedToMediaTable = new Dictionary<string, string>(); |
| 83 | 83 | ||
| @@ -87,22 +87,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 87 | CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); | 87 | CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); |
| 88 | 88 | ||
| 89 | // Supply Compile MediaTemplate Attributes to Cabinet Builder | 89 | // Supply Compile MediaTemplate Attributes to Cabinet Builder |
| 90 | int MaximumCabinetSizeForLargeFileSplitting; | 90 | this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize); |
| 91 | int MaximumUncompressedMediaSize; | ||
| 92 | this.GetMediaTemplateAttributes(out MaximumCabinetSizeForLargeFileSplitting, out MaximumUncompressedMediaSize); | ||
| 93 | cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting; | 91 | cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting; |
| 94 | cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize; | 92 | cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize; |
| 95 | 93 | ||
| 96 | foreach (var entry in this.FileRowsByCabinet) | 94 | foreach (var entry in this.FileRowsByCabinet) |
| 97 | { | 95 | { |
| 98 | MediaRow mediaRow = entry.Key; | 96 | var mediaRow = entry.Key; |
| 99 | IEnumerable<FileFacade> files = entry.Value; | 97 | IEnumerable<FileFacade> files = entry.Value; |
| 100 | CompressionLevel compressionLevel = this.DefaultCompressionLevel; | 98 | CompressionLevel compressionLevel = this.DefaultCompressionLevel; |
| 101 | 99 | ||
| 102 | WixMediaRow wixMediaRow = null; | ||
| 103 | string mediaLayoutFolder = null; | 100 | string mediaLayoutFolder = null; |
| 104 | 101 | ||
| 105 | if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) | 102 | if (wixMediaRows.TryGetValue(mediaRow.Id.Id, out var wixMediaRow)) |
| 106 | { | 103 | { |
| 107 | mediaLayoutFolder = wixMediaRow.Layout; | 104 | mediaLayoutFolder = wixMediaRow.Layout; |
| 108 | 105 | ||
| @@ -185,7 +182,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 185 | /// <param name="fileFacades">Collection of files in this cabinet.</param> | 182 | /// <param name="fileFacades">Collection of files in this cabinet.</param> |
| 186 | /// <param name="fileTransfers">Array of files to be transfered.</param> | 183 | /// <param name="fileTransfers">Array of files to be transfered.</param> |
| 187 | /// <returns>created CabinetWorkItem object</returns> | 184 | /// <returns>created CabinetWorkItem object</returns> |
| 188 | private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaRow mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades, List<FileTransfer> fileTransfers) | 185 | private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaTuple mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades, List<FileTransfer> fileTransfers) |
| 189 | { | 186 | { |
| 190 | CabinetWorkItem cabinetWorkItem = null; | 187 | CabinetWorkItem cabinetWorkItem = null; |
| 191 | string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); | 188 | string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); |
| @@ -254,8 +251,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 254 | else | 251 | else |
| 255 | { | 252 | { |
| 256 | string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); | 253 | string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); |
| 257 | FileTransfer transfer; | 254 | if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out var transfer)) |
| 258 | if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out transfer)) | ||
| 259 | { | 255 | { |
| 260 | transfer.Built = true; | 256 | transfer.Built = true; |
| 261 | fileTransfers.Add(transfer); | 257 | fileTransfers.Add(transfer); |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs index 42a69310..7c7b07cc 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| @@ -9,49 +9,40 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 9 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
| 10 | using WixToolset.Data; | 10 | using WixToolset.Data; |
| 11 | using WixToolset.Data.Rows; | 11 | using WixToolset.Data.Rows; |
| 12 | using WixToolset.Data.Tuples; | ||
| 12 | 13 | ||
| 13 | /// <summary> | 14 | /// <summary> |
| 14 | /// Creates delta patches and updates the appropriate rows to point to the newly generated patches. | 15 | /// Creates delta patches and updates the appropriate rows to point to the newly generated patches. |
| 15 | /// </summary> | 16 | /// </summary> |
| 16 | internal class CreateDeltaPatchesCommand | 17 | internal class CreateDeltaPatchesCommand |
| 17 | { | 18 | { |
| 18 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 19 | public CreateDeltaPatchesCommand(List<FileFacade> fileFacades, string intermediateFolder, WixPatchIdTuple wixPatchId) |
| 20 | { | ||
| 21 | this.FileFacades = fileFacades; | ||
| 22 | this.IntermediateFolder = intermediateFolder; | ||
| 23 | this.WixPatchId = wixPatchId; | ||
| 24 | } | ||
| 19 | 25 | ||
| 20 | public Table WixPatchIdTable { private get; set; } | 26 | private IEnumerable<FileFacade> FileFacades { get; } |
| 21 | 27 | ||
| 22 | public string TempFilesLocation { private get; set; } | 28 | private WixPatchIdTuple WixPatchId { get; } |
| 29 | |||
| 30 | private string IntermediateFolder { get; } | ||
| 23 | 31 | ||
| 24 | public void Execute() | 32 | public void Execute() |
| 25 | { | 33 | { |
| 26 | #if REVISIT_FOR_PATCHING | 34 | var optimizePatchSizeForLargeFiles = this.WixPatchId?.OptimizePatchSizeForLargeFiles ?? false; |
| 27 | bool optimizePatchSizeForLargeFiles = false; | 35 | var apiPatchingSymbolFlags = (PatchSymbolFlagsType)(this.WixPatchId?.ApiPatchingSymbolFlags ?? 0); |
| 28 | PatchSymbolFlagsType apiPatchingSymbolFlags = 0; | ||
| 29 | |||
| 30 | if (null != this.WixPatchIdTable) | ||
| 31 | { | ||
| 32 | Row row = this.WixPatchIdTable.Rows[0]; | ||
| 33 | if (null != row) | ||
| 34 | { | ||
| 35 | if (null != row[2]) | ||
| 36 | { | ||
| 37 | optimizePatchSizeForLargeFiles = (1 == Convert.ToUInt32(row[2], CultureInfo.InvariantCulture)); | ||
| 38 | } | ||
| 39 | |||
| 40 | if (null != row[3]) | ||
| 41 | { | ||
| 42 | apiPatchingSymbolFlags = (PatchSymbolFlagsType)Convert.ToUInt32(row[3], CultureInfo.InvariantCulture); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | 36 | ||
| 37 | #if REVISIT_FOR_PATCHING | ||
| 47 | foreach (FileFacade facade in this.FileFacades) | 38 | foreach (FileFacade facade in this.FileFacades) |
| 48 | { | 39 | { |
| 49 | if (RowOperation.Modify == facade.File.Operation && | 40 | if (RowOperation.Modify == facade.File.Operation && |
| 50 | 0 != (facade.WixFile.PatchAttributes & PatchAttributeType.IncludeWholeFile)) | 41 | 0 != (facade.WixFile.PatchAttributes & PatchAttributeType.IncludeWholeFile)) |
| 51 | { | 42 | { |
| 52 | string deltaBase = String.Concat("delta_", facade.File.File); | 43 | string deltaBase = String.Concat("delta_", facade.File.File); |
| 53 | string deltaFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".dpf")); | 44 | string deltaFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".dpf")); |
| 54 | string headerFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".phd")); | 45 | string headerFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".phd")); |
| 55 | 46 | ||
| 56 | bool retainRangeWarning = false; | 47 | bool retainRangeWarning = false; |
| 57 | 48 | ||
| @@ -84,6 +75,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 84 | } | 75 | } |
| 85 | } | 76 | } |
| 86 | #endif | 77 | #endif |
| 78 | |||
| 87 | throw new NotImplementedException(); | 79 | throw new NotImplementedException(); |
| 88 | } | 80 | } |
| 89 | } | 81 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs new file mode 100644 index 00000000..85b3b25a --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs | |||
| @@ -0,0 +1,230 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Linq; | ||
| 7 | using WixToolset.Core.Native; | ||
| 8 | using WixToolset.Data; | ||
| 9 | using WixToolset.Data.Rows; | ||
| 10 | using WixToolset.Data.Tuples; | ||
| 11 | |||
| 12 | internal class CreateOutputFromIRCommand | ||
| 13 | { | ||
| 14 | public CreateOutputFromIRCommand(IntermediateSection section, TableDefinitionCollection tableDefinitions) | ||
| 15 | { | ||
| 16 | this.Section = section; | ||
| 17 | this.TableDefinitions = tableDefinitions; | ||
| 18 | } | ||
| 19 | |||
| 20 | private TableDefinitionCollection TableDefinitions { get; } | ||
| 21 | |||
| 22 | private IntermediateSection Section { get; } | ||
| 23 | |||
| 24 | public Output Output { get; private set; } | ||
| 25 | |||
| 26 | public void Execute() | ||
| 27 | { | ||
| 28 | var output = new Output(this.Section.Tuples.First().SourceLineNumbers); | ||
| 29 | output.Codepage = this.Section.Codepage; | ||
| 30 | output.Type = SectionTypeToOutputType(this.Section.Type); | ||
| 31 | |||
| 32 | this.AddSectionToOutput(this.Section, output); | ||
| 33 | |||
| 34 | this.Output = output; | ||
| 35 | } | ||
| 36 | |||
| 37 | private void AddSectionToOutput(IntermediateSection section, Output output) | ||
| 38 | { | ||
| 39 | foreach (var tuple in section.Tuples) | ||
| 40 | { | ||
| 41 | switch (tuple.Definition.Type) | ||
| 42 | { | ||
| 43 | case TupleDefinitionType.File: | ||
| 44 | this.AddFileTuple((FileTuple)tuple, output); | ||
| 45 | break; | ||
| 46 | |||
| 47 | case TupleDefinitionType.WixAction: | ||
| 48 | this.AddWixActionTuple((WixActionTuple)tuple, output); | ||
| 49 | break; | ||
| 50 | |||
| 51 | default: | ||
| 52 | this.AddTupleDefaultly(tuple, output); | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | private void AddFileTuple(FileTuple tuple, Output output) | ||
| 59 | { | ||
| 60 | var table = output.EnsureTable(this.TableDefinitions["File"]); | ||
| 61 | var row = (FileRow)table.CreateRow(tuple.SourceLineNumbers); | ||
| 62 | row.File = tuple.File; | ||
| 63 | row.Component = tuple.Component_; | ||
| 64 | row.FileName = GetMsiFilenameValue(tuple.ShortFileName, tuple.LongFileName); | ||
| 65 | row.FileSize = tuple.FileSize; | ||
| 66 | row.Version = tuple.Version; | ||
| 67 | row.Language = tuple.Language; | ||
| 68 | |||
| 69 | var attributes = tuple.Checksum ? MsiInterop.MsidbFileAttributesChecksum : 0; | ||
| 70 | attributes |= (tuple.Compressed.HasValue && tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesCompressed : 0; | ||
| 71 | attributes |= (tuple.Compressed.HasValue && !tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesNoncompressed : 0; | ||
| 72 | attributes |= tuple.Hidden ? MsiInterop.MsidbFileAttributesHidden : 0; | ||
| 73 | attributes |= tuple.ReadOnly ? MsiInterop.MsidbFileAttributesReadOnly : 0; | ||
| 74 | attributes |= tuple.System ? MsiInterop.MsidbFileAttributesSystem : 0; | ||
| 75 | attributes |= tuple.Vital ? MsiInterop.MsidbFileAttributesVital : 0; | ||
| 76 | row.Attributes = attributes; | ||
| 77 | } | ||
| 78 | |||
| 79 | private void AddWixActionTuple(WixActionTuple actionRow, Output output) | ||
| 80 | { | ||
| 81 | // Get the table definition for the action (and ensure the proper table exists for a module). | ||
| 82 | TableDefinition sequenceTableDefinition = null; | ||
| 83 | switch (actionRow.SequenceTable) | ||
| 84 | { | ||
| 85 | case SequenceTable.AdminExecuteSequence: | ||
| 86 | if (OutputType.Module == output.Type) | ||
| 87 | { | ||
| 88 | output.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]); | ||
| 89 | sequenceTableDefinition = this.TableDefinitions["ModuleAdminExecuteSequence"]; | ||
| 90 | } | ||
| 91 | else | ||
| 92 | { | ||
| 93 | sequenceTableDefinition = this.TableDefinitions["AdminExecuteSequence"]; | ||
| 94 | } | ||
| 95 | break; | ||
| 96 | case SequenceTable.AdminUISequence: | ||
| 97 | if (OutputType.Module == output.Type) | ||
| 98 | { | ||
| 99 | output.EnsureTable(this.TableDefinitions["AdminUISequence"]); | ||
| 100 | sequenceTableDefinition = this.TableDefinitions["ModuleAdminUISequence"]; | ||
| 101 | } | ||
| 102 | else | ||
| 103 | { | ||
| 104 | sequenceTableDefinition = this.TableDefinitions["AdminUISequence"]; | ||
| 105 | } | ||
| 106 | break; | ||
| 107 | case SequenceTable.AdvtExecuteSequence: | ||
| 108 | if (OutputType.Module == output.Type) | ||
| 109 | { | ||
| 110 | output.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]); | ||
| 111 | sequenceTableDefinition = this.TableDefinitions["ModuleAdvtExecuteSequence"]; | ||
| 112 | } | ||
| 113 | else | ||
| 114 | { | ||
| 115 | sequenceTableDefinition = this.TableDefinitions["AdvtExecuteSequence"]; | ||
| 116 | } | ||
| 117 | break; | ||
| 118 | case SequenceTable.InstallExecuteSequence: | ||
| 119 | if (OutputType.Module == output.Type) | ||
| 120 | { | ||
| 121 | output.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]); | ||
| 122 | sequenceTableDefinition = this.TableDefinitions["ModuleInstallExecuteSequence"]; | ||
| 123 | } | ||
| 124 | else | ||
| 125 | { | ||
| 126 | sequenceTableDefinition = this.TableDefinitions["InstallExecuteSequence"]; | ||
| 127 | } | ||
| 128 | break; | ||
| 129 | case SequenceTable.InstallUISequence: | ||
| 130 | if (OutputType.Module == output.Type) | ||
| 131 | { | ||
| 132 | output.EnsureTable(this.TableDefinitions["InstallUISequence"]); | ||
| 133 | sequenceTableDefinition = this.TableDefinitions["ModuleInstallUISequence"]; | ||
| 134 | } | ||
| 135 | else | ||
| 136 | { | ||
| 137 | sequenceTableDefinition = this.TableDefinitions["InstallUISequence"]; | ||
| 138 | } | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | // create the action sequence row in the output | ||
| 143 | var sequenceTable = output.EnsureTable(sequenceTableDefinition); | ||
| 144 | var row = sequenceTable.CreateRow(actionRow.SourceLineNumbers); | ||
| 145 | |||
| 146 | if (SectionType.Module == this.Section.Type) | ||
| 147 | { | ||
| 148 | row[0] = actionRow.Action; | ||
| 149 | if (0 != actionRow.Sequence) | ||
| 150 | { | ||
| 151 | row[1] = actionRow.Sequence; | ||
| 152 | } | ||
| 153 | else | ||
| 154 | { | ||
| 155 | bool after = (null == actionRow.Before); | ||
| 156 | row[2] = after ? actionRow.After : actionRow.Before; | ||
| 157 | row[3] = after ? 1 : 0; | ||
| 158 | } | ||
| 159 | row[4] = actionRow.Condition; | ||
| 160 | } | ||
| 161 | else | ||
| 162 | { | ||
| 163 | row[0] = actionRow.Action; | ||
| 164 | row[1] = actionRow.Condition; | ||
| 165 | row[2] = actionRow.Sequence; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | private void AddTupleDefaultly(IntermediateTuple tuple, Output output) | ||
| 170 | { | ||
| 171 | if (!this.TableDefinitions.TryGet(tuple.Definition.Name, out var tableDefinition)) | ||
| 172 | { | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | var table = output.EnsureTable(tableDefinition); | ||
| 177 | var row = table.CreateRow(tuple.SourceLineNumbers); | ||
| 178 | for (var i = 0; i < tuple.Fields.Length; ++i) | ||
| 179 | { | ||
| 180 | if (i < tableDefinition.Columns.Count) | ||
| 181 | { | ||
| 182 | var column = tableDefinition.Columns[i]; | ||
| 183 | |||
| 184 | switch (column.Type) | ||
| 185 | { | ||
| 186 | case ColumnType.Number: | ||
| 187 | row[i] = tuple.AsNumber(i); | ||
| 188 | break; | ||
| 189 | |||
| 190 | default: | ||
| 191 | row[i] = tuple.AsString(i); | ||
| 192 | break; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | private static OutputType SectionTypeToOutputType(SectionType type) | ||
| 199 | { | ||
| 200 | switch (type) | ||
| 201 | { | ||
| 202 | case SectionType.Bundle: | ||
| 203 | return OutputType.Bundle; | ||
| 204 | case SectionType.Module: | ||
| 205 | return OutputType.Module; | ||
| 206 | case SectionType.Product: | ||
| 207 | return OutputType.Product; | ||
| 208 | case SectionType.PatchCreation: | ||
| 209 | return OutputType.PatchCreation; | ||
| 210 | case SectionType.Patch: | ||
| 211 | return OutputType.Patch; | ||
| 212 | |||
| 213 | default: | ||
| 214 | throw new ArgumentOutOfRangeException(nameof(type)); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | private static string GetMsiFilenameValue(string shortName, string longName) | ||
| 219 | { | ||
| 220 | if (String.IsNullOrEmpty(shortName)) | ||
| 221 | { | ||
| 222 | return longName; | ||
| 223 | } | ||
| 224 | else | ||
| 225 | { | ||
| 226 | return shortName + "|" + longName; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs index aef130b0..ab2e8201 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs | |||
| @@ -1,67 +1,72 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Linq; | ||
| 7 | using WixToolset.Data; | 8 | using WixToolset.Data; |
| 8 | using WixToolset.Data.Rows; | 9 | using WixToolset.Data.Tuples; |
| 9 | 10 | ||
| 10 | internal class CreateSpecialPropertiesCommand | 11 | internal class CreateSpecialPropertiesCommand |
| 11 | { | 12 | { |
| 12 | public Table PropertyTable { private get; set; } | 13 | public CreateSpecialPropertiesCommand(IntermediateSection section) |
| 14 | { | ||
| 15 | this.Section = section; | ||
| 16 | } | ||
| 13 | 17 | ||
| 14 | public Table WixPropertyTable { private get; set; } | 18 | private IntermediateSection Section { get; } |
| 15 | 19 | ||
| 16 | public void Execute() | 20 | public void Execute() |
| 17 | { | 21 | { |
| 18 | // Create the special properties. | 22 | // Create lists of the properties that contribute to the special lists of properties. |
| 19 | if (null != this.WixPropertyTable) | 23 | SortedSet<string> adminProperties = new SortedSet<string>(); |
| 20 | { | 24 | SortedSet<string> secureProperties = new SortedSet<string>(); |
| 21 | // Create lists of the properties that contribute to the special lists of properties. | 25 | SortedSet<string> hiddenProperties = new SortedSet<string>(); |
| 22 | SortedSet<string> adminProperties = new SortedSet<string>(); | ||
| 23 | SortedSet<string> secureProperties = new SortedSet<string>(); | ||
| 24 | SortedSet<string> hiddenProperties = new SortedSet<string>(); | ||
| 25 | 26 | ||
| 26 | foreach (WixPropertyRow wixPropertyRow in this.WixPropertyTable.Rows) | 27 | foreach (var wixPropertyRow in this.Section.Tuples.OfType<WixPropertyTuple>()) |
| 28 | { | ||
| 29 | if (wixPropertyRow.Admin) | ||
| 27 | { | 30 | { |
| 28 | if (wixPropertyRow.Admin) | 31 | adminProperties.Add(wixPropertyRow.Property_); |
| 29 | { | ||
| 30 | adminProperties.Add(wixPropertyRow.Id); | ||
| 31 | } | ||
| 32 | |||
| 33 | if (wixPropertyRow.Hidden) | ||
| 34 | { | ||
| 35 | hiddenProperties.Add(wixPropertyRow.Id); | ||
| 36 | } | ||
| 37 | |||
| 38 | if (wixPropertyRow.Secure) | ||
| 39 | { | ||
| 40 | secureProperties.Add(wixPropertyRow.Id); | ||
| 41 | } | ||
| 42 | } | 32 | } |
| 43 | 33 | ||
| 44 | Table propertyTable = this.PropertyTable; | 34 | if (wixPropertyRow.Hidden) |
| 45 | if (0 < adminProperties.Count) | ||
| 46 | { | 35 | { |
| 47 | PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); | 36 | hiddenProperties.Add(wixPropertyRow.Property_); |
| 48 | row.Property = "AdminProperties"; | ||
| 49 | row.Value = String.Join(";", adminProperties); | ||
| 50 | } | 37 | } |
| 51 | 38 | ||
| 52 | if (0 < secureProperties.Count) | 39 | if (wixPropertyRow.Secure) |
| 53 | { | 40 | { |
| 54 | PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); | 41 | secureProperties.Add(wixPropertyRow.Property_); |
| 55 | row.Property = "SecureCustomProperties"; | ||
| 56 | row.Value = String.Join(";", secureProperties); | ||
| 57 | } | 42 | } |
| 43 | } | ||
| 58 | 44 | ||
| 59 | if (0 < hiddenProperties.Count) | 45 | if (0 < adminProperties.Count) |
| 60 | { | 46 | { |
| 61 | PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); | 47 | var tuple = new PropertyTuple(null, new Identifier("AdminProperties", AccessModifier.Private)); |
| 62 | row.Property = "MsiHiddenProperties"; | 48 | tuple.Property = "AdminProperties"; |
| 63 | row.Value = String.Join(";", hiddenProperties); | 49 | tuple.Value = String.Join(";", adminProperties); |
| 64 | } | 50 | |
| 51 | this.Section.Tuples.Add(tuple); | ||
| 52 | } | ||
| 53 | |||
| 54 | if (0 < secureProperties.Count) | ||
| 55 | { | ||
| 56 | var tuple = new PropertyTuple(null, new Identifier("SecureCustomProperties", AccessModifier.Private)); | ||
| 57 | tuple.Property = "SecureCustomProperties"; | ||
| 58 | tuple.Value = String.Join(";", secureProperties); | ||
| 59 | |||
| 60 | this.Section.Tuples.Add(tuple); | ||
| 61 | } | ||
| 62 | |||
| 63 | if (0 < hiddenProperties.Count) | ||
| 64 | { | ||
| 65 | var tuple = new PropertyTuple(null, new Identifier("MsiHiddenProperties", AccessModifier.Private)); | ||
| 66 | tuple.Property = "MsiHiddenProperties"; | ||
| 67 | tuple.Value = String.Join(";", hiddenProperties); | ||
| 68 | |||
| 69 | this.Section.Tuples.Add(tuple); | ||
| 65 | } | 70 | } |
| 66 | } | 71 | } |
| 67 | } | 72 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs index 0d3e7bd1..32d1cfda 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| @@ -10,7 +10,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 10 | using System.Linq; | 10 | using System.Linq; |
| 11 | using System.Runtime.InteropServices; | 11 | using System.Runtime.InteropServices; |
| 12 | using WixToolset.Data; | 12 | using WixToolset.Data; |
| 13 | using WixToolset.Data.Rows; | ||
| 14 | using WixToolset.MergeMod; | 13 | using WixToolset.MergeMod; |
| 15 | using WixToolset.Msi; | 14 | using WixToolset.Msi; |
| 16 | using WixToolset.Core.Native; | 15 | using WixToolset.Core.Native; |
| @@ -23,13 +22,17 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 23 | /// </summary> | 22 | /// </summary> |
| 24 | internal class ExtractMergeModuleFilesCommand | 23 | internal class ExtractMergeModuleFilesCommand |
| 25 | { | 24 | { |
| 26 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 25 | public ExtractMergeModuleFilesCommand(IntermediateSection section, List<WixMergeTuple> wixMergeTuples) |
| 26 | { | ||
| 27 | this.Section = section; | ||
| 28 | this.WixMergeTuples = wixMergeTuples; | ||
| 29 | } | ||
| 27 | 30 | ||
| 28 | public Table FileTable { private get; set; } | 31 | private IntermediateSection Section { get; } |
| 29 | 32 | ||
| 30 | public Table WixFileTable { private get; set; } | 33 | private List<WixMergeTuple> WixMergeTuples { get; } |
| 31 | 34 | ||
| 32 | public Table WixMergeTable { private get; set; } | 35 | public IEnumerable<FileFacade> FileFacades { private get; set; } |
| 33 | 36 | ||
| 34 | public int OutputInstallerVersion { private get; set; } | 37 | public int OutputInstallerVersion { private get; set; } |
| 35 | 38 | ||
| @@ -41,7 +44,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 41 | 44 | ||
| 42 | public void Execute() | 45 | public void Execute() |
| 43 | { | 46 | { |
| 44 | List<FileFacade> mergeModulesFileFacades = new List<FileFacade>(); | 47 | var mergeModulesFileFacades = new List<FileFacade>(); |
| 45 | 48 | ||
| 46 | IMsmMerge2 merge = MsmInterop.GetMsmMerge(); | 49 | IMsmMerge2 merge = MsmInterop.GetMsmMerge(); |
| 47 | 50 | ||
| @@ -52,9 +55,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 52 | // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let | 55 | // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let |
| 53 | // this case be slightly more expensive because the cost of maintaining an indexed file row collection | 56 | // this case be slightly more expensive because the cost of maintaining an indexed file row collection |
| 54 | // is a lot more costly for the common cases. | 57 | // is a lot more costly for the common cases. |
| 55 | Dictionary<string, FileFacade> indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal); | 58 | var indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal); |
| 56 | 59 | ||
| 57 | foreach (WixMergeRow wixMergeRow in this.WixMergeTable.Rows) | 60 | foreach (var wixMergeRow in this.WixMergeTuples) |
| 58 | { | 61 | { |
| 59 | bool containsFiles = this.CreateFacadesForMergeModuleFiles(wixMergeRow, mergeModulesFileFacades, indexedFileFacades); | 62 | bool containsFiles = this.CreateFacadesForMergeModuleFiles(wixMergeRow, mergeModulesFileFacades, indexedFileFacades); |
| 60 | 63 | ||
| @@ -68,7 +71,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 68 | this.MergeModulesFileFacades = mergeModulesFileFacades; | 71 | this.MergeModulesFileFacades = mergeModulesFileFacades; |
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | private bool CreateFacadesForMergeModuleFiles(WixMergeRow wixMergeRow, List<FileFacade> mergeModulesFileFacades, Dictionary<string, FileFacade> indexedFileFacades) | 74 | private bool CreateFacadesForMergeModuleFiles(WixMergeTuple wixMergeRow, List<FileFacade> mergeModulesFileFacades, Dictionary<string, FileFacade> indexedFileFacades) |
| 72 | { | 75 | { |
| 73 | bool containsFiles = false; | 76 | bool containsFiles = false; |
| 74 | 77 | ||
| @@ -98,7 +101,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 98 | // rows are created by merging in the actual modules. | 101 | // rows are created by merging in the actual modules. |
| 99 | var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(record[1], AccessModifier.Private)); | 102 | var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(record[1], AccessModifier.Private)); |
| 100 | fileRow.File = record[1]; | 103 | fileRow.File = record[1]; |
| 101 | fileRow.Compressed = (wixMergeRow.FileCompression == YesNoType.Yes) ? true : (wixMergeRow.FileCompression == YesNoType.No) ? (bool?)false : null; | 104 | fileRow.Compressed = wixMergeRow.FileCompression; |
| 102 | //FileRow fileRow = (FileRow)this.FileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); | 105 | //FileRow fileRow = (FileRow)this.FileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); |
| 103 | //fileRow.File = record[1]; | 106 | //fileRow.File = record[1]; |
| 104 | //fileRow.Compressed = wixMergeRow.FileCompression; | 107 | //fileRow.Compressed = wixMergeRow.FileCompression; |
| @@ -107,7 +110,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 107 | wixFileRow.Directory_ = record[2]; | 110 | wixFileRow.Directory_ = record[2]; |
| 108 | wixFileRow.DiskId = wixMergeRow.DiskId; | 111 | wixFileRow.DiskId = wixMergeRow.DiskId; |
| 109 | wixFileRow.PatchGroup = -1; | 112 | wixFileRow.PatchGroup = -1; |
| 110 | wixFileRow.Source = Path.Combine(this.IntermediateFolder, "MergeId.", wixMergeRow.Number.ToString(CultureInfo.InvariantCulture), record[1]); | 113 | wixFileRow.Source = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]); |
| 111 | //WixFileRow wixFileRow = (WixFileRow)this.WixFileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); | 114 | //WixFileRow wixFileRow = (WixFileRow)this.WixFileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); |
| 112 | //wixFileRow.Directory = record[2]; | 115 | //wixFileRow.Directory = record[2]; |
| 113 | //wixFileRow.DiskId = wixMergeRow.DiskId; | 116 | //wixFileRow.DiskId = wixMergeRow.DiskId; |
| @@ -119,11 +122,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 119 | // If case-sensitive collision with another merge module or a user-authored file identifier. | 122 | // If case-sensitive collision with another merge module or a user-authored file identifier. |
| 120 | if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade)) | 123 | if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade)) |
| 121 | { | 124 | { |
| 122 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, collidingFacade.File.File)); | 125 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.File)); |
| 123 | } | 126 | } |
| 124 | else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module | 127 | else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module |
| 125 | { | 128 | { |
| 126 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); | 129 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); |
| 127 | } | 130 | } |
| 128 | else // no collision | 131 | else // no collision |
| 129 | { | 132 | { |
| @@ -150,12 +153,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 150 | int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture); | 153 | int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture); |
| 151 | if (moduleInstallerVersion > this.OutputInstallerVersion) | 154 | if (moduleInstallerVersion > this.OutputInstallerVersion) |
| 152 | { | 155 | { |
| 153 | Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleInstallerVersion, this.OutputInstallerVersion)); | 156 | Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, moduleInstallerVersion, this.OutputInstallerVersion)); |
| 154 | } | 157 | } |
| 155 | } | 158 | } |
| 156 | catch (FormatException) | 159 | catch (FormatException) |
| 157 | { | 160 | { |
| 158 | throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile, moduleInstallerVersionString)); | 161 | throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile, moduleInstallerVersionString)); |
| 159 | } | 162 | } |
| 160 | } | 163 | } |
| 161 | } | 164 | } |
| @@ -166,24 +169,26 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 166 | } | 169 | } |
| 167 | catch (Win32Exception) | 170 | catch (Win32Exception) |
| 168 | { | 171 | { |
| 169 | throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile)); | 172 | throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile)); |
| 170 | } | 173 | } |
| 171 | 174 | ||
| 172 | return containsFiles; | 175 | return containsFiles; |
| 173 | } | 176 | } |
| 174 | 177 | ||
| 175 | private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeRow wixMergeRow) | 178 | private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeTuple wixMergeRow) |
| 176 | { | 179 | { |
| 177 | bool moduleOpen = false; | 180 | bool moduleOpen = false; |
| 178 | short mergeLanguage; | 181 | short mergeLanguage; |
| 179 | 182 | ||
| 183 | var mergeId = wixMergeRow.Id.Id; | ||
| 184 | |||
| 180 | try | 185 | try |
| 181 | { | 186 | { |
| 182 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); | 187 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); |
| 183 | } | 188 | } |
| 184 | catch (System.FormatException) | 189 | catch (FormatException) |
| 185 | { | 190 | { |
| 186 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); | 191 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, mergeId, wixMergeRow.Language.ToString())); |
| 187 | return; | 192 | return; |
| 188 | } | 193 | } |
| 189 | 194 | ||
| @@ -192,13 +197,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 192 | merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage); | 197 | merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage); |
| 193 | moduleOpen = true; | 198 | moduleOpen = true; |
| 194 | 199 | ||
| 195 | string safeMergeId = wixMergeRow.Number.ToString(CultureInfo.InvariantCulture.NumberFormat); | ||
| 196 | |||
| 197 | // extract the module cabinet, then explode all of the files to a temp directory | 200 | // extract the module cabinet, then explode all of the files to a temp directory |
| 198 | string moduleCabPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, safeMergeId, ".module.cab"); | 201 | string moduleCabPath = Path.Combine(this.IntermediateFolder, mergeId + ".cab"); |
| 199 | merge.ExtractCAB(moduleCabPath); | 202 | merge.ExtractCAB(moduleCabPath); |
| 200 | 203 | ||
| 201 | string mergeIdPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, "MergeId.", safeMergeId); | 204 | string mergeIdPath = Path.Combine(this.IntermediateFolder, mergeId); |
| 202 | Directory.CreateDirectory(mergeIdPath); | 205 | Directory.CreateDirectory(mergeIdPath); |
| 203 | 206 | ||
| 204 | using (var extractCab = new WixExtractCab()) | 207 | using (var extractCab = new WixExtractCab()) |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs index 47b58058..a3d3ecf7 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs index 9bbb4763..70ba971f 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| @@ -8,57 +8,50 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 8 | using System.Linq; | 8 | using System.Linq; |
| 9 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
| 10 | using WixToolset.Data; | 10 | using WixToolset.Data; |
| 11 | using WixToolset.Data.Rows; | 11 | using WixToolset.Data.Tuples; |
| 12 | 12 | ||
| 13 | internal class GetFileFacadesCommand | 13 | internal class GetFileFacadesCommand |
| 14 | { | 14 | { |
| 15 | public Table FileTable { private get; set; } | 15 | public GetFileFacadesCommand(IntermediateSection section) |
| 16 | 16 | { | |
| 17 | public Table WixFileTable { private get; set; } | 17 | this.Section = section; |
| 18 | 18 | } | |
| 19 | public Table WixDeltaPatchFileTable { private get; set; } | ||
| 20 | 19 | ||
| 21 | public Table WixDeltaPatchSymbolPathsTable { private get; set; } | 20 | private IntermediateSection Section { get; } |
| 22 | 21 | ||
| 23 | public List<FileFacade> FileFacades { get; private set; } | 22 | public List<FileFacade> FileFacades { get; private set; } |
| 24 | 23 | ||
| 25 | public void Execute() | 24 | public void Execute() |
| 26 | { | 25 | { |
| 27 | throw new NotImplementedException(); | 26 | var facades = new List<FileFacade>(); |
| 28 | #if TODO | ||
| 29 | List<FileFacade> facades = new List<FileFacade>(this.FileTable.Rows.Count); | ||
| 30 | 27 | ||
| 31 | RowDictionary<WixFileRow> wixFiles = new RowDictionary<WixFileRow>(this.WixFileTable); | 28 | var wixFiles = this.Section.Tuples.OfType<WixFileTuple>().ToDictionary(t => t.File_); |
| 32 | RowDictionary<WixDeltaPatchFileRow> deltaPatchFiles = new RowDictionary<WixDeltaPatchFileRow>(this.WixDeltaPatchFileTable); | 29 | var deltaPatchFiles = this.Section.Tuples.OfType<WixDeltaPatchFileTuple>().ToDictionary(t => t.File_); |
| 33 | 30 | ||
| 34 | foreach (FileRow file in this.FileTable.Rows) | 31 | foreach (var file in this.Section.Tuples.OfType<FileTuple>()) |
| 35 | { | 32 | { |
| 36 | WixDeltaPatchFileRow deltaPatchFile = null; | 33 | var wixFile = wixFiles[file.File]; |
| 37 | 34 | ||
| 38 | deltaPatchFiles.TryGetValue(file.File, out deltaPatchFile); | 35 | deltaPatchFiles.TryGetValue(file.File, out var deltaPatchFile); |
| 39 | 36 | ||
| 40 | facades.Add(new FileFacade(file, wixFiles[file.File], deltaPatchFile)); | 37 | facades.Add(new FileFacade(file, wixFile, deltaPatchFile)); |
| 41 | } | 38 | } |
| 42 | 39 | ||
| 43 | if (null != this.WixDeltaPatchSymbolPathsTable) | 40 | this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades); |
| 44 | { | ||
| 45 | this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades); | ||
| 46 | } | ||
| 47 | 41 | ||
| 48 | this.FileFacades = facades; | 42 | this.FileFacades = facades; |
| 49 | #endif | ||
| 50 | } | 43 | } |
| 51 | 44 | ||
| 52 | /// <summary> | 45 | /// <summary> |
| 53 | /// Merge data from the WixPatchSymbolPaths rows into the WixDeltaPatchFile rows. | 46 | /// Merge data from the WixPatchSymbolPaths rows into the WixDeltaPatchFile rows. |
| 54 | /// </summary> | 47 | /// </summary> |
| 55 | public RowDictionary<WixDeltaPatchFileRow> ResolveDeltaPatchSymbolPaths(RowDictionary<WixDeltaPatchFileRow> deltaPatchFiles, IEnumerable<FileFacade> facades) | 48 | public void ResolveDeltaPatchSymbolPaths(Dictionary<string, WixDeltaPatchFileTuple> deltaPatchFiles, IEnumerable<FileFacade> facades) |
| 56 | { | 49 | { |
| 57 | ILookup<string, FileFacade> filesByComponent = null; | 50 | ILookup<string, FileFacade> filesByComponent = null; |
| 58 | ILookup<string, FileFacade> filesByDirectory = null; | 51 | ILookup<string, FileFacade> filesByDirectory = null; |
| 59 | ILookup<string, FileFacade> filesByDiskId = null; | 52 | ILookup<string, FileFacade> filesByDiskId = null; |
| 60 | 53 | ||
| 61 | foreach (WixDeltaPatchSymbolPathsRow row in this.WixDeltaPatchSymbolPathsTable.RowsAs<WixDeltaPatchSymbolPathsRow>().OrderBy(r => r.Type)) | 54 | foreach (var row in this.Section.Tuples.OfType<WixDeltaPatchSymbolPathsTuple>().OrderBy(r => r.Type)) |
| 62 | { | 55 | { |
| 63 | switch (row.Type) | 56 | switch (row.Type) |
| 64 | { | 57 | { |
| @@ -72,7 +65,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 72 | filesByComponent = facades.ToLookup(f => f.File.Component_); | 65 | filesByComponent = facades.ToLookup(f => f.File.Component_); |
| 73 | } | 66 | } |
| 74 | 67 | ||
| 75 | foreach (FileFacade facade in filesByComponent[row.Id]) | 68 | foreach (var facade in filesByComponent[row.Id]) |
| 76 | { | 69 | { |
| 77 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); | 70 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); |
| 78 | } | 71 | } |
| @@ -84,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 84 | filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_); | 77 | filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_); |
| 85 | } | 78 | } |
| 86 | 79 | ||
| 87 | foreach (FileFacade facade in filesByDirectory[row.Id]) | 80 | foreach (var facade in filesByDirectory[row.Id]) |
| 88 | { | 81 | { |
| 89 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); | 82 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); |
| 90 | } | 83 | } |
| @@ -96,14 +89,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 96 | filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture)); | 89 | filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture)); |
| 97 | } | 90 | } |
| 98 | 91 | ||
| 99 | foreach (FileFacade facade in filesByDiskId[row.Id]) | 92 | foreach (var facade in filesByDiskId[row.Id]) |
| 100 | { | 93 | { |
| 101 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); | 94 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); |
| 102 | } | 95 | } |
| 103 | break; | 96 | break; |
| 104 | 97 | ||
| 105 | case SymbolPathType.Product: | 98 | case SymbolPathType.Product: |
| 106 | foreach (WixDeltaPatchFileRow fileRow in deltaPatchFiles.Values) | 99 | foreach (var fileRow in deltaPatchFiles.Values) |
| 107 | { | 100 | { |
| 108 | this.MergeSymbolPaths(row, fileRow); | 101 | this.MergeSymbolPaths(row, fileRow); |
| 109 | } | 102 | } |
| @@ -114,8 +107,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 114 | break; | 107 | break; |
| 115 | } | 108 | } |
| 116 | } | 109 | } |
| 117 | |||
| 118 | return deltaPatchFiles; | ||
| 119 | } | 110 | } |
| 120 | 111 | ||
| 121 | /// <summary> | 112 | /// <summary> |
| @@ -124,17 +115,18 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 124 | /// <param name="row">Row from the WixPatchSymbolsPaths table.</param> | 115 | /// <param name="row">Row from the WixPatchSymbolsPaths table.</param> |
| 125 | /// <param name="file">FileRow into which to set symbol information.</param> | 116 | /// <param name="file">FileRow into which to set symbol information.</param> |
| 126 | /// <comment>This includes PreviousData as well.</comment> | 117 | /// <comment>This includes PreviousData as well.</comment> |
| 127 | private void MergeSymbolPaths(WixDeltaPatchSymbolPathsRow row, WixDeltaPatchFileRow file) | 118 | private void MergeSymbolPaths(WixDeltaPatchSymbolPathsTuple row, WixDeltaPatchFileTuple file) |
| 128 | { | 119 | { |
| 129 | if (null == file.Symbols) | 120 | if (file.SymbolPaths is null) |
| 130 | { | 121 | { |
| 131 | file.Symbols = row.SymbolPaths; | 122 | file.SymbolPaths = row.SymbolPaths; |
| 132 | } | 123 | } |
| 133 | else | 124 | else |
| 134 | { | 125 | { |
| 135 | file.Symbols = String.Concat(file.Symbols, ";", row.SymbolPaths); | 126 | file.SymbolPaths = String.Concat(file.SymbolPaths, ";", row.SymbolPaths); |
| 136 | } | 127 | } |
| 137 | 128 | ||
| 129 | #if REVISIT_FOR_PATCHING | ||
| 138 | Field field = row.Fields[2]; | 130 | Field field = row.Fields[2]; |
| 139 | if (null != field.PreviousData) | 131 | if (null != field.PreviousData) |
| 140 | { | 132 | { |
| @@ -147,6 +139,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 147 | file.PreviousSymbols = String.Concat(file.PreviousSymbols, ";", field.PreviousData); | 139 | file.PreviousSymbols = String.Concat(file.PreviousSymbols, ";", field.PreviousData); |
| 148 | } | 140 | } |
| 149 | } | 141 | } |
| 142 | #endif | ||
| 150 | } | 143 | } |
| 151 | } | 144 | } |
| 152 | } | 145 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs index f1605eca..dcf67c05 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs | |||
| @@ -1,20 +1,13 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Collections.Specialized; | ||
| 8 | using System.ComponentModel; | ||
| 9 | using System.Diagnostics; | ||
| 10 | using System.Globalization; | 7 | using System.Globalization; |
| 11 | using System.IO; | 8 | using System.IO; |
| 12 | using System.Linq; | ||
| 13 | using System.Runtime.InteropServices; | 9 | using System.Runtime.InteropServices; |
| 14 | using System.Text; | 10 | using System.Text; |
| 15 | using System.Xml; | ||
| 16 | using System.Xml.XPath; | ||
| 17 | using WixToolset.Clr.Interop; | ||
| 18 | using WixToolset.Data; | 11 | using WixToolset.Data; |
| 19 | using WixToolset.Data.Rows; | 12 | using WixToolset.Data.Rows; |
| 20 | using WixToolset.MergeMod; | 13 | using WixToolset.MergeMod; |
| @@ -35,12 +28,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 35 | 28 | ||
| 36 | public IEnumerable<string> SuppressedTableNames { private get; set; } | 29 | public IEnumerable<string> SuppressedTableNames { private get; set; } |
| 37 | 30 | ||
| 38 | public string TempFilesLocation { private get; set; } | 31 | public string IntermediateFolder { private get; set; } |
| 39 | 32 | ||
| 40 | public void Execute() | 33 | public void Execute() |
| 41 | { | 34 | { |
| 42 | Debug.Assert(OutputType.Product == this.Output.Type); | ||
| 43 | |||
| 44 | Table wixMergeTable = this.Output.Tables["WixMerge"]; | 35 | Table wixMergeTable = this.Output.Tables["WixMerge"]; |
| 45 | Table wixFeatureModulesTable = this.Output.Tables["WixFeatureModules"]; | 36 | Table wixFeatureModulesTable = this.Output.Tables["WixFeatureModules"]; |
| 46 | 37 | ||
| @@ -59,7 +50,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 59 | { | 50 | { |
| 60 | merge = MsmInterop.GetMsmMerge(); | 51 | merge = MsmInterop.GetMsmMerge(); |
| 61 | 52 | ||
| 62 | logPath = Path.Combine(this.TempFilesLocation, "merge.log"); | 53 | logPath = Path.Combine(this.IntermediateFolder, "merge.log"); |
| 63 | merge.OpenLog(logPath); | 54 | merge.OpenLog(logPath); |
| 64 | logOpen = true; | 55 | logOpen = true; |
| 65 | 56 | ||
| @@ -79,7 +70,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 79 | { | 70 | { |
| 80 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); | 71 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); |
| 81 | } | 72 | } |
| 82 | catch (System.FormatException) | 73 | catch (FormatException) |
| 83 | { | 74 | { |
| 84 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); | 75 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); |
| 85 | continue; | 76 | continue; |
| @@ -284,7 +275,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 284 | Messaging.Instance.OnMessage(WixVerboses.ResequencingMergeModuleFiles()); | 275 | Messaging.Instance.OnMessage(WixVerboses.ResequencingMergeModuleFiles()); |
| 285 | using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?")) | 276 | using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?")) |
| 286 | { | 277 | { |
| 287 | foreach (FileFacade file in this.FileFacades) | 278 | foreach (var file in this.FileFacades) |
| 288 | { | 279 | { |
| 289 | if (!file.FromModule) | 280 | if (!file.FromModule) |
| 290 | { | 281 | { |
| @@ -307,32 +298,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 307 | //recordUpdate.SetInteger(1, file.File.Sequence); | 298 | //recordUpdate.SetInteger(1, file.File.Sequence); |
| 308 | throw new NotImplementedException(); | 299 | throw new NotImplementedException(); |
| 309 | 300 | ||
| 310 | // update the file attributes to match the compression specified | 301 | // Update the file attributes to match the compression specified |
| 311 | // on the Merge element or on the Package element | 302 | // on the Merge element or on the Package element. |
| 312 | int attributes = 0; | 303 | var attributes = 0; |
| 313 | 304 | ||
| 314 | // get the current value if its not null | 305 | // Get the current value if its not null. |
| 315 | if (!recordUpdate.IsNull(2)) | 306 | if (!recordUpdate.IsNull(2)) |
| 316 | { | 307 | { |
| 317 | attributes = recordUpdate.GetInteger(2); | 308 | attributes = recordUpdate.GetInteger(2); |
| 318 | } | 309 | } |
| 319 | 310 | ||
| 320 | // not specified | ||
| 321 | if (!file.File.Compressed.HasValue) | 311 | if (!file.File.Compressed.HasValue) |
| 322 | { | 312 | { |
| 323 | // clear any compression bits | 313 | // Clear all compression bits. |
| 324 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; | 314 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; |
| 325 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; | 315 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; |
| 326 | } | 316 | } |
| 327 | else if (file.File.Compressed.Value) | 317 | else if (file.File.Compressed.Value) |
| 328 | { | 318 | { |
| 329 | // these are mutually exclusive | ||
| 330 | attributes |= MsiInterop.MsidbFileAttributesCompressed; | 319 | attributes |= MsiInterop.MsidbFileAttributesCompressed; |
| 331 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; | 320 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; |
| 332 | } | 321 | } |
| 333 | else if (!file.File.Compressed.Value) | 322 | else if (!file.File.Compressed.Value) |
| 334 | { | 323 | { |
| 335 | // these are mutually exclusive | ||
| 336 | attributes |= MsiInterop.MsidbFileAttributesNoncompressed; | 324 | attributes |= MsiInterop.MsidbFileAttributesNoncompressed; |
| 337 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; | 325 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; |
| 338 | } | 326 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs index b3c09b9e..d71724d1 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs | |||
| @@ -1,39 +1,42 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 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.IO; | 7 | using System.IO; |
| 9 | using WixToolset.Data; | 8 | using WixToolset.Data; |
| 10 | using WixToolset.Data.Rows; | ||
| 11 | using WixToolset.Msi; | 9 | using WixToolset.Msi; |
| 12 | using WixToolset.Core.Native; | 10 | using WixToolset.Core.Native; |
| 13 | using WixToolset.Bind; | 11 | using WixToolset.Bind; |
| 14 | using WixToolset.Core.Bind; | 12 | using WixToolset.Core.Bind; |
| 15 | using WixToolset.Data.Bind; | 13 | using WixToolset.Data.Bind; |
| 14 | using WixToolset.Data.Tuples; | ||
| 15 | using System.Linq; | ||
| 16 | 16 | ||
| 17 | /// <summary> | 17 | /// <summary> |
| 18 | /// Defines the file transfers necessary to layout the uncompressed files. | 18 | /// Defines the file transfers necessary to layout the uncompressed files. |
| 19 | /// </summary> | 19 | /// </summary> |
| 20 | internal class ProcessUncompressedFilesCommand | 20 | internal class ProcessUncompressedFilesCommand |
| 21 | { | 21 | { |
| 22 | public ProcessUncompressedFilesCommand(IntermediateSection section) | ||
| 23 | { | ||
| 24 | this.Section = section; | ||
| 25 | } | ||
| 26 | |||
| 27 | private IntermediateSection Section { get; } | ||
| 28 | |||
| 22 | public string DatabasePath { private get; set; } | 29 | public string DatabasePath { private get; set; } |
| 23 | 30 | ||
| 24 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 31 | public IEnumerable<FileFacade> FileFacades { private get; set; } |
| 25 | 32 | ||
| 26 | public RowDictionary<MediaRow> MediaRows { private get; set; } | ||
| 27 | |||
| 28 | public string LayoutDirectory { private get; set; } | 33 | public string LayoutDirectory { private get; set; } |
| 29 | 34 | ||
| 30 | public bool Compressed { private get; set; } | 35 | public bool Compressed { private get; set; } |
| 31 | 36 | ||
| 32 | public bool LongNamesInImage { private get; set; } | 37 | public bool LongNamesInImage { private get; set; } |
| 33 | 38 | ||
| 34 | public Func<MediaRow, string, string, string> ResolveMedia { private get; set; } | 39 | public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; } |
| 35 | |||
| 36 | public Table WixMediaTable { private get; set; } | ||
| 37 | 40 | ||
| 38 | public IEnumerable<FileTransfer> FileTransfers { get; private set; } | 41 | public IEnumerable<FileTransfer> FileTransfers { get; private set; } |
| 39 | 42 | ||
| @@ -41,9 +44,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 41 | { | 44 | { |
| 42 | List<FileTransfer> fileTransfers = new List<FileTransfer>(); | 45 | List<FileTransfer> fileTransfers = new List<FileTransfer>(); |
| 43 | 46 | ||
| 44 | Hashtable directories = new Hashtable(); | 47 | var directories = new Dictionary<string, ResolvedDirectory>(); |
| 45 | 48 | ||
| 46 | RowDictionary<WixMediaRow> wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable); | 49 | var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId); |
| 50 | |||
| 51 | var wixMediaRows = this.Section.Tuples.OfType<WixMediaTuple>().ToDictionary(t => t.DiskId_); | ||
| 47 | 52 | ||
| 48 | using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) | 53 | using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) |
| 49 | { | 54 | { |
| @@ -72,18 +77,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 72 | // for each file in the array of uncompressed files | 77 | // for each file in the array of uncompressed files |
| 73 | foreach (FileFacade facade in this.FileFacades) | 78 | foreach (FileFacade facade in this.FileFacades) |
| 74 | { | 79 | { |
| 75 | MediaRow mediaRow = this.MediaRows.Get(facade.WixFile.DiskId); | 80 | var mediaTuple = mediaRows[facade.WixFile.DiskId]; |
| 76 | string relativeFileLayoutPath = null; | 81 | string relativeFileLayoutPath = null; |
| 77 | |||
| 78 | WixMediaRow wixMediaRow = null; | ||
| 79 | string mediaLayoutFolder = null; | 82 | string mediaLayoutFolder = null; |
| 80 | 83 | ||
| 81 | if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) | 84 | if (wixMediaRows.TryGetValue(facade.WixFile.DiskId, out var wixMediaRow)) |
| 82 | { | 85 | { |
| 83 | mediaLayoutFolder = wixMediaRow.Layout; | 86 | mediaLayoutFolder = wixMediaRow.Layout; |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | string mediaLayoutDirectory = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory); | 89 | var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory); |
| 87 | 90 | ||
| 88 | // setup up the query record and find the appropriate file in the | 91 | // setup up the query record and find the appropriate file in the |
| 89 | // previously executed file view | 92 | // previously executed file view |
| @@ -102,8 +105,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 102 | 105 | ||
| 103 | // finally put together the base media layout path and the relative file layout path | 106 | // finally put together the base media layout path and the relative file layout path |
| 104 | string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); | 107 | string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); |
| 105 | FileTransfer transfer; | 108 | if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out var transfer)) |
| 106 | if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out transfer)) | ||
| 107 | { | 109 | { |
| 108 | fileTransfers.Add(transfer); | 110 | fileTransfers.Add(transfer); |
| 109 | } | 111 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs new file mode 100644 index 00000000..cf9c0332 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs | |||
| @@ -0,0 +1,671 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.Globalization; | ||
| 8 | using System.Linq; | ||
| 9 | using WixToolset.Core.Native; | ||
| 10 | using WixToolset.Data; | ||
| 11 | using WixToolset.Data.Tuples; | ||
| 12 | |||
| 13 | internal class SequenceActionsCommand | ||
| 14 | { | ||
| 15 | public SequenceActionsCommand(IntermediateSection section) | ||
| 16 | { | ||
| 17 | this.Section = section; | ||
| 18 | |||
| 19 | this.RelativeActionsForActions = new Dictionary<string, RelativeActions>(); | ||
| 20 | |||
| 21 | this.StandardActionsById = WindowsInstallerStandard.StandardActions().ToDictionary(a => a.Id.Id); | ||
| 22 | } | ||
| 23 | |||
| 24 | private IntermediateSection Section { get; } | ||
| 25 | |||
| 26 | private Dictionary<string, RelativeActions> RelativeActionsForActions { get; } | ||
| 27 | |||
| 28 | private Dictionary<string, WixActionTuple> StandardActionsById { get; } | ||
| 29 | |||
| 30 | public Messaging Messaging { private get; set; } | ||
| 31 | |||
| 32 | public void Execute() | ||
| 33 | { | ||
| 34 | var actions = this.Section.Tuples.OfType<WixActionTuple>().ToList(); | ||
| 35 | var suppressActions = this.Section.Tuples.OfType<WixSuppressActionTuple>().ToList(); | ||
| 36 | |||
| 37 | this.SequenceActions(actions, suppressActions); | ||
| 38 | } | ||
| 39 | |||
| 40 | /// <summary> | ||
| 41 | /// Set sequence numbers for all the actions and create rows in the output object. | ||
| 42 | /// </summary> | ||
| 43 | /// <param name="actionRows">Collection of actions to schedule.</param> | ||
| 44 | /// <param name="suppressActionRows">Collection of actions to suppress.</param> | ||
| 45 | private void SequenceActions(List<WixActionTuple> actionRows, List<WixSuppressActionTuple> suppressActionRows) | ||
| 46 | { | ||
| 47 | var overridableActionRows = new Dictionary<string, WixActionTuple>(); | ||
| 48 | var requiredActionRows = new Dictionary<string, WixActionTuple>(); | ||
| 49 | |||
| 50 | // Get the standard actions required based on tuples in the section. | ||
| 51 | var requiredActionIds = this.GetRequiredActionIds(); | ||
| 52 | |||
| 53 | foreach (var actionId in requiredActionIds) | ||
| 54 | { | ||
| 55 | var standardAction = this.StandardActionsById[actionId]; | ||
| 56 | |||
| 57 | overridableActionRows.Add(standardAction.Id.Id, standardAction); | ||
| 58 | } | ||
| 59 | |||
| 60 | // Index all the action rows and look for collisions. | ||
| 61 | foreach (var actionRow in this.Section.Tuples.OfType<WixActionTuple>()) | ||
| 62 | { | ||
| 63 | if (actionRow.Overridable) // overridable action | ||
| 64 | { | ||
| 65 | if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) | ||
| 66 | { | ||
| 67 | this.Messaging.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
| 68 | if (null != collidingActionRow.SourceLineNumbers) | ||
| 69 | { | ||
| 70 | this.Messaging.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers)); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | else | ||
| 74 | { | ||
| 75 | overridableActionRows.Add(actionRow.Id.Id, actionRow); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | else // unsequenced or sequenced action. | ||
| 79 | { | ||
| 80 | // Unsequenced action (allowed for certain standard actions). | ||
| 81 | if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence) | ||
| 82 | { | ||
| 83 | if (this.StandardActionsById.TryGetValue(actionRow.Id.Id, out var standardAction)) | ||
| 84 | { | ||
| 85 | // Populate the sequence from the standard action | ||
| 86 | actionRow.Sequence = standardAction.Sequence; | ||
| 87 | } | ||
| 88 | else // not a supported unscheduled action. | ||
| 89 | { | ||
| 90 | throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) | ||
| 95 | { | ||
| 96 | this.Messaging.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
| 97 | if (null != collidingActionRow.SourceLineNumbers) | ||
| 98 | { | ||
| 99 | this.Messaging.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers)); | ||
| 100 | } | ||
| 101 | } | ||
| 102 | else | ||
| 103 | { | ||
| 104 | requiredActionRows.Add(actionRow.Id.Id, actionRow); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | // Add the overridable action rows that are not overridden to the required action rows. | ||
| 110 | foreach (var actionRow in overridableActionRows.Values) | ||
| 111 | { | ||
| 112 | if (!requiredActionRows.ContainsKey(actionRow.Id.Id)) | ||
| 113 | { | ||
| 114 | requiredActionRows.Add(actionRow.Id.Id, actionRow); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | // Suppress the required actions that are overridable. | ||
| 119 | foreach (var suppressActionRow in suppressActionRows) | ||
| 120 | { | ||
| 121 | var key = suppressActionRow.Id.Id; | ||
| 122 | |||
| 123 | // If there is an overridable row to suppress; suppress it. There is no warning if there | ||
| 124 | // is no action to suppress because the action may be suppressed from a merge module in | ||
| 125 | // the binder. | ||
| 126 | if (requiredActionRows.TryGetValue(key, out var requiredActionRow)) | ||
| 127 | { | ||
| 128 | if (requiredActionRow.Overridable) | ||
| 129 | { | ||
| 130 | this.Messaging.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, suppressActionRow.Action, suppressActionRow.SequenceTable.ToString())); | ||
| 131 | if (null != requiredActionRow.SourceLineNumbers) | ||
| 132 | { | ||
| 133 | this.Messaging.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers)); | ||
| 134 | } | ||
| 135 | |||
| 136 | requiredActionRows.Remove(key); | ||
| 137 | } | ||
| 138 | else // suppressing a non-overridable action row | ||
| 139 | { | ||
| 140 | this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, suppressActionRow.SequenceTable.ToString(), suppressActionRow.Action)); | ||
| 141 | if (null != requiredActionRow.SourceLineNumbers) | ||
| 142 | { | ||
| 143 | this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers)); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | // Build up dependency trees of the relatively scheduled actions. | ||
| 150 | // Use ToList() to create a copy of the required action rows so that new tuples can | ||
| 151 | // be added while enumerating. | ||
| 152 | foreach (var actionRow in requiredActionRows.Values.ToList()) | ||
| 153 | { | ||
| 154 | if (0 == actionRow.Sequence) | ||
| 155 | { | ||
| 156 | // check for standard actions that don't have a sequence number in a merge module | ||
| 157 | if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action)) | ||
| 158 | { | ||
| 159 | this.Messaging.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
| 160 | } | ||
| 161 | |||
| 162 | this.SequenceActionRow(actionRow, requiredActionRows); | ||
| 163 | } | ||
| 164 | else if (SectionType.Module == this.Section.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number | ||
| 165 | { | ||
| 166 | this.Messaging.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | // Look for standard actions with sequence restrictions that aren't necessarily scheduled based | ||
| 171 | // on the presence of a particular table. | ||
| 172 | if (requiredActionRows.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionRows.ContainsKey("InstallExecuteSequence/InstallFiles")) | ||
| 173 | { | ||
| 174 | var standardAction = this.StandardActionsById["InstallExecuteSequence/InstallFiles"]; | ||
| 175 | requiredActionRows.Add(standardAction.Id.Id, standardAction); | ||
| 176 | } | ||
| 177 | |||
| 178 | // Schedule actions. | ||
| 179 | List<WixActionTuple> scheduledActionRows; | ||
| 180 | if (SectionType.Module == this.Section.Type) | ||
| 181 | { | ||
| 182 | scheduledActionRows = requiredActionRows.Values.ToList(); | ||
| 183 | } | ||
| 184 | else | ||
| 185 | { | ||
| 186 | scheduledActionRows = ScheduleActions(requiredActionRows); | ||
| 187 | } | ||
| 188 | |||
| 189 | // Remove all existing WixActionTuples from the section then add the | ||
| 190 | // scheduled actions back to the section. Note: we add the indices in | ||
| 191 | // reverse order to make it easy to remove them from the list later. | ||
| 192 | var removeIndices = new List<int>(); | ||
| 193 | for (var i = this.Section.Tuples.Count - 1; i >= 0; --i) | ||
| 194 | { | ||
| 195 | var tuple = this.Section.Tuples[i]; | ||
| 196 | if (tuple.Definition.Type == TupleDefinitionType.WixAction) | ||
| 197 | { | ||
| 198 | removeIndices.Add(i); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | foreach (var removeIndex in removeIndices) | ||
| 203 | { | ||
| 204 | this.Section.Tuples.RemoveAt(removeIndex); | ||
| 205 | } | ||
| 206 | |||
| 207 | foreach (var action in scheduledActionRows) | ||
| 208 | { | ||
| 209 | this.Section.Tuples.Add(action); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | private List<WixActionTuple> ScheduleActions(Dictionary<string, WixActionTuple> requiredActionRows) | ||
| 214 | { | ||
| 215 | var scheduledActionRows = new List<WixActionTuple>(); | ||
| 216 | |||
| 217 | // Process each sequence table individually. | ||
| 218 | foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable))) | ||
| 219 | { | ||
| 220 | // Create a collection of just the action rows in this sequence | ||
| 221 | var sequenceActionRows = requiredActionRows.Values.Where(a => a.SequenceTable == sequenceTable).ToList(); | ||
| 222 | |||
| 223 | // Schedule the absolutely scheduled actions (by sorting them by their sequence numbers). | ||
| 224 | var absoluteActionRows = new List<WixActionTuple>(); | ||
| 225 | foreach (var actionRow in sequenceActionRows) | ||
| 226 | { | ||
| 227 | if (0 != actionRow.Sequence) | ||
| 228 | { | ||
| 229 | // Look for sequence number collisions | ||
| 230 | foreach (var sequenceScheduledActionRow in absoluteActionRows) | ||
| 231 | { | ||
| 232 | if (sequenceScheduledActionRow.Sequence == actionRow.Sequence) | ||
| 233 | { | ||
| 234 | this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence)); | ||
| 235 | if (null != sequenceScheduledActionRow.SourceLineNumbers) | ||
| 236 | { | ||
| 237 | this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers)); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | absoluteActionRows.Add(actionRow); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | absoluteActionRows.Sort((x, y) => x.Sequence.CompareTo(y.Sequence)); | ||
| 247 | |||
| 248 | // Schedule the relatively scheduled actions (by resolving the dependency trees). | ||
| 249 | var previousUsedSequence = 0; | ||
| 250 | var relativeActionRows = new List<WixActionTuple>(); | ||
| 251 | for (int j = 0; j < absoluteActionRows.Count; j++) | ||
| 252 | { | ||
| 253 | var absoluteActionRow = absoluteActionRows[j]; | ||
| 254 | |||
| 255 | // Get all the relatively scheduled action rows occuring before and after this absolutely scheduled action row. | ||
| 256 | var relativeActions = this.GetAllRelativeActionsForSequenceType(sequenceTable, absoluteActionRow); | ||
| 257 | |||
| 258 | // Check for relatively scheduled actions occuring before/after a special action | ||
| 259 | // (those actions with a negative sequence number). | ||
| 260 | if (absoluteActionRow.Sequence < 0 && (relativeActions.PreviousActions.Any() || relativeActions.NextActions.Any())) | ||
| 261 | { | ||
| 262 | // Create errors for all the before actions. | ||
| 263 | foreach (var actionRow in relativeActions.PreviousActions) | ||
| 264 | { | ||
| 265 | this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); | ||
| 266 | } | ||
| 267 | |||
| 268 | // Create errors for all the after actions. | ||
| 269 | foreach (var actionRow in relativeActions.NextActions) | ||
| 270 | { | ||
| 271 | this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); | ||
| 272 | } | ||
| 273 | |||
| 274 | // If there is source line information for the absolutely scheduled action display it | ||
| 275 | if (absoluteActionRow.SourceLineNumbers != null) | ||
| 276 | { | ||
| 277 | this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers)); | ||
| 278 | } | ||
| 279 | |||
| 280 | continue; | ||
| 281 | } | ||
| 282 | |||
| 283 | // Schedule the action rows before this one. | ||
| 284 | var unusedSequence = absoluteActionRow.Sequence - 1; | ||
| 285 | for (var i = relativeActions.PreviousActions.Count - 1; i >= 0; i--) | ||
| 286 | { | ||
| 287 | var relativeActionRow = relativeActions.PreviousActions[i]; | ||
| 288 | |||
| 289 | // look for collisions | ||
| 290 | if (unusedSequence == previousUsedSequence) | ||
| 291 | { | ||
| 292 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); | ||
| 293 | if (absoluteActionRow.SourceLineNumbers != null) | ||
| 294 | { | ||
| 295 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); | ||
| 296 | } | ||
| 297 | |||
| 298 | unusedSequence++; | ||
| 299 | } | ||
| 300 | |||
| 301 | relativeActionRow.Sequence = unusedSequence; | ||
| 302 | relativeActionRows.Add(relativeActionRow); | ||
| 303 | |||
| 304 | unusedSequence--; | ||
| 305 | } | ||
| 306 | |||
| 307 | // Determine the next used action sequence number. | ||
| 308 | var nextUsedSequence = Int16.MaxValue + 1; | ||
| 309 | if (absoluteActionRows.Count > j + 1) | ||
| 310 | { | ||
| 311 | nextUsedSequence = absoluteActionRows[j + 1].Sequence; | ||
| 312 | } | ||
| 313 | |||
| 314 | // Schedule the action rows after this one. | ||
| 315 | unusedSequence = absoluteActionRow.Sequence + 1; | ||
| 316 | for (var i = 0; i < relativeActions.NextActions.Count; i++) | ||
| 317 | { | ||
| 318 | var relativeActionRow = relativeActions.NextActions[i]; | ||
| 319 | |||
| 320 | if (unusedSequence == nextUsedSequence) | ||
| 321 | { | ||
| 322 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); | ||
| 323 | if (absoluteActionRow.SourceLineNumbers != null) | ||
| 324 | { | ||
| 325 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); | ||
| 326 | } | ||
| 327 | |||
| 328 | unusedSequence--; | ||
| 329 | } | ||
| 330 | |||
| 331 | relativeActionRow.Sequence = unusedSequence; | ||
| 332 | relativeActionRows.Add(relativeActionRow); | ||
| 333 | |||
| 334 | unusedSequence++; | ||
| 335 | } | ||
| 336 | |||
| 337 | // keep track of this sequence number as the previous used sequence number for the next iteration | ||
| 338 | previousUsedSequence = absoluteActionRow.Sequence; | ||
| 339 | } | ||
| 340 | |||
| 341 | // add the absolutely and relatively scheduled actions to the list of scheduled actions | ||
| 342 | scheduledActionRows.AddRange(absoluteActionRows); | ||
| 343 | scheduledActionRows.AddRange(relativeActionRows); | ||
| 344 | } | ||
| 345 | |||
| 346 | return scheduledActionRows; | ||
| 347 | } | ||
| 348 | |||
| 349 | private IEnumerable<string> GetRequiredActionIds() | ||
| 350 | { | ||
| 351 | var set = new HashSet<string>(); | ||
| 352 | |||
| 353 | // gather the required actions for the output type | ||
| 354 | if (SectionType.Product == this.Section.Type) | ||
| 355 | { | ||
| 356 | // AdminExecuteSequence table | ||
| 357 | set.Add("AdminExecuteSequence/CostFinalize"); | ||
| 358 | set.Add("AdminExecuteSequence/CostInitialize"); | ||
| 359 | set.Add("AdminExecuteSequence/FileCost"); | ||
| 360 | set.Add("AdminExecuteSequence/InstallAdminPackage"); | ||
| 361 | set.Add("AdminExecuteSequence/InstallFiles"); | ||
| 362 | set.Add("AdminExecuteSequence/InstallFinalize"); | ||
| 363 | set.Add("AdminExecuteSequence/InstallInitialize"); | ||
| 364 | set.Add("AdminExecuteSequence/InstallValidate"); | ||
| 365 | |||
| 366 | // AdminUISequence table | ||
| 367 | set.Add("AdminUISequence/CostFinalize"); | ||
| 368 | set.Add("AdminUISequence/CostInitialize"); | ||
| 369 | set.Add("AdminUISequence/ExecuteAction"); | ||
| 370 | set.Add("AdminUISequence/FileCost"); | ||
| 371 | |||
| 372 | // AdvtExecuteSequence table | ||
| 373 | set.Add("AdvtExecuteSequence/CostFinalize"); | ||
| 374 | set.Add("AdvtExecuteSequence/CostInitialize"); | ||
| 375 | set.Add("AdvtExecuteSequence/InstallFinalize"); | ||
| 376 | set.Add("AdvtExecuteSequence/InstallValidate"); | ||
| 377 | set.Add("AdvtExecuteSequence/PublishFeatures"); | ||
| 378 | set.Add("AdvtExecuteSequence/PublishProduct"); | ||
| 379 | |||
| 380 | // InstallExecuteSequence table | ||
| 381 | set.Add("InstallExecuteSequence/CostFinalize"); | ||
| 382 | set.Add("InstallExecuteSequence/CostInitialize"); | ||
| 383 | set.Add("InstallExecuteSequence/FileCost"); | ||
| 384 | set.Add("InstallExecuteSequence/InstallFinalize"); | ||
| 385 | set.Add("InstallExecuteSequence/InstallInitialize"); | ||
| 386 | set.Add("InstallExecuteSequence/InstallValidate"); | ||
| 387 | set.Add("InstallExecuteSequence/ProcessComponents"); | ||
| 388 | set.Add("InstallExecuteSequence/PublishFeatures"); | ||
| 389 | set.Add("InstallExecuteSequence/PublishProduct"); | ||
| 390 | set.Add("InstallExecuteSequence/RegisterProduct"); | ||
| 391 | set.Add("InstallExecuteSequence/RegisterUser"); | ||
| 392 | set.Add("InstallExecuteSequence/UnpublishFeatures"); | ||
| 393 | set.Add("InstallExecuteSequence/ValidateProductID"); | ||
| 394 | |||
| 395 | // InstallUISequence table | ||
| 396 | set.Add("InstallUISequence/CostFinalize"); | ||
| 397 | set.Add("InstallUISequence/CostInitialize"); | ||
| 398 | set.Add("InstallUISequence/ExecuteAction"); | ||
| 399 | set.Add("InstallUISequence/FileCost"); | ||
| 400 | set.Add("InstallUISequence/ValidateProductID"); | ||
| 401 | } | ||
| 402 | |||
| 403 | // Gather the required actions for each tuple type. | ||
| 404 | foreach (var tupleType in this.Section.Tuples.Select(t => t.Definition.Type).Distinct()) | ||
| 405 | { | ||
| 406 | switch (tupleType) | ||
| 407 | { | ||
| 408 | case TupleDefinitionType.AppSearch: | ||
| 409 | set.Add("InstallExecuteSequence/AppSearch"); | ||
| 410 | set.Add("InstallUISequence/AppSearch"); | ||
| 411 | break; | ||
| 412 | case TupleDefinitionType.BindImage: | ||
| 413 | set.Add("InstallExecuteSequence/BindImage"); | ||
| 414 | break; | ||
| 415 | case TupleDefinitionType.CCPSearch: | ||
| 416 | set.Add("InstallExecuteSequence/AppSearch"); | ||
| 417 | set.Add("InstallExecuteSequence/CCPSearch"); | ||
| 418 | set.Add("InstallExecuteSequence/RMCCPSearch"); | ||
| 419 | set.Add("InstallUISequence/AppSearch"); | ||
| 420 | set.Add("InstallUISequence/CCPSearch"); | ||
| 421 | set.Add("InstallUISequence/RMCCPSearch"); | ||
| 422 | break; | ||
| 423 | case TupleDefinitionType.Class: | ||
| 424 | set.Add("AdvtExecuteSequence/RegisterClassInfo"); | ||
| 425 | set.Add("InstallExecuteSequence/RegisterClassInfo"); | ||
| 426 | set.Add("InstallExecuteSequence/UnregisterClassInfo"); | ||
| 427 | break; | ||
| 428 | case TupleDefinitionType.Complus: | ||
| 429 | set.Add("InstallExecuteSequence/RegisterComPlus"); | ||
| 430 | set.Add("InstallExecuteSequence/UnregisterComPlus"); | ||
| 431 | break; | ||
| 432 | case TupleDefinitionType.CreateFolder: | ||
| 433 | set.Add("InstallExecuteSequence/CreateFolders"); | ||
| 434 | set.Add("InstallExecuteSequence/RemoveFolders"); | ||
| 435 | break; | ||
| 436 | case TupleDefinitionType.DuplicateFile: | ||
| 437 | set.Add("InstallExecuteSequence/DuplicateFiles"); | ||
| 438 | set.Add("InstallExecuteSequence/RemoveDuplicateFiles"); | ||
| 439 | break; | ||
| 440 | case TupleDefinitionType.Environment: | ||
| 441 | set.Add("InstallExecuteSequence/WriteEnvironmentStrings"); | ||
| 442 | set.Add("InstallExecuteSequence/RemoveEnvironmentStrings"); | ||
| 443 | break; | ||
| 444 | case TupleDefinitionType.Extension: | ||
| 445 | set.Add("AdvtExecuteSequence/RegisterExtensionInfo"); | ||
| 446 | set.Add("InstallExecuteSequence/RegisterExtensionInfo"); | ||
| 447 | set.Add("InstallExecuteSequence/UnregisterExtensionInfo"); | ||
| 448 | break; | ||
| 449 | case TupleDefinitionType.File: | ||
| 450 | set.Add("InstallExecuteSequence/InstallFiles"); | ||
| 451 | set.Add("InstallExecuteSequence/RemoveFiles"); | ||
| 452 | break; | ||
| 453 | case TupleDefinitionType.Font: | ||
| 454 | set.Add("InstallExecuteSequence/RegisterFonts"); | ||
| 455 | set.Add("InstallExecuteSequence/UnregisterFonts"); | ||
| 456 | break; | ||
| 457 | case TupleDefinitionType.IniFile: | ||
| 458 | case TupleDefinitionType.RemoveIniFile: | ||
| 459 | set.Add("InstallExecuteSequence/WriteIniValues"); | ||
| 460 | set.Add("InstallExecuteSequence/RemoveIniValues"); | ||
| 461 | break; | ||
| 462 | case TupleDefinitionType.IsolatedComponent: | ||
| 463 | set.Add("InstallExecuteSequence/IsolateComponents"); | ||
| 464 | break; | ||
| 465 | case TupleDefinitionType.LaunchCondition: | ||
| 466 | set.Add("InstallExecuteSequence/LaunchConditions"); | ||
| 467 | set.Add("InstallUISequence/LaunchConditions"); | ||
| 468 | break; | ||
| 469 | case TupleDefinitionType.MIME: | ||
| 470 | set.Add("AdvtExecuteSequence/RegisterMIMEInfo"); | ||
| 471 | set.Add("InstallExecuteSequence/RegisterMIMEInfo"); | ||
| 472 | set.Add("InstallExecuteSequence/UnregisterMIMEInfo"); | ||
| 473 | break; | ||
| 474 | case TupleDefinitionType.MoveFile: | ||
| 475 | set.Add("InstallExecuteSequence/MoveFiles"); | ||
| 476 | break; | ||
| 477 | case TupleDefinitionType.MsiAssembly: | ||
| 478 | set.Add("AdvtExecuteSequence/MsiPublishAssemblies"); | ||
| 479 | set.Add("InstallExecuteSequence/MsiPublishAssemblies"); | ||
| 480 | set.Add("InstallExecuteSequence/MsiUnpublishAssemblies"); | ||
| 481 | break; | ||
| 482 | case TupleDefinitionType.MsiServiceConfig: | ||
| 483 | case TupleDefinitionType.MsiServiceConfigFailureActions: | ||
| 484 | set.Add("InstallExecuteSequence/MsiConfigureServices"); | ||
| 485 | break; | ||
| 486 | case TupleDefinitionType.ODBCDataSource: | ||
| 487 | case TupleDefinitionType.ODBCTranslator: | ||
| 488 | case TupleDefinitionType.ODBCDriver: | ||
| 489 | set.Add("InstallExecuteSequence/SetODBCFolders"); | ||
| 490 | set.Add("InstallExecuteSequence/InstallODBC"); | ||
| 491 | set.Add("InstallExecuteSequence/RemoveODBC"); | ||
| 492 | break; | ||
| 493 | case TupleDefinitionType.ProgId: | ||
| 494 | set.Add("AdvtExecuteSequence/RegisterProgIdInfo"); | ||
| 495 | set.Add("InstallExecuteSequence/RegisterProgIdInfo"); | ||
| 496 | set.Add("InstallExecuteSequence/UnregisterProgIdInfo"); | ||
| 497 | break; | ||
| 498 | case TupleDefinitionType.PublishComponent: | ||
| 499 | set.Add("AdvtExecuteSequence/PublishComponents"); | ||
| 500 | set.Add("InstallExecuteSequence/PublishComponents"); | ||
| 501 | set.Add("InstallExecuteSequence/UnpublishComponents"); | ||
| 502 | break; | ||
| 503 | case TupleDefinitionType.Registry: | ||
| 504 | case TupleDefinitionType.RemoveRegistry: | ||
| 505 | set.Add("InstallExecuteSequence/WriteRegistryValues"); | ||
| 506 | set.Add("InstallExecuteSequence/RemoveRegistryValues"); | ||
| 507 | break; | ||
| 508 | case TupleDefinitionType.RemoveFile: | ||
| 509 | set.Add("InstallExecuteSequence/RemoveFiles"); | ||
| 510 | break; | ||
| 511 | case TupleDefinitionType.SelfReg: | ||
| 512 | set.Add("InstallExecuteSequence/SelfRegModules"); | ||
| 513 | set.Add("InstallExecuteSequence/SelfUnregModules"); | ||
| 514 | break; | ||
| 515 | case TupleDefinitionType.ServiceControl: | ||
| 516 | set.Add("InstallExecuteSequence/StartServices"); | ||
| 517 | set.Add("InstallExecuteSequence/StopServices"); | ||
| 518 | set.Add("InstallExecuteSequence/DeleteServices"); | ||
| 519 | break; | ||
| 520 | case TupleDefinitionType.ServiceInstall: | ||
| 521 | set.Add("InstallExecuteSequence/InstallServices"); | ||
| 522 | break; | ||
| 523 | case TupleDefinitionType.Shortcut: | ||
| 524 | set.Add("AdvtExecuteSequence/CreateShortcuts"); | ||
| 525 | set.Add("InstallExecuteSequence/CreateShortcuts"); | ||
| 526 | set.Add("InstallExecuteSequence/RemoveShortcuts"); | ||
| 527 | break; | ||
| 528 | case TupleDefinitionType.TypeLib: | ||
| 529 | set.Add("InstallExecuteSequence/RegisterTypeLibraries"); | ||
| 530 | set.Add("InstallExecuteSequence/UnregisterTypeLibraries"); | ||
| 531 | break; | ||
| 532 | case TupleDefinitionType.Upgrade: | ||
| 533 | set.Add("InstallExecuteSequence/FindRelatedProducts"); | ||
| 534 | set.Add("InstallUISequence/FindRelatedProducts"); | ||
| 535 | |||
| 536 | // Only add the MigrateFeatureStates action if MigrateFeature attribute is set on | ||
| 537 | // at least one UpgradeVersion element. | ||
| 538 | if (this.Section.Tuples.OfType<UpgradeTuple>().Any(t => (t.Attributes & MsiInterop.MsidbUpgradeAttributesMigrateFeatures) == MsiInterop.MsidbUpgradeAttributesMigrateFeatures)) | ||
| 539 | { | ||
| 540 | set.Add("InstallExecuteSequence/MigrateFeatureStates"); | ||
| 541 | set.Add("InstallUISequence/MigrateFeatureStates"); | ||
| 542 | } | ||
| 543 | break; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | return set; | ||
| 548 | } | ||
| 549 | |||
| 550 | private IEnumerable<WixActionTuple> GetActions(SequenceTable sequence, string[] actionNames) | ||
| 551 | { | ||
| 552 | foreach (var action in WindowsInstallerStandard.StandardActions()) | ||
| 553 | { | ||
| 554 | if (action.SequenceTable == sequence && actionNames.Contains(action.Action)) | ||
| 555 | { | ||
| 556 | yield return action; | ||
| 557 | } | ||
| 558 | } | ||
| 559 | } | ||
| 560 | |||
| 561 | /// <summary> | ||
| 562 | /// Sequence an action before or after a standard action. | ||
| 563 | /// </summary> | ||
| 564 | /// <param name="actionRow">The action row to be sequenced.</param> | ||
| 565 | /// <param name="requiredActionRows">Collection of actions which must be included.</param> | ||
| 566 | private void SequenceActionRow(WixActionTuple actionRow, Dictionary<string, WixActionTuple> requiredActionRows) | ||
| 567 | { | ||
| 568 | var after = false; | ||
| 569 | |||
| 570 | if (actionRow.After != null) | ||
| 571 | { | ||
| 572 | after = true; | ||
| 573 | } | ||
| 574 | else if (actionRow.Before == null) | ||
| 575 | { | ||
| 576 | throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); | ||
| 577 | } | ||
| 578 | |||
| 579 | var parentActionName = (after ? actionRow.After : actionRow.Before); | ||
| 580 | var parentActionKey = actionRow.SequenceTable.ToString() + "/" + parentActionName; | ||
| 581 | |||
| 582 | if (!requiredActionRows.TryGetValue(parentActionKey, out var parentActionRow)) | ||
| 583 | { | ||
| 584 | // If the missing parent action is a standard action (with a suggested sequence number), add it. | ||
| 585 | if (this.StandardActionsById.TryGetValue(parentActionKey, out parentActionRow)) | ||
| 586 | { | ||
| 587 | // Create a clone to avoid modifying the static copy of the object. | ||
| 588 | // TODO: consider this: parentActionRow = parentActionRow.Clone(); | ||
| 589 | |||
| 590 | requiredActionRows.Add(parentActionRow.Id.Id, parentActionRow); | ||
| 591 | } | ||
| 592 | else | ||
| 593 | { | ||
| 594 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_FoundActionRowWinNonExistentAction, (after ? "After" : "Before"), parentActionName)); | ||
| 595 | } | ||
| 596 | } | ||
| 597 | else if (actionRow == parentActionRow || this.ContainsChildActionRow(actionRow, parentActionRow)) // cycle detected | ||
| 598 | { | ||
| 599 | throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action)); | ||
| 600 | } | ||
| 601 | |||
| 602 | // Add this action to the appropriate list of dependent action rows. | ||
| 603 | var relativeActions = this.GetRelativeActions(parentActionRow); | ||
| 604 | var relatedRows = (after ? relativeActions.NextActions : relativeActions.PreviousActions); | ||
| 605 | relatedRows.Add(actionRow); | ||
| 606 | } | ||
| 607 | |||
| 608 | private bool ContainsChildActionRow(WixActionTuple childTuple, WixActionTuple parentTuple) | ||
| 609 | { | ||
| 610 | var result = false; | ||
| 611 | |||
| 612 | if (this.RelativeActionsForActions.TryGetValue(childTuple.Id.Id, out var relativeActions)) | ||
| 613 | { | ||
| 614 | result = relativeActions.NextActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id) || | ||
| 615 | relativeActions.PreviousActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id); | ||
| 616 | } | ||
| 617 | |||
| 618 | return result; | ||
| 619 | } | ||
| 620 | |||
| 621 | private RelativeActions GetRelativeActions(WixActionTuple action) | ||
| 622 | { | ||
| 623 | if (!this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var relativeActions)) | ||
| 624 | { | ||
| 625 | relativeActions = new RelativeActions(); | ||
| 626 | this.RelativeActionsForActions.Add(action.Id.Id, relativeActions); | ||
| 627 | } | ||
| 628 | |||
| 629 | return relativeActions; | ||
| 630 | } | ||
| 631 | |||
| 632 | private RelativeActions GetAllRelativeActionsForSequenceType(SequenceTable sequenceType, WixActionTuple action) | ||
| 633 | { | ||
| 634 | var relativeActions = new RelativeActions(); | ||
| 635 | |||
| 636 | if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives)) | ||
| 637 | { | ||
| 638 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, relativeActions.PreviousActions); | ||
| 639 | |||
| 640 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, relativeActions.NextActions); | ||
| 641 | } | ||
| 642 | |||
| 643 | return relativeActions; | ||
| 644 | } | ||
| 645 | |||
| 646 | private void RecurseRelativeActionsForSequenceType(SequenceTable sequenceType, List<WixActionTuple> actions, List<WixActionTuple> visitedActions) | ||
| 647 | { | ||
| 648 | foreach (var action in actions.Where(a => a.SequenceTable == sequenceType)) | ||
| 649 | { | ||
| 650 | if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives)) | ||
| 651 | { | ||
| 652 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, visitedActions); | ||
| 653 | } | ||
| 654 | |||
| 655 | visitedActions.Add(action); | ||
| 656 | |||
| 657 | if (actionRelatives != null) | ||
| 658 | { | ||
| 659 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, visitedActions); | ||
| 660 | } | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | private class RelativeActions | ||
| 665 | { | ||
| 666 | public List<WixActionTuple> PreviousActions { get; } = new List<WixActionTuple>(); | ||
| 667 | |||
| 668 | public List<WixActionTuple> NextActions { get; } = new List<WixActionTuple>(); | ||
| 669 | } | ||
| 670 | } | ||
| 671 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs index 7da32206..9579e0f8 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.IO; | 6 | using System.IO; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs index 20058597..030bc4cc 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Collections.Specialized; | ||
| 8 | using System.ComponentModel; | 7 | using System.ComponentModel; |
| 9 | using System.Globalization; | 8 | using System.Globalization; |
| 10 | using System.IO; | 9 | using System.IO; |
| @@ -14,7 +13,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 14 | using WixToolset.Clr.Interop; | 13 | using WixToolset.Clr.Interop; |
| 15 | using WixToolset.Core.Bind; | 14 | using WixToolset.Core.Bind; |
| 16 | using WixToolset.Data; | 15 | using WixToolset.Data; |
| 17 | using WixToolset.Data.Rows; | ||
| 18 | using WixToolset.Data.Tuples; | 16 | using WixToolset.Data.Tuples; |
| 19 | using WixToolset.Msi; | 17 | using WixToolset.Msi; |
| 20 | 18 | ||
| @@ -23,13 +21,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 23 | /// </summary> | 21 | /// </summary> |
| 24 | internal class UpdateFileFacadesCommand | 22 | internal class UpdateFileFacadesCommand |
| 25 | { | 23 | { |
| 26 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 24 | public UpdateFileFacadesCommand(IntermediateSection section) |
| 25 | { | ||
| 26 | this.Section = section; | ||
| 27 | } | ||
| 27 | 28 | ||
| 28 | public IEnumerable<FileFacade> UpdateFileFacades { private get; set; } | 29 | private IntermediateSection Section { get; } |
| 29 | 30 | ||
| 30 | public string ModularizationGuid { private get; set; } | 31 | public IEnumerable<FileFacade> FileFacades { private get; set; } |
| 31 | 32 | ||
| 32 | public Output Output { private get; set; } | 33 | public IEnumerable<FileFacade> UpdateFileFacades { private get; set; } |
| 33 | 34 | ||
| 34 | public bool OverwriteHash { private get; set; } | 35 | public bool OverwriteHash { private get; set; } |
| 35 | 36 | ||
| @@ -47,6 +48,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 47 | 48 | ||
| 48 | private void UpdateFileFacade(FileFacade file) | 49 | private void UpdateFileFacade(FileFacade file) |
| 49 | { | 50 | { |
| 51 | var assemblyNameTuples = new Dictionary<string, MsiAssemblyNameTuple>(); | ||
| 52 | foreach (var assemblyTuple in this.Section.Tuples.OfType<MsiAssemblyNameTuple>()) | ||
| 53 | { | ||
| 54 | assemblyNameTuples.Add(assemblyTuple.Component_ + "/" + assemblyTuple.Name, assemblyTuple); | ||
| 55 | } | ||
| 56 | |||
| 50 | FileInfo fileInfo = null; | 57 | FileInfo fileInfo = null; |
| 51 | try | 58 | try |
| 52 | { | 59 | { |
| @@ -149,9 +156,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 149 | 156 | ||
| 150 | if (null == file.Hash) | 157 | if (null == file.Hash) |
| 151 | { | 158 | { |
| 152 | //Table msiFileHashTable = this.Output.EnsureTable(this.TableDefinitions["MsiFileHash"]); | 159 | file.Hash = new MsiFileHashTuple(file.File.SourceLineNumbers, file.File.Id); |
| 153 | //file.Hash = msiFileHashTable.CreateRow(file.File.SourceLineNumbers); | 160 | this.Section.Tuples.Add(file.Hash); |
| 154 | throw new NotImplementedException(); | ||
| 155 | } | 161 | } |
| 156 | 162 | ||
| 157 | file.Hash.File_ = file.File.File; | 163 | file.Hash.File_ = file.File.File; |
| @@ -198,13 +204,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 198 | { | 204 | { |
| 199 | if (!String.IsNullOrEmpty(file.File.Version)) | 205 | if (!String.IsNullOrEmpty(file.File.Version)) |
| 200 | { | 206 | { |
| 201 | string key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File)); | 207 | var key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", file.File.File); |
| 202 | this.VariableCache[key] = file.File.Version; | 208 | this.VariableCache[key] = file.File.Version; |
| 203 | } | 209 | } |
| 204 | 210 | ||
| 205 | if (!String.IsNullOrEmpty(file.File.Language)) | 211 | if (!String.IsNullOrEmpty(file.File.Language)) |
| 206 | { | 212 | { |
| 207 | string key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", Common.Demodularize(this.Output.Type, ModularizationGuid, file.File.File)); | 213 | var key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", file.File.File); |
| 208 | this.VariableCache[key] = file.File.Language; | 214 | this.VariableCache[key] = file.File.Language; |
| 209 | } | 215 | } |
| 210 | } | 216 | } |
| @@ -214,14 +220,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 214 | if (FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType) | 220 | if (FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType) |
| 215 | { | 221 | { |
| 216 | bool targetNetfx1 = false; | 222 | bool targetNetfx1 = false; |
| 217 | StringDictionary assemblyNameValues = new StringDictionary(); | 223 | var assemblyNameValues = new Dictionary<string, string>(); |
| 218 | 224 | ||
| 219 | ClrInterop.IReferenceIdentity referenceIdentity = null; | ||
| 220 | Guid referenceIdentityGuid = ClrInterop.ReferenceIdentityGuid; | 225 | Guid referenceIdentityGuid = ClrInterop.ReferenceIdentityGuid; |
| 221 | uint result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out referenceIdentity); | 226 | var result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out var referenceIdentity); |
| 222 | if (0 == result && null != referenceIdentity) | 227 | if (0 == result && null != referenceIdentity) |
| 223 | { | 228 | { |
| 224 | string imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion"); | 229 | var imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion"); |
| 225 | if (null != imageRuntimeVersion) | 230 | if (null != imageRuntimeVersion) |
| 226 | { | 231 | { |
| 227 | targetNetfx1 = imageRuntimeVersion.StartsWith("v1", StringComparison.OrdinalIgnoreCase); | 232 | targetNetfx1 = imageRuntimeVersion.StartsWith("v1", StringComparison.OrdinalIgnoreCase); |
| @@ -269,15 +274,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 269 | return; | 274 | return; |
| 270 | } | 275 | } |
| 271 | 276 | ||
| 272 | Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]); | 277 | if (assemblyNameValues.TryGetValue("name", out var value)) |
| 273 | if (assemblyNameValues.ContainsKey("name")) | ||
| 274 | { | 278 | { |
| 275 | this.SetMsiAssemblyName(assemblyNameTable, file, "name", assemblyNameValues["name"]); | 279 | this.SetMsiAssemblyName(assemblyNameTuples, file, "name", value); |
| 276 | } | 280 | } |
| 277 | 281 | ||
| 278 | if (!String.IsNullOrEmpty(version)) | 282 | if (!String.IsNullOrEmpty(version)) |
| 279 | { | 283 | { |
| 280 | this.SetMsiAssemblyName(assemblyNameTable, file, "fileVersion", version); | 284 | this.SetMsiAssemblyName(assemblyNameTuples, file, "fileVersion", version); |
| 281 | } | 285 | } |
| 282 | 286 | ||
| 283 | if (assemblyNameValues.ContainsKey("version")) | 287 | if (assemblyNameValues.ContainsKey("version")) |
| @@ -303,33 +307,33 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 303 | } | 307 | } |
| 304 | } | 308 | } |
| 305 | 309 | ||
| 306 | this.SetMsiAssemblyName(assemblyNameTable, file, "version", assemblyVersion); | 310 | this.SetMsiAssemblyName(assemblyNameTuples, file, "version", assemblyVersion); |
| 307 | } | 311 | } |
| 308 | 312 | ||
| 309 | if (assemblyNameValues.ContainsKey("culture")) | 313 | if (assemblyNameValues.ContainsKey("culture")) |
| 310 | { | 314 | { |
| 311 | this.SetMsiAssemblyName(assemblyNameTable, file, "culture", assemblyNameValues["culture"]); | 315 | this.SetMsiAssemblyName(assemblyNameTuples, file, "culture", assemblyNameValues["culture"]); |
| 312 | } | 316 | } |
| 313 | 317 | ||
| 314 | if (assemblyNameValues.ContainsKey("publicKeyToken")) | 318 | if (assemblyNameValues.ContainsKey("publicKeyToken")) |
| 315 | { | 319 | { |
| 316 | this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]); | 320 | this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]); |
| 317 | } | 321 | } |
| 318 | 322 | ||
| 319 | if (!String.IsNullOrEmpty(file.WixFile.ProcessorArchitecture)) | 323 | if (!String.IsNullOrEmpty(file.WixFile.ProcessorArchitecture)) |
| 320 | { | 324 | { |
| 321 | this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", file.WixFile.ProcessorArchitecture); | 325 | this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", file.WixFile.ProcessorArchitecture); |
| 322 | } | 326 | } |
| 323 | 327 | ||
| 324 | if (assemblyNameValues.ContainsKey("processorArchitecture")) | 328 | if (assemblyNameValues.ContainsKey("processorArchitecture")) |
| 325 | { | 329 | { |
| 326 | this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]); | 330 | this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]); |
| 327 | } | 331 | } |
| 328 | 332 | ||
| 329 | // add the assembly name to the information cache | 333 | // add the assembly name to the information cache |
| 330 | if (null != this.VariableCache) | 334 | if (null != this.VariableCache) |
| 331 | { | 335 | { |
| 332 | string fileId = Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File); | 336 | string fileId = file.File.File; |
| 333 | string key = String.Concat("assemblyfullname.", fileId); | 337 | string key = String.Concat("assemblyfullname.", fileId); |
| 334 | string assemblyName = String.Concat(assemblyNameValues["name"], ", version=", assemblyNameValues["version"], ", culture=", assemblyNameValues["culture"], ", publicKeyToken=", String.IsNullOrEmpty(assemblyNameValues["publicKeyToken"]) ? "null" : assemblyNameValues["publicKeyToken"]); | 338 | string assemblyName = String.Concat(assemblyNameValues["name"], ", version=", assemblyNameValues["version"], ", culture=", assemblyNameValues["culture"], ", publicKeyToken=", String.IsNullOrEmpty(assemblyNameValues["publicKeyToken"]) ? "null" : assemblyNameValues["publicKeyToken"]); |
| 335 | if (assemblyNameValues.ContainsKey("processorArchitecture")) | 339 | if (assemblyNameValues.ContainsKey("processorArchitecture")) |
| @@ -437,30 +441,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 437 | Messaging.Instance.OnMessage(WixErrors.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source), "manifest", xe.Message)); | 441 | Messaging.Instance.OnMessage(WixErrors.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source), "manifest", xe.Message)); |
| 438 | } | 442 | } |
| 439 | 443 | ||
| 440 | Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]); | ||
| 441 | if (!String.IsNullOrEmpty(win32Name)) | 444 | if (!String.IsNullOrEmpty(win32Name)) |
| 442 | { | 445 | { |
| 443 | this.SetMsiAssemblyName(assemblyNameTable, file, "name", win32Name); | 446 | this.SetMsiAssemblyName(assemblyNameTuples, file, "name", win32Name); |
| 444 | } | 447 | } |
| 445 | 448 | ||
| 446 | if (!String.IsNullOrEmpty(win32Version)) | 449 | if (!String.IsNullOrEmpty(win32Version)) |
| 447 | { | 450 | { |
| 448 | this.SetMsiAssemblyName(assemblyNameTable, file, "version", win32Version); | 451 | this.SetMsiAssemblyName(assemblyNameTuples, file, "version", win32Version); |
| 449 | } | 452 | } |
| 450 | 453 | ||
| 451 | if (!String.IsNullOrEmpty(win32Type)) | 454 | if (!String.IsNullOrEmpty(win32Type)) |
| 452 | { | 455 | { |
| 453 | this.SetMsiAssemblyName(assemblyNameTable, file, "type", win32Type); | 456 | this.SetMsiAssemblyName(assemblyNameTuples, file, "type", win32Type); |
| 454 | } | 457 | } |
| 455 | 458 | ||
| 456 | if (!String.IsNullOrEmpty(win32ProcessorArchitecture)) | 459 | if (!String.IsNullOrEmpty(win32ProcessorArchitecture)) |
| 457 | { | 460 | { |
| 458 | this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", win32ProcessorArchitecture); | 461 | this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", win32ProcessorArchitecture); |
| 459 | } | 462 | } |
| 460 | 463 | ||
| 461 | if (!String.IsNullOrEmpty(win32PublicKeyToken)) | 464 | if (!String.IsNullOrEmpty(win32PublicKeyToken)) |
| 462 | { | 465 | { |
| 463 | this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", win32PublicKeyToken); | 466 | this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", win32PublicKeyToken); |
| 464 | } | 467 | } |
| 465 | } | 468 | } |
| 466 | } | 469 | } |
| @@ -469,11 +472,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 469 | /// Set an MsiAssemblyName row. If it was directly authored, override the value, otherwise | 472 | /// Set an MsiAssemblyName row. If it was directly authored, override the value, otherwise |
| 470 | /// create a new row. | 473 | /// create a new row. |
| 471 | /// </summary> | 474 | /// </summary> |
| 472 | /// <param name="assemblyNameTable">MsiAssemblyName table.</param> | 475 | /// <param name="assemblyNameTuples">MsiAssemblyName table.</param> |
| 473 | /// <param name="file">FileFacade containing the assembly read for the MsiAssemblyName row.</param> | 476 | /// <param name="file">FileFacade containing the assembly read for the MsiAssemblyName row.</param> |
| 474 | /// <param name="name">MsiAssemblyName name.</param> | 477 | /// <param name="name">MsiAssemblyName name.</param> |
| 475 | /// <param name="value">MsiAssemblyName value.</param> | 478 | /// <param name="value">MsiAssemblyName value.</param> |
| 476 | private void SetMsiAssemblyName(Table assemblyNameTable, FileFacade file, string name, string value) | 479 | private void SetMsiAssemblyName(Dictionary<string, MsiAssemblyNameTuple> assemblyNameTuples, FileFacade file, string name, string value) |
| 477 | { | 480 | { |
| 478 | // check for null value (this can occur when grabbing the file version from an assembly without one) | 481 | // check for null value (this can occur when grabbing the file version from an assembly without one) |
| 479 | if (String.IsNullOrEmpty(value)) | 482 | if (String.IsNullOrEmpty(value)) |
| @@ -482,18 +485,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 482 | } | 485 | } |
| 483 | else | 486 | else |
| 484 | { | 487 | { |
| 485 | Row assemblyNameRow = null; | ||
| 486 | |||
| 487 | // override directly authored value | ||
| 488 | foreach (Row row in assemblyNameTable.Rows) | ||
| 489 | { | ||
| 490 | if ((string)row[0] == file.File.Component_ && (string)row[1] == name) | ||
| 491 | { | ||
| 492 | assemblyNameRow = row; | ||
| 493 | break; | ||
| 494 | } | ||
| 495 | } | ||
| 496 | |||
| 497 | // if the assembly will be GAC'd and the name in the file table doesn't match the name in the MsiAssemblyName table, error because the install will fail. | 488 | // if the assembly will be GAC'd and the name in the file table doesn't match the name in the MsiAssemblyName table, error because the install will fail. |
| 498 | if ("name" == name && FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType && | 489 | if ("name" == name && FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType && |
| 499 | String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) && | 490 | String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) && |
| @@ -502,17 +493,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 502 | Messaging.Instance.OnMessage(WixErrors.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value)); | 493 | Messaging.Instance.OnMessage(WixErrors.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value)); |
| 503 | } | 494 | } |
| 504 | 495 | ||
| 505 | if (null == assemblyNameRow) | 496 | // override directly authored value |
| 497 | var lookup = String.Concat(file.File.Component_, "/", name); | ||
| 498 | if (assemblyNameTuples.TryGetValue(lookup, out var assemblyNameRow)) | ||
| 506 | { | 499 | { |
| 507 | throw new NotImplementedException(); | 500 | assemblyNameRow = new MsiAssemblyNameTuple(file.File.SourceLineNumbers); |
| 508 | #if TODO | 501 | assemblyNameRow.Component_ = file.File.Component_; |
| 509 | assemblyNameRow = assemblyNameTable.CreateRow(file.File.SourceLineNumbers); | 502 | assemblyNameRow.Name = name; |
| 510 | assemblyNameRow[0] = file.File.Component_; | 503 | assemblyNameRow.Value = value; |
| 511 | assemblyNameRow[1] = name; | ||
| 512 | assemblyNameRow[2] = value; | ||
| 513 | |||
| 514 | // put the MsiAssemblyName row in the same section as the related File row | ||
| 515 | assemblyNameRow.SectionId = file.File.SectionId; | ||
| 516 | 504 | ||
| 517 | if (null == file.AssemblyNames) | 505 | if (null == file.AssemblyNames) |
| 518 | { | 506 | { |
| @@ -520,17 +508,15 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
| 520 | } | 508 | } |
| 521 | 509 | ||
| 522 | file.AssemblyNames.Add(assemblyNameRow); | 510 | file.AssemblyNames.Add(assemblyNameRow); |
| 523 | #endif | 511 | this.Section.Tuples.Add(assemblyNameRow); |
| 524 | } | ||
| 525 | else | ||
| 526 | { | ||
| 527 | assemblyNameRow[2] = value; | ||
| 528 | } | 512 | } |
| 529 | 513 | ||
| 514 | assemblyNameRow.Value = value; | ||
| 515 | |||
| 530 | if (this.VariableCache != null) | 516 | if (this.VariableCache != null) |
| 531 | { | 517 | { |
| 532 | string key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File)).ToLowerInvariant(); | 518 | var key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, file.File.File).ToLowerInvariant(); |
| 533 | this.VariableCache[key] = (string)assemblyNameRow[2]; | 519 | this.VariableCache[key] = value; |
| 534 | } | 520 | } |
| 535 | } | 521 | } |
| 536 | } | 522 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs new file mode 100644 index 00000000..db74eda5 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.Linq; | ||
| 8 | using WixToolset.Core.Bind; | ||
| 9 | using WixToolset.Data; | ||
| 10 | using WixToolset.Data.Rows; | ||
| 11 | using WixToolset.Data.Tuples; | ||
| 12 | |||
| 13 | internal class UpdateMediaSequencesCommand | ||
| 14 | { | ||
| 15 | public UpdateMediaSequencesCommand(Output output, List<FileFacade> fileFacades, Dictionary<int, MediaTuple> assignedMediaRows) | ||
| 16 | { | ||
| 17 | this.Output = output; | ||
| 18 | this.FileFacades = fileFacades; | ||
| 19 | } | ||
| 20 | |||
| 21 | private Output Output { get; } | ||
| 22 | |||
| 23 | private List<FileFacade> FileFacades { get; } | ||
| 24 | |||
| 25 | public void Execute() | ||
| 26 | { | ||
| 27 | var fileRows = new RowDictionary<FileRow>(this.Output.Tables["File"]); | ||
| 28 | var mediaRows = new RowDictionary<MediaRow>(this.Output.Tables["Media"]); | ||
| 29 | |||
| 30 | // Calculate sequence numbers and media disk id layout for all file media information objects. | ||
| 31 | if (OutputType.Module == this.Output.Type) | ||
| 32 | { | ||
| 33 | var lastSequence = 0; | ||
| 34 | |||
| 35 | // Order by Component to group the files by directory. | ||
| 36 | var optimized = this.OptimizedFileFacades(); | ||
| 37 | foreach (var fileId in optimized.Select(f => f.File.File)) | ||
| 38 | { | ||
| 39 | var fileRow = fileRows.Get(fileId); | ||
| 40 | fileRow.Sequence = ++lastSequence; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | else | ||
| 44 | { | ||
| 45 | int lastSequence = 0; | ||
| 46 | MediaRow mediaRow = null; | ||
| 47 | Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>(); | ||
| 48 | |||
| 49 | // sequence the non-patch-added files | ||
| 50 | var optimized = this.OptimizedFileFacades(); | ||
| 51 | foreach (FileFacade facade in optimized) | ||
| 52 | { | ||
| 53 | if (null == mediaRow) | ||
| 54 | { | ||
| 55 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
| 56 | if (OutputType.Patch == this.Output.Type) | ||
| 57 | { | ||
| 58 | // patch Media cannot start at zero | ||
| 59 | lastSequence = mediaRow.LastSequence; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
| 63 | { | ||
| 64 | mediaRow.LastSequence = lastSequence; | ||
| 65 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
| 66 | } | ||
| 67 | |||
| 68 | if (0 < facade.WixFile.PatchGroup) | ||
| 69 | { | ||
| 70 | if (patchGroups.TryGetValue(facade.WixFile.PatchGroup, out var patchGroup)) | ||
| 71 | { | ||
| 72 | patchGroup = new List<FileFacade>(); | ||
| 73 | patchGroups.Add(facade.WixFile.PatchGroup, patchGroup); | ||
| 74 | } | ||
| 75 | |||
| 76 | patchGroup.Add(facade); | ||
| 77 | } | ||
| 78 | else | ||
| 79 | { | ||
| 80 | var fileRow = fileRows.Get(facade.File.File); | ||
| 81 | fileRow.Sequence = ++lastSequence; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | if (null != mediaRow) | ||
| 86 | { | ||
| 87 | mediaRow.LastSequence = lastSequence; | ||
| 88 | mediaRow = null; | ||
| 89 | } | ||
| 90 | |||
| 91 | // sequence the patch-added files | ||
| 92 | foreach (var patchGroup in patchGroups.Values) | ||
| 93 | { | ||
| 94 | foreach (var facade in patchGroup) | ||
| 95 | { | ||
| 96 | if (null == mediaRow) | ||
| 97 | { | ||
| 98 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
| 99 | } | ||
| 100 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
| 101 | { | ||
| 102 | mediaRow.LastSequence = lastSequence; | ||
| 103 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
| 104 | } | ||
| 105 | |||
| 106 | var fileRow = fileRows.Get(facade.File.File); | ||
| 107 | fileRow.Sequence = ++lastSequence; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | if (null != mediaRow) | ||
| 112 | { | ||
| 113 | mediaRow.LastSequence = lastSequence; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | private IEnumerable<FileFacade> OptimizedFileFacades() | ||
| 119 | { | ||
| 120 | // TODO: Sort these facades even smarter by directory path and component id | ||
| 121 | // and maybe file size or file extension and other creative ideas to | ||
| 122 | // get optimal install speed out of MSI. | ||
| 123 | return this.FileFacades.OrderBy(f => f.File.Component_); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs index 72c876e0..58384325 100644 --- a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs | |||
| @@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe | |||
| 18 | public InscribeMsiPackageCommand(IInscribeContext context) | 18 | public InscribeMsiPackageCommand(IInscribeContext context) |
| 19 | { | 19 | { |
| 20 | this.Context = context; | 20 | this.Context = context; |
| 21 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 21 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | private IInscribeContext Context { get; } | 24 | private IInscribeContext Context { get; } |
diff --git a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs index 3e40a51f..17617dbc 100644 --- a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs +++ b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | namespace WixToolset.Core.WindowsInstaller | 3 | namespace WixToolset.Core.WindowsInstaller |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using WixToolset.Core.WindowsInstaller.Databases; | ||
| 7 | using WixToolset.Core.WindowsInstaller.Unbind; | 6 | using WixToolset.Core.WindowsInstaller.Unbind; |
| 8 | using WixToolset.Data; | 7 | using WixToolset.Data; |
| 9 | using WixToolset.Data.Bind; | 8 | using WixToolset.Data.Bind; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Patch.cs b/src/WixToolset.Core.WindowsInstaller/Patch.cs index f4dac6e6..8e617fdb 100644 --- a/src/WixToolset.Core.WindowsInstaller/Patch.cs +++ b/src/WixToolset.Core.WindowsInstaller/Patch.cs | |||
| @@ -29,7 +29,7 @@ namespace WixToolset.Data | |||
| 29 | public Patch() | 29 | public Patch() |
| 30 | { | 30 | { |
| 31 | this.inspectorExtensions = new List<IInspectorExtension>(); | 31 | this.inspectorExtensions = new List<IInspectorExtension>(); |
| 32 | this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions()); | 32 | this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandardInternal.GetTableDefinitions()); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | /// <summary> | 35 | /// <summary> |
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs index 15445bc8..9cd7b775 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs | |||
| @@ -27,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
| 27 | this.SuppressDemodularization = suppressDemodularization; | 27 | this.SuppressDemodularization = suppressDemodularization; |
| 28 | this.SkipSummaryInfo = skipSummaryInfo; | 28 | this.SkipSummaryInfo = skipSummaryInfo; |
| 29 | 29 | ||
| 30 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 30 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | public Messaging Messaging { get; } | 33 | public Messaging Messaging { get; } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs index c0eda9c7..7eb81ac7 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs | |||
| @@ -4,16 +4,13 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections; | 6 | using System.Collections; |
| 7 | using System.Collections.Generic; | ||
| 8 | using System.ComponentModel; | 7 | using System.ComponentModel; |
| 9 | using System.Globalization; | 8 | using System.Globalization; |
| 10 | using System.IO; | 9 | using System.IO; |
| 11 | using System.Linq; | 10 | using System.Linq; |
| 12 | using System.Text.RegularExpressions; | ||
| 13 | using WixToolset.Core.Native; | 11 | using WixToolset.Core.Native; |
| 14 | using WixToolset.Core.WindowsInstaller.Databases; | 12 | using WixToolset.Core.WindowsInstaller.Bind; |
| 15 | using WixToolset.Data; | 13 | using WixToolset.Data; |
| 16 | using WixToolset.Data.Rows; | ||
| 17 | using WixToolset.Extensibility; | 14 | using WixToolset.Extensibility; |
| 18 | using WixToolset.Msi; | 15 | using WixToolset.Msi; |
| 19 | 16 | ||
| @@ -26,7 +23,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
| 26 | this.ExportBasePath = exportBasePath; | 23 | this.ExportBasePath = exportBasePath; |
| 27 | this.IntermediateFolder = intermediateFolder; | 24 | this.IntermediateFolder = intermediateFolder; |
| 28 | 25 | ||
| 29 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 26 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
| 30 | } | 27 | } |
| 31 | 28 | ||
| 32 | private Messaging Messaging { get; } | 29 | private Messaging Messaging { get; } |
