IIsCompiler.cs :  » Installers-Generators » WiX » Microsoft » Tools » WindowsInstallerXml » Extensions » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Installers Generators » WiX 
WiX » Microsoft » Tools » WindowsInstallerXml » Extensions » IIsCompiler.cs
//-------------------------------------------------------------------------------------------------
// <copyright file="IIsCompiler.cs" company="Microsoft">
//    Copyright (c) Microsoft Corporation.  All rights reserved.
//    
//    The use and distribution terms for this software are covered by the
//    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
//    which can be found in the file CPL.TXT at the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by
//    the terms of this license.
//    
//    You must not remove this notice, or any other, from this software.
// </copyright>
// 
// <summary>
// The compiler for the Windows Installer XML Toolset Internet Information Services Extension.
// </summary>
//-------------------------------------------------------------------------------------------------

namespace Microsoft.Tools.WindowsInstallerXml.Extensions{
    using System;
    using System.Collections;
    using System.Globalization;
    using System.Reflection;
    using System.Xml;
    using System.Xml.Schema;

    /// <summary>
    /// The compiler for the Windows Installer XML Toolset Internet Information Services Extension.
    /// </summary>
    public sealed class IIsCompiler : CompilerExtension
    {
        private XmlSchema schema;

        /// <summary>
        /// Instantiate a new IIsCompiler.
        /// </summary>
        public IIsCompiler()
        {
            this.schema = LoadXmlSchemaHelper(Assembly.GetExecutingAssembly(), "Microsoft.Tools.WindowsInstallerXml.Extensions.Xsd.iis.xsd");
        }

        /// <summary>
        /// Types of objects that custom HTTP Headers can be applied to.
        /// </summary>
        /// <remarks>Note that this must be kept in sync with the eHttpHeaderParentType in scahttpheader.h.</remarks>
        private enum HttpHeaderParentType
        {
            /// <summary>Custom HTTP Header is to be applied to a Web Virtual Directory.</summary>
            WebVirtualDir = 1,
            /// <summary>Custom HTTP Header is to be applied to a Web Site.</summary>
            WebSite = 2,
        }

        /// <summary>
        /// Types of objects that MimeMaps can be applied to.
        /// </summary>
        /// <remarks>Note that this must be kept in sync with the eMimeMapParentType in scamimemap.h.</remarks>
        private enum MimeMapParentType
        {
            /// <summary>MimeMap is to be applied to a Web Virtual Directory.</summary>
            WebVirtualDir = 1,
            WebSite = 2,
        }

        /// <summary>
        /// Types of objects that custom WebErrors can be applied to.
        /// </summary>
        /// <remarks>Note that this must be kept in sync with the eWebErrorParentType in scaweberror.h.</remarks>
        private enum WebErrorParentType
        {
            /// <summary>Custom WebError is to be applied to a Web Virtual Directory.</summary>
            WebVirtualDir = 1,

            /// <summary>Custom WebError is to be applied to a Web Site.</summary>
            WebSite = 2,
        }

        /// <summary>
        /// Gets the schema for this extension.
        /// </summary>
        /// <value>Schema for this extension.</value>
        public override XmlSchema Schema
        {
            get { return this.schema; }
        }

        /// <summary>
        /// Processes an element for the Compiler.
        /// </summary>
        /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
        /// <param name="parentElement">Parent element of element to process.</param>
        /// <param name="element">Element to process.</param>
        /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
        public override void ParseElement(SourceLineNumberCollection sourceLineNumbers, XmlElement parentElement, XmlElement element, params string[] contextValues)
        {
            switch (parentElement.LocalName)
            {
                case "Component":
                    string componentId = contextValues[0];
                    string directoryId = contextValues[1];

                    switch (element.LocalName)
                    {
                        case "Certificate":
                            this.ParseCertificateElement(element, componentId);
                            break;
                        case "WebAppPool":
                            this.ParseWebAppPoolElement(element, componentId);
                            break;
                        case "WebDir":
                            this.ParseWebDirElement(element, componentId, null);
                            break;
                        case "WebFilter":
                            this.ParseWebFilterElement(element, componentId, null);
                            break;
                        case "WebProperty":
                            this.ParseWebPropertyElement(element, componentId);
                            break;
                        case "WebServiceExtension":
                            this.ParseWebServiceExtensionElement(element, componentId);
                            break;
                        case "WebSite":
                            this.ParseWebSiteElement(element, componentId);
                            break;
                        case "WebVirtualDir":
                            this.ParseWebVirtualDirElement(element, componentId, null, null);
                            break;
                        default:
                            this.Core.UnexpectedElement(parentElement, element);
                            break;
                    }
                    break;
                case "Fragment":
                case "Module":
                case "Product":
                    switch (element.LocalName)
                    {
                        case "WebApplication":
                            this.ParseWebApplicationElement(element);
                            break;
                        case "WebAppPool":
                            this.ParseWebAppPoolElement(element, null);
                            break;
                        case "WebDirProperties":
                            this.ParseWebDirPropertiesElement(element);
                            break;
                        case "WebLog":
                            this.ParseWebLogElement(element);
                            break;
                        case "WebSite":
                            this.ParseWebSiteElement(element, null);
                            break;
                        default:
                            this.Core.UnexpectedElement(parentElement, element);
                            break;
                    }
                    break;
                default:
                    this.Core.UnexpectedElement(parentElement, element);
                    break;
            }
        }

