/// <summary>
 /// Creates a PayloadInfoRow row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this Media row belongs to and should get its column definitions from.</param>
 public PayloadInfoRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
Example #2
0
        /// <summary>
        /// Unbind an MSI database file.
        /// </summary>
        /// <param name="databaseFile">The database file.</param>
        /// <param name="database">The opened database.</param>
        /// <param name="outputType">The type of output to create.</param>
        /// <param name="exportBasePath">The path where files should be exported.</param>
        /// <param name="skipSummaryInfo">Option to skip unbinding the _SummaryInformation table.</param>
        /// <returns>The output representing the database.</returns>
        private Output UnbindDatabase(string databaseFile, Database database, OutputType outputType, string exportBasePath, bool skipSummaryInfo)
        {
            string modularizationGuid = null;
            Output output = new Output(SourceLineNumberCollection.FromFileName(databaseFile));
            View validationView = null;

            // set the output type
            output.Type = outputType;

            // get the codepage
            database.Export("_ForceCodepage", this.TempFilesLocation, "_ForceCodepage.idt");
            using (StreamReader sr = File.OpenText(Path.Combine(this.TempFilesLocation, "_ForceCodepage.idt")))
            {
                string line;

                while (null != (line = sr.ReadLine()))
                {
                    string[] data = line.Split('\t');

                    if (2 == data.Length)
                    {
                        output.Codepage = Convert.ToInt32(data[0], CultureInfo.InvariantCulture);
                    }
                }
            }

            // get the summary information table if it exists; it won't if unbinding a transform
            if (!skipSummaryInfo)
            {
                using (SummaryInformation summaryInformation = new SummaryInformation(database))
                {
                    Table table = new Table(null, this.tableDefinitions["_SummaryInformation"]);

                    for (int i = 1; 19 >= i; i++)
                    {
                        string value = summaryInformation.GetProperty(i);

                        if (0 < value.Length)
                        {
                            Row row = table.CreateRow(output.SourceLineNumbers);
                            row[0] = i;
                            row[1] = value;
                        }
                    }

                    output.Tables.Add(table);
                }
            }

            try
            {
                // open a view on the validation table if it exists
                if (database.TableExists("_Validation"))
                {
                    validationView = database.OpenView("SELECT * FROM `_Validation` WHERE `Table` = ? AND `Column` = ?");
                }

                // get the normal tables
                using (View tablesView = database.OpenExecuteView("SELECT * FROM _Tables"))
                {
                    while (true)
                    {
                        using (Record tableRecord = tablesView.Fetch())
                        {
                            if (null == tableRecord)
                            {
                                break;
                            }

                            string tableName = tableRecord.GetString(1);

                            using (View tableView = database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM `{0}`", tableName)))
                            {
                                TableDefinition tableDefinition = new TableDefinition(tableName, false, false);
                                Hashtable tablePrimaryKeys = new Hashtable();

                                using (Record columnNameRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFONAMES),
                                              columnTypeRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFOTYPES))
                                {
                                    int columnCount = columnNameRecord.GetFieldCount();

                                    // index the primary keys
                                    using (Record primaryKeysRecord = database.PrimaryKeys(tableName))
                                    {
                                        int primaryKeysFieldCount = primaryKeysRecord.GetFieldCount();

                                        for (int i = 1; i <= primaryKeysFieldCount; i++)
                                        {
                                            tablePrimaryKeys[primaryKeysRecord.GetString(i)] = null;
                                        }
                                    }

                                    for (int i = 1; i <= columnCount; i++)
                                    {
                                        string columnName = columnNameRecord.GetString(i);
                                        string idtType = columnTypeRecord.GetString(i);

                                        ColumnType columnType;
                                        int length;
                                        bool nullable;

                                        ColumnCategory columnCategory = ColumnCategory.Unknown;
                                        ColumnModularizeType columnModularizeType = ColumnModularizeType.None;
                                        bool primary = tablePrimaryKeys.Contains(columnName);
                                        bool minValueSet = false;
                                        int minValue = -1;
                                        bool maxValueSet = false;
                                        int maxValue = -1;
                                        string keyTable = null;
                                        bool keyColumnSet = false;
                                        int keyColumn = -1;
                                        string category = null;
                                        string set = null;
                                        string description = null;

                                        // get the column type, length, and whether its nullable
                                        switch (Char.ToLower(idtType[0], CultureInfo.InvariantCulture))
                                        {
                                            case 'i':
                                                columnType = ColumnType.Number;
                                                break;
                                            case 'l':
                                                columnType = ColumnType.Localized;
                                                break;
                                            case 's':
                                                columnType = ColumnType.String;
                                                break;
                                            case 'v':
                                                columnType = ColumnType.Object;
                                                break;
                                            default:
                                                // TODO: error
                                                columnType = ColumnType.Unknown;
                                                break;
                                        }
                                        length = Convert.ToInt32(idtType.Substring(1), CultureInfo.InvariantCulture);
                                        nullable = Char.IsUpper(idtType[0]);

                                        // try to get validation information
                                        if (null != validationView)
                                        {
                                            using (Record validationRecord = new Record(2))
                                            {
                                                validationRecord.SetString(1, tableName);
                                                validationRecord.SetString(2, columnName);

                                                validationView.Execute(validationRecord);
                                            }

                                            using (Record validationRecord = validationView.Fetch())
                                            {
                                                if (null != validationRecord)
                                                {
                                                    string validationNullable = validationRecord.GetString(3);
                                                    minValueSet = !validationRecord.IsNull(4);
                                                    minValue = (minValueSet ? validationRecord.GetInteger(4) : -1);
                                                    maxValueSet = !validationRecord.IsNull(5);
                                                    maxValue = (maxValueSet ? validationRecord.GetInteger(5) : -1);
                                                    keyTable = (!validationRecord.IsNull(6) ? validationRecord.GetString(6) : null);
                                                    keyColumnSet = !validationRecord.IsNull(7);
                                                    keyColumn = (keyColumnSet ? validationRecord.GetInteger(7) : -1);
                                                    category = (!validationRecord.IsNull(8) ? validationRecord.GetString(8) : null);
                                                    set = (!validationRecord.IsNull(9) ? validationRecord.GetString(9) : null);
                                                    description = (!validationRecord.IsNull(10) ? validationRecord.GetString(10) : null);

                                                    // check the validation nullable value against the column definition
                                                    if (null == validationNullable)
                                                    {
                                                        // TODO: warn for illegal validation nullable column
                                                    }
                                                    else if ((nullable && "Y" != validationNullable) || (!nullable && "N" != validationNullable))
                                                    {
                                                        // TODO: warn for mismatch between column definition and validation nullable
                                                    }

                                                    // convert category to ColumnCategory
                                                    if (null != category)
                                                    {
                                                        try
                                                        {
                                                            columnCategory = (ColumnCategory)Enum.Parse(typeof(ColumnCategory), category, true);
                                                        }
                                                        catch (ArgumentException)
                                                        {
                                                            columnCategory = ColumnCategory.Unknown;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    // TODO: warn about no validation information
                                                }
                                            }
                                        }

                                        // guess the modularization type
                                        if ("Icon" == keyTable && 1 == keyColumn)
                                        {
                                            columnModularizeType = ColumnModularizeType.Icon;
                                        }
                                        else if ("Condition" == columnName)
                                        {
                                            columnModularizeType = ColumnModularizeType.Condition;
                                        }
                                        else if (ColumnCategory.Formatted == columnCategory || ColumnCategory.FormattedSDDLText == columnCategory)
                                        {
                                            columnModularizeType = ColumnModularizeType.Property;
                                        }
                                        else if (ColumnCategory.Identifier == columnCategory)
                                        {
                                            columnModularizeType = ColumnModularizeType.Column;
                                        }

                                        tableDefinition.Columns.Add(new ColumnDefinition(columnName, columnType, length, primary, nullable, columnModularizeType, (ColumnType.Localized == columnType), minValueSet, minValue, maxValueSet, maxValue, keyTable, keyColumnSet, keyColumn, columnCategory, set, description, true, true));
                                    }
                                }
                                // use our table definitions if core properties are the same; this allows us to take advantage
                                // of wix concepts like localizable columns which current code assumes
                                if (this.tableDefinitions.Contains(tableName) && 0 == tableDefinition.CompareTo(this.tableDefinitions[tableName]))
                                {
                                    tableDefinition = this.tableDefinitions[tableName];
                                }
                                Table table = new Table(null, tableDefinition);

                                while (true)
                                {
                                    using (Record rowRecord = tableView.Fetch())
                                    {
                                        if (null == rowRecord)
                                        {
                                            break;
                                        }

                                        int recordCount = rowRecord.GetFieldCount();
                                        Row row = table.CreateRow(output.SourceLineNumbers);

                                        for (int i = 0; recordCount > i && row.Fields.Length > i; i++)
                                        {
                                            if (rowRecord.IsNull(i + 1))
                                            {
                                                if (!row.Fields[i].Column.IsNullable)
                                                {
                                                    // TODO: display an error for a null value in a non-nullable field OR
                                                    // display a warning and put an empty string in the value to let the compiler handle it
                                                    // (the second option is risky because the later code may make certain assumptions about
                                                    // the contents of a row value)
                                                }
                                            }
                                            else
                                            {
                                                switch (row.Fields[i].Column.Type)
                                                {
                                                    case ColumnType.Number:
                                                        bool success = false;
                                                        int intValue = rowRecord.GetInteger(i + 1);
                                                        if (row.Fields[i].Column.IsLocalizable)
                                                        {
                                                            success = row.BestEffortSetField(i, Convert.ToString(intValue, CultureInfo.InvariantCulture));
                                                        }
                                                        else
                                                        {
                                                            success = row.BestEffortSetField(i, intValue);
                                                        }

                                                        if (!success)
                                                        {
                                                            this.OnMessage(WixWarnings.BadColumnDataIgnored(row.SourceLineNumbers, Convert.ToString(intValue, CultureInfo.InvariantCulture), tableName, row.Fields[i].Column.Name));
                                                        }
                                                        break;
                                                    case ColumnType.Object:
                                                        string sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES";

                                                        if (null != exportBasePath)
                                                        {
                                                            string relativeSourceFile = Path.Combine(tableName, row.GetPrimaryKey('.'));
                                                            sourceFile = Path.Combine(exportBasePath, relativeSourceFile);

                                                            // ensure the parent directory exists
                                                            System.IO.Directory.CreateDirectory(Path.Combine(exportBasePath, tableName));

                                                            using (FileStream fs = System.IO.File.Create(sourceFile))
                                                            {
                                                                int bytesRead;
                                                                byte[] buffer = new byte[512];

                                                                while (0 != (bytesRead = rowRecord.GetStream(i + 1, buffer, buffer.Length)))
                                                                {
                                                                    fs.Write(buffer, 0, bytesRead);
                                                                }
                                                            }
                                                        }

                                                        row[i] = sourceFile;
                                                        break;
                                                    default:
                                                        string value = rowRecord.GetString(i + 1);

                                                        switch (row.Fields[i].Column.Category)
                                                        {
                                                            case ColumnCategory.Guid:
                                                                value = value.ToUpper(CultureInfo.InvariantCulture);
                                                                break;
                                                        }

                                                        // de-modularize
                                                        if (!this.suppressDemodularization && OutputType.Module == output.Type && ColumnModularizeType.None != row.Fields[i].Column.ModularizeType)
                                                        {
                                                            Regex modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}");

                                                            if (null == modularizationGuid)
                                                            {
                                                                Match match = modularization.Match(value);
                                                                if (match.Success)
                                                                {
                                                                    modularizationGuid = String.Concat('{', match.Value.Substring(1).Replace('_', '-'), '}');
                                                                }
                                                            }

                                                            value = modularization.Replace(value, String.Empty);
                                                        }

                                                        // escape "$(" for the preprocessor
                                                        value = value.Replace("$(", "$$(");

                                                        // escape things that look like wix variables
                                                        MatchCollection matches = Common.WixVariableRegex.Matches(value);
                                                        for (int j = matches.Count - 1; 0 <= j; j--)
                                                        {
                                                            value = value.Insert(matches[j].Index, "!");
                                                        }

                                                        row[i] = value;
                                                        break;
                                                }
                                            }
                                        }
                                    }
                                }

                                output.Tables.Add(table);
                            }

                        }
                    }
                }
            }
            finally
            {
                if (null != validationView)
                {
                    validationView.Close();
                }
            }

            // set the modularization guid as the PackageCode
            if (null != modularizationGuid)
            {
                Table table = output.Tables["_SummaryInformation"];

                foreach (Row row in table.Rows)
                {
                    if (9 == (int)row[0]) // PID_REVNUMBER
                    {
                        row[1] = modularizationGuid;
                    }
                }
            }

            if (this.isAdminImage)
            {
                GenerateWixFileTable(databaseFile, output);
                GenerateSectionIds(output);
            }

            return output;
        }
 /// <summary>
 /// Creates an ApprovedExeForElevation row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this ApprovedExeForElevation row belongs to and should get its column definitions from.</param>
 public WixApprovedExeForElevationRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef)
     : base(sourceLineNumbers, tableDef)
 {
 }
Example #4
0
 /// <summary>
 /// Creates a File row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDefinition">TableDefinition this Media row belongs to and should get its column definitions from.</param>
 public FileRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDefinition)
     : base(sourceLineNumbers, tableDefinition)
 {
     this.assemblyType = FileAssemblyType.NotAnAssembly;
     this.previousSource = new string[1];
     this.previousSymbols = new string[1];
     this.previousRetainOffsets = new string[1];
     this.previousRetainLengths = new string[1];
     this.previousIgnoreOffsets = new string[1];
     this.previousIgnoreLengths = new string[1];
 }
Example #5
0
 /// <summary>
 /// Creates a ChainMsiPackage row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this row belongs to and should get its column definitions from.</param>
 public ChainMsiPackageRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
