// 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.DifxApp { using System; using System.Collections.Generic; using System.Xml.Linq; using WixToolset.Data; using WixToolset.DifxApp.Symbols; using WixToolset.Extensibility; /// /// The compiler for the WiX Toolset Driver Install Frameworks for Applications Extension. /// public sealed class DifxAppCompiler : BaseCompilerExtension { private HashSet components; public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/difxapp"; /// /// Instantiate a new DifxAppCompiler. /// public DifxAppCompiler() { this.components = new HashSet(); } /// /// Processes an element for the Compiler. /// /// Source line number for the parent element. /// Parent element of element to process. /// Element to process. /// Extra information about the context in which this element is being parsed. public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) { switch (parentElement.Name.LocalName) { case "Component": var componentId = context["ComponentId"]; var componentWin64 = Boolean.Parse(context["Win64"]); switch (element.Name.LocalName) { case "Driver": this.ParseDriverElement(intermediate, section, element, componentId, componentWin64); break; default: this.ParseHelper.UnexpectedElement(parentElement, element); break; } break; default: this.ParseHelper.UnexpectedElement(parentElement, element); break; } } /// /// Parses a Driver element. /// /// Element to parse. /// Identifier for parent component. private void ParseDriverElement(Intermediate intermediate, IntermediateSection section, XElement node, string componentId, bool win64) { var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); int attributes = 0; var sequence = CompilerConstants.IntegerNotSet; // See https://github.com/wixtoolset/issues/issues/6648. DifxApp is deprecated so warn the user. this.Messaging.Write(WarningMessages.DeprecatedElement(sourceLineNumbers, node.Name.LocalName)); // check the number of times a Driver element has been nested under this Component element if (null != componentId) { if (this.components.Contains(componentId)) { this.Messaging.Write(ErrorMessages.TooManyElements(sourceLineNumbers, "Component", node.Name.LocalName, 1)); } else { this.components.Add(componentId); } } foreach (var attrib in node.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) { switch (attrib.Name.LocalName) { case "AddRemovePrograms": if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { attributes |= 0x4; } break; case "DeleteFiles": if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { attributes |= 0x10; } break; case "ForceInstall": if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { attributes |= 0x1; } break; case "Legacy": if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { attributes |= 0x8; } break; case "PlugAndPlayPrompt": if (YesNoType.No == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { attributes |= 0x2; } break; case "Sequence": sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue); break; default: this.ParseHelper.UnexpectedAttribute(node, attrib); break; } } else { this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); } } this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); if (!this.Messaging.EncounteredError) { this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, "MsiProcessDrivers"); var symbol = section.AddSymbol(new MsiDriverPackagesSymbol(sourceLineNumbers) { ComponentRef = componentId, Flags = attributes, }); if (CompilerConstants.IntegerNotSet != sequence) { symbol.Sequence = sequence; } } } } }