Skip to content

Commit

Permalink
Introducing the WiX Standard Library
Browse files Browse the repository at this point in the history
Completes 7914
  • Loading branch information
robmen committed Dec 16, 2023
1 parent 3799263 commit eff9d42
Show file tree
Hide file tree
Showing 18 changed files with 292 additions and 267 deletions.
4 changes: 3 additions & 1 deletion src/api/wix/WixToolset.Data/Intermediate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,11 @@ public bool RemoveSection(IntermediateSection section)
/// Updates the intermediate level to the specified level.
/// </summary>
/// <param name="level">Intermediate level.</param>
public void UpdateLevel(string level)
public Intermediate UpdateLevel(string level)
{
this.Level = String.IsNullOrEmpty(this.Level) ? level : String.Concat(this.Level, ";", level);

return this;
}

/// <summary>
Expand Down
4 changes: 3 additions & 1 deletion src/api/wix/WixToolset.Data/IntermediateSection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ public T AddSymbol<T>(T symbol) where T : IntermediateSymbol
/// Assigns the section to a library.
/// </summary>
/// <param name="libraryId">Identifier of the library.</param>
public void AssignToLibrary(string libraryId)
public IntermediateSection AssignToLibrary(string libraryId)
{
this.LibraryId = libraryId;

return this;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public static class WindowsInstallerStandard
{
private static readonly Dictionary<string, WixActionSymbol> standardActionsById;
private static readonly HashSet<string> standardActionNames;
private static readonly Dictionary<string, DirectorySymbol> standardDirectoriesById;

/// <summary>
/// References:
Expand Down Expand Up @@ -208,6 +207,41 @@ public static class WindowsInstallerStandard
"WindowsVolume",
};

private static readonly Dictionary<string, string> standardDirectoryNamesById = new Dictionary<string, string>
{
["TARGETDIR"] = "SourceDir",
["AdminToolsFolder"] = "Admin",
["AppDataFolder"] = "AppData",
["CommonAppDataFolder"] = "CommApp",
["CommonFilesFolder"] = "CFiles",
["CommonFiles64Folder"] = "CFiles64",
["CommonFiles6432Folder"] = ".",
["DesktopFolder"] = "Desktop",
["FavoritesFolder"] = "Favs",
["FontsFolder"] = "Fonts",
["LocalAppDataFolder"] = "LocalApp",
["MyPicturesFolder"] = "Pictures",
["NetHoodFolder"] = "NetHood",
["PersonalFolder"] = "Personal",
["PrintHoodFolder"] = "Printers",
["ProgramFilesFolder"] = "PFiles",
["ProgramFiles64Folder"] = "PFiles64",
["ProgramFiles6432Folder"] = ".",
["ProgramMenuFolder"] = "PMenu",
["RecentFolder"] = "Recent",
["SendToFolder"] = "SendTo",
["StartMenuFolder"] = "StrtMenu",
["StartupFolder"] = "StartUp",
["SystemFolder"] = "System",
["System16Folder"] = "System16",
["System64Folder"] = "System64",
["System6432Folder"] = ".",
["TempFolder"] = "Temp",
["TemplateFolder"] = "Template",
["WindowsFolder"] = "Windows",
};


static WindowsInstallerStandard()
{
var standardActions = new[]
Expand Down Expand Up @@ -332,61 +366,35 @@ static WindowsInstallerStandard()
new WixActionSymbol(null, new Identifier(AccessModifier.Virtual, "InstallExecuteSequence/InstallFinalize")) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.InstallExecuteSequence },
};

var standardDirectories = new[]
{
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "TARGETDIR")) { Name = "SourceDir" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "AdminToolsFolder")) { Name = "Admin" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "AppDataFolder")) { Name = "AppData" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "CommonAppDataFolder")) { Name = "CommApp" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "CommonFilesFolder")) { Name = "CFiles" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "CommonFiles64Folder")) { Name = "CFiles64" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "CommonFiles6432Folder")) { Name = "." },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "DesktopFolder")) { Name = "Desktop" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "FavoritesFolder")) { Name = "Favs" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "FontsFolder")) { Name = "Fonts" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "LocalAppDataFolder")) { Name = "LocalApp" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "MyPicturesFolder")) { Name = "Pictures" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "NetHoodFolder")) { Name = "NetHood" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "PersonalFolder")) { Name = "Personal" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "PrintHoodFolder")) { Name = "Printers" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "ProgramFilesFolder")) { Name = "PFiles" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "ProgramFiles64Folder")) { Name = "PFiles64" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "ProgramFiles6432Folder")) { Name = "." },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "ProgramMenuFolder")) { Name = "PMenu" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "RecentFolder")) { Name = "Recent" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "SendToFolder")) { Name = "SendTo" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "StartMenuFolder")) { Name = "StrtMenu" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "StartupFolder")) { Name = "StartUp" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "SystemFolder")) { Name = "System" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "System16Folder")) { Name = "System16" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "System64Folder")) { Name = "System64" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "System6432Folder")) { Name = "." },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "TempFolder")) { Name = "Temp" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "TemplateFolder")) { Name = "Template" },
new DirectorySymbol(null, new Identifier(AccessModifier.Virtual, "WindowsFolder")) { Name = "Windows" },
};

