aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2020-01-13 14:41:17 -0800
committerRob Mensching <rob@firegiant.com>2020-02-05 16:15:47 -0800
commit6e2e67ab55c75f4655397588c0dcc64f50d22f92 (patch)
tree01290e7b07ec6e4e4384e8fed568f14283f65d61 /src
parentc9c3ab2776252d3131fea561bd3f3fac8c045f5e (diff)
downloadwix-6e2e67ab55c75f4655397588c0dcc64f50d22f92.tar.gz
wix-6e2e67ab55c75f4655397588c0dcc64f50d22f92.tar.bz2
wix-6e2e67ab55c75f4655397588c0dcc64f50d22f92.zip
Remove WixActionRowCollection and duplicate actions.xml
Diffstat (limited to 'src')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs79
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs13
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Data/actions.xml76
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs31
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs329
-rw-r--r--src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs30
-rw-r--r--src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj1
7 files changed, 63 insertions, 496 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
index 1651f9d8..107f3208 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
@@ -433,59 +433,63 @@ namespace WixToolset.Core.WindowsInstaller.Bind
433 /// <param name="mainFileRow">The file row that contains information about the patched file.</param> 433 /// <param name="mainFileRow">The file row that contains information about the patched file.</param>
434 private void AddPatchFilesActionToSequenceTable(SequenceTable table, WindowsInstallerData mainTransform, WindowsInstallerData pairedTransform, Row mainFileRow) 434 private void AddPatchFilesActionToSequenceTable(SequenceTable table, WindowsInstallerData mainTransform, WindowsInstallerData pairedTransform, Row mainFileRow)
435 { 435 {
436 var tableName = table.ToString();
437
436 // Find/add PatchFiles action (also determine sequence for it). 438 // Find/add PatchFiles action (also determine sequence for it).
437 // Search mainTransform first, then pairedTransform (pairedTransform overrides). 439 // Search mainTransform first, then pairedTransform (pairedTransform overrides).
438 bool hasPatchFilesAction = false; 440 var hasPatchFilesAction = false;
439 int seqInstallFiles = 0; 441 var installFilesSequence = 0;
440 int seqDuplicateFiles = 0; 442 var duplicateFilesSequence = 0;
441 string tableName = table.ToString();
442 443
443 TestSequenceTableForPatchFilesAction( 444 TestSequenceTableForPatchFilesAction(
444 mainTransform.Tables[tableName], 445 mainTransform.Tables[tableName],
445 ref hasPatchFilesAction, 446 ref hasPatchFilesAction,
446 ref seqInstallFiles, 447 ref installFilesSequence,
447 ref seqDuplicateFiles); 448 ref duplicateFilesSequence);
448 TestSequenceTableForPatchFilesAction( 449 TestSequenceTableForPatchFilesAction(
449 pairedTransform.Tables[tableName], 450 pairedTransform.Tables[tableName],
450 ref hasPatchFilesAction, 451 ref hasPatchFilesAction,
451 ref seqInstallFiles, 452 ref installFilesSequence,
452 ref seqDuplicateFiles); 453 ref duplicateFilesSequence);
453 if (!hasPatchFilesAction) 454 if (!hasPatchFilesAction)
454 { 455 {
455 Table iesTable = pairedTransform.EnsureTable(this.TableDefinitions[tableName]); 456 WindowsInstallerStandard.TryGetStandardAction(tableName, "PatchFiles", out var patchFilesActionTuple);
456 if (0 == iesTable.Rows.Count) 457
457 { 458 var sequence = patchFilesActionTuple.Sequence;
458 iesTable.Operation = TableOperation.Add;
459 }
460 459
461 Row patchAction = iesTable.CreateRow(null);
462 WixActionRow wixPatchAction = WindowsInstallerStandardInternal.GetStandardActionRows()[table, "PatchFiles"];
463 int sequence = wixPatchAction.Sequence;
464 // Test for default sequence value's appropriateness 460 // Test for default sequence value's appropriateness
465 if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence)) 461 if (installFilesSequence >= sequence || (0 != duplicateFilesSequence && duplicateFilesSequence <= sequence))
466 { 462 {
467 if (0 != seqDuplicateFiles) 463 if (0 != duplicateFilesSequence)
468 { 464 {
469 if (seqDuplicateFiles < seqInstallFiles) 465 if (duplicateFilesSequence < installFilesSequence)
470 { 466 {
471 throw new WixException(ErrorMessages.InsertInvalidSequenceActionOrder(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action)); 467 throw new WixException(ErrorMessages.InsertInvalidSequenceActionOrder(mainFileRow.SourceLineNumbers, tableName, "InstallFiles", "DuplicateFiles", patchFilesActionTuple.Action));
472 } 468 }
473 else 469 else
474 { 470 {
475 sequence = (seqDuplicateFiles + seqInstallFiles) / 2; 471 sequence = (duplicateFilesSequence + installFilesSequence) / 2;
476 if (seqInstallFiles == sequence || seqDuplicateFiles == sequence) 472 if (installFilesSequence == sequence || duplicateFilesSequence == sequence)
477 { 473 {
478 throw new WixException(ErrorMessages.InsertSequenceNoSpace(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action)); 474 throw new WixException(ErrorMessages.InsertSequenceNoSpace(mainFileRow.SourceLineNumbers, tableName, "InstallFiles", "DuplicateFiles", patchFilesActionTuple.Action));
479 } 475 }
480 } 476 }
481 } 477 }
482 else 478 else
483 { 479 {
484 sequence = seqInstallFiles + 1; 480 sequence = installFilesSequence + 1;
485 } 481 }
486 } 482 }
487 patchAction[0] = wixPatchAction.Action; 483
488 patchAction[1] = wixPatchAction.Condition; 484 var sequenceTable = pairedTransform.EnsureTable(this.TableDefinitions[tableName]);
485 if (0 == sequenceTable.Rows.Count)
486 {
487 sequenceTable.Operation = TableOperation.Add;
488 }
489
490 var patchAction = sequenceTable.CreateRow(null);
491 patchAction[0] = patchFilesActionTuple.Action;
492 patchAction[1] = patchFilesActionTuple.Condition;
489 patchAction[2] = sequence; 493 patchAction[2] = sequence;
490 patchAction.Operation = RowOperation.Add; 494 patchAction.Operation = RowOperation.Add;
491 } 495 }
@@ -494,27 +498,28 @@ namespace WixToolset.Core.WindowsInstaller.Bind
494 /// <summary> 498 /// <summary>
495 /// Tests sequence table for PatchFiles and associated actions 499 /// Tests sequence table for PatchFiles and associated actions
496 /// </summary> 500 /// </summary>
497 /// <param name="iesTable">The table to test.</param> 501 /// <param name="sequenceTable">The table to test.</param>
498 /// <param name="hasPatchFilesAction">Set to true if PatchFiles action is found. Left unchanged otherwise.</param> 502 /// <param name="hasPatchFilesAction">Set to true if PatchFiles action is found. Left unchanged otherwise.</param>
499 /// <param name="seqInstallFiles">Set to sequence value of InstallFiles action if found. Left unchanged otherwise.</param> 503 /// <param name="installFilesSequence">Set to sequence value of InstallFiles action if found. Left unchanged otherwise.</param>
500 /// <param name="seqDuplicateFiles">Set to sequence value of DuplicateFiles action if found. Left unchanged otherwise.</param> 504 /// <param name="duplicateFilesSequence">Set to sequence value of DuplicateFiles action if found. Left unchanged otherwise.</param>
501 private static void TestSequenceTableForPatchFilesAction(Table iesTable, ref bool hasPatchFilesAction, ref int seqInstallFiles, ref int seqDuplicateFiles) 505 private static void TestSequenceTableForPatchFilesAction(Table sequenceTable, ref bool hasPatchFilesAction, ref int installFilesSequence, ref int duplicateFilesSequence)
502 { 506 {
503 if (null != iesTable) 507 if (null != sequenceTable)
504 { 508 {
505 foreach (Row iesRow in iesTable.Rows) 509 foreach (var row in sequenceTable.Rows)
506 { 510 {
507 if (String.Equals("PatchFiles", (string)iesRow[0], StringComparison.Ordinal)) 511 var actionName = row.FieldAsString(0);
512 if (String.Equals("PatchFiles", actionName, StringComparison.Ordinal))
508 { 513 {
509 hasPatchFilesAction = true; 514 hasPatchFilesAction = true;
510 } 515 }
511 if (String.Equals("InstallFiles", (string)iesRow[0], StringComparison.Ordinal)) 516 else if (String.Equals("InstallFiles", actionName, StringComparison.Ordinal))
512 { 517 {
513 seqInstallFiles = (int)iesRow.Fields[2].Data; 518 installFilesSequence = row.FieldAsInteger(2);
514 } 519 }
515 if (String.Equals("DuplicateFiles", (string)iesRow[0], StringComparison.Ordinal)) 520 else if (String.Equals("DuplicateFiles", actionName, StringComparison.Ordinal))
516 { 521 {
517 seqDuplicateFiles = (int)iesRow.Fields[2].Data; 522 duplicateFilesSequence = row.FieldAsInteger(2);
518 } 523 }
519 } 524 }
520 } 525 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
index 23a5fcba..e9b0d612 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
@@ -18,16 +18,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
18 this.Section = section; 18 this.Section = section;
19 19
20 this.RelativeActionsForActions = new Dictionary<string, RelativeActions>(); 20 this.RelativeActionsForActions = new Dictionary<string, RelativeActions>();
21
22 this.StandardActionsById = WindowsInstallerStandard.StandardActions().ToDictionary(a => a.Id.Id);
23 } 21 }
24 22
25 private IntermediateSection Section { get; } 23 private IntermediateSection Section { get; }
26 24
27 private Dictionary<string, RelativeActions> RelativeActionsForActions { get; } 25 private Dictionary<string, RelativeActions> RelativeActionsForActions { get; }
28 26
29 private Dictionary<string, WixActionTuple> StandardActionsById { get; }
30
31 public IMessaging Messaging { private get; set; } 27 public IMessaging Messaging { private get; set; }
32 28
33 /// <summary> 29 /// <summary>
@@ -63,7 +59,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
63 // Unsequenced action (allowed for certain standard actions). 59 // Unsequenced action (allowed for certain standard actions).
64 if (null == actionTuple.Before && null == actionTuple.After && !actionTuple.Sequence.HasValue) 60 if (null == actionTuple.Before && null == actionTuple.After && !actionTuple.Sequence.HasValue)
65 { 61 {
66 if (this.StandardActionsById.TryGetValue(actionTuple.Id.Id, out var standardAction)) 62 if (WindowsInstallerStandard.TryGetStandardAction(actionTuple.Id.Id, out var standardAction))
67 { 63 {
68 // Populate the sequence from the standard action 64 // Populate the sequence from the standard action
69 actionTuple.Sequence = standardAction.Sequence; 65 actionTuple.Sequence = standardAction.Sequence;
@@ -154,7 +150,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
154 // on the presence of a particular table. 150 // on the presence of a particular table.
155 if (requiredActionTuples.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionTuples.ContainsKey("InstallExecuteSequence/InstallFiles")) 151 if (requiredActionTuples.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionTuples.ContainsKey("InstallExecuteSequence/InstallFiles"))
156 { 152 {
157 var standardAction = this.StandardActionsById["InstallExecuteSequence/InstallFiles"]; 153 WindowsInstallerStandard.TryGetStandardAction("InstallExecuteSequence/InstallFiles", out var standardAction);
158 requiredActionTuples.Add(standardAction.Id.Id, standardAction); 154 requiredActionTuples.Add(standardAction.Id.Id, standardAction);
159 } 155 }
160 156
@@ -201,8 +197,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
201 197
202 foreach (var actionId in requiredActionIds) 198 foreach (var actionId in requiredActionIds)
203 { 199 {
204 var standardAction = this.StandardActionsById[actionId]; 200 WindowsInstallerStandard.TryGetStandardAction(actionId, out var standardAction);
205
206 overridableActionTuples.Add(standardAction.Id.Id, standardAction); 201 overridableActionTuples.Add(standardAction.Id.Id, standardAction);
207 } 202 }
208 203
@@ -597,7 +592,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
597 if (!requiredActionTuples.TryGetValue(parentActionKey, out var parentActionTuple)) 592 if (!requiredActionTuples.TryGetValue(parentActionKey, out var parentActionTuple))
598 { 593 {
599 // If the missing parent action is a standard action (with a suggested sequence number), add it. 594 // If the missing parent action is a standard action (with a suggested sequence number), add it.
600 if (this.StandardActionsById.TryGetValue(parentActionKey, out parentActionTuple)) 595 if (WindowsInstallerStandard.TryGetStandardAction(parentActionKey, out parentActionTuple))
601 { 596 {
602 // Create a clone to avoid modifying the static copy of the object. 597 // Create a clone to avoid modifying the static copy of the object.
603 // TODO: consider this: parentActionTuple = parentActionTuple.Clone(); 598 // TODO: consider this: parentActionTuple = parentActionTuple.Clone();
diff --git a/src/WixToolset.Core.WindowsInstaller/Data/actions.xml b/src/WixToolset.Core.WindowsInstaller/Data/actions.xml
deleted file mode 100644
index f65b792d..00000000
--- a/src/WixToolset.Core.WindowsInstaller/Data/actions.xml
+++ /dev/null
@@ -1,76 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4
5<actions xmlns="http://wixtoolset.org/schemas/v4/wi/actions">
6 <action name="InstallInitialize" sequence="1500" AdminExecuteSequence="yes" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
7 <action name="InstallExecute" condition="NOT Installed" sequence="6500" InstallExecuteSequence="yes" />
8 <action name="InstallExecuteAgain" condition="NOT Installed" sequence="6550" InstallExecuteSequence="yes" />
9 <action name="InstallFinalize" sequence="6600" AdminExecuteSequence="yes" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
10 <action name="InstallFiles" sequence="4000" AdminExecuteSequence="yes" InstallExecuteSequence="yes" />
11 <action name="InstallAdminPackage" sequence="3900" AdminExecuteSequence="yes" />
12 <action name="FileCost" sequence="900" AdminExecuteSequence="yes" AdminUISequence="yes" InstallExecuteSequence="yes" InstallUISequence="yes" />
13 <action name="CostInitialize" sequence="800" AdminExecuteSequence="yes" AdminUISequence="yes" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" InstallUISequence="yes" />
14 <action name="CostFinalize" sequence="1000" AdminExecuteSequence="yes" AdminUISequence="yes" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" InstallUISequence="yes" />
15 <action name="InstallValidate" sequence="1400" AdminExecuteSequence="yes" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
16 <action name="ExecuteAction" sequence="1300" AdminUISequence="yes" InstallUISequence="yes" />
17 <action name="CreateShortcuts" sequence="4500" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
18 <action name="MsiPublishAssemblies" sequence="6250" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
19 <action name="PublishComponents" sequence="6200" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
20 <action name="PublishFeatures" sequence="6300" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
21 <action name="PublishProduct" sequence="6400" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
22 <action name="RegisterClassInfo" sequence="4600" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
23 <action name="RegisterExtensionInfo" sequence="4700" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
24 <action name="RegisterMIMEInfo" sequence="4900" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
25 <action name="RegisterProgIdInfo" sequence="4800" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" />
26 <action name="AllocateRegistrySpace" condition="NOT Installed" sequence="1550" InstallExecuteSequence="yes" />
27 <action name="AppSearch" sequence="50" InstallExecuteSequence="yes" InstallUISequence="yes" />
28 <action name="BindImage" sequence="4300" InstallExecuteSequence="yes" />
29 <action name="CCPSearch" condition="NOT Installed" sequence="500" InstallExecuteSequence="yes" InstallUISequence="yes" />
30 <action name="CreateFolders" sequence="3700" InstallExecuteSequence="yes" />
31 <action name="DeleteServices" condition="VersionNT" sequence="2000" InstallExecuteSequence="yes" />
32 <action name="DuplicateFiles" sequence="4210" InstallExecuteSequence="yes" />
33 <action name="FindRelatedProducts" sequence="25" InstallExecuteSequence="yes" InstallUISequence="yes" />
34 <action name="InstallODBC" sequence="5400" InstallExecuteSequence="yes" />
35 <action name="InstallServices" condition="VersionNT" sequence="5800" InstallExecuteSequence="yes" />
36 <action name="MsiConfigureServices" condition="VersionNT>=600" sequence="5850" InstallExecuteSequence="yes" />
37 <action name="IsolateComponents" sequence="950" InstallExecuteSequence="yes" InstallUISequence="yes" />
38 <action name="LaunchConditions" sequence="100" AdminExecuteSequence="yes" AdminUISequence="yes" InstallExecuteSequence="yes" InstallUISequence="yes" />
39 <action name="MigrateFeatureStates" sequence="1200" InstallExecuteSequence="yes" InstallUISequence="yes" />
40 <action name="MoveFiles" sequence="3800" InstallExecuteSequence="yes" />
41 <action name="PatchFiles" sequence="4090" AdminExecuteSequence="yes" InstallExecuteSequence="yes" />
42 <action name="ProcessComponents" sequence="1600" InstallExecuteSequence="yes" />
43 <action name="RegisterComPlus" sequence="5700" InstallExecuteSequence="yes" />
44 <action name="RegisterFonts" sequence="5300" InstallExecuteSequence="yes" />
45 <action name="RegisterProduct" sequence="6100" InstallExecuteSequence="yes" />
46 <action name="RegisterTypeLibraries" sequence="5500" InstallExecuteSequence="yes" />
47 <action name="RegisterUser" sequence="6000" InstallExecuteSequence="yes" />
48 <action name="RemoveDuplicateFiles" sequence="3400" InstallExecuteSequence="yes" />
49 <action name="RemoveEnvironmentStrings" sequence="3300" InstallExecuteSequence="yes" />
50 <action name="RemoveFiles" sequence="3500" InstallExecuteSequence="yes" />
51 <action name="RemoveFolders" sequence="3600" InstallExecuteSequence="yes" />
52 <action name="RemoveIniValues" sequence="3100" InstallExecuteSequence="yes" />
53 <action name="RemoveODBC" sequence="2400" InstallExecuteSequence="yes" />
54 <action name="RemoveRegistryValues" sequence="2600" InstallExecuteSequence="yes" />
55 <action name="RemoveShortcuts" sequence="3200" InstallExecuteSequence="yes" />
56 <action name="RMCCPSearch" condition="NOT Installed" sequence="600" InstallExecuteSequence="yes" InstallUISequence="yes" />
57 <action name="SelfRegModules" sequence="5600" InstallExecuteSequence="yes" />
58 <action name="SelfUnregModules" sequence="2200" InstallExecuteSequence="yes" />
59 <action name="SetODBCFolders" sequence="1100" InstallExecuteSequence="yes" />
60 <action name="StartServices" condition="VersionNT" sequence="5900" InstallExecuteSequence="yes" />
61 <action name="StopServices" condition="VersionNT" sequence="1900" InstallExecuteSequence="yes" />
62 <action name="MsiUnpublishAssemblies" sequence="1750" InstallExecuteSequence="yes" />
63 <action name="UnpublishComponents" sequence="1700" InstallExecuteSequence="yes" />
64 <action name="UnpublishFeatures" sequence="1800" InstallExecuteSequence="yes" />
65 <action name="UnregisterClassInfo" sequence="2700" InstallExecuteSequence="yes" />
66 <action name="UnregisterComPlus" sequence="2100" InstallExecuteSequence="yes" />
67 <action name="UnregisterExtensionInfo" sequence="2800" InstallExecuteSequence="yes" />
68 <action name="UnregisterFonts" sequence="2500" InstallExecuteSequence="yes" />
69 <action name="UnregisterMIMEInfo" sequence="3000" InstallExecuteSequence="yes" />
70 <action name="UnregisterProgIdInfo" sequence="2900" InstallExecuteSequence="yes" />
71 <action name="UnregisterTypeLibraries" sequence="2300" InstallExecuteSequence="yes" />
72 <action name="ValidateProductID" sequence="700" InstallExecuteSequence="yes" InstallUISequence="yes" />
73 <action name="WriteEnvironmentStrings" sequence="5200" InstallExecuteSequence="yes" />
74 <action name="WriteIniValues" sequence="5100" InstallExecuteSequence="yes" />
75 <action name="WriteRegistryValues" sequence="5000" InstallExecuteSequence="yes" />
76</actions>
diff --git a/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs b/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
index b1222d3d..aa8921ed 100644
--- a/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs
@@ -13,7 +13,6 @@ namespace WixToolset.Core.WindowsInstaller
13 using System.Text.RegularExpressions; 13 using System.Text.RegularExpressions;
14 using System.Xml.Linq; 14 using System.Xml.Linq;
15 using WixToolset.Core; 15 using WixToolset.Core;
16 using WixToolset.Core.WindowsInstaller.Rows;
17 using WixToolset.Data; 16 using WixToolset.Data;
18 using WixToolset.Data.Tuples; 17 using WixToolset.Data.Tuples;
19 using WixToolset.Data.WindowsInstaller; 18 using WixToolset.Data.WindowsInstaller;
@@ -104,7 +103,7 @@ namespace WixToolset.Core.WindowsInstaller
104 { 103 {
105 if (null == output) 104 if (null == output)
106 { 105 {
107 throw new ArgumentNullException("output"); 106 throw new ArgumentNullException(nameof(output));
108 } 107 }
109 108
110 this.OutputType = output.Type; 109 this.OutputType = output.Type;
@@ -1534,9 +1533,7 @@ namespace WixToolset.Core.WindowsInstaller
1534 1533
1535 foreach (Wix.ISchemaElement element in component.Children) 1534 foreach (Wix.ISchemaElement element in component.Children)
1536 { 1535 {
1537 var file = element as Wix.File; 1536 if (element is Wix.File file && Wix.YesNoType.yes == file.KeyPath)
1538
1539 if (null != file && Wix.YesNoType.yes == file.KeyPath)
1540 { 1537 {
1541 file.AddChild(typeLib); 1538 file.AddChild(typeLib);
1542 } 1539 }
@@ -2511,10 +2508,10 @@ namespace WixToolset.Core.WindowsInstaller
2511 2508
2512 if (null != table) 2509 if (null != table)
2513 { 2510 {
2514 var actionRows = new ArrayList(); 2511 var actionRows = new List<WixActionRow>();
2515 var needAbsoluteScheduling = this.SuppressRelativeActionSequencing; 2512 var needAbsoluteScheduling = this.SuppressRelativeActionSequencing;
2516 var nonSequencedActionRows = new WixActionRowCollection(); 2513 var nonSequencedActionRows = new Dictionary<string, WixActionRow>();
2517 var suppressedRelativeActionRows = new WixActionRowCollection(); 2514 var suppressedRelativeActionRows = new Dictionary<string, WixActionRow>();
2518 2515
2519 // create a sorted array of actions in this table 2516 // create a sorted array of actions in this table
2520 foreach (var row in table.Rows) 2517 foreach (var row in table.Rows)
@@ -2538,7 +2535,7 @@ namespace WixToolset.Core.WindowsInstaller
2538 2535
2539 for (var i = 0; i < actionRows.Count && !needAbsoluteScheduling; i++) 2536 for (var i = 0; i < actionRows.Count && !needAbsoluteScheduling; i++)
2540 { 2537 {
2541 var actionRow = (WixActionRow)actionRows[i]; 2538 var actionRow = actionRows[i];
2542 this.StandardActions.TryGetValue(actionRow.GetPrimaryKey(), out var standardActionRow); 2539 this.StandardActions.TryGetValue(actionRow.GetPrimaryKey(), out var standardActionRow);
2543 2540
2544 // 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
@@ -2550,13 +2547,13 @@ namespace WixToolset.Core.WindowsInstaller
2550 // find the previous action row if there is one 2547 // find the previous action row if there is one
2551 if (0 <= i - 1) 2548 if (0 <= i - 1)
2552 { 2549 {
2553 previousActionRow = (WixActionRow)actionRows[i - 1]; 2550 previousActionRow = actionRows[i - 1];
2554 } 2551 }
2555 2552
2556 // find the next action row if there is one 2553 // find the next action row if there is one
2557 if (actionRows.Count > i + 1) 2554 if (actionRows.Count > i + 1)
2558 { 2555 {
2559 nextActionRow = (WixActionRow)actionRows[i + 1]; 2556 nextActionRow = actionRows[i + 1];
2560 } 2557 }
2561 2558
2562 // 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:
@@ -2594,7 +2591,7 @@ namespace WixToolset.Core.WindowsInstaller
2594 } 2591 }
2595 else if (null != standardActionRow && actionRow.Condition != standardActionRow.Condition) // standard actions get their standard sequence numbers 2592 else if (null != standardActionRow && actionRow.Condition != standardActionRow.Condition) // standard actions get their standard sequence numbers
2596 { 2593 {
2597 nonSequencedActionRows.Add(actionRow); 2594 nonSequencedActionRows.Add(actionRow.GetPrimaryKey(), actionRow);
2598 } 2595 }
2599 else if (0 < actionRow.Sequence) 2596 else if (0 < actionRow.Sequence)
2600 { 2597 {
@@ -2603,25 +2600,27 @@ namespace WixToolset.Core.WindowsInstaller
2603 } 2600 }
2604 else 2601 else
2605 { 2602 {
2606 suppressedRelativeActionRows.Add(actionRow); 2603 suppressedRelativeActionRows.Add(actionRow.GetPrimaryKey(), actionRow);
2607 } 2604 }
2608 } 2605 }
2609 2606
2610 // 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
2611 foreach (WixActionRow actionRow in actionRows) 2608 foreach (var actionRow in actionRows)
2612 { 2609 {
2610 var key = actionRow.GetPrimaryKey();
2611
2613 if (needAbsoluteScheduling) 2612 if (needAbsoluteScheduling)
2614 { 2613 {
2615 // remove any before/after information to ensure this is absolutely sequenced 2614 // remove any before/after information to ensure this is absolutely sequenced
2616 actionRow.Before = null; 2615 actionRow.Before = null;
2617 actionRow.After = null; 2616 actionRow.After = null;
2618 } 2617 }
2619 else if (nonSequencedActionRows.Contains(actionRow.SequenceTable, actionRow.Action)) 2618 else if (nonSequencedActionRows.ContainsKey(key))
2620 { 2619 {
2621 // clear the sequence attribute to ensure this action is scheduled without a sequence number (or before/after) 2620 // clear the sequence attribute to ensure this action is scheduled without a sequence number (or before/after)
2622 actionRow.Sequence = 0; 2621 actionRow.Sequence = 0;
2623 } 2622 }
2624 else if (suppressedRelativeActionRows.Contains(actionRow.SequenceTable, actionRow.Action)) 2623 else if (suppressedRelativeActionRows.ContainsKey(key))
2625 { 2624 {
2626 // skip the suppressed relatively scheduled action rows 2625 // skip the suppressed relatively scheduled action rows
2627 continue; 2626 continue;
diff --git a/src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs b/src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs
deleted file mode 100644
index 5abf02ce..00000000
--- a/src/WixToolset.Core.WindowsInstaller/Rows/WixActionRowCollection.cs
+++ /dev/null
@@ -1,329 +0,0 @@
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
3namespace WixToolset.Core.WindowsInstaller.Rows
4{
5 using System;
6 using System.Collections;
7 using System.Diagnostics;
8 using System.Globalization;
9 using System.Xml;
10 using WixToolset.Data.Tuples;
11 using WixToolset.Data.WindowsInstaller.Rows;
12
13 /// <summary>
14 /// A collection of action rows sorted by their sequence table and action name.
15 /// </summary>
16 // TODO: Remove this
17 internal sealed class WixActionRowCollection : ICollection
18 {
19 private readonly SortedList collection;
20
21 /// <summary>
22 /// Creates a new action table object.
23 /// </summary>
24 public WixActionRowCollection()
25 {
26 this.collection = new SortedList();
27 }
28
29 /// <summary>
30 /// Gets the number of items in the collection.
31 /// </summary>
32 /// <value>Number of items in collection.</value>
33 public int Count
34 {
35 get { return this.collection.Count; }
36 }
37
38 /// <summary>
39 /// Gets if the collection has been synchronized.
40 /// </summary>
41 /// <value>True if the collection has been synchronized.</value>
42 public bool IsSynchronized
43 {
44 get { return this.collection.IsSynchronized; }
45 }
46
47 /// <summary>
48 /// Gets the object used to synchronize the collection.
49 /// </summary>
50 /// <value>Oject used the synchronize the collection.</value>
51 public object SyncRoot
52 {
53 get { return this; }
54 }
55
56 /// <summary>
57 /// Get an ActionRow by its sequence table and action name.
58 /// </summary>
59 /// <param name="sequenceTable">The sequence table of the ActionRow.</param>
60 /// <param name="action">The action name of the ActionRow.</param>
61 public WixActionRow this[SequenceTable sequenceTable, string action]
62 {
63 get { return (WixActionRow)this.collection[GetKey(sequenceTable, action)]; }
64 }
65
66 /// <summary>
67 /// Add an ActionRow to the collection.
68 /// </summary>
69 /// <param name="actionRow">The ActionRow to add.</param>
70 /// <param name="overwrite">true to overwrite an existing ActionRow; false otherwise.</param>
71 public void Add(WixActionRow actionRow, bool overwrite)
72 {
73 string key = GetKey(actionRow.SequenceTable, actionRow.Action);
74
75 if (overwrite)
76 {
77 this.collection[key] = actionRow;
78 }
79 else
80 {
81 this.collection.Add(key, actionRow);
82 }
83 }
84
85 /// <summary>
86 /// Add an ActionRow to the collection.
87 /// </summary>
88 /// <param name="actionRow">The ActionRow to add.</param>
89 public void Add(WixActionRow actionRow)
90 {
91 this.Add(actionRow, false);
92 }
93
94 /// <summary>
95 /// Determines if the collection contains an ActionRow with a specific sequence table and name.
96 /// </summary>
97 /// <param name="sequenceTable">The sequence table of the ActionRow.</param>
98 /// <param name="action">The action name of the ActionRow.</param>
99 /// <returns>true if the ActionRow was found; false otherwise.</returns>
100 public bool Contains(SequenceTable sequenceTable, string action)
101 {
102 return this.collection.Contains(GetKey(sequenceTable, action));
103 }
104
105 /// <summary>
106 /// Copies the collection into an array.
107 /// </summary>
108 /// <param name="array">Array to copy the collection into.</param>
109 /// <param name="index">Index to start copying from.</param>
110 public void CopyTo(System.Array array, int index)
111 {
112 this.collection.Values.CopyTo(array, index);
113 }
114
115 /// <summary>
116 /// Gets the enumerator for the collection.
117 /// </summary>
118 /// <returns>The enumerator for the collection.</returns>
119 public IEnumerator GetEnumerator()
120 {
121 return this.collection.Values.GetEnumerator();
122 }
123
124 /// <summary>
125 /// Remove an ActionRow from the collection.
126 /// </summary>
127 /// <param name="sequenceTable">The sequence table of the ActionRow.</param>
128 /// <param name="action">The action name of the ActionRow.</param>
129 public void Remove(SequenceTable sequenceTable, string action)
130 {
131 this.collection.Remove(GetKey(sequenceTable, action));
132 }
133
134 /// <summary>
135 /// Load an action table from an XmlReader.
136 /// </summary>
137 /// <param name="reader">Reader to get data from.</param>
138 /// <returns>The ActionRowCollection represented by the xml.</returns>
139 internal static WixActionRowCollection Load(XmlReader reader)
140 {
141 reader.MoveToContent();
142
143 return Parse(reader);
144 }
145
146 /// <summary>
147 /// Creates a new action table object and populates it from an Xml reader.
148 /// </summary>
149 /// <param name="reader">Reader to get data from.</param>
150 /// <returns>The parsed ActionTable.</returns>
151 private static WixActionRowCollection Parse(XmlReader reader)
152 {
153 if (!reader.LocalName.Equals("actions"))
154 {
155 throw new XmlException();
156 }
157
158 WixActionRowCollection actionRows = new WixActionRowCollection();
159 bool empty = reader.IsEmptyElement;
160
161 while (reader.MoveToNextAttribute())
162 {
163 }
164
165 if (!empty)
166 {
167 bool done = false;
168
169 // loop through all the fields in a row
170 while (!done && reader.Read())
171 {
172 switch (reader.NodeType)
173 {
174 case XmlNodeType.Element:
175 switch (reader.LocalName)
176 {
177 case "action":
178 WixActionRow[] parsedActionRows = ParseActions(reader);
179
180 foreach (WixActionRow actionRow in parsedActionRows)
181 {
182 actionRows.Add(actionRow);
183 }
184 break;
185 default:
186 throw new XmlException();
187 }
188 break;
189 case XmlNodeType.EndElement:
190 done = true;
191 break;
192 }
193 }
194
195 if (!done)
196 {
197 throw new XmlException();
198 }
199 }
200
201 return actionRows;
202 }
203
204 /// <summary>
205 /// Get the key for storing an ActionRow.
206 /// </summary>
207 /// <param name="sequenceTable">The sequence table of the ActionRow.</param>
208 /// <param name="action">The action name of the ActionRow.</param>
209 /// <returns>The string key.</returns>
210 private static string GetKey(SequenceTable sequenceTable, string action)
211 {
212 return GetKey(sequenceTable.ToString(), action);
213 }
214
215 /// <summary>
216 /// Get the key for storing an ActionRow.
217 /// </summary>
218 /// <param name="sequenceTable">The sequence table of the ActionRow.</param>
219 /// <param name="action">The action name of the ActionRow.</param>
220 /// <returns>The string key.</returns>
221 private static string GetKey(string sequenceTable, string action)
222 {
223 return String.Concat(sequenceTable, '/', action);
224 }
225
226 /// <summary>
227 /// Parses ActionRows from the Xml reader.
228 /// </summary>
229 /// <param name="reader">Xml reader that contains serialized ActionRows.</param>
230 /// <returns>The parsed ActionRows.</returns>
231 internal static WixActionRow[] ParseActions(XmlReader reader)
232 {
233 Debug.Assert("action" == reader.LocalName);
234
235 string id = null;
236 string condition = null;
237 bool empty = reader.IsEmptyElement;
238 int sequence = Int32.MinValue;
239 int sequenceCount = 0;
240 SequenceTable[] sequenceTables = new SequenceTable[Enum.GetValues(typeof(SequenceTable)).Length];
241
242 while (reader.MoveToNextAttribute())
243 {
244 switch (reader.Name)
245 {
246 case "name":
247 id = reader.Value;
248 break;
249 case "AdminExecuteSequence":
250 if (reader.Value.Equals("yes"))
251 {
252 sequenceTables[sequenceCount] = SequenceTable.AdminExecuteSequence;
253 ++sequenceCount;
254 }
255 break;
256 case "AdminUISequence":
257 if (reader.Value.Equals("yes"))
258 {
259 sequenceTables[sequenceCount] = SequenceTable.AdminUISequence;
260 ++sequenceCount;
261 }
262 break;
263 case "AdvtExecuteSequence":
264 if (reader.Value.Equals("yes"))
265 {
266 sequenceTables[sequenceCount] = SequenceTable.AdvertiseExecuteSequence;
267 ++sequenceCount;
268 }
269 break;
270 case "condition":
271 condition = reader.Value;
272 break;
273 case "InstallExecuteSequence":
274 if (reader.Value.Equals("yes"))
275 {
276 sequenceTables[sequenceCount] = SequenceTable.InstallExecuteSequence;
277 ++sequenceCount;
278 }
279 break;
280 case "InstallUISequence":
281 if (reader.Value.Equals("yes"))
282 {
283 sequenceTables[sequenceCount] = SequenceTable.InstallUISequence;
284 ++sequenceCount;
285 }
286 break;
287 case "sequence":
288 sequence = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture);
289 break;
290 }
291 }
292
293 if (null == id)
294 {
295 throw new XmlException();
296 }
297
298 if (Int32.MinValue == sequence)
299 {
300 throw new XmlException();
301 }
302 else if (1 > sequence)
303 {
304 throw new XmlException();
305 }
306
307 if (0 == sequenceCount)
308 {
309 throw new XmlException();
310 }
311
312 if (!empty && reader.Read() && XmlNodeType.EndElement != reader.MoveToContent())
313 {
314 throw new XmlException();
315 }
316
317 // create the actions
318 WixActionRow[] actionRows = new WixActionRow[sequenceCount];
319 for (var i = 0; i < sequenceCount; i++)
320 {
321 //WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence);
322 //actionRows[i] = actionRow;
323 throw new NotImplementedException();
324 }
325
326 return actionRows;
327 }
328 }
329}
diff --git a/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs b/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs
index 759bda14..33f1ba04 100644
--- a/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs
+++ b/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs
@@ -2,10 +2,8 @@
2 2
3namespace WixToolset.Core.WindowsInstaller 3namespace WixToolset.Core.WindowsInstaller
4{ 4{
5 using System;
6 using System.Reflection; 5 using System.Reflection;
7 using System.Xml; 6 using System.Xml;
8 using WixToolset.Core.WindowsInstaller.Rows;
9 using WixToolset.Data.WindowsInstaller; 7 using WixToolset.Data.WindowsInstaller;
10 8
11 /// <summary> 9 /// <summary>
@@ -16,9 +14,6 @@ namespace WixToolset.Core.WindowsInstaller
16 private static readonly object lockObject = new object(); 14 private static readonly object lockObject = new object();
17 15
18 private static TableDefinitionCollection tableDefinitions; 16 private static TableDefinitionCollection tableDefinitions;
19#if REVISIT_FOR_PATCHING
20 private static WixActionRowCollection standardActions;
21#endif
22 17
23 /// <summary> 18 /// <summary>
24 /// Gets the table definitions stored in this assembly. 19 /// Gets the table definitions stored in this assembly.
@@ -26,6 +21,8 @@ namespace WixToolset.Core.WindowsInstaller
26 /// <returns>Table definition collection for tables stored in this assembly.</returns> 21 /// <returns>Table definition collection for tables stored in this assembly.</returns>
27 public static TableDefinitionCollection GetTableDefinitions() 22 public static TableDefinitionCollection GetTableDefinitions()
28 { 23 {
24 // TODO: make the data static data structures instead of parsing an XML file and consider
25 // moving it all to WixToolset.Data.WindowsInstallerStandard class.
29 lock (lockObject) 26 lock (lockObject)
30 { 27 {
31 if (null == WindowsInstallerStandardInternal.tableDefinitions) 28 if (null == WindowsInstallerStandardInternal.tableDefinitions)
@@ -39,28 +36,5 @@ namespace WixToolset.Core.WindowsInstaller
39 36
40 return WindowsInstallerStandardInternal.tableDefinitions; 37 return WindowsInstallerStandardInternal.tableDefinitions;
41 } 38 }
42
43 /// <summary>
44 /// Gets the standard actions stored in this assembly.
45 /// </summary>
46 /// <returns>Collection of standard actions in this assembly.</returns>
47 public static WixActionRowCollection GetStandardActionRows()
48 {
49#if REVISIT_FOR_PATCHING
50 lock (lockObject)
51 {
52 if (null == WindowsInstallerStandardInternal.standardActions)
53 {
54 using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Core.WindowsInstaller.Data.actions.xml")))
55 {
56 WindowsInstallerStandardInternal.standardActions = WixActionRowCollection.Load(reader);
57 }
58 }
59 }
60
61 return WindowsInstallerStandardInternal.standardActions;
62#endif
63 throw new NotImplementedException();
64 }
65 } 39 }
66} 40}
diff --git a/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj b/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj
index f1351aba..07007525 100644
--- a/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj
+++ b/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj
@@ -11,7 +11,6 @@
11 </PropertyGroup> 11 </PropertyGroup>
12 12
13 <ItemGroup> 13 <ItemGroup>
14 <EmbeddedResource Include="Data\actions.xml" />
15 <EmbeddedResource Include="Data\tables.xml" /> 14 <EmbeddedResource Include="Data\tables.xml" />
16 </ItemGroup> 15 </ItemGroup>
17 16