Example #6
0
File: Row.cs Project: bleissem/wix3
 /// <summary>
 /// Creates a shallow copy of a row from another row.
 /// </summary>
 /// <param name="source">The row the data is copied from.</param>
 protected Row(Row source)
 {
     this.table = source.table;
     this.tableDefinition = source.tableDefinition;
     this.rowNumber = source.rowNumber;
     this.operation = source.operation;
     this.sectionId = source.sectionId;
     this.sourceLineNumbers = source.sourceLineNumbers;
     this.fields = source.fields;
     this.symbol = source.symbol;
 }
Example #7
0
        /// <summary>
        /// Parses an odbc driver or translator element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="componentId">Identifier of parent component.</param>
        /// <param name="fileId">Default identifer for driver/translator file.</param>
        /// <param name="table">Table we're processing for.</param>
        private void ParseODBCDriverOrTranslator(XmlNode node, string componentId, string fileId, TableDefinition table)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            string driver = fileId;
            string name = null;
            string setup = fileId;

            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 "File":
                            driver = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", driver);
                            break;
                        case "Name":
                            name = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "SetupFile":
                            setup = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                            this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "File", setup);
                            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"));
            }

            // drivers have a few possible children
            if ("ODBCDriver" == table.Name)
            {
                // process any data sources for the driver
                foreach (XmlNode child in node.ChildNodes)
                {
                    if (XmlNodeType.Element == child.NodeType)
                    {
                        if (child.NamespaceURI == this.schema.TargetNamespace)
                        {
                            switch (child.LocalName)
                            {
                                case "ODBCDataSource":
                                    string ignoredKeyPath = null;
                                    this.ParseODBCDataSource(child, componentId, name, out ignoredKeyPath);
                                    break;
                                case "Property":
                                    this.ParseODBCProperty(child, id, "ODBCAttribute");
                                    break;
                                default:
                                    this.core.UnexpectedElement(node, child);
                                    break;
                            }
                        }
                        else
                        {
                            this.core.UnsupportedExtensionElement(node, child);
                        }
                    }
                }
            }
            else
            {
                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, table.Name);
                row[0] = id;
                row[1] = componentId;
                row[2] = name;
                row[3] = driver;
                row[4] = setup;
            }
        }
        /// <summary>
        /// Gets the validation rows for the table.
        /// </summary>
        /// <param name="validationTable">Defintion for the validation table.</param>
        /// <returns>Collection of output rows for the validation table.</returns>
        internal OutputRowCollection GetValidationRows(TableDefinition validationTable)
        {
            OutputRowCollection outputRows = new OutputRowCollection();

            foreach (ColumnDefinition columnDef in this.columns)
            {
                if (columnDef.IsUnreal)
                {
                    continue;
                }

                Row row = new Row(validationTable);

                row[0] = this.name;

                row[1] = columnDef.Name;

                if (columnDef.IsNullable)
                {
                    row[2] = "Y";
                }
                else
                {
                    row[2] = "N";
                }

                if (columnDef.IsMinValueSet)
                {
                    row[3] = columnDef.MinValue;
                }

                if (columnDef.IsMaxValueSet)
                {
                    row[4] = columnDef.MaxValue;
                }

                row[5] = columnDef.KeyTable;

                if (columnDef.IsKeyColumnSet)
                {
                    row[6] = columnDef.KeyColumn;
                }

                if (ColumnCategory.Unknown != columnDef.Category)
                {
                    row[7] = columnDef.Category.ToString();
                }

                row[8] = columnDef.Possibilities;

                row[9] = columnDef.Description;

                outputRows.Add(new OutputRow(row));
            }

            return outputRows;
        }
Example #9
0
        /// <summary>
        /// Parse a table from the xml.
        /// </summary>
        /// <param name="reader">XmlReader where the intermediate is persisted.</param>
        /// <param name="section">Section to populate with persisted data.</param>
        /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param>
        /// <returns>The parsed table.</returns>
        internal static Table Parse(XmlReader reader, Section section, TableDefinitionCollection tableDefinitions)
        {
            Debug.Assert("table" == reader.LocalName);

            bool           empty     = reader.IsEmptyElement;
            TableOperation operation = TableOperation.None;
            string         name      = null;

            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                case "name":
                    name = reader.Value;
                    break;

                case "op":
                    switch (reader.Value)
                    {
                    case "add":
                        operation = TableOperation.Add;
                        break;

                    case "drop":
                        operation = TableOperation.Drop;
                        break;

                    default:
                        throw new WixException(WixErrors.IllegalAttributeValue(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", reader.Name, reader.Value, "Add", "Drop"));
                    }
                    break;

                default:
                    if (!reader.NamespaceURI.StartsWith("http://www.w3.org/", StringComparison.Ordinal))
                    {
                        throw new WixException(WixErrors.UnexpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", reader.Name));
                    }
                    break;
                }
            }

            if (null == name)
            {
                throw new WixException(WixErrors.ExpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", "name"));
            }

            TableDefinition tableDefinition = tableDefinitions[name];
            Table           table           = new Table(section, tableDefinition);

            table.Operation = operation;

            if (!empty)
            {
                bool done = false;

                // loop through all the rows in a table
                while (!done && reader.Read())
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.Element:
                        switch (reader.LocalName)
                        {
                        case "row":
                            Row.Parse(reader, table);
                            break;

                        default:
                            throw new WixException(WixErrors.UnexpectedElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", reader.Name));
                        }
                        break;

                    case XmlNodeType.EndElement:
                        done = true;
                        break;
                    }
                }

                if (!done)
                {
                    throw new WixException(WixErrors.ExpectedEndElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "table"));
                }
            }

            return(table);
        }
Example #10
0
 /// <summary>
 /// Creates an output table with the specified definition.
 /// </summary>
 /// <param name="tableDef">Definition for all tables in this output table.</param>
 public OutputTable(TableDefinition tableDef)
 {
     this.tableDef   = tableDef;
     this.outputRows = new OutputRowCollection();
 }
Example #11
0
        /// <summary>
        /// Parses table definition from xml reader.
        /// </summary>
        /// <param name="reader">Reader to get data from.</param>
        /// <returns>The TableDefintion represented by the Xml.</returns>
        internal static TableDefinition Parse(XmlReader reader)
        {
            Debug.Assert("tableDefinition" == reader.LocalName);

            bool   empty               = reader.IsEmptyElement;
            bool   createSymbols       = false;
            bool   hasPrimaryKeyColumn = false;
            string name   = null;
            bool   unreal = false;

            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                case "createSymbols":
                    createSymbols = Common.IsYes(SourceLineNumberCollection.FromUri(reader.BaseURI), "createSymbols", reader.Name, reader.Value);
                    break;

                case "name":
                    name = reader.Value;
                    break;

                case "unreal":
                    unreal = Common.IsYes(SourceLineNumberCollection.FromUri(reader.BaseURI), "tableDefinition", reader.Name, reader.Value);
                    break;

                default:
                    if (!reader.NamespaceURI.StartsWith("http://www.w3.org/"))
                    {
                        throw new WixException(WixErrors.UnexpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "tableDefinition", reader.Name));
                    }
                    break;
                }
            }

            if (null == name)
            {
                throw new WixException(WixErrors.ExpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "tableDefinition", "name"));
            }

            TableDefinition tableDefinition = new TableDefinition(name, createSymbols, unreal);

            // parse the child elements
            if (!empty)
            {
                bool done = false;

                while (!done && reader.Read())
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.Element:
                        switch (reader.LocalName)
                        {
                        case "columnDefinition":
                            ColumnDefinition columnDefinition = ColumnDefinition.Parse(reader);
                            tableDefinition.columns.Add(columnDefinition);

                            if (columnDefinition.IsLocalizable)
                            {
                                tableDefinition.localizable = true;
                            }

                            if (columnDefinition.IsPrimaryKey)
                            {
                                hasPrimaryKeyColumn = true;
                            }
                            break;

                        default:
                            throw new WixException(WixErrors.UnexpectedElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "tableDefinition", reader.Name));
                        }
                        break;

                    case XmlNodeType.EndElement:
                        done = true;
                        break;
                    }
                }

                if (!unreal && !hasPrimaryKeyColumn)
                {
                    throw new WixException(WixErrors.RealTableMissingPrimaryKeyColumn(SourceLineNumberCollection.FromUri(reader.BaseURI), name));
                }

                if (!done)
                {
                    throw new WixException(WixErrors.ExpectedEndElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "tableDefinition"));
                }
            }

            return(tableDefinition);
        }
Example #12
0
        /// <summary>
        /// Processes an XmlReader and builds up the output table object.
        /// </summary>
        /// <param name="reader">Reader to get data from.</param>
        /// <param name="section">Section to add loaded rows into.</param>
        /// <returns>Output table.</returns>
        internal static OutputTable Parse(XmlReader reader, Section section)
        {
            Debug.Assert("outputTable" == reader.LocalName);

            string name  = null;
            bool   empty = reader.IsEmptyElement;

            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                case "name":
                    name = reader.Value;
                    break;

                default:
                    throw new WixParseException(String.Format("The outputTable element contains an unexpected attribute {0}.", reader.Name));
                }
            }
            if (null == name)
            {
                throw new WixParseException("The outputTable/@name attribute was not found; it is required.");
            }

            OutputTable outputTable = null;

            if (!empty)
            {
                bool done = false;

                // loop through all the fields in a row
                while (!done && reader.Read())
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.Element:
                        switch (reader.LocalName)
                        {
                        case "tableDefinition":
                            outputTable = new OutputTable(TableDefinition.Parse(reader));
                            break;

                        case "tuple":
                            if (null == outputTable)
                            {
                                throw new WixParseException("The outputTable element is missing a tableDefinition child element.");
                            }
                            outputTable.outputRows.Add(new OutputRow(Row.Parse(reader, section, outputTable.tableDef)));
                            break;

                        default:
                            throw new WixParseException(String.Format("The outputTable element contains an unexpected child element {0}.", reader.Name));
                        }
                        break;

                    case XmlNodeType.EndElement:
                        done = true;
                        break;
                    }
                }

                if (!done)
                {
                    throw new WixParseException("Missing end element while processing the outputTable element.");
                }
            }

            return(outputTable);
        }
Example #13
0
        /// <summary>
        /// Parses table definition from xml reader.
        /// </summary>
        /// <param name="reader">Reader to get data from.</param>
        /// <returns>The TableDefintion represented by the Xml.</returns>
        internal static TableDefinition Parse(XmlReader reader)
        {
            Debug.Assert("tableDefinition" == reader.LocalName);

            string name   = null;
            bool   unreal = false;
            bool   empty  = reader.IsEmptyElement;

            // parse the attributes
            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                case "name":
                    name = reader.Value;
                    break;

                case "unreal":
                    unreal = Common.IsYes(reader.Value, null, "tableDefinition", reader.Name, name);
                    break;

                case "xmlns":
                    break;

                default:
                    throw new WixParseException(String.Format("The tableDefinition element contains an unexpected attribute '{0}'.", reader.Name));
                }
            }

            if (null == name)
            {
                throw new WixParseException("The tableDefinition/@name attribute was not found; it is required.");
            }

            TableDefinition tableDefinition = new TableDefinition(name, unreal);

            // parse the child elements
            if (!empty)
            {
                bool done = false;

                while (!done && reader.Read())
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.Element:
                        switch (reader.LocalName)
                        {
                        case "columnDefinition":
                            tableDefinition.columns.Add(ColumnDefinition.Parse(reader));
                            break;

                        default:
                            throw new WixParseException(String.Format("The tableDefinition element contains an unexpected child element {0}.", reader.Name));
                        }
                        break;

                    case XmlNodeType.EndElement:
                        done = true;
                        break;
                    }
                }

                if (!done)
                {
                    throw new WixParseException("Missing end element while processing the tableDefinition element.");
                }
            }

            return(tableDefinition);
        }
Example #14
0
 /// <summary>
 /// Instantiate a new WixExtensionTableDefinitionConflictException.
 /// </summary>
 /// <param name="extension">Extension with conflict.</param>
 /// <param name="tableDefinition">Table definition conflicting</param>
 public WixExtensionTableDefinitionConflictException(SchemaExtension extension, TableDefinition tableDefinition) :
     base(null, ExceptionType)
 {
     this.extension       = extension;
     this.tableDefinition = tableDefinition;
 }
