Skip to content

Commit

Permalink
Scheduling standard actions must override virtual definitions from st…
Browse files Browse the repository at this point in the history
…dlib

Fixes 8115
  • Loading branch information
robmen committed Jul 13, 2024
1 parent 590c667 commit 733886e
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 4 deletions.
12 changes: 9 additions & 3 deletions src/wix/WixToolset.Core/Compiler_Package.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2504,8 +2504,8 @@ private void ParseSequenceElement(XElement node, SequenceTable sequenceTable)
var exitSequence = CompilerConstants.IntegerNotSet;
var sequence = CompilerConstants.IntegerNotSet;
var showDialog = "Show" == actionName;
var specialAction = "InstallExecute" == actionName || "InstallExecuteAgain" == actionName || "RemoveExistingProducts" == actionName || "DisableRollback" == actionName || "ScheduleReboot" == actionName || "ForceReboot" == actionName || "ResolveSource" == actionName;
var specialStandardAction = "AppSearch" == actionName || "CCPSearch" == actionName || "RMCCPSearch" == actionName || "LaunchConditions" == actionName || "FindRelatedProducts" == actionName;
var specialAction = "InstallExecute" == actionName || "InstallExecuteAgain" == actionName || "RemoveExistingProducts" == actionName || "DisableRollback" == actionName || "ScheduleReboot" == actionName || "ForceReboot" == actionName || "ResolveSource" == actionName; // these actions do NOT have default sequence numbers and MUST be scheduled.
var specialStandardAction = "AppSearch" == actionName || "CCPSearch" == actionName || "RMCCPSearch" == actionName || "LaunchConditions" == actionName || "FindRelatedProducts" == actionName; // these standard actions have default sequence numbers so they do NOT have to be scheduled.
var suppress = false;

foreach (var attrib in child.Attributes())
Expand Down Expand Up @@ -2608,6 +2608,8 @@ private void ParseSequenceElement(XElement node, SequenceTable sequenceTable)
}
}

var standardAction = WindowsInstallerStandard.IsStandardAction(actionName);

if (customAction && "Custom" == actionName)
{
this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Action"));
Expand Down Expand Up @@ -2653,7 +2655,7 @@ private void ParseSequenceElement(XElement node, SequenceTable sequenceTable)
}