standardActionNames = new HashSet<string>(standardActions.Select(a => a.Action));
standardActionsById = standardActions.ToDictionary(a => a.Id.Id);
standardDirectoriesById = standardDirectories.ToDictionary(d => d.Id.Id);
}

/// <summary>
/// Find out if an action is a standard action.
/// </summary>
/// <param name="actionName">Name of the action.</param>
/// <returns>true if the action is standard, false otherwise.</returns>
public static bool IsStandardAction(string actionName) => standardActionNames.Contains(actionName);
public static bool IsStandardAction(string actionName)
{
return standardActionNames.Contains(actionName);
}

/// <summary>
/// Standard actions.
/// </summary>
public static IReadOnlyCollection<WixActionSymbol> StandardActions() => standardActionsById.Values;
public static IReadOnlyCollection<WixActionSymbol> StandardActions()
{
return standardActionsById.Values;
}

/// <summary>
/// Standard directories.
/// Standard directory identifiers.
/// </summary>
public static IReadOnlyCollection<DirectorySymbol> StandardDirectories() => standardDirectoriesById.Values;
public static IReadOnlyCollection<string> StandardDirectoryIds()
{
return standardDirectoryNamesById.Keys;
}

/// <summary>
/// Gets the platform specific directory id for a directory. Most directories are not platform
Expand Down Expand Up @@ -418,28 +426,43 @@ public static string GetPlatformSpecificDirectoryId(string directoryId, Platform
/// </summary>
/// <param name="directoryId">Name of the directory.</param>
/// <returns>true if the directory is standard, false otherwise.</returns>
public static bool IsStandardDirectory(string directoryId) => standardDirectoriesById.ContainsKey(directoryId);
public static bool IsStandardDirectory(string directoryId)
{
return standardDirectoryNamesById.ContainsKey(directoryId);
}

/// <summary>
/// Find out if a property is a standard property.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <returns>true if a property is standard, false otherwise.</returns>
public static bool IsStandardProperty(string propertyName) => standardProperties.Contains(propertyName);
public static bool IsStandardProperty(string propertyName)
{
return standardProperties.Contains(propertyName);
}

/// <summary>
/// Try to get standard action by id.
/// </summary>
public static bool TryGetStandardAction(string id, out WixActionSymbol standardAction) => standardActionsById.TryGetValue(id, out standardAction);
public static bool TryGetStandardAction(string id, out WixActionSymbol standardAction)
{
return standardActionsById.TryGetValue(id, out standardAction);
}

/// <summary>
/// Try to get standard action by sequence and action name.
/// </summary>
public static bool TryGetStandardAction(string sequenceName, string actioname, out WixActionSymbol standardAction) => standardActionsById.TryGetValue(String.Concat(sequenceName, "/", actioname), out standardAction);
public static bool TryGetStandardAction(string sequenceName, string actioname, out WixActionSymbol standardAction)
{
return standardActionsById.TryGetValue(String.Concat(sequenceName, "/", actioname), out standardAction);
}

/// <summary>
/// Try to get standard directory symbol by id.
/// Try to get standard directory name by id.
/// </summary>
public static bool TryGetStandardDirectory(string directoryId, out DirectorySymbol symbol) => standardDirectoriesById.TryGetValue(directoryId, out symbol);
public static bool TryGetStandardDirectoryName(string directoryId, out string name)
{
return standardDirectoryNamesById.TryGetValue(directoryId, out name);
}
}
}
152 changes: 152 additions & 0 deletions src/api/wix/WixToolset.Data/WixStandardLibrary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// 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 WixToolset.Data
{
using System;
using System.Collections.Generic;
using System.Linq;
using WixToolset.Data.Bind;
using WixToolset.Data.Symbols;
using WixToolset.Data.WindowsInstaller;

/// <summary>
/// WiX Standard Library implementation.
/// </summary>
public static class WixStandardLibrary
{
private const string WixStandardLibraryId = "wixstd";

/// <summary>
/// Build the wixstd.wixlib Intermediate.
/// </summary>
/// <param name="platform">Target platform for the wixstd.wixlib</param>
/// <returns>Intermediate containing the wixstd.wixlib.</returns>
public static Intermediate Build(Platform platform)
{
var localizations = YieldLocalizations();

var sections = YieldSections(platform);

return new Intermediate(WixStandardLibraryId, IntermediateLevels.Combined, sections, localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase));
}

private static IEnumerable<Localization> YieldLocalizations()
{
var strings = new BindVariable[0];

var localizedControls = new LocalizedControl[0];

yield return new Localization(LocalizationLocation.Library, null, null, String.Empty, strings.ToDictionary(s => s.Id), localizedControls.ToDictionary(l => l.GetKey()));
}

private static IEnumerable<IntermediateSection> YieldSections(Platform platform)
{
var sourceLineNumber = new SourceLineNumber("wixstd.wixlib");

// Actions.
foreach (var actionSymbol in WindowsInstallerStandard.StandardActions())
{
var symbol = new WixActionSymbol(sourceLineNumber, new Identifier(actionSymbol.Id.Access, actionSymbol.Id.Id))
{
Action = actionSymbol.Action,
SequenceTable = actionSymbol.SequenceTable,
Sequence = actionSymbol.Sequence,
Condition = actionSymbol.Condition,
};

var section = CreateSectionAroundSymbol(symbol);

yield return section;
}

// Directories.
foreach (var id in WindowsInstallerStandard.StandardDirectoryIds())
{
var symbol = new DirectorySymbol(sourceLineNumber, new Identifier(AccessModifier.Virtual, id))
{
ParentDirectoryRef = GetStandardDirectoryParent(id, platform),
Name = WindowsInstallerStandard.TryGetStandardDirectoryName(id, out var name) ? name : throw new InvalidOperationException("Standard directories must have a default name")
};

var section = CreateSectionAroundSymbol(symbol);

// Add a reference for the more complicated parent directory references.
if (symbol.ParentDirectoryRef != null && symbol.ParentDirectoryRef != "TARGEDIR")
{
section.AddSymbol(new WixSimpleReferenceSymbol(sourceLineNumber)
{
Table = "Directory",
PrimaryKeys = symbol.ParentDirectoryRef
});
}

yield return section;
}

// Package References.
{
var section = CreateSection(WixStandardLibraryIdentifiers.WixStandardPackageReferences);

section.AddSymbol(new WixFragmentSymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardLibraryIdentifiers.WixStandardPackageReferences)));

section.AddSymbol(new WixSimpleReferenceSymbol(sourceLineNumber)
{
Table = SymbolDefinitions.Directory.Name,
PrimaryKeys = "TARGETDIR"
});

yield return section;
}