        /// <summary>
        /// Parses a certificate element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Identifier for parent component.</param>
        private void ParseCertificateElement(XmlNode node, string componentId)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            int attributes = 0;
            string binaryKey = null;
            string certificatePath = null;
            string name = null;
            string pfxPassword = null;
            int storeLocation = 0;
            string storeName = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "BinaryKey":
                            attributes |= 2; // SCA_CERT_ATTRIBUTE_BINARYDATA
                            binaryKey = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Binary", binaryKey);
                            break;
                        case "CertificatePath":
                            certificatePath = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Name":
                            name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Overwrite":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                attributes |= 4; // SCA_CERT_ATTRIBUTE_OVERWRITE
                            }
                            else
                            {
                                attributes &= ~4; // SCA_CERT_ATTRIBUTE_OVERWRITE
                            }
                            break;
                        case "PFXPassword":
                            pfxPassword = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Request":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                attributes |= 1; // SCA_CERT_ATTRIBUTE_REQUEST
                            }
                            else
                            {
                                attributes &= ~1; // SCA_CERT_ATTRIBUTE_REQUEST
                            }
                            break;
                        case "StoreLocation":
                            string storeLocationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < storeLocationValue.Length)
                            {
                                switch (storeLocationValue)
                                {
                                    case "currentUser":
                                        storeLocation = 1; // SCA_CERTSYSTEMSTORE_CURRENTUSER
                                        break;
                                    case "localMachine":
                                        storeLocation = 2; // SCA_CERTSYSTEMSTORE_LOCALMACHINE
                                        break;
                                    default:
                                        storeLocation = -1;
                                        this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, "StoreLocation", storeLocationValue, "currentUser", "localMachine"));
                                        break;
                                }
                            }
                            break;
                        case "StoreName":
                            string storeNameValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < storeNameValue.Length)
                            {
                                switch (storeNameValue)
                                {
                                    case "ca":
                                        storeName = "CA";
                                        break;
                                    case "my":
                                    case "personal":
                                        storeName = "MY";
                                        break;
                                    case "request":
                                        storeName = "REQUEST";
                                        break;
                                    case "root":
                                        storeName = "Root";
                                        break;
                                    case "otherPeople":
                                        storeName = "AddressBook";
                                        break;
                                    case "trustedPeople":
                                        storeName = "TrustedPeople";
                                        break;
                                    case "trustedPublisher":
                                        storeName = "TrustedPublisher";
                                        break;
                                    default:
                                        this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, "StoreName", storeNameValue, "ca", "my", "request", "root", "otherPeople", "trustedPeople", "trustedPublisher"));
                                        break;
                                }
                            }
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == name)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name"));
            }

            if (0 == storeLocation)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "StoreLocation"));
            }

            if (null == storeName)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "StoreName"));
            }

            if (null != binaryKey && null != certificatePath)
            {
                this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "BinaryKey", "CertificatePath", certificatePath));
            }
            else if (null == binaryKey && null == certificatePath)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttributes(sourceLineNumbers, node.Name, "BinaryKey", "CertificatePath"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            // Reference InstallCertificates and UninstallCertificates since nothing will happen without them
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "InstallCertificates");
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "UninstallCertificates");
            this.Core.EnsureTable(sourceLineNumbers, "CertificateHash"); // Certificate CustomActions require the CertificateHash table

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "Certificate");
                row[0] = id;
                row[1] = componentId;
                row[2] = name;
                row[3] = storeLocation;
                row[4] = storeName;
                row[5] = attributes;
                row[6] = binaryKey;
                row[7] = certificatePath;
                row[8] = pfxPassword;
            }
        }

        /// <summary>
        /// Parses a CertificateRef extension element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="webId">Identifier for parent web site.</param>
        private void ParseCertificateRefElement(XmlNode node, string webId)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Certificate", id);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Certificate", id);

                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebSiteCertificates");
                row[0] = webId;
                row[1] = id;
            }
        }

        /// <summary>
        /// Parses a mime map element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="parentId">Identifier for parent symbol.</param>
        /// <param name="parentType">Type that parentId refers to.</param>
        private void ParseMimeMapElement(XmlNode node, string parentId, MimeMapParentType parentType)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string extension = null;
            string type = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Extension":
                            extension = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Type":
                            type = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == extension)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Extension"));
            }
            else if (0 < extension.Length)
            {
                if (!extension.StartsWith(".", StringComparison.Ordinal))
                {
                    this.Core.OnMessage(IIsErrors.MimeMapExtensionMissingPeriod(sourceLineNumbers, node.Name, "Extension", extension));
                }
            }

            if (null == type)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Type"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsMimeMap");
                row[0] = id;
                row[1] = (int)parentType;
                row[2] = parentId;
                row[3] = type;
                row[4] = extension;
            }
        }

        /// <summary>
        /// Parses a recycle time element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <returns>Recycle time value.</returns>
        private string ParseRecycleTimeElement(XmlNode node)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string value = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Value":
                            value = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == value)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Value"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            return value;
        }

        /// <summary>
        /// Parses a web address element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="parentWeb">Identifier of parent web site.</param>
        /// <returns>Identifier for web address.</returns>
        private string ParseWebAddressElement(XmlNode node, string parentWeb)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string header = null;
            string ip = null;
            string port = null;
            bool secure = false;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Header":
                            header = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "IP":
                            ip = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Port":
                            port = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Secure":
                            secure = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == port)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Port"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebAddress");
                row[0] = id;
                row[1] = parentWeb;
                row[2] = ip;
                row[3] = port;
                row[4] = header;
                row[5] = secure ? 1 : 0;
            }

            return id;
        }

        /// <summary>
        /// Parses a web application element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <returns>Identifier for web application.</returns>
        private string ParseWebApplicationElement(XmlNode node)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            YesNoDefaultType allowSessions = YesNoDefaultType.Default;
            string appPool = null;
            YesNoDefaultType buffer = YesNoDefaultType.Default;
            YesNoDefaultType clientDebugging = YesNoDefaultType.Default;
            string defaultScript = null;
            int isolation = 0;
            string name = null;
            YesNoDefaultType parentPaths = YesNoDefaultType.Default;
            int scriptTimeout = CompilerCore.IntegerNotSet;
            int sessionTimeout = CompilerCore.IntegerNotSet;
            YesNoDefaultType serverDebugging = YesNoDefaultType.Default;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "AllowSessions":
                            allowSessions = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
                            break;
                        case "Buffer":
                            buffer = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
                            break;
                        case "ClientDebugging":
                            clientDebugging = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
                            break;
                        case "DefaultScript":
                            defaultScript = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < defaultScript.Length)
                            {
                                switch (defaultScript)
                                {
                                    case "JScript":
                                    case "VBScript":
                                        // these are valid values
                                        break;
                                    default:
                                        this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, attrib.Name, defaultScript, "JScript", "VBScript"));
                                        break;
                                }
                            }
                            break;
                        case "Isolation":
                            string isolationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < isolationValue.Length)
                            {
                                switch (isolationValue)
                                {
                                    case "low":
                                        isolation = 0;
                                        break;
                                    case "medium":
                                        isolation = 2;
                                        break;
                                    case "high":
                                        isolation = 1;
                                        break;
                                    default:
                                        this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, attrib.Name, isolationValue, "low", "medium", "high"));
                                        break;
                                }
                            }
                            break;
                        case "Name":
                            name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "ParentPaths":
                            parentPaths = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
                            break;
                        case "ScriptTimeout":
                            scriptTimeout = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "ServerDebugging":
                            serverDebugging = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
                            break;
                        case "SessionTimeout":
                            sessionTimeout = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "WebAppPool":
                            appPool = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsAppPool", appPool);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == name)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name"));
            }
            else if (-1 != name.IndexOf("\\", StringComparison.Ordinal))
            {
                this.Core.OnMessage(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, node.Name, "Name", name, '\\'));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        switch (child.LocalName)
                        {
                            case "WebApplicationExtension":
                                this.ParseWebApplicationExtensionElement(child, id);
                                break;
                            default:
                                this.Core.UnexpectedElement(node, child);
                                break;
                        }
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebApplication");
                row[0] = id;
                row[1] = name;
                row[2] = isolation;
                if (YesNoDefaultType.Default != allowSessions)
                {
                    row[3] = YesNoDefaultType.Yes == allowSessions ? 1 : 0;
                }

                if (CompilerCore.IntegerNotSet != sessionTimeout)
                {
                    row[4] = sessionTimeout;
                }

                if (YesNoDefaultType.Default != buffer)
                {
                    row[5] = YesNoDefaultType.Yes == buffer ? 1 : 0;
                }

                if (YesNoDefaultType.Default != parentPaths)
                {
                    row[6] = YesNoDefaultType.Yes == parentPaths ? 1 : 0;
                }
                row[7] = defaultScript;
                if (CompilerCore.IntegerNotSet != scriptTimeout)
                {
                    row[8] = scriptTimeout;
                }

                if (YesNoDefaultType.Default != serverDebugging)
                {
                    row[9] = YesNoDefaultType.Yes == serverDebugging ? 1 : 0;
                }

                if (YesNoDefaultType.Default != clientDebugging)
                {
                    row[10] = YesNoDefaultType.Yes == clientDebugging ? 1 : 0;
                }
                row[11] = appPool;
            }

            return id;
        }

        /// <summary>
        /// Parses a web application extension element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="application">Identifier for parent web application.</param>
        private void ParseWebApplicationExtensionElement(XmlNode node, string application)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            int attributes = 0;
            string executable = null;
            string extension = null;
            string verbs = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "CheckPath":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                attributes |= 4;
                            }
                            else
                            {
                                attributes &= ~4;
                            }
                            break;
                        case "Executable":
                            executable = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Extension":
                            extension = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Script":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                attributes |= 1;
                            }
                            else
                            {
                                attributes &= ~1;
                            }
                            break;
                        case "Verbs":
                            verbs = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebApplicationExtension");
                row[0] = application;
                row[1] = extension;
                row[2] = verbs;
                row[3] = executable;
                if (0 < attributes)
                {
                    row[4] = attributes;
                }
            }
        }

        /// <summary>
        /// Parses web application pool element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Optional identifier of parent component.</param>
        private void ParseWebAppPoolElement(XmlNode node, string componentId)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            int attributes = 0;
            int cpuAction = CompilerCore.IntegerNotSet;
            string cpuMon = null;
            int idleTimeout = CompilerCore.IntegerNotSet;
            int maxCpuUsage = 0;
            int maxWorkerProcs = CompilerCore.IntegerNotSet;
            string name = null;
            int privateMemory = CompilerCore.IntegerNotSet;
            int queueLimit = CompilerCore.IntegerNotSet;
            int recycleMinutes = CompilerCore.IntegerNotSet;
            int recycleRequests = CompilerCore.IntegerNotSet;
            string recycleTimes = null;
            int refreshCpu = CompilerCore.IntegerNotSet;
            string user = null;
            int virtualMemory = CompilerCore.IntegerNotSet;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "CpuAction":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            string cpuActionValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < cpuActionValue.Length)
                            {
                                switch (cpuActionValue)
                                {
                                    case "shutdown":
                                        cpuAction = 1;
                                        break;
                                    case "none":
                                        cpuAction = 0;
                                        break;
                                    default:
                                        this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, attrib.Name, cpuActionValue, "shutdown", "none"));
                                        break;
                                }
                            }
                            break;
                        case "Identity":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            string identityValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < identityValue.Length)
                            {
                                switch (identityValue)
                                {
                                    case "networkService":
                                        attributes = 1;
                                        break;
                                    case "localService":
                                        attributes = 2;
                                        break;
                                    case "localSystem":
                                        attributes = 4;
                                        break;
                                    case "other":
                                        attributes = 8;
                                        break;
                                    default:
                                        this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, attrib.Name, identityValue, "networkService", "localService", "localSystem", "other"));
                                        break;
                                }
                            }
                            break;
                        case "IdleTimeout":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            idleTimeout = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "MaxCpuUsage":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            maxCpuUsage = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 100);
                            break;
                        case "MaxWorkerProcesses":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            maxWorkerProcs = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "Name":
                            name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "PrivateMemory":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            privateMemory = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
                            break;
                        case "QueueLimit":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            queueLimit = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "RecycleMinutes":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            recycleMinutes = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "RecycleRequests":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            recycleRequests = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "RefreshCpu":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            refreshCpu = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
                            break;
                        case "User":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            user = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "User", user);
                            break;
                        case "VirtualMemory":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            virtualMemory = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == name)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name"));
            }

            if (null == user && 8 == attributes)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "User", "Identity", "other"));
            }

            if (null != user && 8 != attributes)
            {
                this.Core.OnMessage(WixErrors.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, node.Name, "User", user, "Identity", "other"));
            }

            cpuMon = maxCpuUsage.ToString(CultureInfo.InvariantCulture.NumberFormat);
            if (CompilerCore.IntegerNotSet != refreshCpu)
            {
                cpuMon = String.Concat(cpuMon, ",", refreshCpu.ToString(CultureInfo.InvariantCulture.NumberFormat));
                if (CompilerCore.IntegerNotSet != cpuAction)
                {
                    cpuMon = String.Concat(cpuMon, ",", cpuAction.ToString(CultureInfo.InvariantCulture.NumberFormat));
                }
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        switch (child.LocalName)
                        {
                            case "RecycleTime":
                                if (null == componentId)
                                {
                                    SourceLineNumberCollection childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, node.Name));
                                }

                                if (null == recycleTimes)
                                {
                                    recycleTimes = this.ParseRecycleTimeElement(child);
                                }
                                else
                                {
                                    recycleTimes = String.Concat(recycleTimes, ",", this.ParseRecycleTimeElement(child));
                                }
                                break;
                            default:
                                this.Core.UnexpectedElement(node, child);
                                break;
                        }
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (null != componentId)
            {
                // Reference ConfigureIIs since nothing will happen without it
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsAppPool");
                row[0] = id;
                row[1] = name;
                row[2] = componentId;
                row[3] = attributes;
                row[4] = user;
                if (CompilerCore.IntegerNotSet != recycleMinutes)
                {
                    row[5] = recycleMinutes;
                }

                if (CompilerCore.IntegerNotSet != recycleRequests)
                {
                    row[6] = recycleRequests;
                }
                row[7] = recycleTimes;
                if (CompilerCore.IntegerNotSet != idleTimeout)
                {
                    row[8] = idleTimeout;
                }

                if (CompilerCore.IntegerNotSet != queueLimit)
                {
                    row[9] = queueLimit;
                }
                row[10] = cpuMon;
                if (CompilerCore.IntegerNotSet != maxWorkerProcs)
                {
                    row[11] = maxWorkerProcs;
                }

                if (CompilerCore.IntegerNotSet != virtualMemory)
                {
                    row[12] = virtualMemory;
                }

                if (CompilerCore.IntegerNotSet != privateMemory)
                {
                    row[13] = privateMemory;
                }
            }
        }

        /// <summary>
        /// Parses a web directory element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Identifier for parent component.</param>
        /// <param name="parentWeb">Optional identifier for parent web site.</param>
        private void ParseWebDirElement(XmlNode node, string componentId, string parentWeb)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string dirProperties = null;
            string path = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "DirProperties":
                            dirProperties = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Path":
                            path = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "WebSite":
                            if (null != parentWeb)
                            {
                                this.Core.OnMessage(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, node.Name));
                            }

                            parentWeb = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebSite", parentWeb);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == path)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Path"));
            }

            if (null == parentWeb)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "WebSite"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        SourceLineNumberCollection childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);

                        switch (child.LocalName)
                        {
                            case "WebDirProperties":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                string childWebDirProperties = this.ParseWebDirPropertiesElement(child);
                                if (null == dirProperties)
                                {
                                    dirProperties = childWebDirProperties;
                                }
                                else
                                {
                                    this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, child.LocalName, "DirProperties", node.LocalName));
                                }
                                break;
                            default:
                                this.Core.UnexpectedElement(node, child);
                                break;
                        }
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (null == dirProperties)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "DirProperties"));
            }

            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebDirProperties", dirProperties);

            // Reference ConfigureIIs since nothing will happen without it
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebDir");
                row[0] = id;
                row[1] = componentId;
                row[2] = parentWeb;
                row[3] = path;
                row[4] = dirProperties;
                row[5] = null; // TODO: why isn't there a way to supply this value?
            }
        }

        /// <summary>
        /// Parses a web directory properties element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <returns>The identifier for this WebDirProperties.</returns>
        private string ParseWebDirPropertiesElement(XmlNode node)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            int access = 0;
            bool accessSet = false;
            int accessSSLFlags = 0;
            bool accessSSLFlagsSet = false;
            string anonymousUser = null;
            YesNoType aspDetailedError = YesNoType.NotSet;
            string authenticationProviders = null;
            int authorization = 0;
            bool authorizationSet = false;
            string cacheControlCustom = null;
            long cacheControlMaxAge = CompilerCore.LongNotSet;
            string defaultDocuments = null;
            string httpExpires = null;
            bool iisControlledPassword = false;
            YesNoType index = YesNoType.NotSet;
            YesNoType logVisits = YesNoType.NotSet;
            YesNoType notCustomError = YesNoType.NotSet;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "AnonymousUser":
                            anonymousUser = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "User", anonymousUser);
                            break;
                        case "AspDetailedError":
                            aspDetailedError = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        case "AuthenticationProviders":
                            authenticationProviders = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "CacheControlCustom":
                            cacheControlCustom = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "CacheControlMaxAge":
                            cacheControlMaxAge = this.Core.GetAttributeLongValue(sourceLineNumbers, attrib, 0, uint.MaxValue); // 4294967295 (uint.MaxValue) represents unlimited
                            break;
                        case "ClearCustomError":
                            notCustomError = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        case "DefaultDocuments":
                            defaultDocuments = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "HttpExpires":
                            httpExpires = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "IIsControlledPassword":
                            iisControlledPassword = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        case "Index":
                            index = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        case "LogVisits":
                            logVisits = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;

                        // Access attributes
                        case "Execute":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                access |= 4;
                            }
                            else
                            {
                                access &= ~4;
                            }
                            accessSet = true;
                            break;
                        case "Read":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                access |= 1;
                            }
                            else
                            {
                                access &= ~1;
                            }
                            accessSet = true;
                            break;
                        case "Script":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                access |= 512;
                            }
                            else
                            {
                                access &= ~512;
                            }
                            accessSet = true;
                            break;
                        case "Write":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                access |= 2;
                            }
                            else
                            {
                                access &= ~2;
                            }
                            accessSet = true;
                            break;

                        // AccessSSL Attributes
                        case "AccessSSL":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                accessSSLFlags |= 8;
                            }
                            else
                            {
                                accessSSLFlags &= ~8;
                            }
                            accessSSLFlagsSet = true;
                            break;
                        case "AccessSSL128":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                accessSSLFlags |= 256;
                            }
                            else
                            {
                                accessSSLFlags &= ~256;
                            }
                            accessSSLFlagsSet = true;
                            break;
                        case "AccessSSLMapCert":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                accessSSLFlags |= 128;
                            }
                            else
                            {
                                accessSSLFlags &= ~128;
                            }
                            accessSSLFlagsSet = true;
                            break;
                        case "AccessSSLNegotiateCert":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                accessSSLFlags |= 32;
                            }
                            else
                            {
                                accessSSLFlags &= ~32;
                            }
                            accessSSLFlagsSet = true;
                            break;
                        case "AccessSSLRequireCert":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                accessSSLFlags |= 64;
                            }
                            else
                            {
                                accessSSLFlags &= ~64;
                            }
                            accessSSLFlagsSet = true;
                            break;

                        // Authorization attributes
                        case "AnonymousAccess":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                authorization |= 1;
                            }
                            else
                            {
                                authorization &= ~1;
                            }
                            authorizationSet = true;
                            break;
                        case "BasicAuthentication":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                authorization |= 2;
                            }
                            else
                            {
                                authorization &= ~2;
                            }
                            authorizationSet = true;
                            break;
                        case "DigestAuthentication":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                authorization |= 16;
                            }
                            else
                            {
                                authorization &= ~16;
                            }
                            authorizationSet = true;
                            break;
                        case "PassportAuthentication":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                authorization |= 64;
                            }
                            else
                            {
                                authorization &= ~64;
                            }
                            authorizationSet = true;
                            break;
                        case "WindowsAuthentication":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                authorization |= 4;
                            }
                            else
                            {
                                authorization &= ~4;
                            }
                            authorizationSet = true;
                            break;

                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebDirProperties");
                row[0] = id;
                if (accessSet)
                {
                    row[1] = access;
                }

                if (authorizationSet)
                {
                    row[2] = authorization;
                }
                row[3] = anonymousUser;
                row[4] = iisControlledPassword ? 1 : 0;
                if (YesNoType.NotSet != logVisits)
                {
                    row[5] = YesNoType.Yes == logVisits ? 1 : 0;
                }

                if (YesNoType.NotSet != index)
                {
                    row[6] = YesNoType.Yes == index ? 1 : 0;
                }
                row[7] = defaultDocuments;
                if (YesNoType.NotSet != aspDetailedError)
                {
                    row[8] = YesNoType.Yes == aspDetailedError ? 1 : 0;
                }
                row[9] = httpExpires;
                if (CompilerCore.LongNotSet != cacheControlMaxAge)
                {
                    row[10] = unchecked((int)cacheControlMaxAge);
                }
                row[11] = cacheControlCustom;
                if (YesNoType.NotSet != notCustomError)
                {
                    row[12] = YesNoType.Yes == notCustomError ? 1 : 0;
                }

                if (accessSSLFlagsSet)
                {
                    row[13] = accessSSLFlags;
                }

                if (null != authenticationProviders)
                {
                    row[14] = authenticationProviders;
                }
            }

            return id;
        }

        /// <summary>
        /// Parses a web error element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="parentType">Type of the parent.</param>
        /// <param name="parent">Id of the parent.</param>
        private void ParseWebErrorElement(XmlNode node, WebErrorParentType parentType, string parent)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            int errorCode = CompilerCore.IntegerNotSet;
            string file = null;
            string url = null;
            int subCode = CompilerCore.IntegerNotSet;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "ErrorCode":
                            errorCode = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 400, 599);
                            break;
                        case "File":
                            file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "SubCode":
                            subCode = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
                            break;
                        case "URL":
                            url = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (CompilerCore.IntegerNotSet == errorCode)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "ErrorCode"));
                errorCode = CompilerCore.IllegalInteger;
            }

            if (CompilerCore.IntegerNotSet == subCode)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "SubCode"));
                subCode = CompilerCore.IllegalInteger;
            }

            if (null != file && null != url)
            {
                this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "File", "URL"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            // Reference ConfigureIIs since nothing will happen without it
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebError");
                row[0] = errorCode;
                row[1] = subCode;
                row[2] = (int)parentType;
                row[3] = parent;
                row[4] = file;
                row[5] = url;
            }
        }

        /// <summary>
        /// Parses a web filter element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Identifier of parent component.</param>
        /// <param name="parentWeb">Optional identifier of parent web site.</param>
        private void ParseWebFilterElement(XmlNode node, string componentId, string parentWeb)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string description = null;
            int flags = 0;
            int loadOrder = CompilerCore.IntegerNotSet;
            string name = null;
            string path = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Description":
                            description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Flags":
                            flags = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
                            break;
                        case "LoadOrder":
                            string loadOrderValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < loadOrderValue.Length)
                            {
                                switch (loadOrderValue)
                                {
                                    case "first":
                                        loadOrder = 0;
                                        break;
                                    case "last":
                                        loadOrder = -1;
                                        break;
                                    default:
                                        loadOrder = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
                                        break;
                                }
                            }
                            break;
                        case "Name":
                            name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Path":
                            path = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "WebSite":
                            if (null != parentWeb)
                            {
                                this.Core.OnMessage(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, node.Name));
                            }

                            parentWeb = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebSite", parentWeb);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == name)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name"));
            }

            if (null == path)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Path"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            // Reference ConfigureIIs since nothing will happen without it
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsFilter");
                row[0] = id;
                row[1] = name;
                row[2] = componentId;
                row[3] = path;
                row[4] = parentWeb;
                row[5] = description;
                row[6] = flags;
                if (CompilerCore.IntegerNotSet != loadOrder)
                {
                    row[7] = loadOrder;
                }
            }
        }

        /// <summary>
        /// Parses web log element.
        /// </summary>
        /// <param name="node">Node to be parsed.</param>
        private void ParseWebLogElement(XmlNode node)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string type = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Type":
                            string typeValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (0 < typeValue.Length)
                            {
                                switch (typeValue)
                                {
                                    case "IIS":
                                        type = "Microsoft IIS Log File Format";
                                        break;
                                    case "NCSA":
                                        type = "NCSA Common Log File Format";
                                        break;
                                    case "none":
                                        type = "none";
                                        break;
                                    case "ODBC":
                                        type = "ODBC Logging";
                                        break;
                                    case "W3C":
                                        type = "W3C Extended Log File Format";
                                        break;
                                    default:
                                        this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, "Type", typeValue, "IIS", "NCSA", "none", "ODBC", "W3C"));
                                        break;
                                }
                            }
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == type)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Type"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebLog");
                row[0] = id;
                row[1] = type;
            }
        }

        /// <summary>
        /// Parses a web property element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Identifier for parent component.</param>
        private void ParseWebPropertyElement(XmlNode node, string componentId)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string value = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Value":
                            value = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            switch (id)
            {
                case "ETagChangeNumber":
                case "MaxGlobalBandwidth":
                    // Must specify a value for these
                    if (null == value)
                    {
                        this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Value", "Id", id));
                    }
                    break;
                case "IIs5IsolationMode":
                case "LogInUTF8":
                    // Can't specify a value for these
                    if (null != value)
                    {
                        this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Value", "Id", id));
                    }
                    break;
                default:
                    this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, "Id", id, "ETagChangeNumber", "IIs5IsolationMode", "LogInUTF8", "MaxGlobalBandwidth"));
                    break;
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            // Reference ConfigureIIs since nothing will happen without it
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsProperty");
                row[0] = id;
                row[1] = componentId;
                row[2] = 0;
                row[3] = value;
            }
        }

        /// <summary>
        /// Parses a web service extension element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Identifier for parent component.</param>
        private void ParseWebServiceExtensionElement(XmlNode node, string componentId)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            int attributes = 0;
            string description = null;
            string file = null;
            string group = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Allow":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                attributes |= 1;
                            }
                            else
                            {
                                attributes &= ~1;
                            }
                            break;
                        case "Description":
                            description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "File":
                            file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Group":
                            group = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "UIDeletable":
                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                attributes |= 2;
                            }
                            else
                            {
                                attributes &= ~2;
                            }
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == file)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "File"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        this.Core.UnexpectedElement(node, child);
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            // Reference ConfigureIIs since nothing will happen without it
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebServiceExtension");
                row[0] = id;
                row[1] = componentId;
                row[2] = file;
                row[3] = description;
                row[4] = group;
                row[5] = attributes;
            }
        }

        /// <summary>
        /// Parses a web site element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Optional identifier of parent component.</param>
        private void ParseWebSiteElement(XmlNode node, string componentId)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string application = null;
            int attributes = 0;
            int connectionTimeout = CompilerCore.IntegerNotSet;
            string description = null;
            string directory = null;
            string dirProperties = null;
            string keyAddress = null;
            string log = null;
            string siteId = null;
            int sequence = CompilerCore.IntegerNotSet;
            int state = CompilerCore.IntegerNotSet;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "AutoStart":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                state = 2;
                            }
                            else if (state != 1)
                            {
                                state = 0;
                            }
                            break;
                        case "ConfigureIfExists":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                attributes &= ~2;
                            }
                            else
                            {
                                attributes |= 2;
                            }
                            break;
                        case "ConnectionTimeout":
                            connectionTimeout = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "Description":
                            description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Directory":
                            directory = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Directory", directory);
                            break;
                        case "DirProperties":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            dirProperties = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "SiteId":
                            siteId = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            if ("*" == siteId)
                            {
                                siteId = "-1";
                            }
                            break;
                        case "Sequence":
                            sequence = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
                            break;
                        case "StartOnInstall":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            // when state is set to 2 it implies 1, so don't set it to 1
                            if (2 != state && YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                            {
                                state = 1;
                            }
                            else if (2 != state)
                            {
                                state = 0;
                            }
                            break;
                        case "WebApplication":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            application = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "WebLog":
                            if (null == componentId)
                            {
                                this.Core.OnMessage(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name, attrib.Name));
                            }

                            log = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebLog", log);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == description)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Description"));
            }

            if (null == directory && null != componentId)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Directory"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        SourceLineNumberCollection childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);
                        switch (child.LocalName)
                        {
                            case "CertificateRef":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                this.ParseCertificateRefElement(child, id);
                                break;
                            case "HttpHeader":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                this.ParseHttpHeaderElement(child, HttpHeaderParentType.WebSite, id);
                                break;
                            case "WebAddress":
                                string address = this.ParseWebAddressElement(child, id);
                                if (null == keyAddress)
                                {
                                    keyAddress = address;
                                }
                                break;
                            case "WebApplication":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                if (null != application)
                                {
                                    this.Core.OnMessage(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, node.Name));
                                }

                                application = this.ParseWebApplicationElement(child);
                                break;
                            case "WebDir":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                this.ParseWebDirElement(child, componentId, id);
                                break;
                            case "WebDirProperties":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                string childWebDirProperties = this.ParseWebDirPropertiesElement(child);
                                if (null == dirProperties)
                                {
                                    dirProperties = childWebDirProperties;
                                }
                                else
                                {
                                    this.Core.OnMessage(WixErrors.IllegalParentAttributeWhenNested(sourceLineNumbers, "WebSite", "DirProperties", child.LocalName));
                                }
                                break;
                            case "WebError":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                this.ParseWebErrorElement(child, WebErrorParentType.WebSite, id);
                                break;
                            case "WebFilter":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                this.ParseWebFilterElement(child, componentId, id);
                                break;
                            case "WebVirtualDir":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                this.ParseWebVirtualDirElement(child, componentId, id, null);
                                break;
                            case "MimeMap":
                                this.ParseMimeMapElement(child, id, MimeMapParentType.WebSite);
                                break;
                            default:
                                this.Core.UnexpectedElement(node, child);
                                break;
                        }
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (null == keyAddress)
            {
                this.Core.OnMessage(WixErrors.ExpectedElement(sourceLineNumbers, node.Name, "WebAddress"));
            }

            if (null != application)
            {
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebApplication", application);
            }

            if (null != dirProperties)
            {
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebDirProperties", dirProperties);
            }

            if (null != componentId)
            {
                // Reference ConfigureIIs since nothing will happen without it
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");
            }

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebSite");
                row[0] = id;
                row[1] = componentId;
                row[2] = description;
                if (CompilerCore.IntegerNotSet != connectionTimeout)
                {
                    row[3] = connectionTimeout;
                }
                row[4] = directory;
                if (CompilerCore.IntegerNotSet != state)
                {
                    row[5] = state;
                }

                if (0 != attributes)
                {
                    row[6] = attributes;
                }
                row[7] = keyAddress;
                row[8] = dirProperties;
                row[9] = application;
                if (CompilerCore.IntegerNotSet != sequence)
                {
                    row[10] = sequence;
                }
                row[11] = log;
                row[12] = siteId;
            }
        }

        /// <summary>
        /// Parses a HTTP Header element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="parentType">Type of the parent.</param>
        /// <param name="parent">Id of the parent.</param>
        private void ParseHttpHeaderElement(XmlNode node, HttpHeaderParentType parentType, string parent)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string headerName = null;
            string headerValue = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                switch (attrib.LocalName)
                {
                    case "Id":
                        id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                        break;
                    case "Name":
                        headerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                        break;
                    case "Value":
                        headerValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                        break;
                    default:
                        this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                        break;
                }
            }

            if (null == headerName)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Name"));
            }
            else if (null == id)
            {
                id = CompilerCore.GetIdentifierFromName(headerName);
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    this.Core.UnexpectedElement(node, child);
                }
            }

            // Reference ConfigureIIs since nothing will happen without it
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");

            Row row = this.Core.CreateRow(sourceLineNumbers, "IIsHttpHeader");
            row[0] = id;
            row[1] = (int)parentType;
            row[2] = parent;
            row[3] = headerName;
            row[4] = headerValue;
            row[5] = 0;
            row[6] = null;
        }

        /// <summary>
        /// Parses a virtual directory element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Identifier of parent component.</param>
        /// <param name="parentWeb">Identifier of parent web site.</param>
        /// <param name="parentAlias">Alias of the parent web site.</param>
        private void ParseWebVirtualDirElement(XmlNode node, string componentId, string parentWeb, string parentAlias)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string alias = null;
            string application = null;
            string directory = null;
            string dirProperties = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Id":
                            id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            break;
                        case "Alias":
                            alias = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Directory":
                            directory = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Directory", directory);
                            break;
                        case "DirProperties":
                            dirProperties = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "WebApplication":
                            application = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "WebSite":
                            if (null != parentWeb)
                            {
                                this.Core.OnMessage(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, node.Name));
                            }

                            parentWeb = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebSite", parentWeb);
                            break;
                        default:
                            this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                            break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            if (null == id)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Id"));
            }

            if (null == alias)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Alias"));
            }
            else if (-1 != alias.IndexOf("\\", StringComparison.Ordinal))
            {
                this.Core.OnMessage(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, node.Name, "Alias", alias, '\\'));
            }

            if (null == directory)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Directory"));
            }

            if (null == parentWeb)
            {
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "WebSite"));
            }

            if (null == componentId)
            {
                this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(sourceLineNumbers, node.Name));
            }

            if (null != parentAlias)
            {
                alias = String.Concat(parentAlias, "/", alias);
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        SourceLineNumberCollection childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);
                        switch (child.LocalName)
                        {
                            case "WebApplication":
                                if (null != application)
                                {
                                    this.Core.OnMessage(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, node.Name));
                                }

                                application = this.ParseWebApplicationElement(child);
                                break;
                            case "WebDirProperties":
                                if (null == componentId)
                                {
                                    this.Core.OnMessage(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name));
                                }

                                string childWebDirProperties = this.ParseWebDirPropertiesElement(child);
                                if (null == dirProperties)
                                {
                                    dirProperties = childWebDirProperties;
                                }
                                else
                                {
                                    this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, child.LocalName, "DirProperties", node.LocalName));
                                }
                                break;

                            case "WebError":
                                this.ParseWebErrorElement(child, WebErrorParentType.WebVirtualDir, id);
                                break;
                            case "WebVirtualDir":
                                this.ParseWebVirtualDirElement(child, componentId, parentWeb, alias);
                                break;
                            case "HttpHeader":
                                this.ParseHttpHeaderElement(child, HttpHeaderParentType.WebVirtualDir, id);
                                break;
                            case "MimeMap":
                                this.ParseMimeMapElement(child, id, MimeMapParentType.WebVirtualDir);
                                break;
                            default:
                                this.Core.UnexpectedElement(node, child);
                                break;
                        }
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (null != dirProperties)
            {
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebDirProperties", dirProperties);
            }

            if (null != application)
            {
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "IIsWebApplication", application);
            }

            // Reference ConfigureIIs since nothing will happen without it
            this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "ConfigureIIs");

            if (!this.Core.EncounteredError)
            {
                Row row = this.Core.CreateRow(sourceLineNumbers, "IIsWebVirtualDir");
                row[0] = id;
                row[1] = componentId;
                row[2] = parentWeb;
                row[3] = alias;
                row[4] = directory;
                row[5] = dirProperties;
                row[6] = application;
            }
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.