Example #15
0
File: Linker.cs Project: zooba/wix3
        /// <summary>
        /// Links the definition of a custom table.
        /// </summary>
        /// <param name="table">The table to link.</param>
        /// <param name="customTableDefinitions">Receives the linked definition of the custom table.</param>
        private void LinkCustomTable(Table table, TableDefinitionCollection customTableDefinitions)
        {
            foreach (Row row in table.Rows)
            {
                bool bootstrapperApplicationData = (null != row[13] && 1 == (int)row[13]);
                TableDefinition customTable = new TableDefinition((string)row[0], false, bootstrapperApplicationData, bootstrapperApplicationData);

                if (null == row[4])
                {
                    this.OnMessage(WixErrors.ExpectedAttribute(row.SourceLineNumbers, "CustomTable/Column", "PrimaryKey"));
                }

                string[] columnNames = row[2].ToString().Split('\t');
                string[] columnTypes = row[3].ToString().Split('\t');
                string[] primaryKeys = row[4].ToString().Split('\t');
                string[] minValues = row[5] == null ? null : row[5].ToString().Split('\t');
                string[] maxValues = row[6] == null ? null : row[6].ToString().Split('\t');
                string[] keyTables = row[7] == null ? null : row[7].ToString().Split('\t');
                string[] keyColumns = row[8] == null ? null : row[8].ToString().Split('\t');
                string[] categories = row[9] == null ? null : row[9].ToString().Split('\t');
                string[] sets = row[10] == null ? null : row[10].ToString().Split('\t');
                string[] descriptions = row[11] == null ? null : row[11].ToString().Split('\t');
                string[] modularizations = row[12] == null ? null : row[12].ToString().Split('\t');

                int currentPrimaryKey = 0;

                for (int i = 0; i < columnNames.Length; ++i)
                {
                    string name = columnNames[i];
                    ColumnType type = ColumnType.Unknown;

                    if (columnTypes[i].StartsWith("s", StringComparison.OrdinalIgnoreCase))
                    {
                        type = ColumnType.String;
                    }
                    else if (columnTypes[i].StartsWith("l", StringComparison.OrdinalIgnoreCase))
                    {
                        type = ColumnType.Localized;
                    }
                    else if (columnTypes[i].StartsWith("i", StringComparison.OrdinalIgnoreCase))
                    {
                        type = ColumnType.Number;
                    }
                    else if (columnTypes[i].StartsWith("v", StringComparison.OrdinalIgnoreCase))
                    {
                        type = ColumnType.Object;
                    }
                    else
                    {
                        throw new WixException(WixErrors.UnknownCustomTableColumnType(row.SourceLineNumbers, columnTypes[i]));
                    }

                    bool nullable = columnTypes[i].Substring(0, 1) == columnTypes[i].Substring(0, 1).ToUpper(CultureInfo.InvariantCulture);
                    int length = Convert.ToInt32(columnTypes[i].Substring(1), CultureInfo.InvariantCulture);

                    bool primaryKey = false;
                    if (currentPrimaryKey < primaryKeys.Length && primaryKeys[currentPrimaryKey] == columnNames[i])
                    {
                        primaryKey = true;
                        currentPrimaryKey++;
                    }

                    bool minValSet = null != minValues && null != minValues[i] && 0 < minValues[i].Length;
                    int minValue = 0;
                    if (minValSet)
                    {
                        minValue = Convert.ToInt32(minValues[i], CultureInfo.InvariantCulture);
                    }

                    bool maxValSet = null != maxValues && null != maxValues[i] && 0 < maxValues[i].Length;
                    int maxValue = 0;
                    if (maxValSet)
                    {
                        maxValue = Convert.ToInt32(maxValues[i], CultureInfo.InvariantCulture);
                    }

                    bool keyColumnSet = null != keyColumns && null != keyColumns[i] && 0 < keyColumns[i].Length;
                    int keyColumn = 0;
                    if (keyColumnSet)
                    {
                        keyColumn = Convert.ToInt32(keyColumns[i], CultureInfo.InvariantCulture);
                    }

                    ColumnCategory category = ColumnCategory.Unknown;
                    if (null != categories && null != categories[i] && 0 < categories[i].Length)
                    {
                        switch (categories[i])
                        {
                            case "Text":
                                category = ColumnCategory.Text;
                                break;
                            case "UpperCase":
                                category = ColumnCategory.UpperCase;
                                break;
                            case "LowerCase":
                                category = ColumnCategory.LowerCase;
                                break;
                            case "Integer":
                                category = ColumnCategory.Integer;
                                break;
                            case "DoubleInteger":
                                category = ColumnCategory.DoubleInteger;
                                break;
                            case "TimeDate":
                                category = ColumnCategory.TimeDate;
                                break;
                            case "Identifier":
                                category = ColumnCategory.Identifier;
                                break;
                            case "Property":
                                category = ColumnCategory.Property;
                                break;
                            case "Filename":
                                category = ColumnCategory.Filename;
                                break;
                            case "WildCardFilename":
                                category = ColumnCategory.WildCardFilename;
                                break;
                            case "Path":
                                category = ColumnCategory.Path;
                                break;
                            case "Paths":
                                category = ColumnCategory.Paths;
                                break;
                            case "AnyPath":
                                category = ColumnCategory.AnyPath;
                                break;
                            case "DefaultDir":
                                category = ColumnCategory.DefaultDir;
                                break;
                            case "RegPath":
                                category = ColumnCategory.RegPath;
                                break;
                            case "Formatted":
                                category = ColumnCategory.Formatted;
                                break;
                            case "FormattedSddl":
                                category = ColumnCategory.FormattedSDDLText;
                                break;
                            case "Template":
                                category = ColumnCategory.Template;
                                break;
                            case "Condition":
                                category = ColumnCategory.Condition;
                                break;
                            case "Guid":
                                category = ColumnCategory.Guid;
                                break;
                            case "Version":
                                category = ColumnCategory.Version;
                                break;
                            case "Language":
                                category = ColumnCategory.Language;
                                break;
                            case "Binary":
                                category = ColumnCategory.Binary;
                                break;
                            case "CustomSource":
                                category = ColumnCategory.CustomSource;
                                break;
                            case "Cabinet":
                                category = ColumnCategory.Cabinet;
                                break;
                            case "Shortcut":
                                category = ColumnCategory.Shortcut;
                                break;
                            default:
                                break;
                        }
                    }

                    string keyTable = keyTables != null ? keyTables[i] : null;
                    string setValue = sets != null ? sets[i] : null;
                    string description = descriptions != null ? descriptions[i] : null;
                    string modString = modularizations != null ? modularizations[i] : null;
                    ColumnModularizeType modularization = ColumnModularizeType.None;
                    if (modString != null)
                    {
                        switch (modString)
                        {
                            case "None":
                                modularization = ColumnModularizeType.None;
                                break;
                            case "Column":
                                modularization = ColumnModularizeType.Column;
                                break;
                            case "Property":
                                modularization = ColumnModularizeType.Property;
                                break;
                            case "Condition":
                                modularization = ColumnModularizeType.Condition;
                                break;
                            case "CompanionFile":
                                modularization = ColumnModularizeType.CompanionFile;
                                break;
                            case "SemicolonDelimited":
                                modularization = ColumnModularizeType.SemicolonDelimited;
                                break;
                        }
                    }

                    ColumnDefinition columnDefinition = new ColumnDefinition(name, type, length, primaryKey, nullable, modularization, ColumnType.Localized == type, minValSet, minValue, maxValSet, maxValue, keyTable, keyColumnSet, keyColumn, category, setValue, description, true, true);
                    customTable.Columns.Add(columnDefinition);
                }

                customTableDefinitions.Add(customTable);
            }
        }
Example #16
0
 /// <summary>
 /// Creates a table in a section.
 /// </summary>
 /// <param name="section">Section to add table to.</param>
 /// <param name="tableDefinition">Definition of the table.</param>
 public Table(Section section, TableDefinition tableDefinition)
 {
     this.section         = section;
     this.tableDefinition = tableDefinition;
     this.rows            = new RowCollection();
 }
Example #17
0
 /// <summary>
 /// Ensure this output contains a particular table.
 /// </summary>
 /// <param name="tableDefinition">Definition of the table that should exist.</param>
 /// <returns>The table in this output.</returns>
 internal Table EnsureTable(TableDefinition tableDefinition)
 {
     return this.tables.EnsureTable(this.entrySection, tableDefinition);
 }
 /// <summary>
 /// Creates a PatchTargetCodeRow row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this PatchTargetCode row belongs to and should get its column definitions from.</param>
 public WixBundlePatchTargetCodeRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
Example #19
0
        /// <summary>
        /// Adds a table definition to the collection.
        /// </summary>
        /// <param name="tableDefinition">Table definition to add to the collection.</param>
        /// <value>Indexes by table definition name.</value>
        public void Add(TableDefinition tableDefinition)
        {
            if (null == tableDefinition)
            {
                throw new ArgumentNullException("tableDefinition");
            }

            this.collection.Add(tableDefinition.Name, tableDefinition);
        }
Example #20
0
 /// <summary>
 /// Ensure this output contains a particular table.
 /// </summary>
 /// <param name="tableDefinition">Definition of the table that should exist.</param>
 /// <returns>The table in this output.</returns>
 internal Table EnsureTable(TableDefinition tableDefinition)
 {
     return(this.tables.EnsureTable(this.entrySection, tableDefinition));
 }
Example #21
0
        /// <summary>
        /// Parses a control group element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="table">Table referred to by control group.</param>
        /// <param name="childTag">Expected child elements.</param>
        private void ParseControlGroupElement(XmlNode node, TableDefinition table, string childTag)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            int order = 0;
            string property = null;

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

            if (null == property)
            {
                this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Property"));
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        if (childTag != child.LocalName)
                        {
                            this.core.UnexpectedElement(node, child);
                        }

                        switch (child.LocalName)
                        {
                            case "ListItem":
                                this.ParseListItemElement(child, table, property, ref order);
                                break;
                            case "Property":
                                this.ParsePropertyElement(child);
                                break;
                            default:
                                this.core.UnexpectedElement(node, child);
                                break;
                        }
                    }
                    else
                    {
                        this.core.UnsupportedExtensionElement(node, child);
                    }
                }
            }
        }
Example #22
0
 /// <summary>
 /// Creates a File row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this Media row belongs to and should get its column definitions from.</param>
 public FileRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
Example #23
0
 /// <summary>
 /// Creates a WixUpdateRegistrationRow row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this WixUpdateRegistrationRow row belongs to and should get its column definitions from.</param>
 public WixUpdateRegistrationRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef)
     : base(sourceLineNumbers, tableDef)
 {
 }
Example #24
0
 /// <summary>Creates a File row that does not belong to a table.</summary>
 /// <param name="tableDef">TableDefinition this File row should get its column definitions from.</param>
 public FileRow(TableDefinition tableDef) :
     base(tableDef)
 {
 }
Example #25
0
 /// <summary>
 /// Creates a Media row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this Media row belongs to and should get its column definitions from.</param>
 public MediaRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef)
     : base(sourceLineNumbers, tableDef)
 {
 }
Example #26
0
 /// <summary>
 /// Creates a WixUpdateRegistrationRow row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this WixUpdateRegistrationRow row belongs to and should get its column definitions from.</param>
 public WixUpdateRegistrationRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
 /// <summary>
 /// Creates a WixSimpleReferenceRow that belongs to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDefinitions">Table definitions for this row.</param>
 public WixSimpleReferenceRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDefinitions)
     : base(sourceLineNumbers, tableDefinitions)
 {
 }
 /// <summary>
 /// Creates a WixCommandLineRow row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this WixCommandLineRow row belongs to and should get its column definitions from.</param>
 public WixCommandLineRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
Example #29
0
 /// <summary>Creates a File row that does not belong to a table.</summary>
 /// <param name="tableDef">TableDefinition this File row should get its column definitions from.</param>
 public FileRow(TableDefinition tableDef)
     : base(tableDef)
 {
 }
Example #30
0
 /// <summary>
 /// Creates a PayloadInfoRow row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this Media row belongs to and should get its column definitions from.</param>
 public PayloadInfoRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
 /// <summary>
 /// Creates a ChainMsiPackage row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this row belongs to and should get its column definitions from.</param>
 public ChainMsiPackageRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef) :
     base(sourceLineNumbers, tableDef)
 {
 }
Example #32
0
 /// <summary>
 /// Creates a WixSimpleReferenceRow that belongs to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDefinitions">Table definitions for this row.</param>
 public WixSimpleReferenceRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDefinitions)
     : base(sourceLineNumbers, tableDefinitions)
 {
 }
        /// <summary>
        /// Ensure this TableCollection contains a particular table.
        /// </summary>
        /// <param name="section">Section containing the new table.</param>
        /// <param name="tableDefinition">Definition of the table that should exist.</param>
        /// <returns>The table in this collection.</returns>
        public Table EnsureTable(Section section, TableDefinition tableDefinition)
        {
            Table table = this[tableDefinition.Name];

            if (null == table)
            {
                table = new Table(section, tableDefinition);
                this.Add(table);
            }

            return table;
        }
