// 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.Core
{
using System;
using System.IO;
using System.Xml.Linq;
using WixToolset.Data;
using WixToolset.Data.Tuples;
using WixToolset.Data.WindowsInstaller;
///
/// Compiler of the WiX toolset.
///
internal partial class Compiler : ICompiler
{
///
/// Parses an EmbeddedChaniner element.
///
/// Element to parse.
private void ParseEmbeddedChainerElement(XElement node)
{
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
Identifier id = null;
string commandLine = null;
string source = null;
var type = 0;
foreach (var attrib in node.Attributes())
{
if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
{
switch (attrib.Name.LocalName)
{
case "Id":
id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
break;
case "BinarySource":
if (null != source)
{
this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "FileSource", "PropertySource"));
}
source = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
type = 0x2;
this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", source); // add a reference to the appropriate Binary
break;
case "CommandLine":
commandLine = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
break;
case "FileSource":
if (null != source)
{
this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "BinarySource", "PropertySource"));
}
source = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
type = 0x12;
this.Core.CreateSimpleReference(sourceLineNumbers, "File", source); // add a reference to the appropriate File
break;
case "PropertySource":
if (null != source)
{
this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "BinarySource", "FileSource"));
}
source = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
type = 0x32;
// cannot add a reference to a Property because it may be created at runtime.
break;
default:
this.Core.UnexpectedAttribute(node, attrib);
break;
}
}
else
{
this.Core.ParseExtensionAttribute(node, attrib);
}
}
// Get the condition from the inner text of the element.
var condition = this.Core.GetConditionInnerText(node);
if (null == id)
{
id = this.Core.CreateIdentifier("mec", source, type.ToString());
}
if (null == source)
{
this.Core.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, node.Name.LocalName, "BinarySource", "FileSource", "PropertySource"));
}
if (!this.Core.EncounteredError)
{
var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiEmbeddedChainer, id);
row.Set(1, condition);
row.Set(2, commandLine);
row.Set(3, source);
row.Set(4, type);
}
}
///
/// Parses an EmbeddedUI element.
///
/// Element to parse.
private void ParseEmbeddedUIElement(XElement node)
{
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
Identifier id = null;
string name = null;
var supportsBasicUI = false;
var messageFilter = WindowsInstallerConstants.INSTALLLOGMODE_FATALEXIT | WindowsInstallerConstants.INSTALLLOGMODE_ERROR | WindowsInstallerConstants.INSTALLLOGMODE_WARNING | WindowsInstallerConstants.INSTALLLOGMODE_USER
| WindowsInstallerConstants.INSTALLLOGMODE_INFO | WindowsInstallerConstants.INSTALLLOGMODE_FILESINUSE | WindowsInstallerConstants.INSTALLLOGMODE_RESOLVESOURCE
| WindowsInstallerConstants.INSTALLLOGMODE_OUTOFDISKSPACE | WindowsInstallerConstants.INSTALLLOGMODE_ACTIONSTART | WindowsInstallerConstants.INSTALLLOGMODE_ACTIONDATA
| WindowsInstallerConstants.INSTALLLOGMODE_PROGRESS | WindowsInstallerConstants.INSTALLLOGMODE_COMMONDATA | WindowsInstallerConstants.INSTALLLOGMODE_INITIALIZE
| WindowsInstallerConstants.INSTALLLOGMODE_TERMINATE | WindowsInstallerConstants.INSTALLLOGMODE_SHOWDIALOG | WindowsInstallerConstants.INSTALLLOGMODE_RMFILESINUSE
| WindowsInstallerConstants.INSTALLLOGMODE_INSTALLSTART | WindowsInstallerConstants.INSTALLLOGMODE_INSTALLEND;
string sourceFile = null;
foreach (var attrib in node.Attributes())
{
if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
{
switch (attrib.Name.LocalName)
{
case "Id":
id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
break;
case "Name":
name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false);
break;
case "IgnoreFatalExit":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_FATALEXIT;
}
break;
case "IgnoreError":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_ERROR;
}
break;
case "IgnoreWarning":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_WARNING;
}
break;
case "IgnoreUser":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_USER;
}
break;
case "IgnoreInfo":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_INFO;
}
break;
case "IgnoreFilesInUse":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_FILESINUSE;
}
break;
case "IgnoreResolveSource":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_RESOLVESOURCE;
}
break;
case "IgnoreOutOfDiskSpace":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_OUTOFDISKSPACE;
}
break;
case "IgnoreActionStart":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_ACTIONSTART;
}
break;
case "IgnoreActionData":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_ACTIONDATA;
}
break;
case "IgnoreProgress":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_PROGRESS;
}
break;
case "IgnoreCommonData":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_COMMONDATA;
}
break;
case "IgnoreInitialize":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_INITIALIZE;
}
break;
case "IgnoreTerminate":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_TERMINATE;
}
break;
case "IgnoreShowDialog":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_SHOWDIALOG;
}
break;
case "IgnoreRMFilesInUse":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_RMFILESINUSE;
}
break;
case "IgnoreInstallStart":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_INSTALLSTART;
}
break;
case "IgnoreInstallEnd":
if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
{
messageFilter ^= WindowsInstallerConstants.INSTALLLOGMODE_INSTALLEND;
}
break;
case "SourceFile":
sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
break;
case "SupportBasicUI":
supportsBasicUI = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
break;
default:
this.Core.UnexpectedAttribute(node, attrib);
break;
}
}
else
{
this.Core.ParseExtensionAttribute(node, attrib);
}
}
if (String.IsNullOrEmpty(sourceFile))
{
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile"));
}
else if (String.IsNullOrEmpty(name))
{
name = Path.GetFileName(sourceFile);
if (!this.Core.IsValidLongFilename(name, false))
{
this.Core.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, node.Name.LocalName, "Source", name));
}
}
if (null == id)
{
if (!String.IsNullOrEmpty(name))
{
id = this.Core.CreateIdentifierFromFilename(name);
}
if (null == id)
{
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
}
else if (!Common.IsIdentifier(id.Id))
{
this.Core.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, node.Name.LocalName, "Id", id.Id));
}
}
else if (String.IsNullOrEmpty(name))
{
name = id.Id;
}
if (!name.Contains("."))
{
this.Core.Write(ErrorMessages.InvalidEmbeddedUIFileName(sourceLineNumbers, name));
}
foreach (var child in node.Elements())
{
if (CompilerCore.WixNamespace == child.Name.Namespace)
{
switch (child.Name.LocalName)
{
case "EmbeddedUIResource":
this.ParseEmbeddedUIResourceElement(child);
break;
default:
this.Core.UnexpectedElement(node, child);
break;
}
}
else
{
this.Core.ParseExtensionElement(node, child);
}
}
if (!this.Core.EncounteredError)
{
var tuple = new MsiEmbeddedUITuple(sourceLineNumbers, id)
{
FileName = name,
EntryPoint = true,
SupportsBasicUI = supportsBasicUI,
MessageFilter = messageFilter,
Source = sourceFile
};
this.Core.AddTuple(tuple);
}
}
///
/// Parses a embedded UI resource element.
///
/// Element to parse.
/// Identifier of parent EmbeddedUI element.
private void ParseEmbeddedUIResourceElement(XElement node)
{
var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
Identifier id = null;
string name = null;
string sourceFile = null;
foreach (var attrib in node.Attributes())
{
if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
{
switch (attrib.Name.LocalName)
{
case "Id":
id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
break;
case "Name":
name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false);
break;
case "SourceFile":
sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
break;
default:
this.Core.UnexpectedAttribute(node, attrib);
break;
}
}
else
{
this.Core.ParseExtensionAttribute(node, attrib);
}
}
if (String.IsNullOrEmpty(sourceFile))
{
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile"));
}
else if (String.IsNullOrEmpty(name))
{
name = Path.GetFileName(sourceFile);
if (!this.Core.IsValidLongFilename(name, false))
{
this.Core.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, node.Name.LocalName, "Source", name));
}
}
if (null == id)
{
if (!String.IsNullOrEmpty(name))
{
id = this.Core.CreateIdentifierFromFilename(name);
}
if (null == id)
{
this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
}
else if (!Common.IsIdentifier(id.Id))
{
this.Core.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, node.Name.LocalName, "Id", id.Id));
}
}
else if (String.IsNullOrEmpty(name))
{
name = id.Id;
}
this.Core.ParseForExtensionElements(node);
if (!this.Core.EncounteredError)
{
var tuple = new MsiEmbeddedUITuple(sourceLineNumbers, id)
{
FileName = name,
Source = sourceFile
};
this.Core.AddTuple(tuple);
}
}
}
}