aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2020-06-12 12:55:28 -0700
committerRob Mensching <rob@firegiant.com>2020-06-13 09:22:27 -0700
commitc0f1332a0e18e9d506fe80c328548b001dcf93df (patch)
tree4980dddd35350e79b00a61574feafa859e857e3f /src
parent167d26d002b1412e72d96ed2bbc0761fc0f1344b (diff)
downloadwix-c0f1332a0e18e9d506fe80c328548b001dcf93df.tar.gz
wix-c0f1332a0e18e9d506fe80c328548b001dcf93df.tar.bz2
wix-c0f1332a0e18e9d506fe80c328548b001dcf93df.zip
Remove use of remaining WixXxxRows
Diffstat (limited to 'src')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs6
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs89
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs23
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs237
5 files changed, 159 insertions, 198 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index b3f81212..6c2968ec 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -428,7 +428,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
428 { 428 {
429 this.Messaging.Write(VerboseMessages.CreatingCabinetFiles()); 429 this.Messaging.Write(VerboseMessages.CreatingCabinetFiles());
430 430
431 var command = new CreateCabinetsCommand(this.ServiceProvider, this.BackendHelper); 431 var mediaTemplate = section.Tuples.OfType<WixMediaTemplateTuple>().FirstOrDefault();
432
433 var command = new CreateCabinetsCommand(this.ServiceProvider, this.BackendHelper, mediaTemplate);
432 command.CabbingThreadCount = this.CabbingThreadCount; 434 command.CabbingThreadCount = this.CabbingThreadCount;
433 command.CabCachePath = this.CabCachePath; 435 command.CabCachePath = this.CabCachePath;
434 command.DefaultCompressionLevel = this.DefaultCompressionLevel; 436 command.DefaultCompressionLevel = this.DefaultCompressionLevel;
@@ -438,7 +440,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
438 command.LayoutDirectory = layoutDirectory; 440 command.LayoutDirectory = layoutDirectory;
439 command.Compressed = compressed; 441 command.Compressed = compressed;
440 command.ModularizationSuffix = modularizationSuffix; 442 command.ModularizationSuffix = modularizationSuffix;
441 command.FileRowsByCabinet = filesByCabinetMedia; 443 command.FileFacadesByCabinet = filesByCabinetMedia;
442 command.ResolveMedia = this.ResolveMedia; 444 command.ResolveMedia = this.ResolveMedia;
443 command.TableDefinitions = tableDefinitions; 445 command.TableDefinitions = tableDefinitions;
444 command.IntermediateFolder = this.IntermediateFolder; 446 command.IntermediateFolder = this.IntermediateFolder;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
index f2f9895d..de357e53 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
@@ -12,7 +12,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
12 using WixToolset.Data; 12 using WixToolset.Data;
13 using WixToolset.Data.Tuples; 13 using WixToolset.Data.Tuples;
14 using WixToolset.Data.WindowsInstaller; 14 using WixToolset.Data.WindowsInstaller;
15 using WixToolset.Data.WindowsInstaller.Rows;
16 using WixToolset.Extensibility; 15 using WixToolset.Extensibility;
17 using WixToolset.Extensibility.Data; 16 using WixToolset.Extensibility.Data;
18 using WixToolset.Extensibility.Services; 17 using WixToolset.Extensibility.Services;
@@ -33,7 +32,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
33 32
34 private Dictionary<string, string> lastCabinetAddedToMediaTable; // Key is First Cabinet Name, Value is Last Cabinet Added in the Split Sequence 33 private Dictionary<string, string> lastCabinetAddedToMediaTable; // Key is First Cabinet Name, Value is Last Cabinet Added in the Split Sequence
35 34
36 public CreateCabinetsCommand(IWixToolsetServiceProvider serviceProvider, IBackendHelper backendHelper) 35 public CreateCabinetsCommand(IWixToolsetServiceProvider serviceProvider, IBackendHelper backendHelper, WixMediaTemplateTuple mediaTemplate)
37 { 36 {
38 this.fileTransfers = new List<IFileTransfer>(); 37 this.fileTransfers = new List<IFileTransfer>();
39 38
@@ -44,11 +43,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
44 this.ServiceProvider = serviceProvider; 43 this.ServiceProvider = serviceProvider;
45 44
46 this.BackendHelper = backendHelper; 45 this.BackendHelper = backendHelper;
46
47 this.MediaTemplate = mediaTemplate;
47 } 48 }
48 49
49 public IWixToolsetServiceProvider ServiceProvider { get; } 50 private IWixToolsetServiceProvider ServiceProvider { get; }
51
52 private IBackendHelper BackendHelper { get; }
50 53
51 public IBackendHelper BackendHelper { get; } 54 private WixMediaTemplateTuple MediaTemplate { get; }
52 55
53 /// <summary> 56 /// <summary>
54 /// Sets the number of threads to use for cabinet creation. 57 /// Sets the number of threads to use for cabinet creation.
@@ -77,7 +80,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
77 80
78 public string ModularizationSuffix { private get; set; } 81 public string ModularizationSuffix { private get; set; }
79 82
80 public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileRowsByCabinet { private get; set; } 83 public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileFacadesByCabinet { private get; set; }
81 84
82 public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; } 85 public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; }
83 86
@@ -90,7 +93,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
90 /// <param name="output">Output to generate image for.</param> 93 /// <param name="output">Output to generate image for.</param>
91 /// <param name="layoutDirectory">The directory in which the image should be layed out.</param> 94 /// <param name="layoutDirectory">The directory in which the image should be layed out.</param>
92 /// <param name="compressed">Flag if source image should be compressed.</param> 95 /// <param name="compressed">Flag if source image should be compressed.</param>
93 /// <returns>The uncompressed file rows.</returns>
94 public void Execute() 96 public void Execute()
95 { 97 {
96 this.lastCabinetAddedToMediaTable = new Dictionary<string, string>(); 98 this.lastCabinetAddedToMediaTable = new Dictionary<string, string>();
@@ -109,7 +111,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
109 cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = maximumCabinetSizeForLargeFileSplitting; 111 cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = maximumCabinetSizeForLargeFileSplitting;
110 cabinetBuilder.MaximumUncompressedMediaSize = maximumUncompressedMediaSize; 112 cabinetBuilder.MaximumUncompressedMediaSize = maximumUncompressedMediaSize;
111 113
112 foreach (var entry in this.FileRowsByCabinet) 114 foreach (var entry in this.FileFacadesByCabinet)
113 { 115 {
114 var mediaTuple = entry.Key; 116 var mediaTuple = entry.Key;
115 var files = entry.Value; 117 var files = entry.Value;
@@ -175,28 +177,28 @@ namespace WixToolset.Core.WindowsInstaller.Bind
175 /// </summary> 177 /// </summary>
176 /// <param name="output">Output for the current database.</param> 178 /// <param name="output">Output for the current database.</param>
177 /// <param name="cabinetDir">Directory to create cabinet in.</param> 179 /// <param name="cabinetDir">Directory to create cabinet in.</param>
178 /// <param name="mediaRow">MediaRow containing information about the cabinet.</param> 180 /// <param name="mediaTuple">Media tuple containing information about the cabinet.</param>
179 /// <param name="fileFacades">Collection of files in this cabinet.</param> 181 /// <param name="fileFacades">Collection of files in this cabinet.</param>
180 /// <returns>created CabinetWorkItem object</returns> 182 /// <returns>created CabinetWorkItem object</returns>
181 private CabinetWorkItem CreateCabinetWorkItem(WindowsInstallerData output, string cabinetDir, MediaTuple mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades) 183 private CabinetWorkItem CreateCabinetWorkItem(WindowsInstallerData output, string cabinetDir, MediaTuple mediaTuple, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades)
182 { 184 {
183 CabinetWorkItem cabinetWorkItem = null; 185 CabinetWorkItem cabinetWorkItem = null;
184 string tempCabinetFileX = Path.Combine(this.IntermediateFolder, mediaRow.Cabinet); 186 var tempCabinetFileX = Path.Combine(this.IntermediateFolder, mediaTuple.Cabinet);
185 187
186 // check for an empty cabinet 188 // check for an empty cabinet
187 if (!fileFacades.Any()) 189 if (!fileFacades.Any())
188 { 190 {
189 // Remove the leading '#' from the embedded cabinet name to make the warning easier to understand 191 // Remove the leading '#' from the embedded cabinet name to make the warning easier to understand
190 var cabinetName = mediaRow.Cabinet.TrimStart('#'); 192 var cabinetName = mediaTuple.Cabinet.TrimStart('#');
191 193
192 // If building a patch, remind them to run -p for torch. 194 // If building a patch, remind them to run -p for torch.
193 if (OutputType.Patch == output.Type) 195 if (OutputType.Patch == output.Type)
194 { 196 {
195 this.Messaging.Write(WarningMessages.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName, true)); 197 this.Messaging.Write(WarningMessages.EmptyCabinet(mediaTuple.SourceLineNumbers, cabinetName, true));
196 } 198 }
197 else 199 else
198 { 200 {
199 this.Messaging.Write(WarningMessages.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName)); 201 this.Messaging.Write(WarningMessages.EmptyCabinet(mediaTuple.SourceLineNumbers, cabinetName));
200 } 202 }
201 } 203 }
202 204
@@ -212,7 +214,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
212 } 214 }
213 else // reuse the cabinet from the cabinet cache. 215 else // reuse the cabinet from the cabinet cache.
214 { 216 {
215 this.Messaging.Write(VerboseMessages.ReusingCabCache(mediaRow.SourceLineNumbers, mediaRow.Cabinet, resolvedCabinet.Path)); 217 this.Messaging.Write(VerboseMessages.ReusingCabCache(mediaTuple.SourceLineNumbers, mediaTuple.Cabinet, resolvedCabinet.Path));
216 218
217 try 219 try
218 { 220 {
@@ -226,27 +228,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind
226 } 228 }
227 catch (Exception e) 229 catch (Exception e)
228 { 230 {
229 this.Messaging.Write(WarningMessages.CannotUpdateCabCache(mediaRow.SourceLineNumbers, resolvedCabinet.Path, e.Message)); 231 this.Messaging.Write(WarningMessages.CannotUpdateCabCache(mediaTuple.SourceLineNumbers, resolvedCabinet.Path, e.Message));
230 } 232 }
231 } 233 }
232 234
233 var trackResolvedCabinet = this.BackendHelper.TrackFile(resolvedCabinet.Path, TrackedFileType.Intermediate, mediaRow.SourceLineNumbers); 235 var trackResolvedCabinet = this.BackendHelper.TrackFile(resolvedCabinet.Path, TrackedFileType.Intermediate, mediaTuple.SourceLineNumbers);
234 this.trackedFiles.Add(trackResolvedCabinet); 236 this.trackedFiles.Add(trackResolvedCabinet);
235 237
236 if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal)) 238 if (mediaTuple.Cabinet.StartsWith("#", StringComparison.Ordinal))
237 { 239 {
238 var streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]); 240 var streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]);
239 241
240 var streamRow = streamsTable.CreateRow(mediaRow.SourceLineNumbers); 242 var streamRow = streamsTable.CreateRow(mediaTuple.SourceLineNumbers);
241 streamRow[0] = mediaRow.Cabinet.Substring(1); 243 streamRow[0] = mediaTuple.Cabinet.Substring(1);
242 streamRow[1] = resolvedCabinet.Path; 244 streamRow[1] = resolvedCabinet.Path;
243 } 245 }
244 else 246 else
245 { 247 {
246 var trackDestination = this.BackendHelper.TrackFile(Path.Combine(cabinetDir, mediaRow.Cabinet), TrackedFileType.Final, mediaRow.SourceLineNumbers); 248 var trackDestination = this.BackendHelper.TrackFile(Path.Combine(cabinetDir, mediaTuple.Cabinet), TrackedFileType.Final, mediaTuple.SourceLineNumbers);
247 this.trackedFiles.Add(trackDestination); 249 this.trackedFiles.Add(trackDestination);
248 250
249 var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, trackDestination.Path, resolvedCabinet.BuildOption == CabinetBuildOption.BuildAndMove, mediaRow.SourceLineNumbers); 251 var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, trackDestination.Path, resolvedCabinet.BuildOption == CabinetBuildOption.BuildAndMove, mediaTuple.SourceLineNumbers);
250 this.fileTransfers.Add(transfer); 252 this.fileTransfers.Add(transfer);
251 } 253 }
252 254
@@ -417,36 +419,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
417 /// <summary> 419 /// <summary>
418 /// Gets Compiler Values of MediaTemplate Attributes governing Maximum Cabinet Size after applying Environment Variable Overrides 420 /// Gets Compiler Values of MediaTemplate Attributes governing Maximum Cabinet Size after applying Environment Variable Overrides
419 /// </summary> 421 /// </summary>
420 /// <param name="output">Output to generate image for.</param>
421 /// <param name="fileRows">The indexed file rows.</param>
422 private void GetMediaTemplateAttributes(out int maxCabSizeForLargeFileSplitting, out int maxUncompressedMediaSize) 422 private void GetMediaTemplateAttributes(out int maxCabSizeForLargeFileSplitting, out int maxUncompressedMediaSize)
423 { 423 {
424 // Get Environment Variable Overrides for MediaTemplate Attributes governing Maximum Cabinet Size 424 // Get Environment Variable Overrides for MediaTemplate Attributes governing Maximum Cabinet Size
425 string mcslfsString = Environment.GetEnvironmentVariable("WIX_MCSLFS"); 425 var mcslfsString = Environment.GetEnvironmentVariable("WIX_MCSLFS");
426 string mumsString = Environment.GetEnvironmentVariable("WIX_MUMS"); 426 var mumsString = Environment.GetEnvironmentVariable("WIX_MUMS");
427 int maxCabSizeForLargeFileInMB = 0;
428 int maxPreCompressedSizeInMB = 0;
429 ulong testOverFlow = 0;
430 427
431 // Supply Compile MediaTemplate Attributes to Cabinet Builder 428 // Supply Compile MediaTemplate Attributes to Cabinet Builder
432 Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"]; 429 if (this.MediaTemplate != null)
433 if (mediaTemplateTable != null)
434 { 430 {
435 WixMediaTemplateRow mediaTemplateRow = (WixMediaTemplateRow)mediaTemplateTable.Rows[0];
436
437 // Get the Value for Max Cab Size for File Splitting 431 // Get the Value for Max Cab Size for File Splitting
432 var maxCabSizeForLargeFileInMB = 0;
438 try 433 try
439 { 434 {
440 // Override authored mcslfs value if environment variable is authored. 435 // Override authored mcslfs value if environment variable is authored.
441 if (!String.IsNullOrEmpty(mcslfsString)) 436 maxCabSizeForLargeFileInMB = !String.IsNullOrEmpty(mcslfsString) ? Int32.Parse(mcslfsString) : this.MediaTemplate.MaximumCabinetSizeForLargeFileSplitting ?? MaxValueOfMaxCabSizeForLargeFileSplitting;
442 { 437
443 maxCabSizeForLargeFileInMB = Int32.Parse(mcslfsString); 438 var testOverFlow = (ulong)maxCabSizeForLargeFileInMB * 1024 * 1024;
444 } 439 maxCabSizeForLargeFileSplitting = maxCabSizeForLargeFileInMB;
445 else
446 {
447 maxCabSizeForLargeFileInMB = mediaTemplateRow.MaximumCabinetSizeForLargeFileSplitting;
448 }
449 testOverFlow = (ulong)maxCabSizeForLargeFileInMB * 1024 * 1024;
450 } 440 }
451 catch (FormatException) 441 catch (FormatException)
452 { 442 {
@@ -457,18 +447,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
457 throw new WixException(ErrorMessages.MaximumCabinetSizeForLargeFileSplittingTooLarge(null, maxCabSizeForLargeFileInMB, MaxValueOfMaxCabSizeForLargeFileSplitting)); 447 throw new WixException(ErrorMessages.MaximumCabinetSizeForLargeFileSplittingTooLarge(null, maxCabSizeForLargeFileInMB, MaxValueOfMaxCabSizeForLargeFileSplitting));
458 } 448 }
459 449
450 var maxPreCompressedSizeInMB = 0;
460 try 451 try
461 { 452 {
462 // Override authored mums value if environment variable is authored. 453 // Override authored mums value if environment variable is authored.
463 if (!String.IsNullOrEmpty(mumsString)) 454 maxPreCompressedSizeInMB = !String.IsNullOrEmpty(mumsString) ? Int32.Parse(mumsString) : this.MediaTemplate.MaximumUncompressedMediaSize ?? DefaultMaximumUncompressedMediaSize;
464 { 455
465 maxPreCompressedSizeInMB = Int32.Parse(mumsString); 456 var testOverFlow = (ulong)maxPreCompressedSizeInMB * 1024 * 1024;
466 } 457 maxUncompressedMediaSize = maxPreCompressedSizeInMB;
467 else
468 {
469 maxPreCompressedSizeInMB = mediaTemplateRow.MaximumUncompressedMediaSize;
470 }
471 testOverFlow = (ulong)maxPreCompressedSizeInMB * 1024 * 1024;
472 } 458 }
473 catch (FormatException) 459 catch (FormatException)
474 { 460 {
@@ -478,9 +464,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
478 { 464 {
479 throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCompressedSizeInMB)); 465 throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCompressedSizeInMB));
480 } 466 }
481
482 maxCabSizeForLargeFileSplitting = maxCabSizeForLargeFileInMB;
483 maxUncompressedMediaSize = maxPreCompressedSizeInMB;
484 } 467 }
485 else 468 else
486 { 469 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
index 21c39423..448ed607 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
@@ -15,9 +15,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
15 15
16 internal class CreateOutputFromIRCommand 16 internal class CreateOutputFromIRCommand
17 { 17 {
18 private const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
19 private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
20
21 public CreateOutputFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions, IWindowsInstallerBackendHelper backendHelper) 18 public CreateOutputFromIRCommand(IMessaging messaging, IntermediateSection section, TableDefinitionCollection tableDefinitions, IEnumerable<IWindowsInstallerBackendBinderExtension> backendExtensions, IWindowsInstallerBackendHelper backendHelper)
22 { 19 {
23 this.Messaging = messaging; 20 this.Messaging = messaging;
@@ -189,10 +186,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
189 this.AddWixActionTuple((WixActionTuple)tuple); 186 this.AddWixActionTuple((WixActionTuple)tuple);
190 break; 187 break;
191 188
192 case TupleDefinitionType.WixMediaTemplate:
193 this.AddWixMediaTemplateTuple((WixMediaTemplateTuple)tuple);
194 break;
195
196 case TupleDefinitionType.WixCustomTableCell: 189 case TupleDefinitionType.WixCustomTableCell:
197 this.IndexCustomTableCellTuple((WixCustomTableCellTuple)tuple, cellsByTableAndRowId); 190 this.IndexCustomTableCellTuple((WixCustomTableCellTuple)tuple, cellsByTableAndRowId);
198 break; 191 break;
@@ -202,6 +195,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
202 break; 195 break;
203 196
204 // Tuples used internally and are not added to the output. 197 // Tuples used internally and are not added to the output.
198 case TupleDefinitionType.WixBuildInfo:
205 case TupleDefinitionType.WixComponentGroup: 199 case TupleDefinitionType.WixComponentGroup:
206 case TupleDefinitionType.WixComplexReference: 200 case TupleDefinitionType.WixComplexReference:
207 case TupleDefinitionType.WixDeltaPatchFile: 201 case TupleDefinitionType.WixDeltaPatchFile:
@@ -211,6 +205,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
211 case TupleDefinitionType.WixInstanceComponent: 205 case TupleDefinitionType.WixInstanceComponent:
212 case TupleDefinitionType.WixInstanceTransforms: 206 case TupleDefinitionType.WixInstanceTransforms:
213 case TupleDefinitionType.WixFeatureModules: 207 case TupleDefinitionType.WixFeatureModules:
208 case TupleDefinitionType.WixGroup:
209 case TupleDefinitionType.WixMediaTemplate:
214 case TupleDefinitionType.WixMerge: 210 case TupleDefinitionType.WixMerge:
215 case TupleDefinitionType.WixOrdering: 211 case TupleDefinitionType.WixOrdering:
216 case TupleDefinitionType.WixPatchBaseline: 212 case TupleDefinitionType.WixPatchBaseline:
@@ -946,7 +942,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
946 } 942 }
947 else 943 else
948 { 944 {
949 bool after = (null == tuple.Before); 945 var after = (null == tuple.Before);
950 row[2] = after ? tuple.After : tuple.Before; 946 row[2] = after ? tuple.After : tuple.Before;
951 row[3] = after ? 1 : 0; 947 row[3] = after ? 1 : 0;
952 } 948 }
@@ -1052,17 +1048,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1052 this.Output.EnsureTable(tableDefinition); 1048 this.Output.EnsureTable(tableDefinition);
1053 } 1049 }
1054 1050
1055 private void AddWixMediaTemplateTuple(WixMediaTemplateTuple tuple)
1056 {
1057 var row = (WixMediaTemplateRow)this.CreateRow(tuple, "WixMediaTemplate");
1058 row.CabinetTemplate = tuple.CabinetTemplate;
1059 row.CompressionLevel = tuple.CompressionLevel;
1060 row.DiskPrompt = tuple.DiskPrompt;
1061 row.VolumeLabel = tuple.VolumeLabel;
1062 row.MaximumUncompressedMediaSize = tuple.MaximumUncompressedMediaSize ?? DefaultMaximumUncompressedMediaSize;
1063 row.MaximumCabinetSizeForLargeFileSplitting = tuple.MaximumCabinetSizeForLargeFileSplitting ?? MaxValueOfMaxCabSizeForLargeFileSplitting;
1064 }
1065
1066 private bool AddTupleFromExtension(IntermediateTuple tuple) 1051 private bool AddTupleFromExtension(IntermediateTuple tuple)
1067 { 1052 {
1068 foreach (var extension in this.BackendExtensions) 1053 foreach (var extension in this.BackendExtensions)
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs
index 201a890c..fc713954 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateTransformCommand.cs
@@ -160,6 +160,7 @@ namespace WixToolset.Core.WindowsInstaller
160 { 160 {
161 if (index.TryGetValue(primaryKey, out var collisionRow)) 161 if (index.TryGetValue(primaryKey, out var collisionRow))
162 { 162 {
163#if TODO_PATCH // This case doesn't seem like it can happen any longer.
163 // Overriding WixActionRows have a primary key defined and take precedence in the index. 164 // Overriding WixActionRows have a primary key defined and take precedence in the index.
164 if (row is WixActionRow actionRow) 165 if (row is WixActionRow actionRow)
165 { 166 {
@@ -176,6 +177,7 @@ namespace WixToolset.Core.WindowsInstaller
176 // If we got this far, the row does not need to be indexed. 177 // If we got this far, the row does not need to be indexed.
177 return; 178 return;
178 } 179 }
180#endif
179 181
180 if (this.ShowPedanticMessages) 182 if (this.ShowPedanticMessages)
181 { 183 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs b/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
index 54a92f3c..34f57284 100644
--- a/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
@@ -262,23 +262,23 @@ namespace WixToolset.Core.WindowsInstaller
262 /// <summary> 262 /// <summary>
263 /// Creates an action element. 263 /// Creates an action element.
264 /// </summary> 264 /// </summary>
265 /// <param name="actionRow">The action row from which the element should be created.</param> 265 /// <param name="actionTuple">The action from which the element should be created.</param>
266 private void CreateActionElement(WixActionRow actionRow) 266 private void CreateActionElement(WixActionTuple actionTuple)
267 { 267 {
268 Wix.ISchemaElement actionElement = null; 268 Wix.ISchemaElement actionElement = null;
269 269
270 if (null != this.core.GetIndexedElement("CustomAction", actionRow.Action)) // custom action 270 if (null != this.core.GetIndexedElement("CustomAction", actionTuple.Action)) // custom action
271 { 271 {
272 var custom = new Wix.Custom(); 272 var custom = new Wix.Custom();
273 273
274 custom.Action = actionRow.Action; 274 custom.Action = actionTuple.Action;
275 275
276 if (null != actionRow.Condition) 276 if (null != actionTuple.Condition)
277 { 277 {
278 custom.Content = actionRow.Condition; 278 custom.Content = actionTuple.Condition;
279 } 279 }
280 280
281 switch (actionRow.Sequence) 281 switch (actionTuple.Sequence)
282 { 282 {
283 case (-4): 283 case (-4):
284 custom.OnExit = Wix.ExitType.suspend; 284 custom.OnExit = Wix.ExitType.suspend;
@@ -293,35 +293,35 @@ namespace WixToolset.Core.WindowsInstaller
293 custom.OnExit = Wix.ExitType.success; 293 custom.OnExit = Wix.ExitType.success;
294 break; 294 break;
295 default: 295 default:
296 if (null != actionRow.Before) 296 if (null != actionTuple.Before)
297 { 297 {
298 custom.Before = actionRow.Before; 298 custom.Before = actionTuple.Before;
299 } 299 }
300 else if (null != actionRow.After) 300 else if (null != actionTuple.After)
301 { 301 {
302 custom.After = actionRow.After; 302 custom.After = actionTuple.After;
303 } 303 }
304 else if (0 < actionRow.Sequence) 304 else if (actionTuple.Sequence.HasValue)
305 { 305 {
306 custom.Sequence = actionRow.Sequence; 306 custom.Sequence = actionTuple.Sequence.Value;
307 } 307 }
308 break; 308 break;
309 } 309 }
310 310
311 actionElement = custom; 311 actionElement = custom;
312 } 312 }
313 else if (null != this.core.GetIndexedElement("Dialog", actionRow.Action)) // dialog 313 else if (null != this.core.GetIndexedElement("Dialog", actionTuple.Action)) // dialog
314 { 314 {
315 var show = new Wix.Show(); 315 var show = new Wix.Show();
316 316
317 show.Dialog = actionRow.Action; 317 show.Dialog = actionTuple.Action;
318 318
319 if (null != actionRow.Condition) 319 if (null != actionTuple.Condition)
320 { 320 {
321 show.Content = actionRow.Condition; 321 show.Content = actionTuple.Condition;
322 } 322 }
323 323
324 switch (actionRow.Sequence) 324 switch (actionTuple.Sequence)
325 { 325 {
326 case (-4): 326 case (-4):
327 show.OnExit = Wix.ExitType.suspend; 327 show.OnExit = Wix.ExitType.suspend;
@@ -336,17 +336,17 @@ namespace WixToolset.Core.WindowsInstaller
336 show.OnExit = Wix.ExitType.success; 336 show.OnExit = Wix.ExitType.success;
337 break; 337 break;
338 default: 338 default:
339 if (null != actionRow.Before) 339 if (null != actionTuple.Before)
340 { 340 {
341 show.Before = actionRow.Before; 341 show.Before = actionTuple.Before;
342 } 342 }
343 else if (null != actionRow.After) 343 else if (null != actionTuple.After)
344 { 344 {
345 show.After = actionRow.After; 345 show.After = actionTuple.After;
346 } 346 }
347 else if (0 < actionRow.Sequence) 347 else if (actionTuple.Sequence.HasValue)
348 { 348 {
349 show.Sequence = actionRow.Sequence; 349 show.Sequence = actionTuple.Sequence.Value;
350 } 350 }
351 break; 351 break;
352 } 352 }
@@ -355,18 +355,18 @@ namespace WixToolset.Core.WindowsInstaller
355 } 355 }
356 else // possibly a standard action without suggested sequence information 356 else // possibly a standard action without suggested sequence information
357 { 357 {
358 actionElement = this.CreateStandardActionElement(actionRow); 358 actionElement = this.CreateStandardActionElement(actionTuple);
359 } 359 }
360 360
361 // add the action element to the appropriate sequence element 361 // add the action element to the appropriate sequence element
362 if (null != actionElement) 362 if (null != actionElement)
363 { 363 {
364 var sequenceTable = actionRow.SequenceTable.ToString(); 364 var sequenceTable = actionTuple.SequenceTable.ToString();
365 var sequenceElement = (Wix.IParentElement)this.sequenceElements[sequenceTable]; 365 var sequenceElement = (Wix.IParentElement)this.sequenceElements[sequenceTable];
366 366
367 if (null == sequenceElement) 367 if (null == sequenceElement)
368 { 368 {
369 switch (actionRow.SequenceTable) 369 switch (actionTuple.SequenceTable)
370 { 370 {
371 case SequenceTable.AdminExecuteSequence: 371 case SequenceTable.AdminExecuteSequence:
372 sequenceElement = new Wix.AdminExecuteSequence(); 372 sequenceElement = new Wix.AdminExecuteSequence();
@@ -397,7 +397,7 @@ namespace WixToolset.Core.WindowsInstaller
397 } 397 }
398 catch (System.ArgumentException) // action/dialog is not valid for this sequence 398 catch (System.ArgumentException) // action/dialog is not valid for this sequence
399 { 399 {
400 this.Messaging.Write(WarningMessages.IllegalActionInSequence(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); 400 this.Messaging.Write(WarningMessages.IllegalActionInSequence(actionTuple.SourceLineNumbers, actionTuple.SequenceTable.ToString(), actionTuple.Action));
401 } 401 }
402 } 402 }
403 } 403 }
@@ -405,40 +405,40 @@ namespace WixToolset.Core.WindowsInstaller
405 /// <summary> 405 /// <summary>
406 /// Creates a standard action element. 406 /// Creates a standard action element.
407 /// </summary> 407 /// </summary>
408 /// <param name="actionRow">The action row from which the element should be created.</param> 408 /// <param name="actionTuple">The action row from which the element should be created.</param>
409 /// <returns>The created element.</returns> 409 /// <returns>The created element.</returns>
410 private Wix.ISchemaElement CreateStandardActionElement(WixActionRow actionRow) 410 private Wix.ISchemaElement CreateStandardActionElement(WixActionTuple actionTuple)
411 { 411 {
412 Wix.ActionSequenceType actionElement = null; 412 Wix.ActionSequenceType actionElement = null;
413 413
414 switch (actionRow.Action) 414 switch (actionTuple.Action)
415 { 415 {
416 case "AllocateRegistrySpace": 416 case "AllocateRegistrySpace":
417 actionElement = new Wix.AllocateRegistrySpace(); 417 actionElement = new Wix.AllocateRegistrySpace();
418 break; 418 break;
419 case "AppSearch": 419 case "AppSearch":
420 this.StandardActions.TryGetValue(actionRow.GetPrimaryKey(), out var appSearchActionRow); 420 this.StandardActions.TryGetValue(actionTuple.Id.Id, out var appSearchActionRow);
421 421
422 if (null != actionRow.Before || null != actionRow.After || (null != appSearchActionRow && actionRow.Sequence != appSearchActionRow.Sequence)) 422 if (null != actionTuple.Before || null != actionTuple.After || (null != appSearchActionRow && actionTuple.Sequence != appSearchActionRow.Sequence))
423 { 423 {
424 var appSearch = new Wix.AppSearch(); 424 var appSearch = new Wix.AppSearch();
425 425
426 if (null != actionRow.Condition) 426 if (null != actionTuple.Condition)
427 { 427 {
428 appSearch.Content = actionRow.Condition; 428 appSearch.Content = actionTuple.Condition;
429 } 429 }
430 430
431 if (null != actionRow.Before) 431 if (null != actionTuple.Before)
432 { 432 {
433 appSearch.Before = actionRow.Before; 433 appSearch.Before = actionTuple.Before;
434 } 434 }
435 else if (null != actionRow.After) 435 else if (null != actionTuple.After)
436 { 436 {
437 appSearch.After = actionRow.After; 437 appSearch.After = actionTuple.After;
438 } 438 }
439 else if (0 < actionRow.Sequence) 439 else if (actionTuple.Sequence.HasValue)
440 { 440 {
441 appSearch.Sequence = actionRow.Sequence; 441 appSearch.Sequence = actionTuple.Sequence.Value;
442 } 442 }
443 443
444 return appSearch; 444 return appSearch;
@@ -449,7 +449,7 @@ namespace WixToolset.Core.WindowsInstaller
449 break; 449 break;
450 case "CCPSearch": 450 case "CCPSearch":
451 var ccpSearch = new Wix.CCPSearch(); 451 var ccpSearch = new Wix.CCPSearch();
452 Decompiler.SequenceRelativeAction(actionRow, ccpSearch); 452 Decompiler.SequenceRelativeAction(actionTuple, ccpSearch);
453 return ccpSearch; 453 return ccpSearch;
454 case "CostFinalize": 454 case "CostFinalize":
455 actionElement = new Wix.CostFinalize(); 455 actionElement = new Wix.CostFinalize();
@@ -468,7 +468,7 @@ namespace WixToolset.Core.WindowsInstaller
468 break; 468 break;
469 case "DisableRollback": 469 case "DisableRollback":
470 var disableRollback = new Wix.DisableRollback(); 470 var disableRollback = new Wix.DisableRollback();
471 Decompiler.SequenceRelativeAction(actionRow, disableRollback); 471 Decompiler.SequenceRelativeAction(actionTuple, disableRollback);
472 return disableRollback; 472 return disableRollback;
473 case "DuplicateFiles": 473 case "DuplicateFiles":
474 actionElement = new Wix.DuplicateFiles(); 474 actionElement = new Wix.DuplicateFiles();
@@ -481,22 +481,22 @@ namespace WixToolset.Core.WindowsInstaller
481 break; 481 break;
482 case "FindRelatedProducts": 482 case "FindRelatedProducts":
483 var findRelatedProducts = new Wix.FindRelatedProducts(); 483 var findRelatedProducts = new Wix.FindRelatedProducts();
484 Decompiler.SequenceRelativeAction(actionRow, findRelatedProducts); 484 Decompiler.SequenceRelativeAction(actionTuple, findRelatedProducts);
485 return findRelatedProducts; 485 return findRelatedProducts;
486 case "ForceReboot": 486 case "ForceReboot":
487 var forceReboot = new Wix.ForceReboot(); 487 var forceReboot = new Wix.ForceReboot();
488 Decompiler.SequenceRelativeAction(actionRow, forceReboot); 488 Decompiler.SequenceRelativeAction(actionTuple, forceReboot);
489 return forceReboot; 489 return forceReboot;
490 case "InstallAdminPackage": 490 case "InstallAdminPackage":
491 actionElement = new Wix.InstallAdminPackage(); 491 actionElement = new Wix.InstallAdminPackage();
492 break; 492 break;
493 case "InstallExecute": 493 case "InstallExecute":
494 var installExecute = new Wix.InstallExecute(); 494 var installExecute = new Wix.InstallExecute();
495 Decompiler.SequenceRelativeAction(actionRow, installExecute); 495 Decompiler.SequenceRelativeAction(actionTuple, installExecute);
496 return installExecute; 496 return installExecute;
497 case "InstallExecuteAgain": 497 case "InstallExecuteAgain":
498 var installExecuteAgain = new Wix.InstallExecuteAgain(); 498 var installExecuteAgain = new Wix.InstallExecuteAgain();
499 Decompiler.SequenceRelativeAction(actionRow, installExecuteAgain); 499 Decompiler.SequenceRelativeAction(actionTuple, installExecuteAgain);
500 return installExecuteAgain; 500 return installExecuteAgain;
501 case "InstallFiles": 501 case "InstallFiles":
502 actionElement = new Wix.InstallFiles(); 502 actionElement = new Wix.InstallFiles();
@@ -521,7 +521,7 @@ namespace WixToolset.Core.WindowsInstaller
521 break; 521 break;
522 case "LaunchConditions": 522 case "LaunchConditions":
523 var launchConditions = new Wix.LaunchConditions(); 523 var launchConditions = new Wix.LaunchConditions();
524 Decompiler.SequenceRelativeAction(actionRow, launchConditions); 524 Decompiler.SequenceRelativeAction(actionTuple, launchConditions);
525 return launchConditions; 525 return launchConditions;
526 case "MigrateFeatureStates": 526 case "MigrateFeatureStates":
527 actionElement = new Wix.MigrateFeatureStates(); 527 actionElement = new Wix.MigrateFeatureStates();
@@ -585,7 +585,7 @@ namespace WixToolset.Core.WindowsInstaller
585 break; 585 break;
586 case "RemoveExistingProducts": 586 case "RemoveExistingProducts":
587 var removeExistingProducts = new Wix.RemoveExistingProducts(); 587 var removeExistingProducts = new Wix.RemoveExistingProducts();
588 Decompiler.SequenceRelativeAction(actionRow, removeExistingProducts); 588 Decompiler.SequenceRelativeAction(actionTuple, removeExistingProducts);
589 return removeExistingProducts; 589 return removeExistingProducts;
590 case "RemoveFiles": 590 case "RemoveFiles":
591 actionElement = new Wix.RemoveFiles(); 591 actionElement = new Wix.RemoveFiles();
@@ -607,15 +607,15 @@ namespace WixToolset.Core.WindowsInstaller
607 break; 607 break;
608 case "ResolveSource": 608 case "ResolveSource":
609 var resolveSource = new Wix.ResolveSource(); 609 var resolveSource = new Wix.ResolveSource();
610 Decompiler.SequenceRelativeAction(actionRow, resolveSource); 610 Decompiler.SequenceRelativeAction(actionTuple, resolveSource);
611 return resolveSource; 611 return resolveSource;
612 case "RMCCPSearch": 612 case "RMCCPSearch":
613 var rmccpSearch = new Wix.RMCCPSearch(); 613 var rmccpSearch = new Wix.RMCCPSearch();
614 Decompiler.SequenceRelativeAction(actionRow, rmccpSearch); 614 Decompiler.SequenceRelativeAction(actionTuple, rmccpSearch);
615 return rmccpSearch; 615 return rmccpSearch;
616 case "ScheduleReboot": 616 case "ScheduleReboot":
617 var scheduleReboot = new Wix.ScheduleReboot(); 617 var scheduleReboot = new Wix.ScheduleReboot();
618 Decompiler.SequenceRelativeAction(actionRow, scheduleReboot); 618 Decompiler.SequenceRelativeAction(actionTuple, scheduleReboot);
619 return scheduleReboot; 619 return scheduleReboot;
620 case "SelfRegModules": 620 case "SelfRegModules":
621 actionElement = new Wix.SelfRegModules(); 621 actionElement = new Wix.SelfRegModules();
@@ -672,13 +672,13 @@ namespace WixToolset.Core.WindowsInstaller
672 actionElement = new Wix.WriteRegistryValues(); 672 actionElement = new Wix.WriteRegistryValues();
673 break; 673 break;
674 default: 674 default:
675 this.Messaging.Write(WarningMessages.UnknownAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); 675 this.Messaging.Write(WarningMessages.UnknownAction(actionTuple.SourceLineNumbers, actionTuple.SequenceTable.ToString(), actionTuple.Action));
676 return null; 676 return null;
677 } 677 }
678 678
679 if (actionElement != null) 679 if (actionElement != null)
680 { 680 {
681 this.SequenceStandardAction(actionRow, actionElement); 681 this.SequenceStandardAction(actionTuple, actionElement);
682 } 682 }
683 683
684 return actionElement; 684 return actionElement;
@@ -687,48 +687,48 @@ namespace WixToolset.Core.WindowsInstaller
687 /// <summary> 687 /// <summary>
688 /// Applies the condition and sequence to a standard action element based on the action row data. 688 /// Applies the condition and sequence to a standard action element based on the action row data.
689 /// </summary> 689 /// </summary>
690 /// <param name="actionRow">Action row data from the database.</param> 690 /// <param name="actionTuple">Action data from the database.</param>
691 /// <param name="actionElement">Element to be sequenced.</param> 691 /// <param name="actionElement">Element to be sequenced.</param>
692 private void SequenceStandardAction(WixActionRow actionRow, Wix.ActionSequenceType actionElement) 692 private void SequenceStandardAction(WixActionTuple actionTuple, Wix.ActionSequenceType actionElement)
693 { 693 {
694 if (null != actionRow.Condition) 694 if (null != actionTuple.Condition)
695 { 695 {
696 actionElement.Content = actionRow.Condition; 696 actionElement.Content = actionTuple.Condition;
697 } 697 }
698 698
699 if ((null != actionRow.Before || null != actionRow.After) && 0 == actionRow.Sequence) 699 if ((null != actionTuple.Before || null != actionTuple.After) && 0 == actionTuple.Sequence)
700 { 700 {
701 this.Messaging.Write(WarningMessages.DecompiledStandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); 701 this.Messaging.Write(WarningMessages.DecompiledStandardActionRelativelyScheduledInModule(actionTuple.SourceLineNumbers, actionTuple.SequenceTable.ToString(), actionTuple.Action));
702 } 702 }
703 else if (0 < actionRow.Sequence) 703 else if (actionTuple.Sequence.HasValue)
704 { 704 {
705 actionElement.Sequence = actionRow.Sequence; 705 actionElement.Sequence = actionTuple.Sequence.Value;
706 } 706 }
707 } 707 }
708 708
709 /// <summary> 709 /// <summary>
710 /// Applies the condition and relative sequence to an action element based on the action row data. 710 /// Applies the condition and relative sequence to an action element based on the action row data.
711 /// </summary> 711 /// </summary>
712 /// <param name="actionRow">Action row data from the database.</param> 712 /// <param name="actionTuple">Action data from the database.</param>
713 /// <param name="actionElement">Element to be sequenced.</param> 713 /// <param name="actionElement">Element to be sequenced.</param>
714 private static void SequenceRelativeAction(WixActionRow actionRow, Wix.ActionModuleSequenceType actionElement) 714 private static void SequenceRelativeAction(WixActionTuple actionTuple, Wix.ActionModuleSequenceType actionElement)
715 { 715 {
716 if (null != actionRow.Condition) 716 if (null != actionTuple.Condition)
717 { 717 {
718 actionElement.Content = actionRow.Condition; 718 actionElement.Content = actionTuple.Condition;
719 } 719 }
720 720
721 if (null != actionRow.Before) 721 if (null != actionTuple.Before)
722 { 722 {
723 actionElement.Before = actionRow.Before; 723 actionElement.Before = actionTuple.Before;
724 } 724 }
725 else if (null != actionRow.After) 725 else if (null != actionTuple.After)
726 { 726 {
727 actionElement.After = actionRow.After; 727 actionElement.After = actionTuple.After;
728 } 728 }
729 else if (0 < actionRow.Sequence) 729 else if (actionTuple.Sequence.HasValue)
730 { 730 {
731 actionElement.Sequence = actionRow.Sequence; 731 actionElement.Sequence = actionTuple.Sequence.Value;
732 } 732 }
733 } 733 }
734 734
@@ -2495,7 +2495,7 @@ namespace WixToolset.Core.WindowsInstaller
2495 { 2495 {
2496 foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable))) 2496 foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
2497 { 2497 {
2498 var sequenceTableName = GetSequenceTableName(sequenceTable); 2498 var sequenceTableName = sequenceTable.WindowsInstallerTableName();
2499 2499
2500 // if suppressing UI elements, skip UI-related sequence tables 2500 // if suppressing UI elements, skip UI-related sequence tables
2501 if (this.SuppressUI && ("AdminUISequence" == sequenceTableName || "InstallUISequence" == sequenceTableName)) 2501 if (this.SuppressUI && ("AdminUISequence" == sequenceTableName || "InstallUISequence" == sequenceTableName))
@@ -2503,57 +2503,57 @@ namespace WixToolset.Core.WindowsInstaller
2503 continue; 2503 continue;
2504 } 2504 }
2505 2505
2506 var actionsTable = new Table(this.tableDefinitions["WixAction"]);
2507 var table = tables[sequenceTableName]; 2506 var table = tables[sequenceTableName];
2508 2507
2509 if (null != table) 2508 if (null != table)
2510 { 2509 {
2511 var actionRows = new List<WixActionRow>(); 2510 var actionTuples = new List<WixActionTuple>();
2512 var needAbsoluteScheduling = this.SuppressRelativeActionSequencing; 2511 var needAbsoluteScheduling = this.SuppressRelativeActionSequencing;
2513 var nonSequencedActionRows = new Dictionary<string, WixActionRow>(); 2512 var nonSequencedActionRows = new Dictionary<string, WixActionTuple>();
2514 var suppressedRelativeActionRows = new Dictionary<string, WixActionRow>(); 2513 var suppressedRelativeActionRows = new Dictionary<string, WixActionTuple>();
2515 2514
2516 // create a sorted array of actions in this table 2515 // create a sorted array of actions in this table
2517 foreach (var row in table.Rows) 2516 foreach (var row in table.Rows)
2518 { 2517 {
2519 var actionRow = (WixActionRow)actionsTable.CreateRow(null); 2518 var action = row.FieldAsString(0);
2519 var actionTuple = new WixActionTuple(null, new Identifier(AccessModifier.Public, sequenceTable, action));
2520 2520
2521 actionRow.Action = Convert.ToString(row[0]); 2521 actionTuple.Action = action;
2522 2522
2523 if (null != row[1]) 2523 if (null != row[1])
2524 { 2524 {
2525 actionRow.Condition = Convert.ToString(row[1]); 2525 actionTuple.Condition = Convert.ToString(row[1]);
2526 } 2526 }
2527 2527
2528 actionRow.Sequence = Convert.ToInt32(row[2]); 2528 actionTuple.Sequence = Convert.ToInt32(row[2]);
2529 2529
2530 actionRow.SequenceTable = sequenceTable; 2530 actionTuple.SequenceTable = sequenceTable;
2531 2531
2532 actionRows.Add(actionRow); 2532 actionTuples.Add(actionTuple);
2533 } 2533 }
2534 actionRows.Sort(); 2534 actionTuples = actionTuples.OrderBy(t => t.Sequence).ToList();
2535 2535
2536 for (var i = 0; i < actionRows.Count && !needAbsoluteScheduling; i++) 2536 for (var i = 0; i < actionTuples.Count && !needAbsoluteScheduling; i++)
2537 { 2537 {
2538 var actionRow = actionRows[i]; 2538 var actionTuple = actionTuples[i];
2539 this.StandardActions.TryGetValue(actionRow.GetPrimaryKey(), out var standardActionRow); 2539 this.StandardActions.TryGetValue(actionTuple.Id.Id, out var standardActionRow);
2540 2540
2541 // create actions for custom actions, dialogs, AppSearch when its moved, and standard actions with non-standard conditions 2541 // create actions for custom actions, dialogs, AppSearch when its moved, and standard actions with non-standard conditions
2542 if ("AppSearch" == actionRow.Action || null == standardActionRow || actionRow.Condition != standardActionRow.Condition) 2542 if ("AppSearch" == actionTuple.Action || null == standardActionRow || actionTuple.Condition != standardActionRow.Condition)
2543 { 2543 {
2544 WixActionRow previousActionRow = null; 2544 WixActionTuple previousActionTuple = null;
2545 WixActionRow nextActionRow = null; 2545 WixActionTuple nextActionTuple = null;
2546 2546
2547 // find the previous action row if there is one 2547 // find the previous action row if there is one
2548 if (0 <= i - 1) 2548 if (0 <= i - 1)
2549 { 2549 {
2550 previousActionRow = actionRows[i - 1]; 2550 previousActionTuple = actionTuples[i - 1];
2551 } 2551 }
2552 2552
2553 // find the next action row if there is one 2553 // find the next action row if there is one
2554 if (actionRows.Count > i + 1) 2554 if (actionTuples.Count > i + 1)
2555 { 2555 {
2556 nextActionRow = actionRows[i + 1]; 2556 nextActionTuple = actionTuples[i + 1];
2557 } 2557 }
2558 2558
2559 // the logic for setting the before or after attribute for an action: 2559 // the logic for setting the before or after attribute for an action:
@@ -2565,49 +2565,49 @@ namespace WixToolset.Core.WindowsInstaller
2565 // 6. If this action is AppSearch and has all standard information, ignore it. 2565 // 6. If this action is AppSearch and has all standard information, ignore it.
2566 // 7. If this action is standard and has a non-standard condition, create the action without any scheduling information. 2566 // 7. If this action is standard and has a non-standard condition, create the action without any scheduling information.
2567 // 8. Everything must be absolutely sequenced. 2567 // 8. Everything must be absolutely sequenced.
2568 if ((null != previousActionRow && actionRow.Sequence == previousActionRow.Sequence) || (null != nextActionRow && actionRow.Sequence == nextActionRow.Sequence)) 2568 if ((null != previousActionTuple && actionTuple.Sequence == previousActionTuple.Sequence) || (null != nextActionTuple && actionTuple.Sequence == nextActionTuple.Sequence))
2569 { 2569 {
2570 needAbsoluteScheduling = true; 2570 needAbsoluteScheduling = true;
2571 } 2571 }
2572 else if (null != nextActionRow && this.StandardActions.ContainsKey(nextActionRow.GetPrimaryKey()) && actionRow.Sequence + 1 == nextActionRow.Sequence) 2572 else if (null != nextActionTuple && this.StandardActions.ContainsKey(nextActionTuple.Id.Id) && actionTuple.Sequence + 1 == nextActionTuple.Sequence)
2573 { 2573 {
2574 actionRow.Before = nextActionRow.Action; 2574 actionTuple.Before = nextActionTuple.Action;
2575 } 2575 }
2576 else if (null != previousActionRow && this.StandardActions.ContainsKey(previousActionRow.GetPrimaryKey()) && actionRow.Sequence - 1 == previousActionRow.Sequence) 2576 else if (null != previousActionTuple && this.StandardActions.ContainsKey(previousActionTuple.Id.Id) && actionTuple.Sequence - 1 == previousActionTuple.Sequence)
2577 { 2577 {
2578 actionRow.After = previousActionRow.Action; 2578 actionTuple.After = previousActionTuple.Action;
2579 } 2579 }
2580 else if (null == standardActionRow && null != previousActionRow && actionRow.Sequence - 1 == previousActionRow.Sequence && previousActionRow.Before != actionRow.Action) 2580 else if (null == standardActionRow && null != previousActionTuple && actionTuple.Sequence - 1 == previousActionTuple.Sequence && previousActionTuple.Before != actionTuple.Action)
2581 { 2581 {
2582 actionRow.After = previousActionRow.Action; 2582 actionTuple.After = previousActionTuple.Action;
2583 } 2583 }
2584 else if (null == standardActionRow && null != previousActionRow && actionRow.Sequence != previousActionRow.Sequence && null != nextActionRow && actionRow.Sequence + 1 == nextActionRow.Sequence) 2584 else if (null == standardActionRow && null != previousActionTuple && actionTuple.Sequence != previousActionTuple.Sequence && null != nextActionTuple && actionTuple.Sequence + 1 == nextActionTuple.Sequence)
2585 { 2585 {
2586 actionRow.Before = nextActionRow.Action; 2586 actionTuple.Before = nextActionTuple.Action;
2587 } 2587 }
2588 else if ("AppSearch" == actionRow.Action && null != standardActionRow && actionRow.Sequence == standardActionRow.Sequence && actionRow.Condition == standardActionRow.Condition) 2588 else if ("AppSearch" == actionTuple.Action && null != standardActionRow && actionTuple.Sequence == standardActionRow.Sequence && actionTuple.Condition == standardActionRow.Condition)
2589 { 2589 {
2590 // ignore an AppSearch row which has the WiX standard sequence and a standard condition 2590 // ignore an AppSearch row which has the WiX standard sequence and a standard condition
2591 } 2591 }
2592 else if (null != standardActionRow && actionRow.Condition != standardActionRow.Condition) // standard actions get their standard sequence numbers 2592 else if (null != standardActionRow && actionTuple.Condition != standardActionRow.Condition) // standard actions get their standard sequence numbers
2593 { 2593 {
2594 nonSequencedActionRows.Add(actionRow.GetPrimaryKey(), actionRow); 2594 nonSequencedActionRows.Add(actionTuple.Id.Id, actionTuple);
2595 } 2595 }
2596 else if (0 < actionRow.Sequence) 2596 else if (0 < actionTuple.Sequence)
2597 { 2597 {
2598 needAbsoluteScheduling = true; 2598 needAbsoluteScheduling = true;
2599 } 2599 }
2600 } 2600 }
2601 else 2601 else
2602 { 2602 {
2603 suppressedRelativeActionRows.Add(actionRow.GetPrimaryKey(), actionRow); 2603 suppressedRelativeActionRows.Add(actionTuple.Id.Id, actionTuple);
2604 } 2604 }
2605 } 2605 }
2606 2606
2607 // create the actions now that we know if they must be absolutely or relatively scheduled 2607 // create the actions now that we know if they must be absolutely or relatively scheduled
2608 foreach (var actionRow in actionRows) 2608 foreach (var actionRow in actionTuples)
2609 { 2609 {
2610 var key = actionRow.GetPrimaryKey(); 2610 var key = actionRow.Id.Id;
2611 2611
2612 if (needAbsoluteScheduling) 2612 if (needAbsoluteScheduling)
2613 { 2613 {
@@ -2636,7 +2636,7 @@ namespace WixToolset.Core.WindowsInstaller
2636 { 2636 {
2637 foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable))) 2637 foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
2638 { 2638 {
2639 var sequenceTableName = GetSequenceTableName(sequenceTable); 2639 var sequenceTableName = sequenceTable.WindowsInstallerTableName();
2640 2640
2641 // if suppressing UI elements, skip UI-related sequence tables 2641 // if suppressing UI elements, skip UI-related sequence tables
2642 if (this.SuppressUI && ("AdminUISequence" == sequenceTableName || "InstallUISequence" == sequenceTableName)) 2642 if (this.SuppressUI && ("AdminUISequence" == sequenceTableName || "InstallUISequence" == sequenceTableName))
@@ -2651,9 +2651,9 @@ namespace WixToolset.Core.WindowsInstaller
2651 { 2651 {
2652 foreach (var row in table.Rows) 2652 foreach (var row in table.Rows)
2653 { 2653 {
2654 var actionRow = (WixActionRow)actionsTable.CreateRow(null); 2654 var actionRow = new WixActionTuple(null, new Identifier(AccessModifier.Public, sequenceTable, row.FieldAsString(0)));
2655 2655
2656 actionRow.Action = Convert.ToString(row[0]); 2656 actionRow.Action = row.FieldAsString(0);
2657 2657
2658 if (null != row[1]) 2658 if (null != row[1])
2659 { 2659 {
@@ -2684,7 +2684,7 @@ namespace WixToolset.Core.WindowsInstaller
2684 actionRow.SequenceTable = sequenceTable; 2684 actionRow.SequenceTable = sequenceTable;
2685 2685
2686 // create action elements for non-standard actions 2686 // create action elements for non-standard actions
2687 if (!this.StandardActions.ContainsKey(actionRow.GetPrimaryKey()) || null != actionRow.After || null != actionRow.Before) 2687 if (!this.StandardActions.ContainsKey(actionRow.Id.Id) || null != actionRow.After || null != actionRow.Before)
2688 { 2688 {
2689 this.CreateActionElement(actionRow); 2689 this.CreateActionElement(actionRow);
2690 } 2690 }
@@ -2844,17 +2844,6 @@ namespace WixToolset.Core.WindowsInstaller
2844 } 2844 }
2845 } 2845 }
2846 2846
2847 private static string GetSequenceTableName(SequenceTable sequenceTable)
2848 {
2849 switch (sequenceTable)
2850 {
2851 case SequenceTable.AdvertiseExecuteSequence:
2852 return "AdvtExecuteSequence";
2853 default:
2854 return sequenceTable.ToString();
2855 }
2856 }
2857
2858 /// <summary> 2847 /// <summary>
2859 /// Get the path to a file in the source image. 2848 /// Get the path to a file in the source image.
2860 /// </summary> 2849 /// </summary>