aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs35
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs7
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs44
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs1
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs6
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs16
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs31
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs95
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs9
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs25
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs26
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/ModularizeCommand.cs4
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs13
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs60
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs26
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs11
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Differ.cs3
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs10
21 files changed, 235 insertions, 193 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs
index 0f278640..8c6a3e67 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs
@@ -16,6 +16,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
16 /// </summary> 16 /// </summary>
17 internal class AssignMediaCommand 17 internal class AssignMediaCommand
18 { 18 {
19 private const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
20
19 public AssignMediaCommand(IntermediateSection section, IMessaging messaging) 21 public AssignMediaCommand(IntermediateSection section, IMessaging messaging)
20 { 22 {
21 this.CabinetNameTemplate = "Cab{0}.cab"; 23 this.CabinetNameTemplate = "Cab{0}.cab";
@@ -82,7 +84,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
82 } 84 }
83 else 85 else
84 { 86 {
85 this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); 87 this.AutoAssignFiles(mediaTable, filesByCabinetMedia, mediaRows, uncompressedFiles);
86 } 88 }
87 89
88 this.FileFacadesByCabinetMedia = new Dictionary<MediaTuple, IEnumerable<FileFacade>>(); 90 this.FileFacadesByCabinetMedia = new Dictionary<MediaTuple, IEnumerable<FileFacade>>();
@@ -101,7 +103,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
101 /// Assign files to cabinets based on MediaTemplate authoring. 103 /// Assign files to cabinets based on MediaTemplate authoring.
102 /// </summary> 104 /// </summary>
103 /// <param name="fileFacades">FileRowCollection</param> 105 /// <param name="fileFacades">FileRowCollection</param>
104 private void AutoAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles) 106 private void AutoAssignFiles(List<MediaTuple> mediaTable, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles)
105 { 107 {
106 const int MaxCabIndex = 999; 108 const int MaxCabIndex = 999;
107 109
@@ -140,7 +142,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
140 } 142 }
141 else 143 else
142 { 144 {
143 maxPreCabSizeInMB = mediaTemplateRow.MaximumUncompressedMediaSize; 145 maxPreCabSizeInMB = mediaTemplateRow.MaximumUncompressedMediaSize ?? DefaultMaximumUncompressedMediaSize;
144 } 146 }
145 147
146 maxPreCabSizeInBytes = (ulong)maxPreCabSizeInMB * 1024 * 1024; 148 maxPreCabSizeInBytes = (ulong)maxPreCabSizeInMB * 1024 * 1024;
@@ -212,8 +214,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
212 // If there are uncompressed files and no MediaRow, create a default one. 214 // If there are uncompressed files and no MediaRow, create a default one.
213 if (uncompressedFiles.Count > 0 && !this.Section.Tuples.OfType<MediaTuple>().Any()) 215 if (uncompressedFiles.Count > 0 && !this.Section.Tuples.OfType<MediaTuple>().Any())
214 { 216 {
215 var defaultMediaRow = new MediaTuple(null, new Identifier(1, AccessModifier.Private)); 217 var defaultMediaRow = new MediaTuple(null, new Identifier(AccessModifier.Private, 1))
216 defaultMediaRow.DiskId = 1; 218 {
219 DiskId = 1
220 };
217 221
218 mediaRows.Add(1, defaultMediaRow); 222 mediaRows.Add(1, defaultMediaRow);
219 this.Section.Tuples.Add(defaultMediaRow); 223 this.Section.Tuples.Add(defaultMediaRow);
@@ -282,7 +286,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
282 } 286 }
283 else 287 else
284 { 288 {
285 this.Messaging.Write(ErrorMessages.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); 289 this.Messaging.Write(ErrorMessages.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.Id.Id, facade.WixFile.DiskId));
286 } 290 }
287 } 291 }
288 } 292 }
@@ -294,21 +298,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
294 /// <param name="mediaTable"></param> 298 /// <param name="mediaTable"></param>
295 /// <param name="cabIndex"></param> 299 /// <param name="cabIndex"></param>
296 /// <returns></returns> 300 /// <returns></returns>
297 private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateRow, int cabIndex) 301 private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateTuple, int cabIndex)
298 { 302 {
299 var currentMediaRow = new MediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); 303 var currentMediaTuple = new MediaTuple(mediaTemplateTuple.SourceLineNumbers, new Identifier(AccessModifier.Private, cabIndex));
300 currentMediaRow.DiskId = cabIndex; 304 currentMediaTuple.DiskId = cabIndex;
301 currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex); 305 currentMediaTuple.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex);
302 306 currentMediaTuple.CompressionLevel = mediaTemplateTuple.CompressionLevel;
303 this.Section.Tuples.Add(currentMediaRow);
304
305 var row = new WixMediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private));
306 row.DiskId_ = cabIndex;
307 row.CompressionLevel = mediaTemplateRow.CompressionLevel;
308 307
309 this.Section.Tuples.Add(row); 308 this.Section.Tuples.Add(currentMediaTuple);
310 309
311 return currentMediaRow; 310 return currentMediaTuple;
312 } 311 }
313 } 312 }
314} 313}
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index f78cb42c..cf7fe423 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -128,7 +128,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
128 foreach (var propertyRow in section.Tuples.OfType<PropertyTuple>()) 128 foreach (var propertyRow in section.Tuples.OfType<PropertyTuple>())
129 { 129 {
130 // Set the ProductCode if it is to be generated. 130 // Set the ProductCode if it is to be generated.
131 if ("ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) 131 if ("ProductCode".Equals(propertyRow.Id.Id, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal))
132 { 132 {
133 propertyRow.Value = Common.GenerateGuid(); 133 propertyRow.Value = Common.GenerateGuid();
134 134
@@ -159,7 +159,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
159 // Add the property name and value to the variableCache. 159 // Add the property name and value to the variableCache.
160 if (variableCache != null) 160 if (variableCache != null)
161 { 161 {
162 var key = String.Concat("property.", propertyRow.Property); 162 var key = String.Concat("property.", propertyRow.Id.Id);
163 variableCache[key] = propertyRow.Value; 163 variableCache[key] = propertyRow.Value;
164 } 164 }
165 } 165 }
@@ -312,7 +312,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
312 312
313 // Update file sequence. 313 // Update file sequence.
314 { 314 {
315 var command = new UpdateMediaSequencesCommand(output, fileFacades, assignedMediaRows); 315 var command = new UpdateMediaSequencesCommand(output, fileFacades);
316 command.Execute(); 316 command.Execute();
317 } 317 }
318 318
@@ -400,7 +400,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
400 command.ResolveMedia = this.ResolveMedia; 400 command.ResolveMedia = this.ResolveMedia;
401 command.TableDefinitions = this.TableDefinitions; 401 command.TableDefinitions = this.TableDefinitions;
402 command.TempFilesLocation = this.IntermediateFolder; 402 command.TempFilesLocation = this.IntermediateFolder;
403 command.WixMediaTuples = section.Tuples.OfType<WixMediaTuple>();
404 command.Execute(); 403 command.Execute();
405 404
406 fileTransfers.AddRange(command.FileTransfers); 405 fileTransfers.AddRange(command.FileTransfers);
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs
index c9286a38..8aa6047f 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs
@@ -49,13 +49,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
49 bool foundCreatingApplication = false; 49 bool foundCreatingApplication = false;
50 string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); 50 string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture);
51 51
52 foreach (var summaryInformationRow in this.Section.Tuples.OfType<_SummaryInformationTuple>()) 52 foreach (var summaryInformationTuple in this.Section.Tuples.OfType<SummaryInformationTuple>())
53 { 53 {
54 switch (summaryInformationRow.PropertyId) 54 switch (summaryInformationTuple.PropertyId)
55 { 55 {
56 case 1: // PID_CODEPAGE 56 case SumaryInformationType.Codepage: // 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 var codepage = summaryInformationRow.Value; 58 var codepage = summaryInformationTuple.Value;
59 59
60 if (String.IsNullOrEmpty(codepage)) 60 if (String.IsNullOrEmpty(codepage))
61 { 61 {
@@ -63,11 +63,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
63 } 63 }
64 else 64 else
65 { 65 {
66 summaryInformationRow.Value = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); 66 summaryInformationTuple.Value = Common.GetValidCodePage(codepage, false, false, summaryInformationTuple.SourceLineNumbers).ToString(CultureInfo.InvariantCulture);
67 } 67 }
68 break; 68 break;
69 case 9: // PID_REVNUMBER 69 case SumaryInformationType.PackageCode: // PID_REVNUMBER
70 var packageCode = summaryInformationRow.Value; 70 var packageCode = summaryInformationTuple.Value;
71 71
72 if (SectionType.Module == this.Section.Type) 72 if (SectionType.Module == this.Section.Type)
73 { 73 {
@@ -76,19 +76,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
76 else if ("*" == packageCode) 76 else if ("*" == packageCode)
77 { 77 {
78 // set the revision number (package/patch code) if it should be automatically generated 78 // set the revision number (package/patch code) if it should be automatically generated
79 summaryInformationRow.Value = Common.GenerateGuid(); 79 summaryInformationTuple.Value = Common.GenerateGuid();
80 } 80 }
81 break; 81 break;
82 case 12: // PID_CREATE_DTM 82 case SumaryInformationType.Created:
83 foundCreateDataTime = true; 83 foundCreateDataTime = true;
84 break; 84 break;
85 case 13: // PID_LASTSAVE_DTM 85 case SumaryInformationType.LastSaved:
86 foundLastSaveDataTime = true; 86 foundLastSaveDataTime = true;
87 break; 87 break;
88 case 14: 88 case SumaryInformationType.WindowsInstallerVersion:
89 this.InstallerVersion = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); 89 this.InstallerVersion = summaryInformationTuple[SummaryInformationTupleFields.Value].AsNumber();
90 break; 90 break;
91 case 15: // PID_WORDCOUNT 91 case SumaryInformationType.WordCount:
92 if (SectionType.Patch == this.Section.Type) 92 if (SectionType.Patch == this.Section.Type)
93 { 93 {
94 this.LongNames = true; 94 this.LongNames = true;
@@ -96,12 +96,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
96 } 96 }
97 else 97 else
98 { 98 {
99 var attributes = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); 99 var attributes = summaryInformationTuple[SummaryInformationTupleFields.Value].AsNumber();
100 this.LongNames = (0 == (attributes & 1)); 100 this.LongNames = (0 == (attributes & 1));
101 this.Compressed = (2 == (attributes & 2)); 101 this.Compressed = (2 == (attributes & 2));
102 } 102 }
103 break; 103 break;
104 case 18: // PID_APPNAME 104 case SumaryInformationType.CreatingApplication: // PID_APPNAME
105 foundCreatingApplication = true; 105 foundCreatingApplication = true;
106 break; 106 break;
107 } 107 }
@@ -110,8 +110,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
110 // add a summary information row for the create time/date property if its not already set 110 // add a summary information row for the create time/date property if its not already set
111 if (!foundCreateDataTime) 111 if (!foundCreateDataTime)
112 { 112 {
113 var createTimeDateRow = new _SummaryInformationTuple(null, new Identifier(12, AccessModifier.Private)); 113 var createTimeDateRow = new SummaryInformationTuple(null);
114 createTimeDateRow.PropertyId = 12; 114 createTimeDateRow.PropertyId = SumaryInformationType.Created;
115 createTimeDateRow.Value = now; 115 createTimeDateRow.Value = now;
116 116
117 this.Section.Tuples.Add(createTimeDateRow); 117 this.Section.Tuples.Add(createTimeDateRow);
@@ -120,8 +120,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
120 // add a summary information row for the last save time/date property if its not already set 120 // add a summary information row for the last save time/date property if its not already set
121 if (!foundLastSaveDataTime) 121 if (!foundLastSaveDataTime)
122 { 122 {
123 var lastSaveTimeDateRow = new _SummaryInformationTuple(null, new Identifier(13, AccessModifier.Private)); 123 var lastSaveTimeDateRow = new SummaryInformationTuple(null);
124 lastSaveTimeDateRow.PropertyId = 13; 124 lastSaveTimeDateRow.PropertyId = SumaryInformationType.LastSaved;
125 lastSaveTimeDateRow.Value = now; 125 lastSaveTimeDateRow.Value = now;
126 126
127 this.Section.Tuples.Add(lastSaveTimeDateRow); 127 this.Section.Tuples.Add(lastSaveTimeDateRow);
@@ -130,8 +130,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
130 // add a summary information row for the creating application property if its not already set 130 // add a summary information row for the creating application property if its not already set
131 if (!foundCreatingApplication) 131 if (!foundCreatingApplication)
132 { 132 {
133 var creatingApplicationRow = new _SummaryInformationTuple(null, new Identifier(18, AccessModifier.Private)); 133 var creatingApplicationRow = new SummaryInformationTuple(null);
134 creatingApplicationRow.PropertyId = 18; 134 creatingApplicationRow.PropertyId = SumaryInformationType.CreatingApplication;
135 creatingApplicationRow.Value = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString()); 135 creatingApplicationRow.Value = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString());
136 136
137 this.Section.Tuples.Add(creatingApplicationRow); 137 this.Section.Tuples.Add(creatingApplicationRow);
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
index 0c0f3705..2936ad7b 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
@@ -8,6 +8,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
8 using System.IO; 8 using System.IO;
9 using WixToolset.Core.WindowsInstaller.Msi; 9 using WixToolset.Core.WindowsInstaller.Msi;
10 using WixToolset.Data; 10 using WixToolset.Data;
11 using WixToolset.Data.Tuples;
11 using WixToolset.Data.WindowsInstaller; 12 using WixToolset.Data.WindowsInstaller;
12 using WixToolset.Extensibility; 13 using WixToolset.Extensibility;
13 using WixToolset.Extensibility.Services; 14 using WixToolset.Extensibility.Services;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs
index 0c167699..3725b480 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs
@@ -148,7 +148,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
148 { 148 {
149 // Cabinet has Single File, Check if this is Large File than needs Splitting into Multiple cabs 149 // Cabinet has Single File, Check if this is Large File than needs Splitting into Multiple cabs
150 // Get the Value for Max Uncompressed Media Size 150 // Get the Value for Max Uncompressed Media Size
151 maxPreCompressedSizeInBytes = (ulong)MaximumUncompressedMediaSize * 1024 * 1024; 151 maxPreCompressedSizeInBytes = (ulong)this.MaximumUncompressedMediaSize * 1024 * 1024;
152 152
153 foreach (FileFacade facade in cabinetWorkItem.FileFacades) // No other easy way than looping to get the only row 153 foreach (FileFacade facade in cabinetWorkItem.FileFacades) // No other easy way than looping to get the only row
154 { 154 {
@@ -168,8 +168,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
168 168
169 var files = cabinetWorkItem.FileFacades 169 var files = cabinetWorkItem.FileFacades
170 .Select(facade => facade.Hash == null ? 170 .Select(facade => facade.Hash == null ?
171 new CabinetCompressFile(facade.WixFile.Source.Path, facade.File.File) : 171 new CabinetCompressFile(facade.WixFile.Source.Path, facade.File.Id.Id) :
172 new CabinetCompressFile(facade.WixFile.Source.Path, facade.File.File, facade.Hash.HashPart1, facade.Hash.HashPart2, facade.Hash.HashPart3, facade.Hash.HashPart4)) 172 new CabinetCompressFile(facade.WixFile.Source.Path, facade.File.Id.Id, facade.Hash.HashPart1, facade.Hash.HashPart2, facade.Hash.HashPart3, facade.Hash.HashPart4))
173 .ToList(); 173 .ToList();
174 174
175 var cabinetCompressionLevel = (CabinetCompressionLevel)cabinetWorkItem.CompressionLevel; 175 var cabinetCompressionLevel = (CabinetCompressionLevel)cabinetWorkItem.CompressionLevel;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
index 054e3c71..987266f4 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
@@ -112,7 +112,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
112 private IBindFileWithPath CreateBindFileWithPath(FileFacade facade) 112 private IBindFileWithPath CreateBindFileWithPath(FileFacade facade)
113 { 113 {
114 var result = this.ServiceProvider.GetService<IBindFileWithPath>(); 114 var result = this.ServiceProvider.GetService<IBindFileWithPath>();
115 result.Id = facade.File.File; 115 result.Id = facade.File.Id.Id;
116 result.Path = facade.WixFile.Source.Path; 116 result.Path = facade.WixFile.Source.Path;
117 117
118 return result; 118 return result;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs
index a773519a..414984de 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs
@@ -81,25 +81,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind
81 // If the directory Id already exists, we will skip it here since 81 // If the directory Id already exists, we will skip it here since
82 // checking for duplicate primary keys is done later when importing tables 82 // checking for duplicate primary keys is done later when importing tables
83 // into database 83 // into database
84 if (targetPathsByDirectoryId.ContainsKey(row.Directory)) 84 if (targetPathsByDirectoryId.ContainsKey(row.Id.Id))
85 { 85 {
86 continue; 86 continue;
87 } 87 }
88 88
89 var targetName = Common.GetName(row.DefaultDir, false, true); 89 var targetName = Common.GetName(row.DefaultDir, false, true);
90 targetPathsByDirectoryId.Add(row.Directory, new ResolvedDirectory(row.Directory_Parent, targetName)); 90 targetPathsByDirectoryId.Add(row.Id.Id, new ResolvedDirectory(row.Directory_Parent, targetName));
91 } 91 }
92 } 92 }
93 93
94 // If the component id generation seeds have not been indexed 94 // If the component id generation seeds have not been indexed
95 // from the WixDirectory table do that now. 95 // from the Directory tuples do that now.
96 if (componentIdGenSeeds is null) 96 if (componentIdGenSeeds is null)
97 { 97 {
98 // If there are any WixDirectory rows, build up the Component Guid 98 // If there are any Directory tuples, build up the Component Guid
99 // generation seeds indexed by Directory/@Id. 99 // generation seeds indexed by Directory/@Id.
100 componentIdGenSeeds = this.Section.Tuples.OfType<WixDirectoryTuple>() 100 componentIdGenSeeds = this.Section.Tuples.OfType<DirectoryTuple>()
101 .Where(t => !String.IsNullOrEmpty(t.ComponentGuidGenerationSeed)) 101 .Where(t => !String.IsNullOrEmpty(t.ComponentGuidGenerationSeed))
102 .ToDictionary(t => t.Directory_, t => t.ComponentGuidGenerationSeed); 102 .ToDictionary(t => t.Id.Id, t => t.ComponentGuidGenerationSeed);
103 } 103 }
104 104
105 // if the file rows have not been indexed by File.Component yet 105 // if the file rows have not been indexed by File.Component yet
@@ -123,13 +123,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
123 } 123 }
124 124
125 // validate component meets all the conditions to have a generated guid 125 // validate component meets all the conditions to have a generated guid
126 var currentComponentFiles = filesByComponentId[componentTuple.Component]; 126 var currentComponentFiles = filesByComponentId[componentTuple.Id.Id];
127 var numFilesInComponent = currentComponentFiles.Count; 127 var numFilesInComponent = currentComponentFiles.Count;
128 string path = null; 128 string path = null;
129 129
130 foreach (var fileRow in currentComponentFiles) 130 foreach (var fileRow in currentComponentFiles)
131 { 131 {
132 if (fileRow.File == componentTuple.KeyPath) 132 if (fileRow.Id.Id == componentTuple.KeyPath)
133 { 133 {
134 // calculate the key file's canonical target path 134 // calculate the key file's canonical target path
135 string directoryPath = PathResolver.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentTuple.Directory_, true); 135 string directoryPath = PathResolver.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentTuple.Directory_, true);
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
index 890c446c..be3c720f 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
@@ -26,11 +26,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
26 public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB 26 public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
27 public const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB) 27 public const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
28 28
29 private List<IFileTransfer> fileTransfers; 29 private readonly List<IFileTransfer> fileTransfers;
30 30
31 private List<ITrackedFile> trackedFiles; 31 private readonly List<ITrackedFile> trackedFiles;
32 32
33 private FileSplitCabNamesCallback newCabNamesCallBack; 33 private readonly FileSplitCabNamesCallback newCabNamesCallBack;
34 34
35 private Dictionary<string, string> lastCabinetAddedToMediaTable; // Key is First Cabinet Name, Value is Last Cabinet Added in the Split Sequence 35 private Dictionary<string, string> lastCabinetAddedToMediaTable; // Key is First Cabinet Name, Value is Last Cabinet Added in the Split Sequence
36 36
@@ -82,8 +82,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
82 82
83 public TableDefinitionCollection TableDefinitions { private get; set; } 83 public TableDefinitionCollection TableDefinitions { private get; set; }
84 84
85 public IEnumerable<WixMediaTuple> WixMediaTuples { private get; set; }
86
87 public IEnumerable<IFileTransfer> FileTransfers => this.fileTransfers; 85 public IEnumerable<IFileTransfer> FileTransfers => this.fileTransfers;
88 86
89 public IEnumerable<ITrackedFile> TrackedFiles => this.trackedFiles; 87 public IEnumerable<ITrackedFile> TrackedFiles => this.trackedFiles;
@@ -94,14 +92,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
94 /// <returns>The uncompressed file rows.</returns> 92 /// <returns>The uncompressed file rows.</returns>
95 public void Execute() 93 public void Execute()
96 { 94 {
97 var wixMediaTuples = this.WixMediaTuples.ToDictionary(t => t.DiskId_);
98
99 this.lastCabinetAddedToMediaTable = new Dictionary<string, string>(); 95 this.lastCabinetAddedToMediaTable = new Dictionary<string, string>();
100 96
101 this.SetCabbingThreadCount(); 97 this.SetCabbingThreadCount();
102 98
103 // Send Binder object to Facilitate NewCabNamesCallBack Callback 99 // Send Binder object to Facilitate NewCabNamesCallBack Callback
104 CabinetBuilder cabinetBuilder = new CabinetBuilder(this.Messaging, this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); 100 var cabinetBuilder = new CabinetBuilder(this.Messaging, this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack));
105 101
106 // Supply Compile MediaTemplate Attributes to Cabinet Builder 102 // Supply Compile MediaTemplate Attributes to Cabinet Builder
107 this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize); 103 this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize);
@@ -111,22 +107,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
111 foreach (var entry in this.FileRowsByCabinet) 107 foreach (var entry in this.FileRowsByCabinet)
112 { 108 {
113 var mediaTuple = entry.Key; 109 var mediaTuple = entry.Key;
114 IEnumerable<FileFacade> files = entry.Value; 110 var files = entry.Value;
115 CompressionLevel compressionLevel = this.DefaultCompressionLevel ?? CompressionLevel.Medium; 111 var compressionLevel = mediaTuple.CompressionLevel ?? this.DefaultCompressionLevel ?? CompressionLevel.Medium;
116 112 var cabinetDir = this.ResolveMedia(mediaTuple, mediaTuple.Layout, this.LayoutDirectory);
117 string mediaLayoutFolder = null;
118
119 if (wixMediaTuples.TryGetValue(mediaTuple.DiskId, out var wixMediaRow))
120 {
121 mediaLayoutFolder = wixMediaRow.Layout;
122
123 if (wixMediaRow.CompressionLevel.HasValue)
124 {
125 compressionLevel = wixMediaRow.CompressionLevel.Value;
126 }
127 }
128
129 string cabinetDir = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory);
130 113
131 var cabinetWorkItem = this.CreateCabinetWorkItem(this.Output, cabinetDir, mediaTuple, compressionLevel, files); 114 var cabinetWorkItem = this.CreateCabinetWorkItem(this.Output, cabinetDir, mediaTuple, compressionLevel, files);
132 if (null != cabinetWorkItem) 115 if (null != cabinetWorkItem)
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
index 6f33080d..e1781daf 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
@@ -14,6 +14,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
14 14
15 internal class CreateOutputFromIRCommand 15 internal class CreateOutputFromIRCommand
16 { 16 {
17 private const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
18 private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
19
17 public CreateOutputFromIRCommand(IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions) 20 public CreateOutputFromIRCommand(IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions)
18 { 21 {
19 this.Section = section; 22 this.Section = section;
@@ -46,6 +49,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
46 { 49 {
47 switch (tuple.Definition.Type) 50 switch (tuple.Definition.Type)
48 { 51 {
52 case TupleDefinitionType.Binary:
53 this.AddTupleDefaultly(tuple, output, true);
54 break;
55
49 case TupleDefinitionType.BBControl: 56 case TupleDefinitionType.BBControl:
50 this.AddBBControlTuple((BBControlTuple)tuple, output); 57 this.AddBBControlTuple((BBControlTuple)tuple, output);
51 break; 58 break;
@@ -66,6 +73,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
66 this.AddDialogTuple((DialogTuple)tuple, output); 73 this.AddDialogTuple((DialogTuple)tuple, output);
67 break; 74 break;
68 75
76 case TupleDefinitionType.Directory:
77 this.AddDirectoryTuple((DirectoryTuple)tuple, output);
78 break;
79
69 case TupleDefinitionType.Environment: 80 case TupleDefinitionType.Environment:
70 this.AddEnvironmentTuple((EnvironmentTuple)tuple, output); 81 this.AddEnvironmentTuple((EnvironmentTuple)tuple, output);
71 break; 82 break;
@@ -102,14 +113,26 @@ namespace WixToolset.Core.WindowsInstaller.Bind
102 this.AddMsiServiceConfigFailureActionsTuple((MsiServiceConfigFailureActionsTuple)tuple, output); 113 this.AddMsiServiceConfigFailureActionsTuple((MsiServiceConfigFailureActionsTuple)tuple, output);
103 break; 114 break;
104 115
116 case TupleDefinitionType.MoveFile:
117 this.AddMoveFileTuple((MoveFileTuple)tuple, output);
118 break;
119
105 case TupleDefinitionType.Property: 120 case TupleDefinitionType.Property:
106 this.AddPropertyTuple((PropertyTuple)tuple, output); 121 this.AddPropertyTuple((PropertyTuple)tuple, output);
107 break; 122 break;
108 123
124 case TupleDefinitionType.RemoveFile:
125 this.AddRemoveFileTuple((RemoveFileTuple)tuple, output);
126 break;
127
109 case TupleDefinitionType.Registry: 128 case TupleDefinitionType.Registry:
110 this.AddRegistryTuple((RegistryTuple)tuple, output); 129 this.AddRegistryTuple((RegistryTuple)tuple, output);
111 break; 130 break;
112 131
132 case TupleDefinitionType.RegLocator:
133 this.AddRegLocatorTuple((RegLocatorTuple)tuple, output);
134 break;
135
113 case TupleDefinitionType.RemoveRegistry: 136 case TupleDefinitionType.RemoveRegistry:
114 this.AddRemoveRegistryTuple((RemoveRegistryTuple)tuple, output); 137 this.AddRemoveRegistryTuple((RemoveRegistryTuple)tuple, output);
115 break; 138 break;
@@ -138,10 +161,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
138 this.AddWixActionTuple((WixActionTuple)tuple, output); 161 this.AddWixActionTuple((WixActionTuple)tuple, output);
139 break; 162 break;
140 163
141 case TupleDefinitionType.WixMedia:
142 // Ignored.
143 break;
144
145 case TupleDefinitionType.WixMediaTemplate: 164 case TupleDefinitionType.WixMediaTemplate:
146 this.AddWixMediaTemplateTuple((WixMediaTemplateTuple)tuple, output); 165 this.AddWixMediaTemplateTuple((WixMediaTemplateTuple)tuple, output);
147 break; 166 break;
@@ -150,6 +169,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
150 this.AddTupleFromExtension(tuple, output); 169 this.AddTupleFromExtension(tuple, output);
151 break; 170 break;
152 171
172 // ignored.
173 case TupleDefinitionType.WixFile:
174 case TupleDefinitionType.WixComponentGroup:
175 case TupleDefinitionType.WixDeltaPatchFile:
176 break;
177
153 default: 178 default:
154 this.AddTupleDefaultly(tuple, output); 179 this.AddTupleDefaultly(tuple, output);
155 break; 180 break;
@@ -311,6 +336,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
311 row[9] = tuple.Control_Cancel; 336 row[9] = tuple.Control_Cancel;
312 } 337 }
313 338
339 private void AddDirectoryTuple(DirectoryTuple tuple, Output output)
340 {
341 var table = output.EnsureTable(this.TableDefinitions["Directory"]);
342 var row = table.CreateRow(tuple.SourceLineNumbers);
343 row[0] = tuple.Id.Id;
344 row[1] = tuple.Directory_Parent;
345 row[2] = tuple.DefaultDir;
346 }
347
314 private void AddEnvironmentTuple(EnvironmentTuple tuple, Output output) 348 private void AddEnvironmentTuple(EnvironmentTuple tuple, Output output)
315 { 349 {
316 var action = String.Empty; 350 var action = String.Empty;
@@ -373,7 +407,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
373 { 407 {
374 var table = output.EnsureTable(this.TableDefinitions["File"]); 408 var table = output.EnsureTable(this.TableDefinitions["File"]);
375 var row = (FileRow)table.CreateRow(tuple.SourceLineNumbers); 409 var row = (FileRow)table.CreateRow(tuple.SourceLineNumbers);
376 row.File = tuple.File; 410 row.File = tuple.Id.Id;
377 row.Component = tuple.Component_; 411 row.Component = tuple.Component_;
378 row.FileName = GetMsiFilenameValue(tuple.ShortFileName, tuple.LongFileName); 412 row.FileName = GetMsiFilenameValue(tuple.ShortFileName, tuple.LongFileName);
379 row.FileSize = tuple.FileSize; 413 row.FileSize = tuple.FileSize;
@@ -392,7 +426,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
392 426
393 private void AddIniFileTuple(IniFileTuple tuple, Output output) 427 private void AddIniFileTuple(IniFileTuple tuple, Output output)
394 { 428 {
395 string tableName = (InifFileActionType.AddLine == tuple.Action || InifFileActionType.AddTag == tuple.Action || InifFileActionType.CreateLine == tuple.Action) ? "IniFile" : "RemoveIniFile"; 429 var tableName = (InifFileActionType.AddLine == tuple.Action || InifFileActionType.AddTag == tuple.Action || InifFileActionType.CreateLine == tuple.Action) ? "IniFile" : "RemoveIniFile";
396 430
397 var table = output.EnsureTable(this.TableDefinitions[tableName]); 431 var table = output.EnsureTable(this.TableDefinitions[tableName]);
398 var row = table.CreateRow(tuple.SourceLineNumbers); 432 var row = table.CreateRow(tuple.SourceLineNumbers);
@@ -487,6 +521,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
487 row[8] = tuple.Component_; 521 row[8] = tuple.Component_;
488 } 522 }
489 523
524 private void AddMoveFileTuple(MoveFileTuple tuple, Output output)
525 {
526 var table = output.EnsureTable(this.TableDefinitions["MoveFile"]);
527 var row = table.CreateRow(tuple.SourceLineNumbers);
528 row[0] = tuple.Id.Id;
529 row[1] = tuple.Component_;
530 row[2] = tuple.SourceName;
531 row[3] = tuple.DestName;
532 row[4] = tuple.SourceFolder;
533 row[5] = tuple.DestFolder;
534 row[6] = tuple.Delete ? WindowsInstallerConstants.MsidbMoveFileOptionsMove : 0;
535 }
536
490 private void AddPropertyTuple(PropertyTuple tuple, Output output) 537 private void AddPropertyTuple(PropertyTuple tuple, Output output)
491 { 538 {
492 if (String.IsNullOrEmpty(tuple.Value)) 539 if (String.IsNullOrEmpty(tuple.Value))
@@ -496,10 +543,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
496 543
497 var table = output.EnsureTable(this.TableDefinitions["Property"]); 544 var table = output.EnsureTable(this.TableDefinitions["Property"]);
498 var row = (PropertyRow)table.CreateRow(tuple.SourceLineNumbers); 545 var row = (PropertyRow)table.CreateRow(tuple.SourceLineNumbers);
499 row.Property = tuple.Property; 546 row.Property = tuple.Id.Id;
500 row.Value = tuple.Value; 547 row.Value = tuple.Value;
501 } 548 }
502 549
550 private void AddRemoveFileTuple(RemoveFileTuple tuple, Output output)
551 {
552 var installMode = tuple.OnInstall == true ? WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall : 0;
553 installMode |= tuple.OnUninstall == true ? WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove : 0;
554
555 var table = output.EnsureTable(this.TableDefinitions["RemoveFile"]);
556 var row = table.CreateRow(tuple.SourceLineNumbers);
557 row[0] = tuple.Id.Id;
558 row[1] = tuple.Component_;
559 row[2] = tuple.FileName;
560 row[3] = tuple.DirProperty;
561 row[4] = installMode;
562 }
563
503 private void AddRegistryTuple(RegistryTuple tuple, Output output) 564 private void AddRegistryTuple(RegistryTuple tuple, Output output)
504 { 565 {
505 var value = tuple.Value; 566 var value = tuple.Value;
@@ -552,6 +613,20 @@ namespace WixToolset.Core.WindowsInstaller.Bind
552 row[5] = tuple.Component_; 613 row[5] = tuple.Component_;
553 } 614 }
554 615
616 private void AddRegLocatorTuple(RegLocatorTuple tuple, Output output)
617 {
618 var type = (int)tuple.Type;
619 type |= tuple.Win64 ? WindowsInstallerConstants.MsidbLocatorType64bit : 0;
620
621 var table = output.EnsureTable(this.TableDefinitions["RegLocator"]);
622 var row = table.CreateRow(tuple.SourceLineNumbers);
623 row[0] = tuple.Id.Id;
624 row[1] = tuple.Root;
625 row[2] = tuple.Key;
626 row[3] = tuple.Name;
627 row[4] = type;
628 }
629
555 private void AddRemoveRegistryTuple(RemoveRegistryTuple tuple, Output output) 630 private void AddRemoveRegistryTuple(RemoveRegistryTuple tuple, Output output)
556 { 631 {
557 if (tuple.Action == RemoveRegistryActionType.RemoveOnInstall) 632 if (tuple.Action == RemoveRegistryActionType.RemoveOnInstall)
@@ -684,7 +759,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
684 sequenceTableDefinition = this.TableDefinitions["AdminUISequence"]; 759 sequenceTableDefinition = this.TableDefinitions["AdminUISequence"];
685 } 760 }
686 break; 761 break;
687 case SequenceTable.AdvtExecuteSequence: 762 case SequenceTable.AdvertiseExecuteSequence:
688 if (OutputType.Module == output.Type) 763 if (OutputType.Module == output.Type)
689 { 764 {
690 output.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]); 765 output.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]);
@@ -754,8 +829,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
754 row.CompressionLevel = tuple.CompressionLevel; 829 row.CompressionLevel = tuple.CompressionLevel;
755 row.DiskPrompt = tuple.DiskPrompt; 830 row.DiskPrompt = tuple.DiskPrompt;
756 row.VolumeLabel = tuple.VolumeLabel; 831 row.VolumeLabel = tuple.VolumeLabel;
757 row.MaximumUncompressedMediaSize = tuple.MaximumUncompressedMediaSize; 832 row.MaximumUncompressedMediaSize = tuple.MaximumUncompressedMediaSize ?? DefaultMaximumUncompressedMediaSize;
758 row.MaximumCabinetSizeForLargeFileSplitting = tuple.MaximumCabinetSizeForLargeFileSplitting; 833 row.MaximumCabinetSizeForLargeFileSplitting = tuple.MaximumCabinetSizeForLargeFileSplitting ?? MaxValueOfMaxCabSizeForLargeFileSplitting;
759 } 834 }
760 835
761 private void AddTupleFromExtension(IntermediateTuple tuple, Output output) 836 private void AddTupleFromExtension(IntermediateTuple tuple, Output output)
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs
index ab2e8201..b5e5069a 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs
@@ -44,8 +44,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
44 44
45 if (0 < adminProperties.Count) 45 if (0 < adminProperties.Count)
46 { 46 {
47 var tuple = new PropertyTuple(null, new Identifier("AdminProperties", AccessModifier.Private)); 47 var tuple = new PropertyTuple(null, new Identifier(AccessModifier.Private, "AdminProperties"));
48 tuple.Property = "AdminProperties";
49 tuple.Value = String.Join(";", adminProperties); 48 tuple.Value = String.Join(";", adminProperties);
50 49
51 this.Section.Tuples.Add(tuple); 50 this.Section.Tuples.Add(tuple);
@@ -53,8 +52,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
53 52
54 if (0 < secureProperties.Count) 53 if (0 < secureProperties.Count)
55 { 54 {
56 var tuple = new PropertyTuple(null, new Identifier("SecureCustomProperties", AccessModifier.Private)); 55 var tuple = new PropertyTuple(null, new Identifier(AccessModifier.Private, "SecureCustomProperties"));
57 tuple.Property = "SecureCustomProperties";
58 tuple.Value = String.Join(";", secureProperties); 56 tuple.Value = String.Join(";", secureProperties);
59 57
60 this.Section.Tuples.Add(tuple); 58 this.Section.Tuples.Add(tuple);
@@ -62,8 +60,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
62 60
63 if (0 < hiddenProperties.Count) 61 if (0 < hiddenProperties.Count)
64 { 62 {
65 var tuple = new PropertyTuple(null, new Identifier("MsiHiddenProperties", AccessModifier.Private)); 63 var tuple = new PropertyTuple(null, new Identifier(AccessModifier.Private, "MsiHiddenProperties"));
66 tuple.Property = "MsiHiddenProperties";
67 tuple.Value = String.Join(";", hiddenProperties); 64 tuple.Value = String.Join(";", hiddenProperties);
68 65
69 this.Section.Tuples.Add(tuple); 66 this.Section.Tuples.Add(tuple);
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs
index 48b208f2..85567471 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs
@@ -57,7 +57,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
57 // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let 57 // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let
58 // this case be slightly more expensive because the cost of maintaining an indexed file row collection 58 // this case be slightly more expensive because the cost of maintaining an indexed file row collection
59 // is a lot more costly for the common cases. 59 // is a lot more costly for the common cases.
60 var indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal); 60 var indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.Id.Id, StringComparer.Ordinal);
61 61
62 foreach (var wixMergeRow in this.WixMergeTuples) 62 foreach (var wixMergeRow in this.WixMergeTuples)
63 { 63 {
@@ -101,42 +101,33 @@ namespace WixToolset.Core.WindowsInstaller.Bind
101 // NOTE: this is very tricky - the merge module file rows are not added to the 101 // NOTE: this is very tricky - the merge module file rows are not added to the
102 // file table because they should not be created via idt import. Instead, these 102 // file table because they should not be created via idt import. Instead, these
103 // rows are created by merging in the actual modules. 103 // rows are created by merging in the actual modules.
104 var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(record[1], AccessModifier.Private)); 104 var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(AccessModifier.Private, record[1]));
105 fileRow.File = record[1];
106 fileRow.Compressed = wixMergeRow.FileCompression; 105 fileRow.Compressed = wixMergeRow.FileCompression;
107 //FileRow fileRow = (FileRow)this.FileTable.CreateRow(wixMergeRow.SourceLineNumbers, false);
108 //fileRow.File = record[1];
109 //fileRow.Compressed = wixMergeRow.FileCompression;
110 106
111 var wixFileRow = new WixFileTuple(wixMergeRow.SourceLineNumbers); 107 var wixFileRow = new WixFileTuple(wixMergeRow.SourceLineNumbers);
112 wixFileRow.Directory_ = record[2]; 108 wixFileRow.Directory_ = record[2];
113 wixFileRow.DiskId = wixMergeRow.DiskId; 109 wixFileRow.DiskId = wixMergeRow.DiskId;
114 wixFileRow.PatchGroup = -1; 110 wixFileRow.PatchGroup = -1;
115 wixFileRow.Source = new IntermediateFieldPathValue { Path = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]) }; 111 wixFileRow.Source = new IntermediateFieldPathValue { Path = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]) };
116 //WixFileRow wixFileRow = (WixFileRow)this.WixFileTable.CreateRow(wixMergeRow.SourceLineNumbers, false);
117 //wixFileRow.Directory = record[2];
118 //wixFileRow.DiskId = wixMergeRow.DiskId;
119 //wixFileRow.PatchGroup = -1;
120 //wixFileRow.Source = Path.Combine(this.IntermediateFolder, "MergeId.", wixMergeRow.Number.ToString(CultureInfo.InvariantCulture), record[1]);
121 112
122 var mergeModuleFileFacade = new FileFacade(true, fileRow, wixFileRow); 113 var mergeModuleFileFacade = new FileFacade(true, fileRow, wixFileRow);
123 114
124 // If case-sensitive collision with another merge module or a user-authored file identifier. 115 // If case-sensitive collision with another merge module or a user-authored file identifier.
125 if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade)) 116 if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.Id.Id, out var collidingFacade))
126 { 117 {
127 this.Messaging.Write(ErrorMessages.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.File)); 118 this.Messaging.Write(ErrorMessages.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.Id.Id));
128 } 119 }
129 else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module 120 else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.Id.Id, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module
130 { 121 {
131 this.Messaging.Write(ErrorMessages.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); 122 this.Messaging.Write(ErrorMessages.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.Id.Id, collidingFacade.File.Id.Id));
132 } 123 }
133 else // no collision 124 else // no collision
134 { 125 {
135 mergeModulesFileFacades.Add(mergeModuleFileFacade); 126 mergeModulesFileFacades.Add(mergeModuleFileFacade);
136 127
137 // Keep updating the indexes as new rows are added. 128 // Keep updating the indexes as new rows are added.
138 indexedFileFacades.Add(mergeModuleFileFacade.File.File, mergeModuleFileFacade); 129 indexedFileFacades.Add(mergeModuleFileFacade.File.Id.Id, mergeModuleFileFacade);
139 uniqueModuleFileIdentifiers.Add(mergeModuleFileFacade.File.File, mergeModuleFileFacade); 130 uniqueModuleFileIdentifiers.Add(mergeModuleFileFacade.File.Id.Id, mergeModuleFileFacade);
140 } 131 }
141 132
142 containsFiles = true; 133 containsFiles = true;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs
index 70ba971f..3b7627c8 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs
@@ -25,14 +25,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
25 { 25 {
26 var facades = new List<FileFacade>(); 26 var facades = new List<FileFacade>();
27 27
28 var wixFiles = this.Section.Tuples.OfType<WixFileTuple>().ToDictionary(t => t.File_); 28 var wixFiles = this.Section.Tuples.OfType<WixFileTuple>().ToDictionary(t => t.Id.Id);
29 var deltaPatchFiles = this.Section.Tuples.OfType<WixDeltaPatchFileTuple>().ToDictionary(t => t.File_); 29 var deltaPatchFiles = this.Section.Tuples.OfType<WixDeltaPatchFileTuple>().ToDictionary(t => t.Id.Id);
30 30
31 foreach (var file in this.Section.Tuples.OfType<FileTuple>()) 31 foreach (var file in this.Section.Tuples.OfType<FileTuple>())
32 { 32 {
33 var wixFile = wixFiles[file.File]; 33 var wixFile = wixFiles[file.Id.Id];
34 34
35 deltaPatchFiles.TryGetValue(file.File, out var deltaPatchFile); 35 deltaPatchFiles.TryGetValue(file.Id.Id, out var deltaPatchFile);
36 36
37 facades.Add(new FileFacade(file, wixFile, deltaPatchFile)); 37 facades.Add(new FileFacade(file, wixFile, deltaPatchFile));
38 } 38 }
@@ -51,12 +51,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
51 ILookup<string, FileFacade> filesByDirectory = null; 51 ILookup<string, FileFacade> filesByDirectory = null;
52 ILookup<string, FileFacade> filesByDiskId = null; 52 ILookup<string, FileFacade> filesByDiskId = null;
53 53
54 foreach (var row in this.Section.Tuples.OfType<WixDeltaPatchSymbolPathsTuple>().OrderBy(r => r.Type)) 54 foreach (var row in this.Section.Tuples.OfType<WixDeltaPatchSymbolPathsTuple>().OrderBy(r => r.SymbolType))
55 { 55 {
56 switch (row.Type) 56 switch (row.SymbolType)
57 { 57 {
58 case SymbolPathType.File: 58 case SymbolPathType.File:
59 this.MergeSymbolPaths(row, deltaPatchFiles[row.Id]); 59 this.MergeSymbolPaths(row, deltaPatchFiles[row.SymbolId]);
60 break; 60 break;
61 61
62 case SymbolPathType.Component: 62 case SymbolPathType.Component:
@@ -65,9 +65,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
65 filesByComponent = facades.ToLookup(f => f.File.Component_); 65 filesByComponent = facades.ToLookup(f => f.File.Component_);
66 } 66 }
67 67
68 foreach (var facade in filesByComponent[row.Id]) 68 foreach (var facade in filesByComponent[row.SymbolId])
69 { 69 {
70 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); 70 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.Id.Id]);
71 } 71 }
72 break; 72 break;
73 73
@@ -77,9 +77,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
77 filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_); 77 filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_);
78 } 78 }
79 79
80 foreach (var facade in filesByDirectory[row.Id]) 80 foreach (var facade in filesByDirectory[row.SymbolId])
81 { 81 {
82 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); 82 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.Id.Id]);
83 } 83 }
84 break; 84 break;
85 85
@@ -89,9 +89,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
89 filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture)); 89 filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture));
90 } 90 }
91 91
92 foreach (var facade in filesByDiskId[row.Id]) 92 foreach (var facade in filesByDiskId[row.SymbolId])
93 { 93 {
94 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); 94 this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.Id.Id]);
95 } 95 }
96 break; 96 break;
97 97
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
index 4000c923..db887f09 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
@@ -286,7 +286,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
286 286
287 using (Record record = new Record(1)) 287 using (Record record = new Record(1))
288 { 288 {
289 record.SetString(1, file.File.File); 289 record.SetString(1, file.File.Id.Id);
290 view.Execute(record); 290 view.Execute(record);
291 } 291 }
292 292
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ModularizeCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ModularizeCommand.cs
index ba6af986..f0a43085 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/ModularizeCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/ModularizeCommand.cs
@@ -1,4 +1,4 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. 1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 2
3namespace WixToolset.Core.WindowsInstaller.Bind 3namespace WixToolset.Core.WindowsInstaller.Bind
4{ 4{
@@ -21,7 +21,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
21 this.ModularizationGuid = modularizationGuid; 21 this.ModularizationGuid = modularizationGuid;
22 22
23 // Gather all the unique suppress modularization identifiers. 23 // Gather all the unique suppress modularization identifiers.
24 this.SuppressModularizationIdentifiers = new HashSet<string>(suppressTuples.Select(s => s.WixSuppressModularization)); 24 this.SuppressModularizationIdentifiers = new HashSet<string>(suppressTuples.Select(s => s.Id.Id));
25 } 25 }
26 26
27 private Output Output { get; } 27 private Output Output { get; }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
index f5561b42..369c241c 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
@@ -54,8 +54,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
54 54
55 var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId); 55 var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId);
56 56
57 var wixMediaRows = this.Section.Tuples.OfType<WixMediaTuple>().ToDictionary(t => t.DiskId_);
58
59 using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) 57 using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly))
60 { 58 {
61 using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) 59 using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`"))
@@ -85,25 +83,20 @@ namespace WixToolset.Core.WindowsInstaller.Bind
85 { 83 {
86 var mediaTuple = mediaRows[facade.WixFile.DiskId]; 84 var mediaTuple = mediaRows[facade.WixFile.DiskId];
87 string relativeFileLayoutPath = null; 85 string relativeFileLayoutPath = null;
88 string mediaLayoutFolder = null; 86 string mediaLayoutFolder = mediaTuple.Layout;
89
90 if (wixMediaRows.TryGetValue(facade.WixFile.DiskId, out var wixMediaRow))
91 {
92 mediaLayoutFolder = wixMediaRow.Layout;
93 }
94 87
95 var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory); 88 var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory);
96 89
97 // setup up the query record and find the appropriate file in the 90 // setup up the query record and find the appropriate file in the
98 // previously executed file view 91 // previously executed file view
99 fileQueryRecord[1] = facade.File.File; 92 fileQueryRecord[1] = facade.File.Id.Id;
100 fileView.Execute(fileQueryRecord); 93 fileView.Execute(fileQueryRecord);
101 94
102 using (Record fileRecord = fileView.Fetch()) 95 using (Record fileRecord = fileView.Fetch())
103 { 96 {
104 if (null == fileRecord) 97 if (null == fileRecord)
105 { 98 {
106 throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File)); 99 throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.Id.Id));
107 } 100 }
108 101
109 relativeFileLayoutPath = PathResolver.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage); 102 relativeFileLayoutPath = PathResolver.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage);
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
index f1a47f70..3cba0f51 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
@@ -6,7 +6,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Globalization; 7 using System.Globalization;
8 using System.Linq; 8 using System.Linq;
9 using WixToolset.Core.Native;
10 using WixToolset.Data; 9 using WixToolset.Data;
11 using WixToolset.Data.Tuples; 10 using WixToolset.Data.Tuples;
12 using WixToolset.Data.WindowsInstaller; 11 using WixToolset.Data.WindowsInstaller;
@@ -31,20 +30,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
31 30
32 public IMessaging Messaging { private get; set; } 31 public IMessaging Messaging { private get; set; }
33 32
34 public void Execute()
35 {
36 var actions = this.Section.Tuples.OfType<WixActionTuple>().ToList();
37 var suppressActions = this.Section.Tuples.OfType<WixSuppressActionTuple>().ToList();
38
39 this.SequenceActions(actions, suppressActions);
40 }
41
42 /// <summary> 33 /// <summary>
43 /// Set sequence numbers for all the actions and create rows in the output object. 34 /// Set sequence numbers for all the actions and create rows in the output object.
44 /// </summary> 35 /// </summary>
45 /// <param name="actionRows">Collection of actions to schedule.</param> 36 public void Execute()
46 /// <param name="suppressActionRows">Collection of actions to suppress.</param>
47 private void SequenceActions(List<WixActionTuple> actionRows, List<WixSuppressActionTuple> suppressActionRows)
48 { 37 {
49 var overridableActionRows = new Dictionary<string, WixActionTuple>(); 38 var overridableActionRows = new Dictionary<string, WixActionTuple>();
50 var requiredActionRows = new Dictionary<string, WixActionTuple>(); 39 var requiredActionRows = new Dictionary<string, WixActionTuple>();
@@ -118,7 +107,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
118 } 107 }
119 108
120 // Suppress the required actions that are overridable. 109 // Suppress the required actions that are overridable.
121 foreach (var suppressActionRow in suppressActionRows) 110 foreach (var suppressActionRow in this.Section.Tuples.OfType<WixSuppressActionTuple>())
122 { 111 {
123 var key = suppressActionRow.Id.Id; 112 var key = suppressActionRow.Id.Id;
124 113
@@ -233,7 +222,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
233 { 222 {
234 if (sequenceScheduledActionRow.Sequence == actionRow.Sequence) 223 if (sequenceScheduledActionRow.Sequence == actionRow.Sequence)
235 { 224 {
236 this.Messaging.Write(WarningMessages.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence)); 225 this.Messaging.Write(WarningMessages.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence ?? 0));
237 if (null != sequenceScheduledActionRow.SourceLineNumbers) 226 if (null != sequenceScheduledActionRow.SourceLineNumbers)
238 { 227 {
239 this.Messaging.Write(WarningMessages.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers)); 228 this.Messaging.Write(WarningMessages.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers));
@@ -245,7 +234,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
245 } 234 }
246 } 235 }
247 236
248 absoluteActionRows.Sort((x, y) => x.Sequence.CompareTo(y.Sequence)); 237 absoluteActionRows.Sort((x, y) => (x.Sequence ?? 0).CompareTo(y.Sequence ?? 0));
249 238
250 // Schedule the relatively scheduled actions (by resolving the dependency trees). 239 // Schedule the relatively scheduled actions (by resolving the dependency trees).
251 var previousUsedSequence = 0; 240 var previousUsedSequence = 0;
@@ -310,7 +299,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
310 var nextUsedSequence = Int16.MaxValue + 1; 299 var nextUsedSequence = Int16.MaxValue + 1;
311 if (absoluteActionRows.Count > j + 1) 300 if (absoluteActionRows.Count > j + 1)
312 { 301 {
313 nextUsedSequence = absoluteActionRows[j + 1].Sequence; 302 nextUsedSequence = absoluteActionRows[j + 1].Sequence ?? 0;
314 } 303 }
315 304
316 // Schedule the action rows after this one. 305 // Schedule the action rows after this one.
@@ -337,7 +326,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
337 } 326 }
338 327
339 // keep track of this sequence number as the previous used sequence number for the next iteration 328 // keep track of this sequence number as the previous used sequence number for the next iteration
340 previousUsedSequence = absoluteActionRow.Sequence; 329 previousUsedSequence = absoluteActionRow.Sequence ?? 0;
341 } 330 }
342 331
343 // add the absolutely and relatively scheduled actions to the list of scheduled actions 332 // add the absolutely and relatively scheduled actions to the list of scheduled actions
@@ -412,9 +401,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
412 set.Add("InstallExecuteSequence/AppSearch"); 401 set.Add("InstallExecuteSequence/AppSearch");
413 set.Add("InstallUISequence/AppSearch"); 402 set.Add("InstallUISequence/AppSearch");
414 break; 403 break;
415 case TupleDefinitionType.BindImage:
416 set.Add("InstallExecuteSequence/BindImage");
417 break;
418 case TupleDefinitionType.CCPSearch: 404 case TupleDefinitionType.CCPSearch:
419 set.Add("InstallExecuteSequence/AppSearch"); 405 set.Add("InstallExecuteSequence/AppSearch");
420 set.Add("InstallExecuteSequence/CCPSearch"); 406 set.Add("InstallExecuteSequence/CCPSearch");
@@ -452,10 +438,32 @@ namespace WixToolset.Core.WindowsInstaller.Bind
452 case TupleDefinitionType.File: 438 case TupleDefinitionType.File:
453 set.Add("InstallExecuteSequence/InstallFiles"); 439 set.Add("InstallExecuteSequence/InstallFiles");
454 set.Add("InstallExecuteSequence/RemoveFiles"); 440 set.Add("InstallExecuteSequence/RemoveFiles");
455 break; 441
456 case TupleDefinitionType.Font: 442 var foundFont = false;
457 set.Add("InstallExecuteSequence/RegisterFonts"); 443 var foundSelfReg = false;
458 set.Add("InstallExecuteSequence/UnregisterFonts"); 444 var foundBindPath = false;
445 foreach (var file in this.Section.Tuples.OfType<FileTuple>())
446 {
447 if (!foundFont && !String.IsNullOrEmpty(file.FontTitle))
448 {
449 set.Add("InstallExecuteSequence/RegisterFonts");
450 set.Add("InstallExecuteSequence/UnregisterFonts");
451 foundFont = true;
452 }
453
454 if (!foundSelfReg && file.SelfRegCost.HasValue)
455 {
456 set.Add("InstallExecuteSequence/SelfRegModules");
457 set.Add("InstallExecuteSequence/SelfUnregModules");
458 foundSelfReg = true;
459 }
460
461 if (!foundBindPath && !String.IsNullOrEmpty(file.BindPath))
462 {
463 set.Add("InstallExecuteSequence/BindImage");
464 foundBindPath = true;
465 }
466 }
459 break; 467 break;
460 case TupleDefinitionType.IniFile: 468 case TupleDefinitionType.IniFile:
461 case TupleDefinitionType.RemoveIniFile: 469 case TupleDefinitionType.RemoveIniFile:
@@ -511,10 +519,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
511 case TupleDefinitionType.RemoveFile: 519 case TupleDefinitionType.RemoveFile:
512 set.Add("InstallExecuteSequence/RemoveFiles"); 520 set.Add("InstallExecuteSequence/RemoveFiles");
513 break; 521 break;
514 case TupleDefinitionType.SelfReg:
515 set.Add("InstallExecuteSequence/SelfRegModules");
516 set.Add("InstallExecuteSequence/SelfUnregModules");
517 break;
518 case TupleDefinitionType.ServiceControl: 522 case TupleDefinitionType.ServiceControl:
519 set.Add("InstallExecuteSequence/StartServices"); 523 set.Add("InstallExecuteSequence/StartServices");
520 set.Add("InstallExecuteSequence/StopServices"); 524 set.Add("InstallExecuteSequence/StopServices");
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
index 0df5329a..c8451a1e 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
@@ -79,7 +79,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
79 79
80 if (!fileInfo.Exists) 80 if (!fileInfo.Exists)
81 { 81 {
82 this.Messaging.Write(ErrorMessages.CannotFindFile(file.File.SourceLineNumbers, file.File.File, file.File.LongFileName, file.WixFile.Source.Path)); 82 this.Messaging.Write(ErrorMessages.CannotFindFile(file.File.SourceLineNumbers, file.File.Id.Id, file.File.LongFileName, file.WixFile.Source.Path));
83 return; 83 return;
84 } 84 }
85 85
@@ -127,16 +127,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
127 // 127 //
128 // Also, if we do not find a matching file identifier then the user provided a default version and is providing a version 128 // Also, if we do not find a matching file identifier then the user provided a default version and is providing a version
129 // for unversioned file. That's allowed but generally a dangerous thing to do so let's point that out to the user. 129 // for unversioned file. That's allowed but generally a dangerous thing to do so let's point that out to the user.
130 if (!this.FileFacades.Any(r => file.File.Version.Equals(r.File.File, StringComparison.Ordinal))) 130 if (!this.FileFacades.Any(r => file.File.Version.Equals(r.File.Id.Id, StringComparison.Ordinal)))
131 { 131 {
132 this.Messaging.Write(WarningMessages.DefaultVersionUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Version, file.File.File)); 132 this.Messaging.Write(WarningMessages.DefaultVersionUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Version, file.File.Id.Id));
133 } 133 }
134 } 134 }
135 else 135 else
136 { 136 {
137 if (null != file.File.Language) 137 if (null != file.File.Language)
138 { 138 {
139 this.Messaging.Write(WarningMessages.DefaultLanguageUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.File)); 139 this.Messaging.Write(WarningMessages.DefaultLanguageUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.Id.Id));
140 } 140 }
141 141
142 int[] hash; 142 int[] hash;
@@ -162,7 +162,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
162 this.Section.Tuples.Add(file.Hash); 162 this.Section.Tuples.Add(file.Hash);
163 } 163 }
164 164
165 file.Hash.File_ = file.File.File; 165 file.Hash.File_ = file.File.Id.Id;
166 file.Hash.Options = 0; 166 file.Hash.Options = 0;
167 file.Hash.HashPart1 = hash[0]; 167 file.Hash.HashPart1 = hash[0];
168 file.Hash.HashPart2 = hash[1]; 168 file.Hash.HashPart2 = hash[1];
@@ -178,7 +178,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
178 { 178 {
179 file.File.Version = version; 179 file.File.Version = version;
180 } 180 }
181 else if (!this.FileFacades.Any(r => file.File.Version.Equals(r.File.File, StringComparison.Ordinal))) // this looks expensive, but see explanation below. 181 else if (!this.FileFacades.Any(r => file.File.Version.Equals(r.File.Id.Id, StringComparison.Ordinal))) // this looks expensive, but see explanation below.
182 { 182 {
183 // The user provided a default version for the file row so we looked for a companion file (a file row with Id matching 183 // The user provided a default version for the file row so we looked for a companion file (a file row with Id matching
184 // the version value). We didn't find it so, we will override the default version they provided with the actual 184 // the version value). We didn't find it so, we will override the default version they provided with the actual
@@ -194,7 +194,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
194 194
195 if (!String.IsNullOrEmpty(file.File.Language) && String.IsNullOrEmpty(language)) 195 if (!String.IsNullOrEmpty(file.File.Language) && String.IsNullOrEmpty(language))
196 { 196 {
197 this.Messaging.Write(WarningMessages.DefaultLanguageUsedForVersionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.File)); 197 this.Messaging.Write(WarningMessages.DefaultLanguageUsedForVersionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.Id.Id));
198 } 198 }
199 else // override the default provided by the user (usually nothing) with the actual language from the file itself. 199 else // override the default provided by the user (usually nothing) with the actual language from the file itself.
200 { 200 {
@@ -206,13 +206,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
206 { 206 {
207 if (!String.IsNullOrEmpty(file.File.Version)) 207 if (!String.IsNullOrEmpty(file.File.Version))
208 { 208 {
209 var key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", file.File.File); 209 var key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", file.File.Id.Id);
210 this.VariableCache[key] = file.File.Version; 210 this.VariableCache[key] = file.File.Version;
211 } 211 }
212 212
213 if (!String.IsNullOrEmpty(file.File.Language)) 213 if (!String.IsNullOrEmpty(file.File.Language))
214 { 214 {
215 var key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", file.File.File); 215 var key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", file.File.Id.Id);
216 this.VariableCache[key] = file.File.Language; 216 this.VariableCache[key] = file.File.Language;
217 } 217 }
218 } 218 }
@@ -256,7 +256,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
256 // add the assembly name to the information cache 256 // add the assembly name to the information cache
257 if (null != this.VariableCache) 257 if (null != this.VariableCache)
258 { 258 {
259 this.VariableCache[$"assemblyfullname.{file.File.File}"] = assemblyName.GetFullName(); 259 this.VariableCache[$"assemblyfullname.{file.File.Id.Id}"] = assemblyName.GetFullName();
260 } 260 }
261 } 261 }
262 catch (WixException e) 262 catch (WixException e)
@@ -269,10 +269,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
269 // TODO: Consider passing in the this.FileFacades as an indexed collection instead of searching through 269 // TODO: Consider passing in the this.FileFacades as an indexed collection instead of searching through
270 // all files like this. Even though this is a rare case it looks like we might be able to index the 270 // all files like this. Even though this is a rare case it looks like we might be able to index the
271 // file earlier. 271 // file earlier.
272 var fileManifest = this.FileFacades.SingleOrDefault(r => r.File.File.Equals(file.WixFile.File_AssemblyManifest, StringComparison.Ordinal)); 272 var fileManifest = this.FileFacades.FirstOrDefault(r => r.File.Id.Id.Equals(file.WixFile.File_AssemblyManifest, StringComparison.Ordinal));
273 if (null == fileManifest) 273 if (null == fileManifest)
274 { 274 {
275 this.Messaging.Write(ErrorMessages.MissingManifestForWin32Assembly(file.File.SourceLineNumbers, file.File.File, file.WixFile.File_AssemblyManifest)); 275 this.Messaging.Write(ErrorMessages.MissingManifestForWin32Assembly(file.File.SourceLineNumbers, file.File.Id.Id, file.WixFile.File_AssemblyManifest));
276 } 276 }
277 277
278 try 278 try
@@ -358,7 +358,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
358 358
359 if (this.VariableCache != null) 359 if (this.VariableCache != null)
360 { 360 {
361 var key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, file.File.File).ToLowerInvariant(); 361 var key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, file.File.Id.Id).ToLowerInvariant();
362 this.VariableCache[key] = value; 362 this.VariableCache[key] = value;
363 } 363 }
364 } 364 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs
index 0767adb0..e6738bb7 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs
@@ -1,4 +1,4 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. 1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 2
3namespace WixToolset.Core.WindowsInstaller.Bind 3namespace WixToolset.Core.WindowsInstaller.Bind
4{ 4{
@@ -6,13 +6,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
6 using System.Linq; 6 using System.Linq;
7 using WixToolset.Core.Bind; 7 using WixToolset.Core.Bind;
8 using WixToolset.Data; 8 using WixToolset.Data;
9 using WixToolset.Data.Tuples;
10 using WixToolset.Data.WindowsInstaller; 9 using WixToolset.Data.WindowsInstaller;
11 using WixToolset.Data.WindowsInstaller.Rows; 10 using WixToolset.Data.WindowsInstaller.Rows;
12 11
13 internal class UpdateMediaSequencesCommand 12 internal class UpdateMediaSequencesCommand
14 { 13 {
15 public UpdateMediaSequencesCommand(Output output, List<FileFacade> fileFacades, Dictionary<int, MediaTuple> assignedMediaRows) 14 public UpdateMediaSequencesCommand(Output output, List<FileFacade> fileFacades)
16 { 15 {
17 this.Output = output; 16 this.Output = output;
18 this.FileFacades = fileFacades; 17 this.FileFacades = fileFacades;
@@ -34,7 +33,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
34 33
35 // Order by Component to group the files by directory. 34 // Order by Component to group the files by directory.
36 var optimized = this.OptimizedFileFacades(); 35 var optimized = this.OptimizedFileFacades();
37 foreach (var fileId in optimized.Select(f => f.File.File)) 36 foreach (var fileId in optimized.Select(f => f.File.Id.Id))
38 { 37 {
39 var fileRow = fileRows.Get(fileId); 38 var fileRow = fileRows.Get(fileId);
40 fileRow.Sequence = ++lastSequence; 39 fileRow.Sequence = ++lastSequence;
@@ -77,7 +76,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
77 } 76 }
78 else 77 else
79 { 78 {
80 var fileRow = fileRows.Get(facade.File.File); 79 var fileRow = fileRows.Get(facade.File.Id.Id);
81 fileRow.Sequence = ++lastSequence; 80 fileRow.Sequence = ++lastSequence;
82 } 81 }
83 } 82 }
@@ -103,7 +102,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
103 mediaRow = mediaRows.Get(facade.WixFile.DiskId); 102 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
104 } 103 }
105 104
106 var fileRow = fileRows.Get(facade.File.File); 105 var fileRow = fileRows.Get(facade.File.Id.Id);
107 fileRow.Sequence = ++lastSequence; 106 fileRow.Sequence = ++lastSequence;
108 } 107 }
109 } 108 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs b/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
index b6b6b8c3..b4d25786 100644
--- a/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
@@ -375,7 +375,7 @@ namespace WixToolset.Core.WindowsInstaller
375 case SequenceTable.AdminUISequence: 375 case SequenceTable.AdminUISequence:
376 sequenceElement = new Wix.AdminUISequence(); 376 sequenceElement = new Wix.AdminUISequence();
377 break; 377 break;
378 case SequenceTable.AdvtExecuteSequence: 378 case SequenceTable.AdvertiseExecuteSequence:
379 sequenceElement = new Wix.AdvertiseExecuteSequence(); 379 sequenceElement = new Wix.AdvertiseExecuteSequence();
380 break; 380 break;
381 case SequenceTable.InstallExecuteSequence: 381 case SequenceTable.InstallExecuteSequence:
diff --git a/src/WixToolset.Core.WindowsInstaller/Differ.cs b/src/WixToolset.Core.WindowsInstaller/Differ.cs
index c7fe8960..209773e0 100644
--- a/src/WixToolset.Core.WindowsInstaller/Differ.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Differ.cs
@@ -8,6 +8,7 @@ namespace WixToolset.Core.WindowsInstaller
8 using System.Globalization; 8 using System.Globalization;
9 using WixToolset.Core.WindowsInstaller.Msi; 9 using WixToolset.Core.WindowsInstaller.Msi;
10 using WixToolset.Data; 10 using WixToolset.Data;
11 using WixToolset.Data.Tuples;
11 using WixToolset.Data.WindowsInstaller; 12 using WixToolset.Data.WindowsInstaller;
12 using WixToolset.Data.WindowsInstaller.Rows; 13 using WixToolset.Data.WindowsInstaller.Rows;
13 using WixToolset.Extensibility; 14 using WixToolset.Extensibility;
@@ -18,7 +19,7 @@ namespace WixToolset.Core.WindowsInstaller
18 /// </summary> 19 /// </summary>
19 public sealed class Differ 20 public sealed class Differ
20 { 21 {
21 private List<IInspectorExtension> inspectorExtensions; 22 private readonly List<IInspectorExtension> inspectorExtensions;
22 private bool showPedanticMessages; 23 private bool showPedanticMessages;
23 private bool suppressKeepingSpecialRows; 24 private bool suppressKeepingSpecialRows;
24 private bool preserveUnchangedRows; 25 private bool preserveUnchangedRows;
diff --git a/src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs b/src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs
index 9964b414..5abf02ce 100644
--- a/src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs
@@ -16,7 +16,7 @@ namespace WixToolset.Core.WindowsInstaller.Rows
16 // TODO: Remove this 16 // TODO: Remove this
17 internal sealed class WixActionRowCollection : ICollection 17 internal sealed class WixActionRowCollection : ICollection
18 { 18 {
19 private SortedList collection; 19 private readonly SortedList collection;
20 20
21 /// <summary> 21 /// <summary>
22 /// Creates a new action table object. 22 /// Creates a new action table object.
@@ -235,7 +235,7 @@ namespace WixToolset.Core.WindowsInstaller.Rows
235 string id = null; 235 string id = null;
236 string condition = null; 236 string condition = null;
237 bool empty = reader.IsEmptyElement; 237 bool empty = reader.IsEmptyElement;
238 int sequence = int.MinValue; 238 int sequence = Int32.MinValue;
239 int sequenceCount = 0; 239 int sequenceCount = 0;
240 SequenceTable[] sequenceTables = new SequenceTable[Enum.GetValues(typeof(SequenceTable)).Length]; 240 SequenceTable[] sequenceTables = new SequenceTable[Enum.GetValues(typeof(SequenceTable)).Length];
241 241
@@ -263,7 +263,7 @@ namespace WixToolset.Core.WindowsInstaller.Rows
263 case "AdvtExecuteSequence": 263 case "AdvtExecuteSequence":
264 if (reader.Value.Equals("yes")) 264 if (reader.Value.Equals("yes"))
265 { 265 {
266 sequenceTables[sequenceCount] = SequenceTable.AdvtExecuteSequence; 266 sequenceTables[sequenceCount] = SequenceTable.AdvertiseExecuteSequence;
267 ++sequenceCount; 267 ++sequenceCount;
268 } 268 }
269 break; 269 break;
@@ -295,7 +295,7 @@ namespace WixToolset.Core.WindowsInstaller.Rows
295 throw new XmlException(); 295 throw new XmlException();
296 } 296 }
297 297
298 if (int.MinValue == sequence) 298 if (Int32.MinValue == sequence)
299 { 299 {
300 throw new XmlException(); 300 throw new XmlException();
301 } 301 }
@@ -316,7 +316,7 @@ namespace WixToolset.Core.WindowsInstaller.Rows
316 316
317 // create the actions 317 // create the actions
318 WixActionRow[] actionRows = new WixActionRow[sequenceCount]; 318 WixActionRow[] actionRows = new WixActionRow[sequenceCount];
319 for (int i = 0; i < sequenceCount; i++) 319 for (var i = 0; i < sequenceCount; i++)
320 { 320 {
321 //WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence); 321 //WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence);
322 //actionRows[i] = actionRow; 322 //actionRows[i] = actionRow;