Example #34
0
        /// <summary>
        /// Unbind an MSI database file.
        /// </summary>
        /// <param name="databaseFile">The database file.</param>
        /// <param name="database">The opened database.</param>
        /// <param name="outputType">The type of output to create.</param>
        /// <param name="exportBasePath">The path where files should be exported.</param>
        /// <returns>The output representing the database.</returns>
        private Output UnbindDatabase(string databaseFile, Database database, OutputType outputType, string exportBasePath)
        {
            string modularizationGuid = null;
            Output output             = new Output(SourceLineNumberCollection.FromFileName(databaseFile));
            View   validationView     = null;

            // set the output type
            output.Type = outputType;

            // get the codepage
            database.Export("_ForceCodepage", this.TempFilesLocation, "_ForceCodepage.idt");
            using (StreamReader sr = File.OpenText(Path.Combine(this.TempFilesLocation, "_ForceCodepage.idt")))
            {
                string line;

                while (null != (line = sr.ReadLine()))
                {
                    string[] data = line.Split('\t');

                    if (2 == data.Length)
                    {
                        output.Codepage = Convert.ToInt32(data[0], CultureInfo.InvariantCulture);
                    }
                }
            }

            // get the summary information table
            using (SummaryInformation summaryInformation = new SummaryInformation(database))
            {
                Table table = new Table(null, this.tableDefinitions["_SummaryInformation"]);

                for (int i = 1; 19 >= i; i++)
                {
                    string value = summaryInformation.GetProperty(i);

                    if (0 < value.Length)
                    {
                        Row row = table.CreateRow(output.SourceLineNumbers);
                        row[0] = i;
                        row[1] = value;
                    }
                }

                output.Tables.Add(table);
            }

            try
            {
                // open a view on the validation table if it exists
                if (database.TableExists("_Validation"))
                {
                    validationView = database.OpenView("SELECT * FROM `_Validation` WHERE `Table` = ? AND `Column` = ?");
                }

                // get the normal tables
                using (View tablesView = database.OpenExecuteView("SELECT * FROM _Tables"))
                {
                    Record tableRecord;

                    while (null != (tableRecord = tablesView.Fetch()))
                    {
                        string tableName = tableRecord.GetString(1);

                        using (View tableView = database.OpenExecuteView(String.Format(CultureInfo.InvariantCulture, "SELECT * FROM `{0}`", tableName)))
                        {
                            Record          rowRecord;
                            Table           table;
                            TableDefinition tableDefinition;

                            if (this.tableDefinitions.Contains(tableName))
                            {
                                tableDefinition = this.tableDefinitions[tableName];

                                // TODO: verify table definitions
                                // - error for different column name or data type
                                // - warn for additional columns
                                // - need extra info for new columns in standard tables (MSI 4.0 changes)
                            }
                            else // custom table
                            {
                                TableDefinition customTableDefinition  = new TableDefinition(tableName, false, false);
                                Hashtable       customTablePrimaryKeys = new Hashtable();

                                Record customColumnNameRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFONAMES);
                                Record customColumnTypeRecord = tableView.GetColumnInfo(MsiInterop.MSICOLINFOTYPES);
                                int    customColumnCount      = customColumnNameRecord.GetFieldCount();

                                // index the primary keys
                                using (Record primaryKeysRecord = database.PrimaryKeys(tableName))
                                {
                                    int primaryKeysFieldCount = primaryKeysRecord.GetFieldCount();

                                    for (int i = 1; i <= primaryKeysFieldCount; i++)
                                    {
                                        customTablePrimaryKeys[primaryKeysRecord.GetString(i)] = null;
                                    }
                                }

                                for (int i = 1; i <= customColumnCount; i++)
                                {
                                    string columnName = customColumnNameRecord.GetString(i);
                                    string idtType    = customColumnTypeRecord.GetString(i);

                                    ColumnType columnType;
                                    int        length;
                                    bool       nullable;

                                    ColumnCategory       columnCategory       = ColumnCategory.Unknown;
                                    ColumnModularizeType columnModularizeType = ColumnModularizeType.None;
                                    bool   primary      = customTablePrimaryKeys.Contains(columnName);
                                    bool   minValueSet  = false;
                                    int    minValue     = -1;
                                    bool   maxValueSet  = false;
                                    int    maxValue     = -1;
                                    string keyTable     = null;
                                    bool   keyColumnSet = false;
                                    int    keyColumn    = -1;
                                    string category     = null;
                                    string set          = null;
                                    string description  = null;

                                    // get the column type, length, and whether its nullable
                                    switch (Char.ToLower(idtType[0], CultureInfo.InvariantCulture))
                                    {
                                    case 'i':
                                        columnType = ColumnType.Number;
                                        break;

                                    case 'l':
                                        columnType = ColumnType.Localized;
                                        break;

                                    case 's':
                                        columnType = ColumnType.String;
                                        break;

                                    case 'v':
                                        columnType = ColumnType.Object;
                                        break;

                                    default:
                                        // TODO: error
                                        columnType = ColumnType.Unknown;
                                        break;
                                    }
                                    length   = Convert.ToInt32(idtType.Substring(1), CultureInfo.InvariantCulture);
                                    nullable = Char.IsUpper(idtType[0]);

                                    // try to get validation information
                                    if (null != validationView)
                                    {
                                        Record validationRecord = new Record(2);
                                        validationRecord.SetString(1, tableName);
                                        validationRecord.SetString(2, columnName);

                                        validationView.Execute(validationRecord);
                                        validationRecord.Close();

                                        if (null != (validationRecord = validationView.Fetch()))
                                        {
                                            string validationNullable = validationRecord.GetString(3);
                                            minValueSet  = !validationRecord.IsNull(4);
                                            minValue     = (minValueSet ? validationRecord.GetInteger(4) : -1);
                                            maxValueSet  = !validationRecord.IsNull(5);
                                            maxValue     = (maxValueSet ? validationRecord.GetInteger(5) : -1);
                                            keyTable     = (!validationRecord.IsNull(6) ? validationRecord.GetString(6) : null);
                                            keyColumnSet = !validationRecord.IsNull(7);
                                            keyColumn    = (keyColumnSet ? validationRecord.GetInteger(7) : -1);
                                            category     = (!validationRecord.IsNull(8) ? validationRecord.GetString(8) : null);
                                            set          = (!validationRecord.IsNull(9) ? validationRecord.GetString(9) : null);
                                            description  = (!validationRecord.IsNull(10) ? validationRecord.GetString(10) : null);

                                            // check the validation nullable value against the column definition
                                            if (null == validationNullable)
                                            {
                                                // TODO: warn for illegal validation nullable column
                                            }
                                            else if ((nullable && "Y" != validationNullable) || (!nullable && "N" != validationNullable))
                                            {
                                                // TODO: warn for mismatch between column definition and validation nullable
                                            }

                                            // convert category to ColumnCategory
                                            if (null != category)
                                            {
                                                try
                                                {
                                                    columnCategory = (ColumnCategory)Enum.Parse(typeof(ColumnCategory), category, true);
                                                }
                                                catch (ArgumentException)
                                                {
                                                    columnCategory = ColumnCategory.Unknown;
                                                }
                                            }

                                            validationRecord.Close();
                                        }
                                        else
                                        {
                                            // TODO: warn about no validation information
                                        }
                                    }

                                    // guess the modularization type
                                    if ("Icon" == keyTable && 1 == keyColumn)
                                    {
                                        columnModularizeType = ColumnModularizeType.Icon;
                                    }
                                    else if ("Condition" == columnName)
                                    {
                                        columnModularizeType = ColumnModularizeType.Condition;
                                    }
                                    else if (ColumnCategory.Formatted == columnCategory)
                                    {
                                        columnModularizeType = ColumnModularizeType.Property;
                                    }
                                    else if (ColumnCategory.Identifier == columnCategory)
                                    {
                                        columnModularizeType = ColumnModularizeType.Column;
                                    }

                                    customTableDefinition.Columns.Add(new ColumnDefinition(columnName, columnType, length, primary, nullable, columnModularizeType, (ColumnType.Localized == columnType), minValueSet, minValue, maxValueSet, maxValue, keyTable, keyColumnSet, keyColumn, columnCategory, set, description, true, true));
                                }

                                tableDefinition = customTableDefinition;

                                customColumnNameRecord.Close();
                                customColumnTypeRecord.Close();
                            }

                            table = new Table(null, tableDefinition);

                            while (null != (rowRecord = tableView.Fetch()))
                            {
                                int recordCount = rowRecord.GetFieldCount();
                                Row row         = table.CreateRow(output.SourceLineNumbers);

                                for (int i = 0; recordCount > i && row.Fields.Length > i; i++)
                                {
                                    if (rowRecord.IsNull(i + 1))
                                    {
                                        if (!row.Fields[i].Column.IsNullable)
                                        {
                                            // TODO: display an error for a null value in a non-nullable field OR
                                            // display a warning and put an empty string in the value to let the compiler handle it
                                            // (the second option is risky because the later code may make certain assumptions about
                                            // the contents of a row value)
                                        }
                                    }
                                    else
                                    {
                                        switch (row.Fields[i].Column.Type)
                                        {
                                        case ColumnType.Number:
                                            if (row.Fields[i].Column.IsLocalizable)
                                            {
                                                row[i] = Convert.ToString(rowRecord.GetInteger(i + 1), CultureInfo.InvariantCulture);
                                            }
                                            else
                                            {
                                                row[i] = rowRecord.GetInteger(i + 1);
                                            }
                                            break;

                                        case ColumnType.Object:
                                            string sourceFile = "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES";

                                            if (null != exportBasePath)
                                            {
                                                string relativeSourceFile = Path.Combine(tableName, row.GetPrimaryKey('.'));
                                                sourceFile = Path.Combine(exportBasePath, relativeSourceFile);

                                                // ensure the parent directory exists
                                                System.IO.Directory.CreateDirectory(Path.Combine(exportBasePath, tableName));

                                                using (FileStream fs = System.IO.File.Create(sourceFile))
                                                {
                                                    int    bytesRead;
                                                    byte[] buffer = new byte[512];

                                                    while (0 != (bytesRead = rowRecord.GetStream(i + 1, buffer, buffer.Length)))
                                                    {
                                                        fs.Write(buffer, 0, bytesRead);
                                                    }
                                                }
                                            }

                                            row[i] = sourceFile;
                                            break;

                                        default:
                                            string value = rowRecord.GetString(i + 1);

                                            switch (row.Fields[i].Column.Category)
                                            {
                                            case ColumnCategory.Guid:
                                                value = value.ToUpper(CultureInfo.InvariantCulture);
                                                break;
                                            }

                                            // de-modularize
                                            if (!this.suppressDemodularization && OutputType.Module == output.Type && ColumnModularizeType.None != row.Fields[i].Column.ModularizeType)
                                            {
                                                Regex modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}");

                                                if (null == modularizationGuid)
                                                {
                                                    Match match = modularization.Match(value);
                                                    if (match.Success)
                                                    {
                                                        modularizationGuid = String.Concat('{', match.Value.Substring(1).Replace('_', '-'), '}');
                                                    }
                                                }

                                                value = modularization.Replace(value, String.Empty);
                                            }

                                            // escape "$(" for the preprocessor
                                            value = value.Replace("$(", "$$(");

                                            // escape things that look like wix variables
                                            MatchCollection matches = Common.WixVariableRegex.Matches(value);
                                            for (int j = matches.Count - 1; 0 <= j; j--)
                                            {
                                                value = value.Insert(matches[j].Index, "!");
                                            }

                                            row[i] = value;
                                            break;
                                        }
                                    }
                                }

                                rowRecord.Close();
                            }

                            output.Tables.Add(table);
                        }

                        tableRecord.Close();
                    }
                }
            }
            finally
            {
                if (null != validationView)
                {
                    validationView.Close();
                }
            }

            // set the modularization guid as the PackageCode
            if (null != modularizationGuid)
            {
                Table table = output.Tables["_SummaryInformation"];

                foreach (Row row in table.Rows)
                {
                    if (9 == (int)row[0]) // PID_REVNUMBER
                    {
                        row[1] = modularizationGuid;
                    }
                }
            }

            return(output);
        }
Example #35
0
File: Table.cs Project: zooba/wix3
 /// <summary>
 /// Creates a table in a section.
 /// </summary>
 /// <param name="section">Section to add table to.</param>
 /// <param name="tableDefinition">Definition of the table.</param>
 public Table(Section section, TableDefinition tableDefinition)
 {
     this.section = section;
     this.tableDefinition = tableDefinition;
     this.rows = new RowCollection();
 }
Example #36
0
 /// <summary>
 /// Creates an output table with the specified definition.
 /// </summary>
 /// <param name="tableDef">Definition for all tables in this output table.</param>
 public OutputTable(TableDefinition tableDef)
 {
     this.tableDef = tableDef;
     this.outputRows = new OutputRowCollection();
 }
Example #37
0
File: Row.cs Project: bleissem/wix3
        /// <summary>
        /// Creates a row that does not belong to a table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <param name="tableDefinition">TableDefinition this row should get its column definitions from.</param>
        /// <remarks>This constructor is used in cases where there isn't a clear owner of the row.  The linker uses this constructor for the rows it generates.</remarks>
        public Row(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDefinition)
        {
            if (null == tableDefinition)
            {
                throw new ArgumentNullException("tableDefinition");
            }

            this.rowNumber = rowCount++;
            this.sourceLineNumbers = sourceLineNumbers;
            this.fields = new Field[tableDefinition.Columns.Count];
            this.tableDefinition = tableDefinition;

            for (int i = 0; i < this.fields.Length; ++i)
            {
                this.fields[i] = Field.NewField(this.tableDefinition.Columns[i]);
            }
        }
Example #38
0
        /// <summary>
        /// Creates a Row from the XmlReader
        /// </summary>
        /// <param name="reader">Reader to get data from.</param>
        /// <param name="section">Section the row is added to.</param>
        /// <param name="tableDef">Table definition for this row.</param>
        /// <returns>New row object.</returns>
        internal static Row Parse(XmlReader reader, Section section, TableDefinition tableDef)
        {
            Debug.Assert("tuple" == reader.LocalName);

            bool empty = reader.IsEmptyElement;
            string sectionId = null;
            SourceLineNumberCollection sourceLineNumbers = null;

            while (reader.MoveToNextAttribute())
            {
                switch (reader.LocalName)
                {
                    case "sectionId":
                        sectionId = reader.Value;
                        break;
                    case "sourceLineNumber":
                        sourceLineNumbers = new SourceLineNumberCollection(reader.Value);
                        break;
                    default:
                        throw new WixParseException(String.Format("The tuple element contains an unexpected attribute {0}.", reader.Name));
                }
            }

            Row row = Common.CreateRowInSection(sourceLineNumbers, section, tableDef);
            row.sectionId = sectionId;

            // loop through all the fields in a row
            if (!empty)
            {
                bool done = false;
                int field = 0;

                // loop through all the fields in a row
                while (!done && reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element:
                        switch (reader.LocalName)
                        {
                            case "field":
                                if (row.Fields.Length <= field)
                                {
                                    throw new WixParseException(String.Format("This tuple has more fields for table '{0}' than are defined. This is potentially because a standard table is being redefined as a custom table.", tableDef.Name));
                                }
                                row[field] = Field.Parse(reader);
                                ++field;
                                break;
                            default:
                                throw new WixParseException(String.Format("The tuple element contains an unexpected child element {0}.", reader.Name));
                        }
                            break;
                        case XmlNodeType.EndElement:
                            done = true;
                            break;
                    }
                }

                if (!done)
                {
                    throw new WixParseException("Missing end element while processing the tuple element.");
                }
            }

            return row;
        }
Example #39
0
 /// <summary>Creates a Control row that does not belong to a table.</summary>
 /// <param name="tableDef">TableDefinition this Control row should get its column definitions from.</param>
 public BBControlRow(TableDefinition tableDef)
     : base(tableDef)
 {
 }
Example #40
0
 /// <summary>
 /// Creates a row that does not belong to a table.
 /// </summary>
 /// <param name="tableDef">TableDefinition this row should get its column definitions from.</param>
 /// <remarks>This constructor is used in cases where there isn't a clear owner of the row.  The linker uses this constructor for the rows it generates.</remarks>
 public Row(TableDefinition tableDef)
     : this(null, null == tableDef ? null : tableDef.Columns)
 {
     this.tableDef = tableDef;
 }
Example #41
0
        /// <summary>
        /// Parses a list item element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="table">Table to add row to.</param>
        /// <param name="property">Identifier of property referred to by list item.</param>
        /// <param name="order">Relative order of list items.</param>
        private void ParseListItemElement(XmlNode node, TableDefinition table, string property, ref int order)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string icon = null;
            string text = null;
            string value = null;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                        case "Icon":
                            if ("ListView" == table.Name)
                            {
                                icon = this.core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                                this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Binary", icon);
                            }
                            else
                            {
                                this.core.OnMessage(WixErrors.IllegalAttributeExceptOnElement(sourceLineNumbers, node.Name, attrib.Name, "ListView"));
                            }
                            break;
                        case "Text":
                            text = this.core.GetAttributeValue(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);
                }
            }

            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);
                    }
                }
            }

            if (!this.core.EncounteredError)
            {
                Row row = this.core.CreateRow(sourceLineNumbers, table.Name);
                row[0] = property;
                row[1] = ++order;
                row[2] = value;
                row[3] = text;
                if (null != icon)
                {
                    row[4] = icon;
                }
            }
        }