// normal standard actions cannot be set overridable by the user (since they are overridable by default)
if (overridable && WindowsInstallerStandard.IsStandardAction(actionName) && !specialAction)
if (overridable && standardAction && !specialAction)
{
this.Core.Write(ErrorMessages.UnexpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Overridable"));
}
Expand Down Expand Up @@ -2688,6 +2690,10 @@ private void ParseSequenceElement(XElement node, SequenceTable sequenceTable)
{
access = actionIdentifier.Access;
}
else if (standardAction)
{
access = AccessModifier.Override;
}

var symbol = this.Core.AddSymbol(new WixActionSymbol(childSourceLineNumbers, new Identifier(access, sequenceTable, actionName))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,16 @@ public void Execute()
// Ensure referenced override symbols actually overrode a virtual symbol.
foreach (var referencedOverrideSymbol in this.OverrideSymbols.Where(s => this.ResolvedSections.Contains(s.Section)))
{
// The easiest check is to see if the symbol overrode a virtual symbol. If not, check to see if there were any possible
// virtual symbols that could have been overridden. If not, then we have an error.
if (referencedOverrideSymbol.Overrides is null)
{
this.Messaging.Write(LinkerErrors.VirtualSymbolNotFoundForOverride(referencedOverrideSymbol.Symbol));
var otherVirtualsCount = referencedOverrideSymbol.PossiblyConflicts.Count(s => s.Access == AccessModifier.Virtual);

if (otherVirtualsCount == 0)
{
this.Messaging.Write(LinkerErrors.VirtualSymbolNotFoundForOverride(referencedOverrideSymbol.Symbol));
}
}
}

Expand Down
124 changes: 124 additions & 0 deletions src/wix/test/WixToolsetTest.CoreIntegration/StandardActionFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// 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.

namespace WixToolsetTest.CoreIntegration
{
using System.IO;
using System.Linq;
using WixInternal.Core.TestPackage;
using WixInternal.TestSupport;
using Xunit;

public class StandardActionFixture
{
[Fact]
public void CanCompileSpecialActionWithOverride()
{
using var fs = new DisposableFileSystem();

var results = BuildAndQueryMsi(fs, "SpecialActionOverride.wxs");

WixAssert.CompareLineByLine(new[]
{
"InstallExecuteSequence:AppSearch\t\t99",
"InstallExecuteSequence:CostFinalize\t\t1000",
"InstallExecuteSequence:CostInitialize\t\t800",
"InstallExecuteSequence:CreateFolders\t\t3700",
"InstallExecuteSequence:FileCost\t\t900",
"InstallExecuteSequence:FindRelatedProducts\t\t98",
"InstallExecuteSequence:InstallFiles\t\t4000",
"InstallExecuteSequence:InstallFinalize\t\t6600",
"InstallExecuteSequence:InstallInitialize\t\t1500",
"InstallExecuteSequence:InstallValidate\t\t1400",
"InstallExecuteSequence:LaunchConditions\t\t100",
"InstallExecuteSequence:MigrateFeatureStates\t\t1200",
"InstallExecuteSequence:ProcessComponents\t\t1600",
"InstallExecuteSequence:PublishFeatures\t\t6300",
"InstallExecuteSequence:PublishProduct\t\t6400",
"InstallExecuteSequence:RegisterProduct\t\t6100",
"InstallExecuteSequence:RegisterUser\t\t6000",
"InstallExecuteSequence:RemoveExistingProducts\t\t1401",
"InstallExecuteSequence:RemoveFiles\t\t3500",
"InstallExecuteSequence:RemoveFolders\t\t3600",
"InstallExecuteSequence:UnpublishFeatures\t\t1800",
"InstallExecuteSequence:ValidateProductID\t\t700",
"InstallUISequence:CostFinalize\t\t1000",
"InstallUISequence:CostInitialize\t\t800",
"InstallUISequence:ExecuteAction\t\t1300",
"InstallUISequence:FileCost\t\t900",
"InstallUISequence:FindRelatedProducts\t\t25",
"InstallUISequence:LaunchConditions\t\t100",
"InstallUISequence:MigrateFeatureStates\t\t1200",
"InstallUISequence:ValidateProductID\t\t700",
}, results);
}

[Fact]
public void CanCompileStandardActionWithOverride()
{
using var fs = new DisposableFileSystem();

var results = BuildAndQueryMsi(fs, "StandardActionOverride.wxs");

WixAssert.CompareLineByLine(new[]
{
"InstallExecuteSequence:CostFinalize\t\t1000",
"InstallExecuteSequence:CostInitialize\t\t800",
"InstallExecuteSequence:CreateFolders\t\t3700",
"InstallExecuteSequence:FileCost\t\t900",
"InstallExecuteSequence:FindRelatedProducts\t\t25",
"InstallExecuteSequence:InstallFiles\tTEST_CONDITION\t4000",
"InstallExecuteSequence:InstallFinalize\t\t6600",
"InstallExecuteSequence:InstallInitialize\t\t1500",
"InstallExecuteSequence:InstallValidate\t\t1400",
"InstallExecuteSequence:LaunchConditions\t\t100",
"InstallExecuteSequence:MigrateFeatureStates\t\t1200",
"InstallExecuteSequence:ProcessComponents\t\t1600",
"InstallExecuteSequence:PublishFeatures\t\t6300",
"InstallExecuteSequence:PublishProduct\t\t6400",
"InstallExecuteSequence:RegisterProduct\t\t6100",
"InstallExecuteSequence:RegisterUser\t\t6000",
"InstallExecuteSequence:RemoveExistingProducts\t\t1401",
"InstallExecuteSequence:RemoveFiles\t\t3500",
"InstallExecuteSequence:RemoveFolders\t\t3600",
"InstallExecuteSequence:UnpublishFeatures\t\t1800",
"InstallExecuteSequence:ValidateProductID\t\t700",
"InstallUISequence:CostFinalize\t\t1000",
"InstallUISequence:CostInitialize\t\t800",
"InstallUISequence:ExecuteAction\t\t1300",
"InstallUISequence:FileCost\t\t900",
"InstallUISequence:FindRelatedProducts\t\t25",
"InstallUISequence:LaunchConditions\t\t100",
"InstallUISequence:MigrateFeatureStates\t\t1200",
"InstallUISequence:ValidateProductID\t\t700",
}, results);
}

private static string[] BuildAndQueryMsi(DisposableFileSystem fs, string sourceFile)
{
var folder = TestData.Get(@"TestData");

var baseFolder = fs.GetFolder();
var intermediateFolder = Path.Combine(baseFolder, "obj");
var msiPath = Path.Combine(baseFolder, "bin", "test.msi");

var result = WixRunner.Execute(new[]
{
"build",
Path.Combine(folder, "StandardAction", sourceFile),
"-bindpath", Path.Combine(folder, "SingleFile", "data"),
"-intermediateFolder", intermediateFolder,
"-o", msiPath
});

result.AssertSuccess();

var results = Query.QueryDatabase(msiPath, new[]
{
"InstallExecuteSequence",
"InstallUISequence"
}).ToArray();

return results;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="~SpecialActionOverride" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"
Compressed="no">
<File Source="test.txt" />

<InstallExecuteSequence>
<FindRelatedProducts Before="LaunchConditions" />
<AppSearch After="FindRelatedProducts" />
</InstallExecuteSequence>
</Package>
</Wix>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package Name="~StandardActionOverride" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"
Compressed="no">
<File Source="test.txt" />

<InstallExecuteSequence>
<InstallFiles Condition="TEST_CONDITION" />
</InstallExecuteSequence>
</Package>
</Wix>

0 comments on commit 733886e

Please sign in to comment.