Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scheduling standard actions must override virtual definitions from stdlib #545

Merged
merged 1 commit into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
Loading