Example #42
0
 /// <summary>
 /// Creates a row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this row should get its column definitions from.</param>
 /// <remarks>This constructor is used in cases where there isn't a clear owner of the row.  The linker uses this constructor for the rows it generates.</remarks>
 public Row(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef)
     : this(sourceLineNumbers, null == tableDef ? null : tableDef.Columns)
 {
     this.tableDef = tableDef;
 }
Example #43
0
        /// <summary>
        /// Parses a control element.
        /// </summary>
        /// <param name="node">Element to parse.</param>
        /// <param name="dialog">Identifier for parent dialog.</param>
        /// <param name="table">Table control belongs in.</param>
        /// <param name="lastTabRow">Last row in the tab order.</param>
        /// <param name="firstControl">Name of the first control in the tab order.</param>
        /// <param name="defaultControl">Name of the default control.</param>
        /// <param name="cancelControl">Name of the candle control.</param>
        /// <param name="trackDiskSpace">True if the containing dialog tracks disk space.</param>
        private void ParseControlElement(XmlNode node, string dialog, TableDefinition table, ref Row lastTabRow, ref string firstControl, ref string defaultControl, ref string cancelControl, bool trackDiskSpace)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
            string id = null;
            BitArray bits = new BitArray(32);
            int attributes = 0;
            string checkBoxPropertyRef = null;
            string checkboxValue = null;
            string controlType = null;
            bool disabled = false;
            string height = null;
            string help = null;
            bool isCancel = false;
            bool isDefault = false;
            bool notTabbable = false;
            string property = null;
            int publishOrder = 0;
            string[] specialAttributes = null;
            string sourceFile = null;
            string text = null;
            string tooltip = null;
            RadioButtonType radioButtonsType = RadioButtonType.NotSet;
            string width = null;
            string x = null;
            string y = null;

            // The rest of the method relies on the control's Type, so we have to get that first.
            XmlAttribute typeAttribute = node.Attributes["Type"];
            if (null == typeAttribute)
            {
                this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Type"));
            }
            else
            {
                controlType = this.core.GetAttributeValue(sourceLineNumbers, typeAttribute);
            }

            switch (controlType)
            {
                case "Billboard":
                    specialAttributes = null;
                    notTabbable = true;
                    disabled = true;

                    this.core.EnsureTable(sourceLineNumbers, "Billboard");
                    break;
                case "Bitmap":
                    specialAttributes = MsiInterop.BitmapControlAttributes;
                    notTabbable = true;
                    disabled = true;
                    break;
                case "CheckBox":
                    specialAttributes = MsiInterop.CheckboxControlAttributes;
                    break;
                case "ComboBox":
                    specialAttributes = MsiInterop.ComboboxControlAttributes;
                    break;
                case "DirectoryCombo":
                    specialAttributes = MsiInterop.VolumeControlAttributes;
                    break;
                case "DirectoryList":
                    specialAttributes = null;
                    break;
                case "Edit":
                    specialAttributes = MsiInterop.EditControlAttributes;
                    break;
                case "GroupBox":
                    specialAttributes = null;
                    notTabbable = true;
                    break;
                case "Hyperlink":
                    specialAttributes = MsiInterop.HyperlinkControlAttributes;
                    break;
                case "Icon":
                    specialAttributes = MsiInterop.IconControlAttributes;
                    notTabbable = true;
                    disabled = true;
                    break;
                case "Line":
                    specialAttributes = null;
                    notTabbable = true;
                    disabled = true;
                    break;
                case "ListBox":
                    specialAttributes = MsiInterop.ListboxControlAttributes;
                    break;
                case "ListView":
                    specialAttributes = MsiInterop.ListviewControlAttributes;
                    break;
                case "MaskedEdit":
                    specialAttributes = MsiInterop.EditControlAttributes;
                    break;
                case "PathEdit":
                    specialAttributes = MsiInterop.EditControlAttributes;
                    break;
                case "ProgressBar":
                    specialAttributes = MsiInterop.ProgressControlAttributes;
                    notTabbable = true;
                    disabled = true;
                    break;
                case "PushButton":
                    specialAttributes = MsiInterop.ButtonControlAttributes;
                    break;
                case "RadioButtonGroup":
                    specialAttributes = MsiInterop.RadioControlAttributes;
                    break;
                case "ScrollableText":
                    specialAttributes = null;
                    break;
                case "SelectionTree":
                    specialAttributes = null;
                    break;
                case "Text":
                    specialAttributes = MsiInterop.TextControlAttributes;
                    notTabbable = true;
                    break;
                case "VolumeCostList":
                    specialAttributes = MsiInterop.VolumeControlAttributes;
                    notTabbable = true;
                    break;
                case "VolumeSelectCombo":
                    specialAttributes = MsiInterop.VolumeControlAttributes;
                    break;
                default:
                    specialAttributes = null;
                    notTabbable = true;
                    break;
            }

            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": // already processed
                            break;
                        case "Cancel":
                            isCancel = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        case "CheckBoxPropertyRef":
                            checkBoxPropertyRef = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "CheckBoxValue":
                            checkboxValue = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Default":
                            isDefault = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        case "Height":
                            height = this.core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "Help":
                            help = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "IconSize":
                            string iconSizeValue = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            if (null != specialAttributes)
                            {
                                if (0 < iconSizeValue.Length)
                                {
                                    Wix.Control.IconSizeType iconsSizeType = Wix.Control.ParseIconSizeType(iconSizeValue);
                                    switch (iconsSizeType)
                                    {
                                        case Wix.Control.IconSizeType.Item16:
                                            CompilerCore.NameToBit(specialAttributes, "Icon16", YesNoType.Yes, bits, 16);
                                            break;
                                        case Wix.Control.IconSizeType.Item32:
                                            CompilerCore.NameToBit(specialAttributes, "Icon32", YesNoType.Yes, bits, 16);
                                            break;
                                        case Wix.Control.IconSizeType.Item48:
                                            CompilerCore.NameToBit(specialAttributes, "Icon16", YesNoType.Yes, bits, 16);
                                            CompilerCore.NameToBit(specialAttributes, "Icon32", YesNoType.Yes, bits, 16);
                                            break;
                                        default:
                                            this.core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name, attrib.Name, iconSizeValue, "16", "32", "48"));
                                            break;
                                    }
                                }
                            }
                            else
                            {
                                this.core.OnMessage(WixErrors.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, node.Name, attrib.Name, iconSizeValue, "Type"));
                            }
                            break;
                        case "Property":
                            property = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "TabSkip":
                            notTabbable = YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            break;
                        case "Text":
                            text = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "ToolTip":
                            tooltip = this.core.GetAttributeValue(sourceLineNumbers, attrib);
                            break;
                        case "Width":
                            width = this.core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "X":
                            x = this.core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        case "Y":
                            y = this.core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
                            break;
                        default:
                            YesNoType attribValue = this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
                            if (!CompilerCore.NameToBit(MsiInterop.CommonControlAttributes, attrib.Name, attribValue, bits, 0))
                            {
                                if (null == specialAttributes || !CompilerCore.NameToBit(specialAttributes, attrib.Name, attribValue, bits, 16))
                                {
                                    this.core.UnexpectedAttribute(sourceLineNumbers, attrib);
                                }
                            }
                            break;
                    }
                }
                else
                {
                    this.core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            attributes = CompilerCore.ConvertBitArrayToInt32(bits);

            if (disabled)
            {
                attributes |= MsiInterop.MsidbControlAttributesEnabled; // bit will be inverted when stored
            }

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

            if (null == height)
            {
                this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Height"));
            }

            if (null == width)
            {
                this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Width"));
            }

            if (null == x)
            {
                this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "X"));
            }

            if (null == y)
            {
                this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Y"));
            }

            if (isCancel)
            {
                cancelControl = id;
            }

            if (isDefault)
            {
                defaultControl = id;
            }

            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 "Binary":
                                this.ParseBinaryElement(child);
                                break;
                            case "ComboBox":
                                this.ParseControlGroupElement(child, this.tableDefinitions["ComboBox"], "ListItem");
                                break;
                            case "Condition":
                                this.ParseConditionElement(child, node.LocalName, id, dialog);
                                break;
                            case "ListBox":
                                this.ParseControlGroupElement(child, this.tableDefinitions["ListBox"], "ListItem");
                                break;
                            case "ListView":
                                this.ParseControlGroupElement(child, this.tableDefinitions["ListView"], "ListItem");
                                break;
                            case "Property":
                                this.ParsePropertyElement(child);
                                break;
                            case "Publish":
                                // ensure that the dialog and control identifiers are not null
                                if (null == dialog)
                                {
                                    dialog = String.Empty;
                                }

                                if (null == id)
                                {
                                    id = String.Empty;
                                }

                                this.ParsePublishElement(child, dialog, id, ref publishOrder);
                                break;
                            case "RadioButtonGroup":
                                radioButtonsType = this.ParseRadioButtonGroupElement(child, property, radioButtonsType);
                                break;
                            case "Subscribe":
                                this.ParseSubscribeElement(child, dialog, id);
                                break;
                            case "Text":
                                foreach (XmlAttribute attrib in child.Attributes)
                                {
                                    switch (attrib.LocalName)
                                    {
                                        case "SourceFile":
                                        case "src":
                                            if (null != sourceFile)
                                            {
                                                this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(childSourceLineNumbers, node.Name, "src", "SourceFile"));
                                            }

                                            if ("src" == attrib.LocalName)
                                            {
                                                this.core.OnMessage(WixWarnings.DeprecatedAttribute(childSourceLineNumbers, node.Name, attrib.Name, "SourceFile"));
                                            }
                                            sourceFile = this.core.GetAttributeValue(childSourceLineNumbers, attrib);
                                            break;
                                        default:
                                            this.core.UnexpectedAttribute(childSourceLineNumbers, attrib);
                                            break;
                                    }
                                }

                                if (0 < child.InnerText.Length)
                                {
                                    if (null != sourceFile)
                                    {
                                        this.core.OnMessage(WixErrors.IllegalAttributeWithInnerText(childSourceLineNumbers, child.Name, "SourceFile"));
                                    }
                                    else
                                    {
                                        text = child.InnerText;
                                    }
                                }
                                break;
                            default:
                                this.core.UnexpectedElement(node, child);
                                break;
                        }
                    }
                    else
                    {
                        this.core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            // If the radio buttons have icons, then we need to add the icon attribute.
            switch (radioButtonsType)
            {
                case RadioButtonType.Bitmap:
                    attributes |= MsiInterop.MsidbControlAttributesBitmap;
                    break;
                case RadioButtonType.Icon:
                    attributes |= MsiInterop.MsidbControlAttributesIcon;
                    break;
                case RadioButtonType.Text:
                    // Text is the default so nothing needs to be added bits
                    break;
            }

            // If we're tracking disk space, and this is a non-FormatSize Text control, and the text attribute starts with 
            // '[' and ends with ']', add a space. It is not necessary for the whole string to be a property, just 
            // those two characters matter.
            if (trackDiskSpace && "Text" == controlType &&
                MsiInterop.MsidbControlAttributesFormatSize != (attributes & MsiInterop.MsidbControlAttributesFormatSize) &&
                null != text && text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal))
            {
                text = String.Concat(text, " ");
            }

            // the logic for creating control rows is a little tricky because of the way tabable controls are set
            Row row = null;
            if (!this.core.EncounteredError)
            {
                if ("CheckBox" == controlType)
                {
                    if (String.IsNullOrEmpty(property) && String.IsNullOrEmpty(checkBoxPropertyRef))
                    {
                        this.core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name, "Property", "CheckBoxPropertyRef", true));
                    }
                    else if (!String.IsNullOrEmpty(property) && !String.IsNullOrEmpty(checkBoxPropertyRef))
                    {
                        this.core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name, "Property", "CheckBoxPropertyRef"));
                    }
                    else if (!String.IsNullOrEmpty(property))
                    {
                        row = this.core.CreateRow(sourceLineNumbers, "CheckBox");
                        row[0] = property;
                        row[1] = checkboxValue;
                    }
                    else
                    {
                        this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CheckBox", checkBoxPropertyRef);
                    }
                }

                row = this.core.CreateRow(sourceLineNumbers, table.Name);
                row[0] = dialog;
                row[1] = id;
                row[2] = controlType;
                row[3] = x;
                row[4] = y;
                row[5] = width;
                row[6] = height;
                row[7] = attributes ^ (MsiInterop.MsidbControlAttributesVisible | MsiInterop.MsidbControlAttributesEnabled);
                if ("BBControl" == table.Name)
                {
                    row[8] = text; // BBControl.Text

                    if (null != sourceFile)
                    {
                        Row wixBBControlRow = this.core.CreateRow(sourceLineNumbers, "WixBBControl");
                        wixBBControlRow[0] = dialog;
                        wixBBControlRow[1] = id;
                        wixBBControlRow[2] = sourceFile;
                    }
                }
                else
                {
                    row[8] = !String.IsNullOrEmpty(property) ? property : checkBoxPropertyRef;
                    row[9] = text;
                    if (null != tooltip || null != help)
                    {
                        row[11] = String.Concat(tooltip, "|", help); // Separator is required, even if only one is non-null.
                    }

                    if (null != sourceFile)
                    {
                        Row wixControlRow = this.core.CreateRow(sourceLineNumbers, "WixControl");
                        wixControlRow[0] = dialog;
                        wixControlRow[1] = id;
                        wixControlRow[2] = sourceFile;
                    }
                }
            }

            if (!notTabbable)
            {
                if ("BBControl" == table.Name)
                {
                    this.core.OnMessage(WixErrors.TabbableControlNotAllowedInBillboard(sourceLineNumbers, node.Name, controlType));
                }

                if (null == firstControl)
                {
                    firstControl = id;
                }

                if (null != lastTabRow)
                {
                    lastTabRow[10] = id;
                }
                lastTabRow = row;
            }

            // bitmap and icon controls contain a foreign key into the binary table in the text column;
            // add a reference if the identifier of the binary entry is known during compilation
            if (("Bitmap" == controlType || "Icon" == controlType) && CompilerCore.IsIdentifier(text))
            {
                this.core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Binary", text);
            }
        }