// Module References.
{
var section = CreateSection(WixStandardLibraryIdentifiers.WixStandardModuleReferences);

section.AddSymbol(new WixFragmentSymbol(sourceLineNumber, new Identifier(AccessModifier.Global, WixStandardLibraryIdentifiers.WixStandardModuleReferences)));

section.AddSymbol(new WixSimpleReferenceSymbol(sourceLineNumber)
{
Table = SymbolDefinitions.Directory.Name,
PrimaryKeys = "TARGETDIR"
});

yield return section;
}
}

private static IntermediateSection CreateSection(string sectionId)
{
return new IntermediateSection(sectionId, SectionType.Fragment, WixStandardLibraryId).AssignToLibrary(WixStandardLibraryId);
}

private static IntermediateSection CreateSectionAroundSymbol(IntermediateSymbol symbol)
{
var section = CreateSection(symbol.Id.Id);

section.AddSymbol(symbol);

return section;
}

private static string GetStandardDirectoryParent(string directoryId, Platform platform)
{
switch (directoryId)
{
case "TARGETDIR":
return null;

case "CommonFiles6432Folder":
return platform == Platform.X86 ? "CommonFilesFolder" : "CommonFiles64Folder";

case "ProgramFiles6432Folder":
return platform == Platform.X86 ? "ProgramFilesFolder" : "ProgramFiles64Folder";

case "System6432Folder":
return platform == Platform.X86 ? "SystemFolder" : "System64Folder";

default:
return "TARGETDIR";
}
}
}
}
20 changes: 20 additions & 0 deletions src/api/wix/WixToolset.Data/WixStandardLibraryIdentifiers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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 WixToolset.Data
{
/// <summary>
/// Well-known identifier names from the wixstd.wixlib.
/// </summary>
public static class WixStandardLibraryIdentifiers
{
/// <summary>
/// WiX Standard references for packages.
/// </summary>
public static readonly string WixStandardPackageReferences = "WixStandardPackageReferences";

/// <summary>
/// WiX Standard references for modules.
/// </summary>
public static readonly string WixStandardModuleReferences = "WixStandardModuleReferences";
}
}
10 changes: 10 additions & 0 deletions src/api/wix/WixToolset.Extensibility/Data/ILinkContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ public interface ILinkContext
/// </summary>
string OutputPath { get; set; }

/// <summary>
/// Gets or sets the platform for the output.
/// </summary>
Platform Platform { get; set; }

/// <summary>
/// Gets or sets whether to skip the standard wixlib.
/// </summary>
bool SkipStdWixlib { get; set; }

/// <summary>
/// Symbol definition creator used to load extension data.
/// </summary>
Expand Down
1 change: 0 additions & 1 deletion src/ext/UI/wixlib/WixUI_Minimal.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ Patch dialog sequence:

<InstallUISequence>
<Show Dialog="override WelcomeDlg" Before="WelcomeEulaDlg" Condition="Installed AND PATCH" />
<Show Dialog="override WelcomeEulaDlg" Before="ProgressDlg" Condition="NOT Installed" />
</InstallUISequence>

<Property Id="ARPNOMODIFY" Value="1" />
Expand Down
Loading

0 comments on commit eff9d42

Please sign in to comment.