Example #44
0
        /// <summary>
        /// Create a row in a section.
        /// </summary>
        /// <param name="sourceLineNumbers">Line number information about the row.</param>
        /// <param name="section">Section in which a row is to be added.</param>
        /// <param name="tableDefinition">Table definition for the row being added.</param>
        /// <returns>The row added to the section.</returns>
        internal static Row CreateRowInSection(SourceLineNumberCollection sourceLineNumbers, Section section, TableDefinition tableDefinition)
        {
            Table table = section.Tables[tableDefinition.Name];
            if (null == table)
            {
                table = new Table(section, tableDefinition);
                section.Tables.Add(table);
            }

            return table.CreateRow(sourceLineNumbers);
        }
Example #45
0
        /// <summary>
        /// Links an array of intermediates into an output.
        /// </summary>
        /// <param name="intermediates">Array of intermediates to link together.</param>
        /// <returns>Output object from the linking.</returns>
        public Output Link(Intermediate[] intermediates)
        {
            Output output = null;

            try
            {
                SymbolCollection allSymbols;
                Section entrySection;
                bool containsModuleSubstitution = false;
                bool containsModuleConfiguration = false;

                StringCollection referencedSymbols = new StringCollection();
                ArrayList unresolvedReferences = new ArrayList();

                ConnectToFeatureCollection componentGroupsToFeatures = new ConnectToFeatureCollection();
                ConnectToModuleCollection componentGroupsToModules = new ConnectToModuleCollection();
                ComplexReferenceCollection componentsToComponentGroupsComplexReferences = new ComplexReferenceCollection();
                ConnectToFeatureCollection componentsToFeatures = new ConnectToFeatureCollection();
                ConnectToFeatureCollection featuresToFeatures = new ConnectToFeatureCollection();

                this.activeOutput = null;
                this.foundError = false;

                SortedList adminProperties = new SortedList();
                SortedList secureProperties = new SortedList();
                SortedList hiddenProperties = new SortedList();

                ActionTable requiredActions = new ActionTable();
                RowCollection suppressActionRows = new RowCollection();
                TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection();
                RowCollection customRows = new RowCollection();

                foreach (SchemaExtension extension in this.extensions.Values)
                {
                    extension.Messages = this.extensionMessages;
                }

                // first find the entry section and create the symbols hash for all
                // the sections in all the intermediates
                Common.FindEntrySectionAndLoadSymbols(intermediates, this.allowIdenticalRows, this, out entrySection, out allSymbols);

                // should have found an entry section by now
                if (null == entrySection)
                {
                    this.OnMessage(WixErrors.MissingEntrySection());
                    return null;
                }

                // add the standard action symbols to the entry section's symbol table
                this.LoadStandardActionSymbols(allSymbols, entrySection, this.standardActions);

                // now that we know where we're starting from, create the output object
                output = new Output(entrySection); // Note: this entry section will get added to the output section collection later
                if (null != this.localizer && -1 != this.localizer.Codepage)
                {
                    output.Codepage = this.localizer.Codepage;
                }
                this.activeOutput = output;

                // resolve the symbol references to find the set of sections we
                // care about then resolve complex references in those sections
                Common.ResolveReferences(output.Type, output.Sections, output.EntrySection, allSymbols, referencedSymbols, unresolvedReferences, this);
                this.ProcessComplexReferences(output, output.Sections, referencedSymbols, componentsToComponentGroupsComplexReferences, componentGroupsToFeatures, componentGroupsToModules, componentsToFeatures, featuresToFeatures);
                for (int i = 0; i < unresolvedReferences.Count; ++i)
                {
                    Common.ReferenceSection referenceSection = (Common.ReferenceSection)unresolvedReferences[i];
                    if (this.allowUnresolvedReferences)
                    {
                        this.OnMessage(WixWarnings.UnresolvedReferenceWarning(SourceLineNumberCollection.FromFileName(referenceSection.section.Intermediate.SourcePath), referenceSection.section.Type.ToString(), referenceSection.section.Id, referenceSection.reference.SymbolicName));
                    }
                    else
                    {
                        this.OnMessage(WixErrors.UnresolvedReference(SourceLineNumberCollection.FromFileName(referenceSection.section.Intermediate.SourcePath), referenceSection.section.Type.ToString(), referenceSection.section.Id, referenceSection.reference.SymbolicName));
                    }
                }

                if (this.foundError)
                {
                    return null;
                }

                this.ResolveComponentGroups(output, referencedSymbols, componentsToComponentGroupsComplexReferences, componentGroupsToFeatures, componentGroupsToModules, componentsToFeatures);
                this.FindOrphanedSymbols(referencedSymbols);

                // resolve the feature backlink for each section then update the feature to feature connects
                this.ResolveFeatureBacklinks(output, componentsToFeatures, allSymbols, referencedSymbols, unresolvedReferences);
                this.ResolveFeatureToFeatureConnects(featuresToFeatures, allSymbols, referencedSymbols, unresolvedReferences);

                // create a Hashtable of all the suppressed sequence types
                Hashtable suppressedSequenceTypes = new Hashtable();
                // create a Hashtable of all the suppressed standard actions
                Hashtable suppressedStandardActions = new Hashtable();

                if (this.suppressAdminSequence)
                {
                    suppressedSequenceTypes[SequenceType.adminExecute] = null;
                    suppressedSequenceTypes[SequenceType.adminUI] = null;
                }
                if (this.suppressAdvertiseSequence)
                {
                    suppressedSequenceTypes[SequenceType.advertiseExecute] = null;
                }
                if (this.suppressUISequence)
                {
                    suppressedSequenceTypes[SequenceType.adminUI] = null;
                    suppressedSequenceTypes[SequenceType.installUI] = null;
                }

                // start generating OutputTables and OutputRows for all the sections in the output
                RowCollection ensureTableRows = new RowCollection();
                foreach (Section section in this.activeOutput.Sections)
                {
                    // add this sections list of identifiers to ignore modularization
                    this.activeOutput.IgnoreModularizations.Add(section.IgnoreModularizations);

                    foreach (Table table in section.Tables)
                    {
                        bool copyRows = !table.Definition.IsUnreal; // by default, copy rows if the table is not unreal

                        // handle special tables
                        switch (table.Name)
                        {
                            case "Actions":
                                foreach (Row row in table.Rows)
                                {
                                    SequenceType sequenceType;
                                    string seqType = (string)row[0];
                                    string id = (string)row[1];
                                    int sequence = null == row[3] ? 0 : Convert.ToInt32(row[3]);
                                    bool suppress = 1 == Convert.ToInt32(row[6]);

                                    switch (seqType)
                                    {
                                        case "AdminUISequence":
                                            sequenceType = SequenceType.adminUI;
                                            break;
                                        case "AdminExecuteSequence":
                                            sequenceType = SequenceType.adminExecute;
                                            break;
                                        case "AdvertiseExecuteSequence":
                                            sequenceType = SequenceType.advertiseExecute;
                                            break;
                                        case "InstallExecuteSequence":
                                            sequenceType = SequenceType.installExecute;
                                            break;
                                        case "InstallUISequence":
                                            sequenceType = SequenceType.installUI;
                                            break;
                                        default:
                                            throw new WixInvalidSequenceTypeException(null, seqType);
                                    }

                                    if (suppressedSequenceTypes.Contains(sequenceType))
                                    {
                                        this.OnMessage(WixWarnings.SuppressAction(id, Action.SequenceTypeToString(sequenceType)));
                                        continue;
                                    }

                                    // create a SuppressAction row to allow suppressing the action from a merge module
                                    if (suppress)
                                    {
                                        Row suppressActionRow = new Row(row.SourceLineNumbers, this.tableDefinitions["SuppressAction"]);
                                        if ("AdvertiseExecuteSequence" == (string)row[0])
                                        {
                                            suppressActionRow[0] = "AdvtExecuteSequence";
                                        }
                                        else
                                        {
                                            suppressActionRow[0] = row[0];
                                        }
                                        suppressActionRow[1] = row[1];

                                        suppressActionRows.Add(suppressActionRow);
                                    }

                                    Action action = this.standardActions[sequenceType, id];
                                    string beforeAction = (string)row[4];
                                    string afterAction = (string)row[5];

                                    // if this is not a standard action or there is a before or after action specified
                                    if (null == action || null != beforeAction || null != afterAction)
                                    {
                                        action = new Action(sequenceType, id, (string)row[2], sequence, beforeAction, afterAction);
                                        requiredActions.Add(action, true); // add the action and overwrite even if it already exists since this is a customization

                                        // if the parent action is a standard action add it to the required list
                                        string parentActionName = null != beforeAction ? beforeAction : afterAction;
                                        Action parentAction = this.standardActions[sequenceType, parentActionName];
                                        if (null != parentAction)
                                        {
                                            requiredActions.Add(parentAction);
                                        }
                                    }
                                    else if (!suppress) // must have a standard action that is being overriden (when not suppressed)
                                    {
                                        action.Condition = (string)row[2];
                                        if (0 != sequence) // if the user specified a sequence number, override the default
                                        {
                                            action.SequenceNumber = sequence;
                                        }

                                        requiredActions.Add(action, true); // ensure this action is in the required list
                                    }

                                    // action was suppressed by user
                                    if (suppress && null != action)
                                    {
                                        suppressedStandardActions[String.Concat(action.SequenceType.ToString(), id)] = action;
                                    }
                                }
                                break;

                            case "AppSearch":
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Signature"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "AppSearch"]);
                                requiredActions.Add(this.standardActions[SequenceType.installUI, "AppSearch"]);
                                break;

                            case "Binary":
                            case "Icon":
                            case "MsiDigitalCertificate":
                                foreach (Row row in table.Rows)
                                {
                                    ImportStreamType importStreamType = ImportStreamType.Unknown;
                                    switch (table.Name)
                                    {
                                        case "Binary":
                                            importStreamType = ImportStreamType.Binary;
                                            break;
                                        case "Icon":
                                            importStreamType = ImportStreamType.Icon;
                                            break;
                                        case "MsiDigitalCertificate":
                                            importStreamType = ImportStreamType.DigitalCertificate;
                                            break;
                                    }

                                    ImportStream importStream = new ImportStream(importStreamType, row[0].ToString(), row[1].ToString());
                                    if (this.activeOutput.ImportStreams.Contains(importStream.Name))
                                    {
                                        this.OnMessage(WixErrors.DuplicateSymbol(row.SourceLineNumbers, String.Format("{0} element with Id='{1}' is defined multiple times.", table.Name, row.Symbol.Name)));
                                    }

                                    this.activeOutput.ImportStreams.Add(importStream);
                                }
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions[table.Name]);
                                copyRows = false;
                                break;

                            case "BindImage":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "BindImage"]);
                                break;

                            case "CCPSearch":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "AppSearch"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "CCPSearch"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RMCCPSearch"]);
                                requiredActions.Add(this.standardActions[SequenceType.installUI, "AppSearch"]);
                                requiredActions.Add(this.standardActions[SequenceType.installUI, "CCPSearch"]);
                                requiredActions.Add(this.standardActions[SequenceType.installUI, "RMCCPSearch"]);
                                break;

                            case "Class":
                                requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterClassInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterClassInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterClassInfo"]);
                                break;

                            case "Complus":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterComPlus"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterComPlus"]);
                                break;

                            case "CreateFolder":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "CreateFolders"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveFolders"]);
                                break;

                            case "CustomAction":
                                if (OutputType.Module == this.activeOutput.Type)
                                {
                                    Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminExecuteSequence"]);
                                    Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminUISequence"]);
                                    Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdvtExecuteSequence"]);
                                    Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallExecuteSequence"]);
                                    Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallUISequence"]);
                                }
                                break;

                            case "CustomTables":
                                foreach (Row row in table.Rows)
                                {
                                    TableDefinition customTable = new TableDefinition((string)row[0], false);

                                    if (null == row[4])
                                    {
                                        this.OnMessage(WixErrors.ExpectedAttribute(row.SourceLineNumbers, "CustomTable/Column", "PrimaryKey"));
                                    }

                                    string[] columnNames = row[2].ToString().Split(tabCharacter);
                                    string[] columnTypes = row[3].ToString().Split(tabCharacter);
                                    string[] primaryKeys = row[4].ToString().Split(tabCharacter);
                                    string[] minValues = row[5] == null ? null : row[5].ToString().Split(tabCharacter);
                                    string[] maxValues = row[6] == null ? null : row[6].ToString().Split(tabCharacter);
                                    string[] keyTables = row[7] == null ? null : row[7].ToString().Split(tabCharacter);
                                    string[] keyColumns = row[8] == null ? null : row[8].ToString().Split(tabCharacter);
                                    string[] categories = row[9] == null ? null : row[9].ToString().Split(tabCharacter);
                                    string[] sets = row[10] == null ? null : row[10].ToString().Split(tabCharacter);
                                    string[] descriptions = row[11] == null ? null : row[11].ToString().Split(tabCharacter);
                                    string[] modularizations = row[12] == null ? null : row[12].ToString().Split(tabCharacter);

                                    int currentPrimaryKey = 0;

                                    for (int i = 0; i < columnNames.Length; ++i)
                                    {
                                        string name = columnNames[i];
                                        ColumnType type = ColumnType.Unknown;
                                        switch (columnTypes[i].Substring(0, 1).ToLower(CultureInfo.InvariantCulture))
                                        {
                                            case "s":
                                                type = ColumnType.String;
                                                break;
                                            case "l":
                                                type = ColumnType.Localized;
                                                break;
                                            case "i":
                                                type = ColumnType.Number;
                                                break;
                                            case "g":
                                                type = ColumnType.Object;
                                                break;
                                            default:
                                                throw new ApplicationException(String.Format("Unknown custom table column type: {0}", columnTypes[i]));
                                        }
                                        bool nullable = columnTypes[i].Substring(0, 1) == columnTypes[i].Substring(0, 1).ToUpper(CultureInfo.InvariantCulture);
                                        int length = Convert.ToInt32(columnTypes[i].Substring(1));

                                        bool primaryKey = false;
                                        if (currentPrimaryKey < primaryKeys.Length && primaryKeys[currentPrimaryKey] == columnNames[i])
                                        {
                                            primaryKey = true;
                                            currentPrimaryKey++;
                                        }

                                        bool minValSet = null != minValues && null != minValues[i] && 0 < minValues[i].Length;
                                        int minValue = 0;
                                        if (minValSet)
                                        {
                                            minValue = Convert.ToInt32(minValues[i]);
                                        }

                                        bool maxValSet = null != maxValues && null != maxValues[i] && 0 < maxValues[i].Length;
                                        int maxValue = 0;
                                        if (maxValSet)
                                        {
                                            maxValue = Convert.ToInt32(maxValues[i]);
                                        }

                                        bool keyColumnSet = null != keyColumns && null != keyColumns[i] && 0 < keyColumns[i].Length;
                                        int keyColumn = 0;
                                        if (keyColumnSet)
                                        {
                                            keyColumn = Convert.ToInt32(keyColumns[i]);
                                        }

                                        ColumnCategory category = ColumnCategory.Unknown;
                                        if (null != categories && null != categories[i] && 0 < categories[i].Length)
                                        {
                                            switch (categories[i])
                                            {
                                                case "Text":
                                                    category = ColumnCategory.Text;
                                                    break;
                                                case "UpperCase":
                                                    category = ColumnCategory.UpperCase;
                                                    break;
                                                case "LowerCase":
                                                    category = ColumnCategory.LowerCase;
                                                    break;
                                                case "Integer":
                                                    category = ColumnCategory.Integer;
                                                    break;
                                                case "DoubleInteger":
                                                    category = ColumnCategory.DoubleInteger;
                                                    break;
                                                case "TimeDate":
                                                    category = ColumnCategory.TimeDate;
                                                    break;
                                                case "Identifier":
                                                    category = ColumnCategory.Identifier;
                                                    break;
                                                case "Property":
                                                    category = ColumnCategory.Property;
                                                    break;
                                                case "Filename":
                                                    category = ColumnCategory.Filename;
                                                    break;
                                                case "WildCardFilename":
                                                    category = ColumnCategory.WildCardFilename;
                                                    break;
                                                case "Path":
                                                    category = ColumnCategory.Path;
                                                    break;
                                                case "Paths":
                                                    category = ColumnCategory.Paths;
                                                    break;
                                                case "AnyPath":
                                                    category = ColumnCategory.AnyPath;
                                                    break;
                                                case "DefaultDir":
                                                    category = ColumnCategory.DefaultDir;
                                                    break;
                                                case "RegPath":
                                                    category = ColumnCategory.RegPath;
                                                    break;
                                                case "Formatted":
                                                    category = ColumnCategory.Formatted;
                                                    break;
                                                case "Template":
                                                    category = ColumnCategory.Template;
                                                    break;
                                                case "Condition":
                                                    category = ColumnCategory.Condition;
                                                    break;
                                                case "Guid":
                                                    category = ColumnCategory.Guid;
                                                    break;
                                                case "Version":
                                                    category = ColumnCategory.Version;
                                                    break;
                                                case "Language":
                                                    category = ColumnCategory.Language;
                                                    break;
                                                case "Binary":
                                                    category = ColumnCategory.Binary;
                                                    break;
                                                case "CustomSource":
                                                    category = ColumnCategory.CustomSource;
                                                    break;
                                                case "Cabinet":
                                                    category = ColumnCategory.Cabinet;
                                                    break;
                                                case "Shortcut":
                                                    category = ColumnCategory.Shortcut;
                                                    break;
                                                default:
                                                    break;
                                            }
                                        }

                                        string keyTable = keyTables != null ? keyTables[i] : null;
                                        string setValue = sets != null ? sets[i] : null;
                                        string description = descriptions != null ? descriptions[i] : null;
                                        string modString = modularizations != null ? modularizations[i] : null;
                                        ColumnModularizeType modularization = ColumnModularizeType.None;
                                        if (modString != null)
                                        {
                                            switch (modString)
                                            {
                                                case "None":
                                                    modularization = ColumnModularizeType.None;
                                                    break;
                                                case "Column":
                                                    modularization = ColumnModularizeType.Column;
                                                    break;
                                                case "Property":
                                                    modularization = ColumnModularizeType.Property;
                                                    break;
                                                case "Condition":
                                                    modularization = ColumnModularizeType.Condition;
                                                    break;
                                                case "CompanionFile":
                                                    modularization = ColumnModularizeType.CompanionFile;
                                                    break;
                                                case "SemicolonDelimited":
                                                    modularization = ColumnModularizeType.SemicolonDelimited;
                                                    break;
                                            }
                                        }

                                        ColumnDefinition columnDefinition = new ColumnDefinition(name, type, length, primaryKey, false, nullable, modularization, false, ColumnType.Localized == type, minValSet, minValue, maxValSet, maxValue, keyTable, keyColumnSet, keyColumn, category, setValue, description, true, true);
                                        customTable.Columns.Add(columnDefinition);
                                    }

                                    customTableDefinitions.Add(customTable);
                                }

                                copyRows = false; // we've created table definitions from these rows, no need to process them any longer
                                break;

                            case "RowData":
                                foreach (Row row in table.Rows)
                                {
                                    customRows.Add(row);
                                }

                                copyRows = false;
                                break;

                            case "Dialog":
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ListBox"]);
                                break;

                            case "Directory":
                                foreach (Row row in table.Rows)
                                {
                                    if (OutputType.Module == this.activeOutput.Type && Common.IsStandardDirectory(row[0].ToString()))
                                    {
                                        // if the directory table contains references to standard windows folders
                                        // mergemod.dll will add customactions to set the MSM directory to
                                        // the same directory as the standard windows folder and will add references to
                                        // custom action to all the standard sequence tables.  A problem will occur
                                        // if the MSI does not have these tables as mergemod.dll does not add these
                                        // tables to the MSI if absent.  This code adds the tables in case mergemod.dll
                                        // needs them.
                                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["CustomAction"]);
                                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminExecuteSequence"]);
                                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminUISequence"]);
                                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdvtExecuteSequence"]);
                                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallExecuteSequence"]);
                                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallUISequence"]);
                                        break; // no need to look here any more, we already found all that we needed to
                                    }
                                }
                                break;

                            case "DuplicateFile":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "DuplicateFiles"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveDuplicateFiles"]);
                                break;

                            case "EnsureTables":
                                foreach (Row row in table.Rows)
                                {
                                    ensureTableRows.Add(row);
                                }
                                break;

                            case "Environment":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "WriteEnvironmentStrings"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveEnvironmentStrings"]);
                                break;

                            case "Extension":
                                requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterExtensionInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterExtensionInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterExtensionInfo"]);
                                break;

                            case "File":
                                foreach (FileRow row in table.Rows)
                                {
                                    // DiskId is not valid when creating a module, so set it to
                                    // 0 for all files to ensure proper sorting in the binder
                                    if (OutputType.Module == this.activeOutput.Type)
                                    {
                                        row.DiskId = 0;
                                    }

                                    // if we have an assembly, insert the MsiAssembly row and assembly actions
                                    if (FileAssemblyType.NotAnAssembly != row.AssemblyType)
                                    {
                                        string feature;
                                        if (OutputType.Module == output.Type)
                                        {
                                            feature = Guid.Empty.ToString("B");
                                        }
                                        else
                                        {
                                            ConnectToFeature connect = componentsToFeatures[row.Component];
                                            if (null == connect)
                                            {
                                                throw new WixMissingFeatureException(row.SourceLineNumbers, new FeatureBacklink(row.Component, FeatureBacklinkType.Assembly, row.File));
                                            }
                                            feature = connect.PrimaryFeature;
                                        }

                                        OutputTable assemblyOutputTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiAssembly"]);
                                        Row assemblyRow = new Row(assemblyOutputTable.TableDefinition);
                                        assemblyRow[0] = row.Component;
                                        assemblyRow[1] = feature;
                                        assemblyRow[2] = row.AssemblyManifest;
                                        assemblyRow[3] = row.AssemblyApplication;
                                        assemblyRow[4] = Convert.ToInt32(row.AssemblyType);
                                        assemblyOutputTable.OutputRows.Add(new OutputRow(assemblyRow, this.sectionIdOnTuples ? section.Id : null));

                                        requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "MsiPublishAssemblies"]);
                                        requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiPublishAssemblies"]);
                                        requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiUnpublishAssemblies"]);
                                    }

                                    if (null == row.Source) // source to the file must be provided
                                    {
                                        this.OnMessage(WixErrors.FileSourceRequired(row.SourceLineNumbers, row.File));
                                    }
                                    this.activeOutput.FileMediaInformationCollection.Add(new FileMediaInformation(row));
                                }
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "InstallFiles"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveFiles"]);
                                break;

                            case "Font":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterFonts"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterFonts"]);
                                break;

                            case "IniFile":
                            case "RemoveIniFile":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "WriteIniValues"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveIniValues"]);
                                break;

                            case "IsolatedComponent":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "IsolateComponents"]);
                                break;

                            case "LaunchCondition":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "LaunchConditions"]);
                                requiredActions.Add(this.standardActions[SequenceType.installUI, "LaunchConditions"]);
                                break;

                            case "Media":
                                foreach (MediaRow row in table.Rows)
                                {
                                    this.activeOutput.MediaRows.Add(row);
                                }
                                copyRows = false;
                                break;

                            case "Merge":
                                // just copy the rows to the output
                                copyRows = true;
                                break;

                            case "MIME":
                                requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterMIMEInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterMIMEInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterMIMEInfo"]);
                                break;

                            case "ModuleSignature":
                                if (OutputType.Module == this.activeOutput.Type)
                                {
                                    foreach (Row row in table.Rows)
                                    {
                                        if (null != this.activeOutput.ModularizationGuid)
                                        {
                                            throw new ArgumentOutOfRangeException("Unexpected number of rows found in table", "ModuleSignature");
                                        }

                                        this.activeOutput.ModularizationGuid = row[3].ToString();
                                    }
                                }
                                break;

                            case "ModuleSubstitution":
                                containsModuleSubstitution = true;
                                break;

                            case "ModuleConfiguration":
                                containsModuleConfiguration = true;
                                break;

                            case "MoveFile":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "MoveFiles"]);
                                break;

                            case "MsiAssembly":
                                requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "MsiPublishAssemblies"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiPublishAssemblies"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiUnpublishAssemblies"]);
                                break;

                            case "ODBCDataSource":
                            case "ODBCTranslator":
                            case "ODBCDriver":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "SetODBCFolders"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "InstallODBC"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveODBC"]);
                                break;

                            case "ProgId":
                                requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterProgIdInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterProgIdInfo"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterProgIdInfo"]);
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Extension"]); // Extension table is required with a ProgId table
                                break;

                            case "Property":
                                foreach (PropertyRow row in table.Rows)
                                {
                                    // if there is no value in the property, then it must be virtual
                                    if (null == row.Value || 0 == row.Value.Length)
                                    {
                                        row.IsUnreal = true;
                                    }

                                    if (row.Admin)
                                    {
                                        adminProperties[row.Id] = null;
                                    }

                                    if (row.Secure)
                                    {
                                        secureProperties[row.Id] = null;
                                    }

                                    if (row.Hidden)
                                    {
                                        hiddenProperties[row.Id] = null;
                                    }
                                }
                                break;

                            case "PublishComponent":
                                requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "PublishComponents"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "PublishComponents"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnpublishComponents"]);
                                break;

                            case "Registry":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "WriteRegistryValues"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveRegistryValues"]);
                                break;

                            case "RemoveFile":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveFiles"]);
                                break;

                            case "SelfReg":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "SelfRegModules"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "SelfUnregModules"]);
                                break;

                            case "ServiceControl":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "StartServices"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "StopServices"]);
                                break;

                            case "ServiceInstall":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "InstallServices"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "DeleteServices"]);
                                break;

                            case "Shortcut":
                                requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "CreateShortcuts"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "CreateShortcuts"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveShortcuts"]);
                                break;

                            case "TypeLib":
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterTypeLibraries"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterTypeLibraries"]);
                                break;

                            case "Upgrade":
                            {
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "FindRelatedProducts"]);
                                requiredActions.Add(this.standardActions[SequenceType.installExecute, "MigrateFeatureStates"]);
                                requiredActions.Add(this.standardActions[SequenceType.installUI, "FindRelatedProducts"]);
                                requiredActions.Add(this.standardActions[SequenceType.installUI, "MigrateFeatureStates"]);

                                foreach (UpgradeRow row in table.Rows)
                                {
                                    // this should never happen because candle will make sure that all UpgradeVersion(s) have an ActionProperty...but still don't let it slide
                                    if (null == row.ActionProperty)
                                    {
                                        this.OnMessage(WixErrors.ExpectedAttribute(row.SourceLineNumbers, "UpgradeVersion", "ActionProperty"));
                                    }

                                    secureProperties[row.ActionProperty] = null;
                                }

                                break;
                            }

                            case "_SummaryInformation":
                                // if we are processing a product, reach into the summary
                                // information and pull out the bits that say if the layout
                                // image is supposed to have long file names and is compressed
                                if (OutputType.Product == output.Type)
                                {
                                    foreach (Row row in table.Rows)
                                    {
                                        // we're looking for the "Word Count" property which happens to
                                        // be number 15 (and I thought the answer to the universe was 42, heh).
                                        if ("15" == row[0].ToString())
                                        {
                                            output.LongFileNames = (0 == (Convert.ToInt32(row[1]) & 1));
                                            output.Compressed = (2 == (Convert.ToInt32(row[1]) & 2));

                                            break; // we're done looking for what we came looking for
                                        }
                                    }
                                }
                                break;
                        }

                        if (copyRows)
                        {
                            OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions[table.Name]);
                            this.CopyTableRowsToOutputTable(table, outputTable, section.Id);
                        }
                    }
                }

                if (0 < ensureTableRows.Count)
                {
                    foreach (Row row in ensureTableRows)
                    {
                        string tableId = (string)row[0];
                        TableDefinition tableDef = null;

                        try
                        {
                            tableDef = this.tableDefinitions[tableId];
                        }
                        catch (WixMissingTableDefinitionException)
                        {
                            tableDef = customTableDefinitions[tableId];
                        }

                        Common.EnsureOutputTable(this.activeOutput, tableDef);
                    }
                }

                // copy all the suppress action rows to the output to suppress actions from merge modules
                if (0 < suppressActionRows.Count)
                {
                    OutputTable suppressActionOutputTable = new OutputTable(this.tableDefinitions["SuppressAction"]);
                    this.activeOutput.OutputTables.Add(suppressActionOutputTable);
                    foreach (Row suppressActionRow in suppressActionRows)
                    {
                        suppressActionOutputTable.OutputRows.Add(new OutputRow(suppressActionRow));
                    }
                }

                foreach (Action suppressedAction in suppressedStandardActions.Values)
                {
                    if (requiredActions.Contains(suppressedAction))
                    {
                        // We thought they really ought to have a standard action
                        // that they wanted to suppress, so warn them and remove it
                        this.OnMessage(WixWarnings.SuppressAction(suppressedAction.Id, Action.SequenceTypeToString(suppressedAction.SequenceType)));
                        requiredActions.Remove(suppressedAction);
                    }
                }

                // check for missing table and add them or display an error as appropriate
                switch (this.activeOutput.Type)
                {
                    case OutputType.Module:
                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Component"]);
                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Directory"]);
                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["FeatureComponents"]);
                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["File"]);
                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleComponents"]);
                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleSignature"]);
                        break;
                    case OutputType.PatchCreation:
                        OutputTable imageFamiliesTable = this.activeOutput.OutputTables["ImageFamilies"];
                        OutputTable targetImagesTable = this.activeOutput.OutputTables["TargetImages"];
                        OutputTable upgradedImagesTable = this.activeOutput.OutputTables["UpgradedImages"];

                        if (null == imageFamiliesTable || 1 > imageFamiliesTable.OutputRows.Count)
                        {
                            this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("ImageFamilies"));
                        }

                        if (null == targetImagesTable || 1 > targetImagesTable.OutputRows.Count)
                        {
                            this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("TargetImages"));
                        }

                        if (null == upgradedImagesTable || 1 > upgradedImagesTable.OutputRows.Count)
                        {
                            this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("UpgradedImages"));
                        }

                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Properties"]);
                        break;
                    case OutputType.Product:
                        // AdminExecuteSequence Table
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "CostInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "CostInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "FileCost"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "CostFinalize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallValidate"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallFiles"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallAdminPackage"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallFinalize"]);

                        // AdminUISequence Table
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "CostInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "FileCost"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "CostFinalize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "ExecuteAction"]);

                        // AdvtExecuteSequence Table
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "CostInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "CostFinalize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "InstallValidate"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "InstallInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "PublishFeatures"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "PublishProduct"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "InstallFinalize"]);

                        // InstallExecuteSequence Table
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "ValidateProductID"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "CostInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "FileCost"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "CostFinalize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "InstallValidate"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "InstallInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "ProcessComponents"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "UnpublishFeatures"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "CostInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "RegisterUser"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "RegisterProduct"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "PublishFeatures"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "PublishProduct"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "InstallFinalize"]);

                        // InstallUISequence Table
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "ValidateProductID"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "CostInitialize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "FileCost"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "CostFinalize"]);
                        this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "ExecuteAction"]);

                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["File"]);
                        Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Media"]);
                        break;
                }

                // check for illegal tables
                foreach (OutputTable table in this.activeOutput.OutputTables)
                {
                    switch (this.activeOutput.Type)
                    {
                        case OutputType.Module:
                            if ("BBControl" == table.Name ||
                                "Billboard" == table.Name ||
                                "CCPSearch" == table.Name ||
                                "Feature" == table.Name ||
                                "LaunchCondition" == table.Name ||
                                "Media" == table.Name ||
                                "Merge" == table.Name ||
                                "Patch" == table.Name ||
                                "Upgrade" == table.Name)
                            {
                                foreach (OutputRow outputRow in table.OutputRows)
                                {
                                    this.OnMessage(WixErrors.UnexpectedTableInMergeModule(outputRow.Row.SourceLineNumbers, table.Name));
                                }
                            }
                            else if ("Error" == table.Name)
                            {
                                foreach (OutputRow outputRow in table.OutputRows)
                                {
                                    this.OnMessage(WixWarnings.DangerousTableInMergeModule(outputRow.Row.SourceLineNumbers, table.Name));
                                }
                            }
                            break;
                        case OutputType.PatchCreation:
                            if ("_SummaryInformation" != table.Name &&
                                "ExternalFiles" != table.Name &&
                                "FamilyFileRanges" != table.Name &&
                                "ImageFamilies" != table.Name &&
                                "PatchMetadata" != table.Name &&
                                "PatchSequence" != table.Name &&
                                "Properties" != table.Name &&
                                "TargetFiles_OptionalData" != table.Name &&
                                "TargetImages" != table.Name &&
                                "UpgradedFiles_OptionalData" != table.Name &&
                                "UpgradedFilesToIgnore" != table.Name &&
                                "UpgradedImages" != table.Name)
                            {
                                foreach (OutputRow outputRow in table.OutputRows)
                                {
                                    this.OnMessage(WixErrors.UnexpectedTableInPatchCreationPackage(outputRow.Row.SourceLineNumbers, table.Name));
                                }
                            }
                            break;
                        case OutputType.Product:
                            if ("ModuleAdminExecuteSequence" == table.Name ||
                                "ModuleAdminUISequence" == table.Name ||
                                "ModuleAdvtExecuteSequence" == table.Name ||
                                "ModuleAdvtUISequence" == table.Name ||
                                "ModuleComponents" == table.Name ||
                                "ModuleConfiguration" == table.Name ||
                                "ModuleDependency" == table.Name ||
                                "ModuleExclusion" == table.Name ||
                                "ModuleIgnoreTable" == table.Name ||
                                "ModuleInstallExecuteSequence" == table.Name ||
                                "ModuleInstallUISequence" == table.Name ||
                                "ModuleSignature" == table.Name ||
                                "ModuleSubstitution" == table.Name)
                            {
                                foreach (OutputRow outputRow in table.OutputRows)
                                {
                                    this.OnMessage(WixWarnings.UnexpectedTableInProduct(outputRow.Row.SourceLineNumbers, table.Name));
                                }
                            }
                            break;
                    }
                }

                // add the custom row data
                foreach (Row row in customRows)
                {
                    TableDefinition customTable = (TableDefinition)customTableDefinitions[row[0].ToString()];

                    string[] data = row[2].ToString().Split(tabCharacter);

                    Row customRow = new Row(customTable);
                    for (int i = 0; i < data.Length; ++i)
                    {
                        string[] item = data[i].Split(colonCharacter, 2);
                        customRow.SetData(item[0], item[1]);
                    }

                    bool dataErrors = false;
                    for (int i = 0; i < customTable.Columns.Count; ++i)
                    {
                        if (!customTable.Columns[i].IsNullable && customRow.IsColumnEmpty(i))
                        {
                            this.OnMessage(WixErrors.NoDataForColumn(row.SourceLineNumbers, customTable.Columns[i].Name, customTable.Name));
                            dataErrors = true;
                        }
                    }

                    if (!dataErrors)
                    {
                        OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, customTable);
                        outputTable.OutputRows.Add(new OutputRow(customRow));
                    }
                }

                // update the special properties
                if (0 < adminProperties.Count)
                {
                    Row newRow = new Row(this.tableDefinitions["Property"]);
                    newRow[0] = "AdminProperties";
                    newRow[1] = GetPropertyListString(adminProperties);

                    OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Property"]);
                    outputTable.OutputRows.Add(new OutputRow(newRow));
                }
                if (0 < secureProperties.Count)
                {
                    Row newRow = new Row(this.tableDefinitions["Property"]);
                    newRow[0] = "SecureCustomProperties";
                    newRow[1] = GetPropertyListString(secureProperties);

                    OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Property"]);
                    outputTable.OutputRows.Add(new OutputRow(newRow));
                }
                if (0 < hiddenProperties.Count)
                {
                    Row newRow = new Row(this.tableDefinitions["Property"]);
                    newRow[0] = "MsiHiddenProperties";
                    newRow[1] = GetPropertyListString(hiddenProperties);

                    OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Property"]);
                    outputTable.OutputRows.Add(new OutputRow(newRow));
                }

                if (containsModuleSubstitution)
                {
                    Row newRow = new Row(this.tableDefinitions["ModuleIgnoreTable"]);
                    newRow[0] = "ModuleSubstitution";

                    OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleIgnoreTable"]);
                    outputTable.OutputRows.Add(new OutputRow(newRow));
                }

                if (containsModuleConfiguration)
                {
                    Row newRow = new Row(this.tableDefinitions["ModuleIgnoreTable"]);
                    newRow[0] = "ModuleConfiguration";

                    OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleIgnoreTable"]);
                    outputTable.OutputRows.Add(new OutputRow(newRow));
                }

                // process the actions
                foreach (Action action in requiredActions)
                {
                    // skip actions in suppressed sequences
                    if (suppressedSequenceTypes.Contains(action.SequenceType))
                    {
                        continue;
                    }

                    if (OutputType.Product == this.activeOutput.Type)
                    {
                        this.ResolveActionSequence(action, requiredActions);
                    }

                    TableDefinition sequenceTableDef = null;
                    bool module = OutputType.Module == this.activeOutput.Type;
                    switch (action.SequenceType)
                    {
                        case SequenceType.adminExecute:
                            if (module)
                            {
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminExecuteSequence"]);
                                sequenceTableDef = this.tableDefinitions["ModuleAdminExecuteSequence"];
                            }
                            else
                            {
                                sequenceTableDef = this.tableDefinitions["AdminExecuteSequence"];
                            }
                            break;
                        case SequenceType.adminUI:
                            if (module)
                            {
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminUISequence"]);
                                sequenceTableDef = this.tableDefinitions["ModuleAdminUISequence"];
                            }
                            else
                            {
                                sequenceTableDef = this.tableDefinitions["AdminUISequence"];
                            }
                            break;
                        case SequenceType.advertiseExecute:
                            if (module)
                            {
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdvtExecuteSequence"]);
                                sequenceTableDef = this.tableDefinitions["ModuleAdvtExecuteSequence"];
                            }
                            else
                            {
                                sequenceTableDef = this.tableDefinitions["AdvtExecuteSequence"];
                            }
                            break;
                        case SequenceType.installExecute:
                            if (module)
                            {
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallExecuteSequence"]);
                                sequenceTableDef = this.tableDefinitions["ModuleInstallExecuteSequence"];
                            }
                            else
                            {
                                sequenceTableDef = this.tableDefinitions["InstallExecuteSequence"];
                            }
                            break;
                        case SequenceType.installUI:
                            if (module)
                            {
                                Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallUISequence"]);
                                sequenceTableDef = this.tableDefinitions["ModuleInstallUISequence"];
                            }
                            else
                            {
                                sequenceTableDef = this.tableDefinitions["InstallUISequence"];
                            }
                            break;
                    }

                    Row row = new Row(sequenceTableDef);
                    if (module)
                    {
                        row[0] = action.Id;
                        if (0 != action.SequenceNumber)
                        {
                            row[1] = action.SequenceNumber;
                        }
                        else
                        {
                            bool after = null == action.Before;
                            row[2] = after ? action.After : action.Before;
                            row[3] = after ? 1 : 0;
                        }
                        row[4] = action.Condition;
                    }
                    else // add the row to the sequence table
                    {
                        row[0] = action.Id;
                        row[1] = action.Condition;
                        row[2] = action.SequenceNumber;
                    }

                    OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, sequenceTableDef);
                    outputTable.OutputRows.Add(new OutputRow(row));
                }

                // set the suppressed action sequences
                if (this.suppressAdminSequence)
                {
                    this.activeOutput.SuppressAdminSequence = true;
                }
                if (this.suppressAdvertiseSequence)
                {
                    this.activeOutput.SuppressAdvertiseSequence = true;
                }
                if (this.suppressUISequence)
                {
                    this.activeOutput.SuppressUISequence = true;
                }
            }
            finally
            {
                this.activeOutput = null;
            }

            return (this.foundError ? null : output);
        }
Example #46
0
        /// <summary>
        /// Ensures the output contains a particular table definition and returns the output table.
        /// </summary>
        /// <param name="output">Output to add table definition.</param>
        /// <param name="tableDef">Table definition to add.</param>
        /// <returns>Output table in the output.</returns>
        internal static OutputTable EnsureOutputTable(Output output, TableDefinition tableDef)
        {
            OutputTable outputTable = output.OutputTables[tableDef.Name];
            if (null == outputTable)
            {
                outputTable = new OutputTable(tableDef);
                output.OutputTables.Add(outputTable);
            }

            return outputTable;
        }
Example #47
0
 /// <summary>
 /// Creates a WixBundleRow row that does not belong to a table.
 /// </summary>
 /// <param name="sourceLineNumbers">Original source lines for this row.</param>
 /// <param name="tableDef">TableDefinition this WixBundleRow row belongs to and should get its column definitions from.</param>
 public WixBundleRow(SourceLineNumberCollection sourceLineNumbers, TableDefinition tableDef)
     : base(sourceLineNumbers, tableDef)
 {
 }
Example #48
0
 /// <summary>Creates a Control row that does not belong to a table.</summary>
 /// <param name="tableDef">TableDefinition this Control row should get its column definitions from.</param>
 public BBControlRow(TableDefinition tableDef) :
     base(tableDef)
 {
 }