private static void SetSymbolFieldsFromRow(Wix3.Row row, IntermediateSymbol symbol, bool columnZeroIsId)
        {
            var offset = 0;

            if (columnZeroIsId)
            {
                offset = 1;
            }

            for (var i = offset; i < row.Fields.Length; ++i)
            {
                var column = row.Fields[i].Column;
                switch (column.Type)
                {
                case Wix3.ColumnType.String:
                case Wix3.ColumnType.Localized:
                case Wix3.ColumnType.Object:
                case Wix3.ColumnType.Preserved:
                    symbol.Set(i - offset, FieldAsString(row, i));
                    break;

                case Wix3.ColumnType.Number:
                    int?nullableValue = FieldAsNullableInt(row, i);
                    // TODO: Consider whether null values should be coerced to their default value when
                    // a column is not nullable. For now, just pass through the null.
                    //int value = FieldAsInt(row, i);
                    //symbol.Set(i - offset, column.IsNullable ? nullableValue : value);
                    symbol.Set(i - offset, nullableValue);
                    break;

                case Wix3.ColumnType.Unknown:
                    break;
                }
            }
        }
Beispiel #2
0
        public RollbackBoundaryInfo(Row row)
        {
            this.Id = row[0].ToString();

            this.Vital = (null == row[10] || 1 == (int)row[10]) ? YesNoType.Yes : YesNoType.No;
            this.SourceLineNumbers = row.SourceLineNumbers;
        }
Beispiel #3
0
        private static IntermediateSymbol DefaultSymbolFromRow(Type symbolType, Wix3.Row row, bool columnZeroIsId)
        {
            var symbol = Activator.CreateInstance(symbolType) as IntermediateSymbol;

            SetSymbolFieldsFromRow(row, symbol, columnZeroIsId);

            symbol.SourceLineNumbers = SourceLineNumber4(row.SourceLineNumbers);
            return(symbol);
        }
Beispiel #4
0
        /// <summary>
        /// Creates a new output row.
        /// </summary>
        /// <param name="row">Table row to wrap.</param>
        /// <param name="sectionId">If not null, the sectionId attribute will be set on this row in the output.</param>
        public OutputRow(Row row, string sectionId)
        {
            if (null == row)
            {
                throw new ArgumentNullException("row");
            }

            this.row = row;
            this.row.SectionId = sectionId;
        }
        private static IntermediateSymbol DefaultSymbolFromRow(Type symbolType, Wix3.Row row, bool columnZeroIsId)
        {
            var id = columnZeroIsId ? GetIdentifierForRow(row) : null;

            var createSymbol = symbolType.GetConstructor(new[] { typeof(SourceLineNumber), typeof(Identifier) });
            var symbol       = (IntermediateSymbol)createSymbol.Invoke(new object[] { SourceLineNumber4(row.SourceLineNumbers), id });

            SetSymbolFieldsFromRow(row, symbol, columnZeroIsId);

            return(symbol);
        }
Beispiel #6
0
        public ChainInfo(Row row)
        {
            BundleChainAttributes attributes = (null == row[0]) ? BundleChainAttributes.None : (BundleChainAttributes)row[0];

            this.DisableRollback = (BundleChainAttributes.DisableRollback == (attributes & BundleChainAttributes.DisableRollback));
            this.DisableSystemRestore = (BundleChainAttributes.DisableSystemRestore == (attributes & BundleChainAttributes.DisableSystemRestore));
            this.ParallelCache = (BundleChainAttributes.ParallelCache == (attributes & BundleChainAttributes.ParallelCache));
            this.Packages = new List<ChainPackageInfo>();
            this.RollbackBoundaries = new List<RollbackBoundaryInfo>();
            this.SourceLineNumbers = row.SourceLineNumbers;
        }
Beispiel #7
0
        private static IntermediateSymbol GenericSymbolFromCustomRow(Wix3.Row row, bool columnZeroIsId)
        {
            var columnDefinitions = row.Table.Definition.Columns.Cast <Wix3.ColumnDefinition>();
            var fieldDefinitions  = columnDefinitions.Select(columnDefinition =>
                                                             new IntermediateFieldDefinition(columnDefinition.Name, ColumnType3ToIntermediateFieldType4(columnDefinition.Type))).ToArray();
            var symbolDefinition = new IntermediateSymbolDefinition(row.Table.Name, fieldDefinitions, null);
            var symbol           = new IntermediateSymbol(symbolDefinition, SourceLineNumber4(row.SourceLineNumbers));

            SetSymbolFieldsFromRow(row, symbol, columnZeroIsId);

            return(symbol);
        }
Beispiel #8
0
        private static int?FieldAsNullableInt(Wix3.Row row, int column)
        {
            var field = row.Fields[column];

            if (field.Data == null)
            {
                return(null);
            }
            else
            {
                return(Convert.ToInt32(field.Data));
            }
        }
        private static IntermediateSymbol GenericSymbolFromCustomRow(Wix3.Row row, bool columnZeroIsId)
        {
            var columnDefinitions = row.Table.Definition.Columns.Cast <Wix3.ColumnDefinition>();
            var fieldDefinitions  = columnDefinitions.Select(columnDefinition =>
                                                             new IntermediateFieldDefinition(columnDefinition.Name, ColumnType3ToIntermediateFieldType4(columnDefinition.Type))).ToArray();
            var symbolDefinition = new IntermediateSymbolDefinition(row.Table.Name, fieldDefinitions, null);

            var id = columnZeroIsId ? GetIdentifierForRow(row) : null;

            var createSymbol = typeof(IntermediateSymbol).GetConstructor(new[] { typeof(IntermediateSymbolDefinition), typeof(SourceLineNumber), typeof(Identifier) });
            var symbol       = (IntermediateSymbol)createSymbol.Invoke(new object[] { symbolDefinition, SourceLineNumber4(row.SourceLineNumbers), id });

            SetSymbolFieldsFromRow(row, symbol, columnZeroIsId);

            return(symbol);
        }
Beispiel #10
0
        private static Identifier GetIdentifierForRow(Wix3.Row row)
        {
            var column = row.Fields[0].Column;

            switch (column.Type)
            {
            case Wix3.ColumnType.String:
            case Wix3.ColumnType.Localized:
            case Wix3.ColumnType.Object:
            case Wix3.ColumnType.Preserved:
                return(new Identifier(AccessModifier.Public, (string)row.Fields[0].Data));

            case Wix3.ColumnType.Number:
                return(new Identifier(AccessModifier.Public, FieldAsInt(row, 0)));

            default:
                return(null);
            }
        }
Beispiel #11
0
        private Row CompareRows(Table targetTable, Row targetRow, Row updatedRow, out RowOperation operation, out bool keepRow)
        {
            Row comparedRow = null;
            keepRow = false;
            operation = RowOperation.None;

            if (null == targetRow ^ null == updatedRow)
            {
                if (null == targetRow)
                {
                    operation = updatedRow.Operation = RowOperation.Add;
                    comparedRow = updatedRow;
                }
                else if (null == updatedRow)
                {
                    operation = targetRow.Operation = RowOperation.Delete;
                    targetRow.SectionId = targetRow.SectionId + sectionDelimiter;
                    comparedRow = targetRow;
                    keepRow = true;
                }
            }
            else // possibly modified
            {
                updatedRow.Operation = RowOperation.None;
                if (!this.suppressKeepingSpecialRows && "_SummaryInformation" == targetTable.Name)
                {
                    // ignore rows that shouldn't be in a transform
                    if (Enum.IsDefined(typeof(SummaryInformation.Transform), (int)updatedRow[0]))
                    {
                        updatedRow.SectionId = targetRow.SectionId + sectionDelimiter + updatedRow.SectionId;
                        comparedRow = updatedRow;
                        keepRow = true;
                        operation = RowOperation.Modify;
                    }
                }
                else
                {
                    if (this.preserveUnchangedRows)
                    {
                        keepRow = true;
                    }

                    for (int i = 0; i < updatedRow.Fields.Length; i++)
                    {
                        ColumnDefinition columnDefinition = updatedRow.Fields[i].Column;

                        if (!columnDefinition.IsPrimaryKey)
                        {
                            bool modified = false;

                            if (i >= targetRow.Fields.Length)
                            {
                                columnDefinition.Added = true;
                                modified = true;
                            }
                            else if (ColumnType.Number == columnDefinition.Type && !columnDefinition.IsLocalizable)
                            {
                                if (null == targetRow[i] ^ null == updatedRow[i])
                                {
                                    modified = true;
                                }
                                else if (null != targetRow[i] && null != updatedRow[i])
                                {
                                    modified = ((int)targetRow[i] != (int)updatedRow[i]);
                                }
                            }
                            else if (ColumnType.Preserved == columnDefinition.Type)
                            {
                                updatedRow.Fields[i].PreviousData = (string)targetRow.Fields[i].Data;

                                // keep rows containing preserved fields so the historical data is available to the binder
                                keepRow = !this.suppressKeepingSpecialRows;
                            }
                            else if (ColumnType.Object == columnDefinition.Type)
                            {
                                ObjectField targetObjectField = (ObjectField)targetRow.Fields[i];
                                ObjectField updatedObjectField = (ObjectField)updatedRow.Fields[i];

                                updatedObjectField.PreviousCabinetFileId = targetObjectField.CabinetFileId;
                                updatedObjectField.PreviousBaseUri = targetObjectField.BaseUri;

                                // always keep a copy of the previous data even if they are identical
                                // This makes diff.wixmst clean and easier to control patch logic
                                updatedObjectField.PreviousData = (string)targetObjectField.Data;

                                // always remember the unresolved data for target build
                                updatedObjectField.UnresolvedPreviousData = (string)targetObjectField.UnresolvedData;

                                // keep rows containing object fields so the files can be compared in the binder
                                keepRow = !this.suppressKeepingSpecialRows;
                            }
                            else
                            {
                                modified = ((string)targetRow[i] != (string)updatedRow[i]);
                            }

                            if (modified)
                            {
                                if (null != updatedRow.Fields[i].PreviousData)
                                {
                                    updatedRow.Fields[i].PreviousData = targetRow.Fields[i].Data.ToString();
                                }

                                updatedRow.Fields[i].Modified = true;
                                operation = updatedRow.Operation = RowOperation.Modify;
                                keepRow = true;
                            }
                        }
                    }

                    if (keepRow)
                    {
                        comparedRow = updatedRow;
                        comparedRow.SectionId = targetRow.SectionId + sectionDelimiter + updatedRow.SectionId;
                    }
                }
            }

            return comparedRow;
        }
Beispiel #12
0
 public WixProductSearchInfo(Row row)
     : this((string)row[0], (string)row[1], (int)row[2])
 {
 }
Beispiel #13
0
 public ContainerInfo(Row row, BinderFileManager fileManager)
     : this((string)row[0], (string)row[1], (string)row[2], (string)row[3], fileManager)
 {
     this.SourceLineNumbers = row.SourceLineNumbers;
 }
Beispiel #14
0
 /// <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;
 }
Beispiel #15
0
 /// <summary>
 /// Adds a row to the collection.
 /// </summary>
 /// <param name="row">Row to add to collection.</param>
 public void Add(Row row)
 {
     this.collection.Add(row);
 }
Beispiel #16
0
        private RowCollection CompareTables(Output targetOutput, Table targetTable, Table updatedTable, out TableOperation operation)
        {
            RowCollection rows = new RowCollection();

            operation = TableOperation.None;

            // dropped tables
            if (null == updatedTable ^ null == targetTable)
            {
                if (null == targetTable)
                {
                    operation = TableOperation.Add;
                    rows.AddRange(updatedTable.Rows);
                }
                else if (null == updatedTable)
                {
                    operation = TableOperation.Drop;
                }
            }
            else // possibly modified tables
            {
                SortedList updatedPrimaryKeys = new SortedList();
                SortedList targetPrimaryKeys  = new SortedList();

                // compare the table definitions
                if (0 != targetTable.Definition.CompareTo(updatedTable.Definition))
                {
                    // continue to the next table; may be more mismatches
                    this.OnMessage(WixErrors.DatabaseSchemaMismatch(targetOutput.SourceLineNumbers, targetTable.Name));
                }
                else
                {
                    this.IndexPrimaryKeys(targetTable, targetPrimaryKeys, updatedTable, updatedPrimaryKeys);

                    // diff the target and updated rows
                    foreach (DictionaryEntry targetPrimaryKeyEntry in targetPrimaryKeys)
                    {
                        string       targetPrimaryKey = (string)targetPrimaryKeyEntry.Key;
                        bool         keepRow          = false;
                        RowOperation rowOperation     = RowOperation.None;

                        Row compared = this.CompareRows(targetTable, targetPrimaryKeyEntry.Value as Row, updatedPrimaryKeys[targetPrimaryKey] as Row, out rowOperation, out keepRow);

                        if (keepRow)
                        {
                            rows.Add(compared);
                        }
                    }

                    // find the inserted rows
                    foreach (DictionaryEntry updatedPrimaryKeyEntry in updatedPrimaryKeys)
                    {
                        string updatedPrimaryKey = (string)updatedPrimaryKeyEntry.Key;

                        if (!targetPrimaryKeys.Contains(updatedPrimaryKey))
                        {
                            Row updatedRow = (Row)updatedPrimaryKeyEntry.Value;

                            updatedRow.Operation = RowOperation.Add;
                            updatedRow.SectionId = sectionDelimiter + updatedRow.SectionId;
                            rows.Add(updatedRow);
                        }
                    }
                }
            }

            return(rows);
        }
Beispiel #17
0
        private void UpdateTransformSummaryInformationTable(Table summaryInfoTable, TransformFlags validationFlags)
        {
            // calculate the minimum version of MSI required to process the transform
            int targetMin;
            int updatedMin;
            int minimumVersion = 100;

            if (Int32.TryParse(this.transformSummaryInfo.TargetMinimumVersion, out targetMin) && Int32.TryParse(this.transformSummaryInfo.UpdatedMinimumVersion, out updatedMin))
            {
                minimumVersion = Math.Max(targetMin, updatedMin);
            }

            Hashtable summaryRows = new Hashtable(summaryInfoTable.Rows.Count);

            foreach (Row row in summaryInfoTable.Rows)
            {
                summaryRows[row[0]] = row;

                if ((int)SummaryInformation.Transform.CodePage == (int)row[0])
                {
                    row.Fields[1].Data         = this.transformSummaryInfo.UpdatedSummaryInfoCodepage;
                    row.Fields[1].PreviousData = this.transformSummaryInfo.TargetSummaryInfoCodepage;
                }
                else if ((int)SummaryInformation.Transform.TargetPlatformAndLanguage == (int)row[0])
                {
                    row[1] = this.transformSummaryInfo.TargetPlatformAndLanguage;
                }
                else if ((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage == (int)row[0])
                {
                    row[1] = this.transformSummaryInfo.UpdatedPlatformAndLanguage;
                }
                else if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0])
                {
                    row[1] = String.Concat(this.transformSummaryInfo.TargetProductCode, this.transformSummaryInfo.TargetProductVersion, ';', this.transformSummaryInfo.UpdatedProductCode, this.transformSummaryInfo.UpdatedProductVersion, ';', this.transformSummaryInfo.TargetUpgradeCode);
                }
                else if ((int)SummaryInformation.Transform.InstallerRequirement == (int)row[0])
                {
                    row[1] = minimumVersion.ToString(CultureInfo.InvariantCulture);
                }
                else if ((int)SummaryInformation.Transform.Security == (int)row[0])
                {
                    row[1] = "4";
                }
            }

            if (!summaryRows.Contains((int)SummaryInformation.Transform.TargetPlatformAndLanguage))
            {
                Row summaryRow = summaryInfoTable.CreateRow(null);
                summaryRow[0] = (int)SummaryInformation.Transform.TargetPlatformAndLanguage;
                summaryRow[1] = this.transformSummaryInfo.TargetPlatformAndLanguage;
            }

            if (!summaryRows.Contains((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage))
            {
                Row summaryRow = summaryInfoTable.CreateRow(null);
                summaryRow[0] = (int)SummaryInformation.Transform.UpdatedPlatformAndLanguage;
                summaryRow[1] = this.transformSummaryInfo.UpdatedPlatformAndLanguage;
            }

            if (!summaryRows.Contains((int)SummaryInformation.Transform.ValidationFlags))
            {
                Row summaryRow = summaryInfoTable.CreateRow(null);
                summaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags;
                summaryRow[1] = ((int)validationFlags).ToString(CultureInfo.InvariantCulture);
            }

            if (!summaryRows.Contains((int)SummaryInformation.Transform.InstallerRequirement))
            {
                Row summaryRow = summaryInfoTable.CreateRow(null);
                summaryRow[0] = (int)SummaryInformation.Transform.InstallerRequirement;
                summaryRow[1] = minimumVersion.ToString(CultureInfo.InvariantCulture);
            }

            if (!summaryRows.Contains((int)SummaryInformation.Transform.Security))
            {
                Row summaryRow = summaryInfoTable.CreateRow(null);
                summaryRow[0] = (int)SummaryInformation.Transform.Security;
                summaryRow[1] = "4";
            }
        }
        /// <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;
        }
Beispiel #19
0
 public void AddWixSearchRowInfo(Row row)
 {
     Debug.Assert((string)row[0] == Id);
     Variable = (string)row[1];
     Condition = (string)row[2];
 }
Beispiel #20
0
 public WixRegistrySearchInfo(Row row)
     : this((string)row[0], (int)row[1], (string)row[2], (string)row[3], (int)row[4])
 {
 }
Beispiel #21
0
        /// <summary>
        /// Set an MsiAssemblyName row.  If it was directly authored, override the value, otherwise
        /// create a new row.
        /// </summary>
        /// <param name="assemblyNameOutputTable">MsiAssemblyName output table.</param>
        /// <param name="fileRow">FileRow containing the assembly read for the MsiAssemblyName row.</param>
        /// <param name="name">MsiAssemblyName name.</param>
        /// <param name="value">MsiAssemblyName value.</param>
        private void SetMsiAssemblyName(OutputTable assemblyNameOutputTable, FileRow fileRow, string name, string value)
        {
            // check for null value (this can occur when grabbing the file version from an assembly without one)
            if (null == value || 0 == value.Length)
            {
                this.OnMessage(WixErrors.NullMsiAssemblyNameValue(fileRow.SourceLineNumbers, fileRow.Component, name));
            }

            // override directly authored value
            foreach (OutputRow outputRow in assemblyNameOutputTable.OutputRows)
            {
                if ((string)outputRow.Row[0] == fileRow.Component && (string)outputRow.Row[1] == name)
                {
                    outputRow.Row[2] = value;
                    return;
                }
            }

            Row assemblyNameRow = new Row(assemblyNameOutputTable.TableDefinition);
            assemblyNameRow[0] = fileRow.Component;
            assemblyNameRow[1] = name;
            assemblyNameRow[2] = value;
            assemblyNameOutputTable.OutputRows.Add(new OutputRow(assemblyNameRow));
        }
Beispiel #22
0
 public MsiPropertyInfo(Row row)
     : this((string)row[0], (string)row[1], (string)row[2])
 {
 }
Beispiel #23
0
 public WixFileSearchInfo(Row row)
     : this((string)row[0], (string)row[1], (int)row[9])
 {
 }
 public WixComponentSearchInfo(Row row)
     : this((string)row[0], (string)row[1], (string)row[2], (int)row[3])
 {
 }
 /// <summary>
 /// Adds a row to the collection.
 /// </summary>
 /// <param name="row">Row to add to collection.</param>
 public void Add(Row row)
 {
     this.collection.Add(row);
 }
Beispiel #26
0
 /// <summary>
 /// Creates a new output row.
 /// </summary>
 /// <param name="row">Table row to wrap.</param>
 public OutputRow(Row row)
     : this(row, row.SectionId)
 {
 }
Beispiel #27
0
 public ExitCodeInfo(Row row)
     : this((string)row[0], (int)row[1], (string)row[2])
 {
 }
Beispiel #28
0
 public CommandLineInfo(Row row)
     : this((string)row[0], (string)row[1], (string)row[2], (string)row[3], (string)row[4])
 {
 }
Beispiel #29
0
 /// <summary>
 /// Creates a new instance of the <see cref="ProviderDependency"/> class from a <see cref="Row"/>.
 /// </summary>
 /// <param name="row">The <see cref="Row"/> from which data is imported.</param>
 internal ProvidesDependency(Row row)
     : this((string)row[2], (string)row[3], (string)row[4], (int?)row[5])
 {
 }
Beispiel #30
0
        /// <summary>
        /// Creates a new row in the table.
        /// </summary>
        /// <param name="sourceLineNumbers">Original source lines for this row.</param>
        /// <param name="add">Specifies whether to only create the row or add it to the table automatically.</param>
        /// <returns>Row created in table.</returns>
        public Row CreateRow(SourceLineNumberCollection sourceLineNumbers, bool add)
        {
            Row row;

            switch (this.Name)
            {
                case "BBControl":
                    row = new BBControlRow(sourceLineNumbers, this);
                    break;
                case "ChainMsiPackage":
                    row = new ChainMsiPackageRow(sourceLineNumbers, this);
                    break;
                case "Component":
                    row = new ComponentRow(sourceLineNumbers, this);
                    break;
                case "Control":
                    row = new ControlRow(sourceLineNumbers, this);
                    break;
                case "File":
                    row = new FileRow(sourceLineNumbers, this);
                    break;
                case "Media":
                    row = new MediaRow(sourceLineNumbers, this);
                    break;
                case "PayloadInfo":
                    row = new PayloadInfoRow(sourceLineNumbers, this);
                    break;
                case "Upgrade":
                    row = new UpgradeRow(sourceLineNumbers, this);
                    break;
                case "Variable":
                    row = new VariableRow(sourceLineNumbers, this);
                    break;
                case "WixAction":
                    row = new WixActionRow(sourceLineNumbers, this);
                    break;
                case "WixApprovedExeForElevation":
                    row = new WixApprovedExeForElevationRow(sourceLineNumbers, this);
                    break;
                case "WixBundle":
                    row = new WixBundleRow(sourceLineNumbers, this);
                    break;
                case "WixBundlePatchTargetCode":
                    row = new WixBundlePatchTargetCodeRow(sourceLineNumbers, this);
                    break;
                case "WixBundleUpdate":
                    row = new WixBundleUpdateRow(sourceLineNumbers, this);
                    break;
                case "WixCatalog":
                    row = new WixCatalogRow(sourceLineNumbers, this);
                    break;
                case "WixCommandLine":
                    row = new WixCommandLineRow(sourceLineNumbers, this);
                    break;
                case "WixComplexReference":
                    row = new WixComplexReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixFile":
                    row = new WixFileRow(sourceLineNumbers, this);
                    break;
                case "WixMedia":
                    row = new WixMediaRow(sourceLineNumbers, this);
                    break;
                case "WixMediaTemplate":
                    row = new WixMediaTemplateRow(sourceLineNumbers, this);
                    break;
                case "WixMerge":
                    row = new WixMergeRow(sourceLineNumbers, this);
                    break;
                case "WixProperty":
                    row = new WixPropertyRow(sourceLineNumbers, this);
                    break;
                case "WixSimpleReference":
                    row = new WixSimpleReferenceRow(sourceLineNumbers, this);
                    break;
                case "WixUpdateRegistration":
                    row = new WixUpdateRegistrationRow(sourceLineNumbers, this);
                    break;
                case "WixVariable":
                    row = new WixVariableRow(sourceLineNumbers, this);
                    break;

                default:
                    row = new Row(sourceLineNumbers, this);
                    break;
            }

            if (add)
            {
                this.rows.Add(row);
            }

            return row;
        }
Beispiel #31
0
        /// <summary>
        /// Updates database with signatures from external cabinets.
        /// </summary>
        /// <param name="databaseFile">Path to MSI database.</param>
        /// <param name="outputFile">Ouput for updated MSI database.</param>
        /// <param name="tidy">Clean up files.</param>
        /// <returns>True if database is updated.</returns>
        public bool InscribeDatabase(string databaseFile, string outputFile, bool tidy)
        {
            // Keeps track of whether we've encountered at least one signed cab or not - we'll throw a warning if no signed cabs were encountered
            bool foundUnsignedExternals = false;
            bool shouldCommit           = false;

            FileAttributes attributes = File.GetAttributes(databaseFile);

            if (FileAttributes.ReadOnly == (attributes & FileAttributes.ReadOnly))
            {
                this.OnMessage(WixErrors.ReadOnlyOutputFile(databaseFile));
                return(shouldCommit);
            }

            using (Database database = new Database(databaseFile, OpenDatabase.Transact))
            {
                // Just use the English codepage, because the tables we're importing only have binary streams / MSI identifiers / other non-localizable content
                int codepage = 1252;

                // list of certificates for this database (hash/identifier)
                Dictionary <string, string> certificates = new Dictionary <string, string>();

                // Reset the in-memory tables for this new database
                Table digitalSignatureTable   = new Table(null, this.tableDefinitions["MsiDigitalSignature"]);
                Table digitalCertificateTable = new Table(null, this.tableDefinitions["MsiDigitalCertificate"]);

                // If any digital signature records exist that are not of the media type, preserve them
                if (database.TableExists("MsiDigitalSignature"))
                {
                    using (View digitalSignatureView = database.OpenExecuteView("SELECT `Table`, `SignObject`, `DigitalCertificate_`, `Hash` FROM `MsiDigitalSignature` WHERE `Table` <> 'Media'"))
                    {
                        while (true)
                        {
                            using (Record digitalSignatureRecord = digitalSignatureView.Fetch())
                            {
                                if (null == digitalSignatureRecord)
                                {
                                    break;
                                }

                                Row digitalSignatureRow = null;
                                digitalSignatureRow = digitalSignatureTable.CreateRow(null);

                                string table      = digitalSignatureRecord.GetString(0);
                                string signObject = digitalSignatureRecord.GetString(1);

                                digitalSignatureRow[0] = table;
                                digitalSignatureRow[1] = signObject;
                                digitalSignatureRow[2] = digitalSignatureRecord.GetString(2);

                                if (false == digitalSignatureRecord.IsNull(3))
                                {
                                    // Export to a file, because the MSI API's require us to provide a file path on disk
                                    string hashPath     = Path.Combine(this.TempFilesLocation, "MsiDigitalSignature");
                                    string hashFileName = string.Concat(table, ".", signObject, ".bin");

                                    Directory.CreateDirectory(hashPath);
                                    hashPath = Path.Combine(hashPath, hashFileName);

                                    using (FileStream fs = File.Create(hashPath))
                                    {
                                        int    bytesRead;
                                        byte[] buffer = new byte[1024 * 4];

                                        while (0 != (bytesRead = digitalSignatureRecord.GetStream(3, buffer, buffer.Length)))
                                        {
                                            fs.Write(buffer, 0, bytesRead);
                                        }
                                    }

                                    digitalSignatureRow[3] = hashFileName;
                                }
                            }
                        }
                    }
                }

                // If any digital certificates exist, extract and preserve them
                if (database.TableExists("MsiDigitalCertificate"))
                {
                    using (View digitalCertificateView = database.OpenExecuteView("SELECT * FROM `MsiDigitalCertificate`"))
                    {
                        while (true)
                        {
                            using (Record digitalCertificateRecord = digitalCertificateView.Fetch())
                            {
                                if (null == digitalCertificateRecord)
                                {
                                    break;
                                }

                                string certificateId = digitalCertificateRecord.GetString(1); // get the identifier of the certificate

                                // Export to a file, because the MSI API's require us to provide a file path on disk
                                string certPath = Path.Combine(this.TempFilesLocation, "MsiDigitalCertificate");
                                Directory.CreateDirectory(certPath);
                                certPath = Path.Combine(certPath, string.Concat(certificateId, ".cer"));

                                using (FileStream fs = File.Create(certPath))
                                {
                                    int    bytesRead;
                                    byte[] buffer = new byte[1024 * 4];

                                    while (0 != (bytesRead = digitalCertificateRecord.GetStream(2, buffer, buffer.Length)))
                                    {
                                        fs.Write(buffer, 0, bytesRead);
                                    }
                                }

                                // Add it to our "add to MsiDigitalCertificate" table dictionary
                                Row digitalCertificateRow = digitalCertificateTable.CreateRow(null);
                                digitalCertificateRow[0] = certificateId;

                                // Now set the file path on disk where this binary stream will be picked up at import time
                                digitalCertificateRow[1] = string.Concat(certificateId, ".cer");

                                // Load the cert to get it's thumbprint
                                X509Certificate  cert  = X509Certificate.CreateFromCertFile(certPath);
                                X509Certificate2 cert2 = new X509Certificate2(cert);

                                certificates.Add(cert2.Thumbprint, certificateId);
                            }
                        }
                    }
                }

                using (View mediaView = database.OpenExecuteView("SELECT * FROM `Media`"))
                {
                    while (true)
                    {
                        using (Record mediaRecord = mediaView.Fetch())
                        {
                            if (null == mediaRecord)
                            {
                                break;
                            }

                            X509Certificate2 cert2  = null;
                            Row digitalSignatureRow = null;

                            string cabName = mediaRecord.GetString(4); // get the name of the cab
                            // If there is no cabinet or it's an internal cab, skip it.
                            if (String.IsNullOrEmpty(cabName) || cabName.StartsWith("#", StringComparison.Ordinal))
                            {
                                continue;
                            }

                            string cabId   = mediaRecord.GetString(1); // get the ID of the cab
                            string cabPath = Path.Combine(Path.GetDirectoryName(databaseFile), cabName);

                            // If the cabs aren't there, throw an error but continue to catch the other errors
                            if (!File.Exists(cabPath))
                            {
                                this.OnMessage(WixErrors.WixFileNotFound(cabPath));
                                continue;
                            }

                            try
                            {
                                // Get the certificate from the cab
                                X509Certificate signedFileCert = X509Certificate.CreateFromSignedFile(cabPath);
                                cert2 = new X509Certificate2(signedFileCert);
                            }
                            catch (System.Security.Cryptography.CryptographicException e)
                            {
                                uint HResult = unchecked ((uint)Marshal.GetHRForException(e));

                                // If the file has no cert, continue, but flag that we found at least one so we can later give a warning
                                if (0x80092009 == HResult) // CRYPT_E_NO_MATCH
                                {
                                    foundUnsignedExternals = true;
                                    continue;
                                }

                                // todo: exactly which HRESULT corresponds to this issue?
                                // If it's one of these exact platforms, warn the user that it may be due to their OS.
                                if ((5 == Environment.OSVersion.Version.Major && 2 == Environment.OSVersion.Version.Minor) || // W2K3
                                    (5 == Environment.OSVersion.Version.Major && 1 == Environment.OSVersion.Version.Minor))   // XP
                                {
                                    this.OnMessage(WixErrors.UnableToGetAuthenticodeCertOfFileDownlevelOS(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult)));
                                }
                                else // otherwise, generic error
                                {
                                    this.OnMessage(WixErrors.UnableToGetAuthenticodeCertOfFile(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult)));
                                }
                            }

                            // If we haven't added this cert to the MsiDigitalCertificate table, set it up to be added
                            if (!certificates.ContainsKey(cert2.Thumbprint))
                            {
                                // generate a stable identifier
                                string certificateGeneratedId = Common.GenerateIdentifier("cer", true, cert2.Thumbprint);

                                // Add it to our "add to MsiDigitalCertificate" table dictionary
                                Row digitalCertificateRow = digitalCertificateTable.CreateRow(null);
                                digitalCertificateRow[0] = certificateGeneratedId;

                                // Export to a file, because the MSI API's require us to provide a file path on disk
                                string certPath = Path.Combine(this.TempFilesLocation, "MsiDigitalCertificate");
                                Directory.CreateDirectory(certPath);
                                certPath = Path.Combine(certPath, string.Concat(cert2.Thumbprint, ".cer"));
                                File.Delete(certPath);

                                using (BinaryWriter writer = new BinaryWriter(File.Open(certPath, FileMode.Create)))
                                {
                                    writer.Write(cert2.RawData);
                                    writer.Close();
                                }

                                // Now set the file path on disk where this binary stream will be picked up at import time
                                digitalCertificateRow[1] = string.Concat(cert2.Thumbprint, ".cer");

                                certificates.Add(cert2.Thumbprint, certificateGeneratedId);
                            }

                            digitalSignatureRow = digitalSignatureTable.CreateRow(null);

                            digitalSignatureRow[0] = "Media";
                            digitalSignatureRow[1] = cabId;
                            digitalSignatureRow[2] = certificates[cert2.Thumbprint];
                        }
                    }
                }

                if (digitalCertificateTable.Rows.Count > 0)
                {
                    database.ImportTable(codepage, (IMessageHandler)this, digitalCertificateTable, this.TempFilesLocation, true);
                    shouldCommit = true;
                }

                if (digitalSignatureTable.Rows.Count > 0)
                {
                    database.ImportTable(codepage, (IMessageHandler)this, digitalSignatureTable, this.TempFilesLocation, true);
                    shouldCommit = true;
                }

                // TODO: if we created the table(s), then we should add the _Validation records for them.

                certificates = null;

                // If we did find external cabs but none of them were signed, give a warning
                if (foundUnsignedExternals)
                {
                    this.OnMessage(WixWarnings.ExternalCabsAreNotSigned(databaseFile));
                }

                if (shouldCommit)
                {
                    database.Commit();
                }
            }

            return(shouldCommit);
        }
Beispiel #32
0
        /// <summary>
        /// Tests if the passed in row is identical.
        /// </summary>
        /// <param name="row">Row to compare against.</param>
        /// <returns>True if two rows are identical.</returns>
        public bool IsIdentical(Row row)
        {
            bool identical = (this.TableDefinition.Name == row.TableDefinition.Name && this.fields.Length == row.fields.Length);

            for (int i = 0; identical && i < this.fields.Length; ++i)
            {
                if (!(this.fields[i].IsIdentical(row.fields[i])))
                {
                    identical = false;
                }
            }

            return identical;
        }
Beispiel #33
0
 private static int FieldAsInt(Wix3.Row row, int column)
 {
     return(Convert.ToInt32(row[column]));
 }
Beispiel #34
0
        public ChainPackageInfo(Row chainPackageRow, Table wixGroupTable, Dictionary<string, PayloadInfoRow> allPayloads, Dictionary<string, ContainerInfo> containers, BinderFileManager fileManager, BinderCore core, Output bundle) : base(chainPackageRow.SourceLineNumbers, bundle.Tables["ChainPackageInfo"])
        {
            string id = (string)chainPackageRow[0];
            string packageType = (string)chainPackageRow[1];
            string payloadId = (string)chainPackageRow[2];
            string installCondition = (string)chainPackageRow[3];
            string installCommand = (string)chainPackageRow[4];
            string repairCommand = (string)chainPackageRow[5];
            string uninstallCommand = (string)chainPackageRow[6];
            object cacheData = chainPackageRow[7];
            string cacheId = (string)chainPackageRow[8];
            object attributesData = chainPackageRow[9];
            object vitalData = chainPackageRow[10];
            object perMachineData = chainPackageRow[11];
            string detectCondition = (string)chainPackageRow[12];
            string msuKB = (string)chainPackageRow[13];
            object repairableData = chainPackageRow[14];
            string logPathVariable = (string)chainPackageRow[15];
            string rollbackPathVariable = (string)chainPackageRow[16];
            string protocol = (string)chainPackageRow[17];
            long installSize = (int)chainPackageRow[18];
            object suppressLooseFilePayloadGenerationData = chainPackageRow[19];
            object enableFeatureSelectionData = chainPackageRow[20];
            object forcePerMachineData = chainPackageRow[21];
            object displayInternalUIData = chainPackageRow[22];

            BundlePackageAttributes attributes = (null == attributesData) ? 0 : (BundlePackageAttributes)attributesData;

            YesNoAlwaysType cache = YesNoAlwaysType.NotSet;
            if (null != cacheData)
            {
                switch ((int)cacheData)
                {
                    case 0:
                        cache = YesNoAlwaysType.No;
                        break;
                    case 1:
                        cache = YesNoAlwaysType.Yes;
                        break;
                    case 2:
                        cache = YesNoAlwaysType.Always;
                        break;
                }
            }

            YesNoType vital = (null == vitalData || 1 == (int)vitalData) ? YesNoType.Yes : YesNoType.No;

            YesNoDefaultType perMachine = YesNoDefaultType.NotSet;
            if (null != perMachineData)
            {
                switch ((int)perMachineData)
                {
                    case 0:
                        perMachine = YesNoDefaultType.No;
                        break;
                    case 1:
                        perMachine = YesNoDefaultType.Yes;
                        break;
                    case 2:
                        perMachine = YesNoDefaultType.Default;
                        break;
                }
            }

            YesNoType repairable = YesNoType.NotSet;
            if (null != repairableData)
            {
                repairable = (1 == (int)repairableData) ? YesNoType.Yes : YesNoType.No;
            }

            YesNoType suppressLooseFilePayloadGeneration = YesNoType.NotSet;
            if (null != suppressLooseFilePayloadGenerationData)
            {
                suppressLooseFilePayloadGeneration = (1 == (int)suppressLooseFilePayloadGenerationData) ? YesNoType.Yes : YesNoType.No;
            }

            YesNoType enableFeatureSelection = YesNoType.NotSet;
            if (null != enableFeatureSelectionData)
            {
                enableFeatureSelection = (1 == (int)enableFeatureSelectionData) ? YesNoType.Yes : YesNoType.No;
            }

            YesNoType forcePerMachine = YesNoType.NotSet;
            if (null != forcePerMachineData)
            {
                forcePerMachine = (1 == (int)forcePerMachineData) ? YesNoType.Yes : YesNoType.No;
            }

            YesNoType displayInternalUI = YesNoType.NotSet;
            if (null != displayInternalUIData)
            {
                displayInternalUI = (1 == (int)displayInternalUIData) ? YesNoType.Yes : YesNoType.No;
            }

            this.core = core;

            this.Id = id;
            this.ChainPackageType = (Compiler.ChainPackageType)Enum.Parse(typeof(Compiler.ChainPackageType), packageType, true);
            PayloadInfoRow packagePayload;
            if (!allPayloads.TryGetValue(payloadId, out packagePayload))
            {
                this.core.OnMessage(WixErrors.IdentifierNotFound("Payload", payloadId));
                return;
            }
            this.PackagePayload = packagePayload;
            this.InstallCondition = installCondition;
            this.InstallCommand = installCommand;
            this.RepairCommand = repairCommand;
            this.UninstallCommand = uninstallCommand;

            this.PerMachine = perMachine;
            this.ProductCode = null;
            this.Cache = YesNoAlwaysType.NotSet == cache ? YesNoAlwaysType.Yes : cache; // The default is yes.
            this.CacheId = cacheId;
            this.Permanent = (BundlePackageAttributes.Permanent == (attributes & BundlePackageAttributes.Permanent));
            this.Visible = (BundlePackageAttributes.Visible == (attributes & BundlePackageAttributes.Visible));
            this.Slipstream = (BundlePackageAttributes.Slipstream == (attributes & BundlePackageAttributes.Slipstream));
            this.Vital = (YesNoType.Yes == vital); // true only when specifically requested.
            this.DetectCondition = detectCondition;
            this.MsuKB = msuKB;
            this.Protocol = protocol;
            this.Repairable = (YesNoType.Yes == repairable); // true only when specifically requested.
            this.LogPathVariable = logPathVariable;
            this.RollbackLogPathVariable = rollbackPathVariable;

            this.DisplayInternalUI = (YesNoType.Yes == displayInternalUI);

            this.Payloads = new List<PayloadInfoRow>();
            this.RelatedPackages = new List<RelatedPackage>();
            this.MsiFeatures = new List<MsiFeature>();
            this.MsiProperties = new List<MsiPropertyInfo>();
            this.SlipstreamMsps = new List<string>();
            this.ExitCodes = new List<ExitCodeInfo>();
            this.Provides = new ProvidesDependencyCollection();
            this.TargetCodes = new RowDictionary<WixBundlePatchTargetCodeRow>();

            // Default the display name and description to the package payload.
            this.DisplayName = this.PackagePayload.ProductName;
            this.Description = this.PackagePayload.Description;

            // Start the package size with the package's payload size.
            this.Size = this.PackagePayload.FileSize;

            // get all contained payloads...
            foreach (Row row in wixGroupTable.Rows)
            {
                string rowParentName = (string)row[0];
                string rowParentType = (string)row[1];
                string rowChildName = (string)row[2];
                string rowChildType = (string)row[3];

                if ("Package" == rowParentType && this.Id == rowParentName &&
                    "Payload" == rowChildType && this.PackagePayload.Id != rowChildName)
                {
                    PayloadInfoRow payload = allPayloads[rowChildName];
                    this.Payloads.Add(payload);

                    this.Size += payload.FileSize; // add each payload to the total size of the package.
                }
            }

            // Default the install size to the calculated package size.
            this.InstallSize = this.Size;

            switch (this.ChainPackageType)
            {
                case Compiler.ChainPackageType.Msi:
                    this.ResolveMsiPackage(fileManager, allPayloads, containers, suppressLooseFilePayloadGeneration, enableFeatureSelection, forcePerMachine, bundle);
                    break;
                case Compiler.ChainPackageType.Msp:
                    this.ResolveMspPackage(bundle);
                    break;
                case Compiler.ChainPackageType.Msu:
                    this.ResolveMsuPackage();
                    break;
                case Compiler.ChainPackageType.Exe:
                    this.ResolveExePackage();
                    break;
            }

            if (CompilerCore.IntegerNotSet != installSize)
            {
                this.InstallSize = installSize;
            }
        }
Beispiel #35
0
        /// <summary>
        /// Determines if the given row can be ignored when comparing results.
        /// </summary>
        /// <param name="row">The row to check.</param>
        /// <returns>True if the row can be ignored; otherwise, false.</returns>
        private static bool Ignore(Row row)
        {
            if ("_SummaryInformation" == row.Table.Name)
            {
                // check timestamp and version-dependent fields
                switch ((int)row[0])
                {
                    case 9:
                    case 12:
                    case 13:
                    case 18:
                        return true;
                }
            }
            else if ("Property" == row.Table.Name)
            {
                switch ((string)row[0])
                {
                    case "ProductCode":
                        return true;
                }
            }
            else if ("MsiPatchMetadata" == row.Table.Name)
            {
                switch (row.GetPrimaryKey('/'))
                {
                    case "/CreationTimeUTC":
                        return true;
                }
            }

            return false;
        }
Beispiel #36
0
        /// <summary>
        /// Add a row to the <paramref name="index"/> using the primary key.
        /// </summary>
        /// <param name="index">The indexed rows.</param>
        /// <param name="row">The row to index.</param>
        private void AddIndexedRow(IDictionary index, Row row)
        {
            string primaryKey = row.GetPrimaryKey('/');
            if (null != primaryKey)
            {
                // Overriding WixActionRows have a primary key defined and take precedence in the index.
                if (row is WixActionRow)
                {
                    WixActionRow currentRow = (WixActionRow)row;
                    if (index.Contains(primaryKey))
                    {
                        // If the current row is not overridable, see if the indexed row is.
                        if (!currentRow.Overridable)
                        {
                            WixActionRow indexedRow = index[primaryKey] as WixActionRow;
                            if (null != indexedRow && indexedRow.Overridable)
                            {
                                // The indexed key is overridable and should be replaced
                                // (not removed and re-added which results in two Array.Copy
                                // operations for SortedList, or may be re-hashing in other
                                // implementations of IDictionary).
                                index[primaryKey] = currentRow;
                            }
                        }

                        // If we got this far, the row does not need to be indexed.
                        return;
                    }
                }

                // Nothing else should be added more than once.
                if (!index.Contains(primaryKey))
                {
                    index.Add(primaryKey, row);
                }
                else if (this.showPedanticMessages)
                {
                    this.OnMessage(WixWarnings.DuplicatePrimaryKey(row.SourceLineNumbers, primaryKey, row.Table.Name));
                }
            }
            else // use the string representation of the row as its primary key (it may not be unique)
            {
                // this is provided for compatibility with unreal tables with no primary key
                // all real tables must specify at least one column as the primary key
                primaryKey = row.ToString();
                index[primaryKey] = row;
            }
        }
Beispiel #37
0
        private Row CompareRows(Table targetTable, Row targetRow, Row updatedRow, out RowOperation operation, out bool keepRow)
        {
            Row comparedRow = null;

            keepRow   = false;
            operation = RowOperation.None;

            if (null == targetRow ^ null == updatedRow)
            {
                if (null == targetRow)
                {
                    operation   = updatedRow.Operation = RowOperation.Add;
                    comparedRow = updatedRow;
                }
                else if (null == updatedRow)
                {
                    operation           = targetRow.Operation = RowOperation.Delete;
                    targetRow.SectionId = targetRow.SectionId + sectionDelimiter;
                    comparedRow         = targetRow;
                    keepRow             = true;
                }
            }
            else // possibly modified
            {
                updatedRow.Operation = RowOperation.None;
                if (!this.suppressKeepingSpecialRows && "_SummaryInformation" == targetTable.Name)
                {
                    // ignore rows that shouldn't be in a transform
                    if (Enum.IsDefined(typeof(SummaryInformation.Transform), (int)updatedRow[0]))
                    {
                        updatedRow.SectionId = targetRow.SectionId + sectionDelimiter + updatedRow.SectionId;
                        comparedRow          = updatedRow;
                        keepRow   = true;
                        operation = RowOperation.Modify;
                    }
                }
                else
                {
                    if (this.preserveUnchangedRows)
                    {
                        keepRow = true;
                    }

                    for (int i = 0; i < updatedRow.Fields.Length; i++)
                    {
                        ColumnDefinition columnDefinition = updatedRow.Fields[i].Column;

                        if (!columnDefinition.IsPrimaryKey)
                        {
                            bool modified = false;

                            if (i >= targetRow.Fields.Length)
                            {
                                columnDefinition.Added = true;
                                modified = true;
                            }
                            else if (ColumnType.Number == columnDefinition.Type && !columnDefinition.IsLocalizable)
                            {
                                if (null == targetRow[i] ^ null == updatedRow[i])
                                {
                                    modified = true;
                                }
                                else if (null != targetRow[i] && null != updatedRow[i])
                                {
                                    modified = ((int)targetRow[i] != (int)updatedRow[i]);
                                }
                            }
                            else if (ColumnType.Preserved == columnDefinition.Type)
                            {
                                updatedRow.Fields[i].PreviousData = (string)targetRow.Fields[i].Data;

                                // keep rows containing preserved fields so the historical data is available to the binder
                                keepRow = !this.suppressKeepingSpecialRows;
                            }
                            else if (ColumnType.Object == columnDefinition.Type)
                            {
                                ObjectField targetObjectField  = (ObjectField)targetRow.Fields[i];
                                ObjectField updatedObjectField = (ObjectField)updatedRow.Fields[i];

                                updatedObjectField.PreviousCabinetFileId = targetObjectField.CabinetFileId;
                                updatedObjectField.PreviousBaseUri       = targetObjectField.BaseUri;

                                // always keep a copy of the previous data even if they are identical
                                // This makes diff.wixmst clean and easier to control patch logic
                                updatedObjectField.PreviousData = (string)targetObjectField.Data;

                                // always remember the unresolved data for target build
                                updatedObjectField.UnresolvedPreviousData = (string)targetObjectField.UnresolvedData;

                                // keep rows containing object fields so the files can be compared in the binder
                                keepRow = !this.suppressKeepingSpecialRows;
                            }
                            else
                            {
                                modified = ((string)targetRow[i] != (string)updatedRow[i]);
                            }

                            if (modified)
                            {
                                if (null != updatedRow.Fields[i].PreviousData)
                                {
                                    updatedRow.Fields[i].PreviousData = targetRow.Fields[i].Data.ToString();
                                }

                                updatedRow.Fields[i].Modified = true;
                                operation = updatedRow.Operation = RowOperation.Modify;
                                keepRow   = true;
                            }
                        }
                    }

                    if (keepRow)
                    {
                        comparedRow           = updatedRow;
                        comparedRow.SectionId = targetRow.SectionId + sectionDelimiter + updatedRow.SectionId;
                    }
                }
            }

            return(comparedRow);
        }
Beispiel #38
0
 public VariableInfo(Row row)
     : this((string)row[0], (string)row[1], (string)row[2], (int)row[3] == 1 ? true : false, (int)row[4] == 1 ? true : false)
 {
 }
Beispiel #39
0
        /// <summary>
        /// Update several msi tables with data contained in files references in the File table.
        /// </summary>
        /// <remarks>
        /// For versioned files, update the file version and language in the File table.  For
        /// unversioned files, add a row to the MsiFileHash table for the file.  For assembly
        /// files, add a row to the MsiAssembly table and add AssemblyName information by adding
        /// MsiAssemblyName rows.
        /// </remarks>
        /// <param name="output">Internal representation of the msi database to operate upon.</param>
        private void UpdateFileInformation(Output output)
        {
            OutputTable mergeTable = output.OutputTables["Merge"];
            if (null != mergeTable)
            {
                foreach (OutputRow outputRow in mergeTable.OutputRows)
                {
                    MergeRow mergeRow = (MergeRow)outputRow.Row;
                    string moduleFile = null;
                    try
                    {
                        moduleFile = this.extension.FileResolutionHandler(mergeRow.SourceFile, FileResolutionType.Module);
                    }
                    catch (WixFileNotFoundException wfnfe)
                    {
                        this.OnMessage(WixErrors.BinderExtensionMissingFile(null, ErrorLevel.Normal, wfnfe.Message));
                        continue;
                    }

                    output.Modules.Add(mergeRow);
                    try
                    {
                        // read the module's File table to get its FileMediaInformation entries
                        using (Database db = new Database(moduleFile, OpenDatabase.ReadOnly))
                        {
                            mergeRow.HasFiles = false;

                            if (db.TableExists("File") && db.TableExists("Component"))
                            {
                                Hashtable uniqueModuleFileIdentifiers = System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable();

                                using (View view = db.OpenExecuteView("SELECT `File`, `Directory_` FROM `File`, `Component` WHERE `Component_`=`Component`"))
                                {
                                    Record record;
                                    while (view.Fetch(out record))
                                    {
                                        FileMediaInformation fileMediaInformation = new FileMediaInformation(record[1], record[2], mergeRow.DiskId, String.Concat(this.tempFiles.BasePath, Path.DirectorySeparatorChar, "MergeId.", mergeRow.Id.GetHashCode().ToString("X4", CultureInfo.InvariantCulture.NumberFormat), Path.DirectorySeparatorChar, record[1]), mergeRow.Number, mergeRow.FileCompression, moduleFile, -1);
                                        FileMediaInformation otherFileMediaInformation = output.FileMediaInformationCollection[fileMediaInformation.FileId];
                                        string collidingModuleFileIdentifier = (string)uniqueModuleFileIdentifiers[fileMediaInformation.FileId];

                                        if (null == otherFileMediaInformation && null == collidingModuleFileIdentifier)
                                        {
                                            output.FileMediaInformationCollection.Add(fileMediaInformation);

                                            // keep track of file identifiers in this merge module
                                            uniqueModuleFileIdentifiers.Add(fileMediaInformation.FileId, fileMediaInformation.FileId);
                                        }
                                        else // collision(s) detected
                                        {
                                            // case-sensitive collision with another merge module or a user-authored file identifier
                                            if (null != otherFileMediaInformation)
                                            {
                                                this.OnMessage(WixErrors.DuplicateModuleFileIdentifier(mergeRow.SourceLineNumbers, mergeRow.Id, fileMediaInformation.FileId));
                                            }

                                            // case-insensitive collision with another file identifier in the same merge module
                                            if (null != collidingModuleFileIdentifier)
                                            {
                                                this.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(mergeRow.SourceLineNumbers, mergeRow.Id, fileMediaInformation.FileId, collidingModuleFileIdentifier));
                                            }
                                        }

                                        mergeRow.HasFiles = true;
                                    }
                                }
                            }
                        }
                    }
                    catch (FileNotFoundException fnfe)
                    {
                        throw new WixFileNotFoundException(null, moduleFile, fnfe);
                    }
                    catch (IOException ioe)
                    {
                        throw new WixMergeModuleOpenException(mergeRow.SourceLineNumbers, mergeRow.Id, moduleFile, ioe);
                    }
                }
            }

            // calculate sequence numbers and media disk id layout for all file media information objects
            if (OutputType.Module == output.Type)
            {
                int lastSequence = 0;
                foreach (FileMediaInformation fmi in output.FileMediaInformationCollection)
                {
                    fmi.Modularize(output.ModularizationGuid);
                    fmi.Sequence = ++lastSequence;
                }
            }
            else
            {
                int lastSequence = 0;
                MediaRow mediaRow = null;
                output.FileMediaInformationCollection.Sort();
                SortedList patchGroups = new SortedList();

                // sequence the non-patch-added files
                foreach (FileMediaInformation fmi in output.FileMediaInformationCollection)
                {
                    if (null == mediaRow)
                    {
                        mediaRow = output.MediaRows[fmi.Media];
                    }
                    else if (mediaRow.DiskId != fmi.Media)
                    {
                        mediaRow.LastSequence = lastSequence;
                        mediaRow = output.MediaRows[fmi.Media];
                    }

                    if (0 < fmi.PatchGroup)
                    {
                        ArrayList patchGroup = (ArrayList)patchGroups[fmi.PatchGroup];

                        if (null == patchGroup)
                        {
                            patchGroup = new ArrayList();
                            patchGroups.Add(fmi.PatchGroup, patchGroup);
                        }

                        patchGroup.Add(fmi);
                    }
                    else
                    {
                        fmi.Sequence = ++lastSequence;
                    }
                }
                if (null != mediaRow)
                {
                    mediaRow.LastSequence = lastSequence;
                    mediaRow = null;
                }

                // sequence the patch-added files
                foreach (ArrayList patchGroup in patchGroups.Values)
                {
                    foreach (FileMediaInformation fmi in patchGroup)
                    {
                        if (null == mediaRow)
                        {
                            mediaRow = output.MediaRows[fmi.Media];
                        }
                        else if (mediaRow.DiskId != fmi.Media)
                        {
                            mediaRow.LastSequence = lastSequence;
                            mediaRow = output.MediaRows[fmi.Media];
                        }

                        fmi.Sequence = ++lastSequence;
                    }
                }
                if (null != mediaRow)
                {
                    mediaRow.LastSequence = lastSequence;
                }
            }

            // copy the special media rows back to the real media table
            if (0 < output.MediaRows.Count)
            {
                OutputTable mediaTable = Common.EnsureOutputTable(output, this.tableDefinitions["Media"]);

                foreach (MediaRow mediaRow in output.MediaRows)
                {
                    mediaTable.OutputRows.Add(new OutputRow(mediaRow));
                }
            }

            OutputTable fileTable = output.OutputTables["File"];
            if (null == fileTable)   // no work to do
            {
                return;
            }

            foreach (OutputRow outputRow in fileTable.OutputRows)
            {
                FileRow fileRow = outputRow.Row as FileRow;
                if (null == fileRow)
                {
                    throw new ApplicationException("Expected FileRow");
                }

                // copy the sequence number from the file media information to the file table
                fileRow.Sequence = output.FileMediaInformationCollection[fileRow.File].Sequence;

                string src = fileRow.Source;
                FileInfo fileInfo = null;

                if (!this.suppressFileHashAndInfo || (!this.suppressAssemblies && FileAssemblyType.NotAnAssembly != fileRow.AssemblyType))
                {
                    try
                    {
                        src = this.extension.FileResolutionHandler(fileRow.Source, FileResolutionType.File);
                    }
                    catch (WixFileNotFoundException wfnfe)
                    {
                        this.OnMessage(WixErrors.BinderExtensionMissingFile(fileRow.SourceLineNumbers, ErrorLevel.Normal, wfnfe.Message));
                        continue;
                    }

                    try
                    {
                        fileInfo = new FileInfo(src);
                    }
                    catch (ArgumentException)
                    {
                        this.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, ErrorLevel.Normal, src));
                        continue;
                    }
                    catch (PathTooLongException)
                    {
                        this.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, ErrorLevel.Normal, src));
                        continue;
                    }
                    catch (NotSupportedException)
                    {
                        this.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, ErrorLevel.Normal, src));
                        continue;
                    }
                }

                if (!this.suppressFileHashAndInfo)
                {
                    if (fileInfo.Exists)
                    {
                        string version;
                        string language;

                        fileRow.FileSize = fileInfo.Length;
                        try
                        {
                            MsiBase.FileVersion(fileInfo.FullName, out version, out language);
                        }
                        catch (FileNotFoundException e)
                        {
                            throw new WixFileNotFoundException(null, fileInfo.FullName, e);   // TODO: find a way to get the sourceFile (instead of null)
                        }

                        if (0 == version.Length && 0 == language.Length)   // unversioned files have their hashes added to the MsiFileHash table
                        {
                            int[] hash;
                            try
                            {
                                MsiBase.GetFileHash(fileInfo.FullName, 0, out hash);
                            }
                            catch (FileNotFoundException e)
                            {
                                throw new WixFileNotFoundException(null, fileInfo.FullName, e);   // TODO: find a way to get the sourceFile (instead of null)
                            }

                            OutputTable outputHashTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiFileHash"]);
                            Row hashRow = new Row(outputHashTable.TableDefinition);
                            hashRow[0] = fileRow.File;
                            hashRow[1] = 0;
                            hashRow[2] = hash[0];
                            hashRow[3] = hash[1];
                            hashRow[4] = hash[2];
                            hashRow[5] = hash[3];
                            outputHashTable.OutputRows.Add(new OutputRow(hashRow));
                        }
                        else // update the file row with the version and language information
                        {
                            fileRow.Version = version;
                            fileRow.Language = language;
                        }
                    }
                    else
                    {
                        this.OnMessage(WixErrors.CannotFindFile(fileRow.SourceLineNumbers, ErrorLevel.Normal, fileRow.File, fileRow.FileName, src));
                    }
                }

                // if we're not suppressing automagically grabbing assembly information and this is a
                // CLR assembly, load the assembly and get the assembly name information
                if (!this.suppressAssemblies)
                {
                    if (FileAssemblyType.DotNetAssembly == fileRow.AssemblyType)
                    {
                        StringDictionary assemblyNameValues = new StringDictionary();

                        // under CLR 2.0, use a more robust method of gathering AssemblyName information
                        if (2 <= Environment.Version.Major)
                        {
                            CLRInterop.IReferenceIdentity referenceIdentity = null;
                            Guid referenceIdentityGuid = CLRInterop.ReferenceIdentityGuid;

                            if (0 == CLRInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out referenceIdentity))
                            {
                                if (null != referenceIdentity)
                                {
                                    string culture = referenceIdentity.GetAttribute(null, "Culture");
                                    if (null != culture)
                                    {
                                        assemblyNameValues.Add("Culture", culture);
                                    }

                                    string name = referenceIdentity.GetAttribute(null, "Name");
                                    if (null != name)
                                    {
                                        assemblyNameValues.Add("Name", name);
                                    }

                                    string processorArchitecture = referenceIdentity.GetAttribute(null, "ProcessorArchitecture");
                                    if (null != processorArchitecture)
                                    {
                                        assemblyNameValues.Add("ProcessorArchitecture", processorArchitecture);
                                    }

                                    string publicKeyToken = referenceIdentity.GetAttribute(null, "PublicKeyToken");
                                    if (null != publicKeyToken)
                                    {
                                        assemblyNameValues.Add("PublicKeyToken", publicKeyToken.ToUpper(CultureInfo.InvariantCulture));
                                    }

                                    string version = referenceIdentity.GetAttribute(null, "Version");
                                    if (null != version)
                                    {
                                        assemblyNameValues.Add("Version", version);
                                    }
                                }
                            }
                        }
                        else
                        {
                            AssemblyName assemblyName = null;
                            try
                            {
                                assemblyName = AssemblyName.GetAssemblyName(fileInfo.FullName);

                                if (null != assemblyName.CultureInfo)
                                {
                                    assemblyNameValues.Add("Culture", assemblyName.CultureInfo.ToString());
                                }

                                if (null != assemblyName.Name)
                                {
                                    assemblyNameValues.Add("Name", assemblyName.Name);
                                }

                                byte[] publicKey = assemblyName.GetPublicKeyToken();
                                if (null != publicKey && 0 < publicKey.Length)
                                {
                                    StringBuilder sb = new StringBuilder();
                                    for (int i = 0; i < publicKey.GetLength(0); ++i)
                                    {
                                        sb.AppendFormat("{0:X2}", publicKey[i]);
                                    }
                                    assemblyNameValues.Add("PublicKeyToken", sb.ToString());
                                }

                                if (null != assemblyName.Version)
                                {
                                    assemblyNameValues.Add("Version", assemblyName.Version.ToString());
                                }
                            }
                            catch (FileNotFoundException fnfe)
                            {
                                throw new WixFileNotFoundException(fileRow.SourceLineNumbers, fileInfo.FullName, fnfe);
                            }
                            catch (Exception e)
                            {
                                if (e is NullReferenceException || e is SEHException)
                                {
                                    throw;
                                }
                                else
                                {
                                    throw new WixInvalidAssemblyException(fileRow.SourceLineNumbers, fileInfo, e);
                                }
                            }
                        }

                        OutputTable assemblyNameOutputTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiAssemblyName"]);
                        if (assemblyNameValues.ContainsKey("name"))
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "name", assemblyNameValues["name"]);
                        }

                        string fileVersion = null;
                        if (this.setMsiAssemblyNameFileVersion)
                        {
                            string language;

                            MsiBase.FileVersion(fileInfo.FullName, out fileVersion, out language);
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "fileVersion", fileVersion);
                        }

                        if (assemblyNameValues.ContainsKey("version"))
                        {
                            string assemblyVersion = assemblyNameValues["version"];

                            // there is a bug in fusion that requires the assembly's "version" attribute
                            // to be equal to or longer than the "fileVersion" in length when its present;
                            // the workaround is to prepend zeroes to the last version number in the assembly version
                            if (this.setMsiAssemblyNameFileVersion && null != fileVersion && fileVersion.Length > assemblyVersion.Length)
                            {
                                string padding = new string('0', fileVersion.Length - assemblyVersion.Length);
                                string[] assemblyVersionNumbers = assemblyVersion.Split('.');

                                if (assemblyVersionNumbers.Length > 0)
                                {
                                    assemblyVersionNumbers[assemblyVersionNumbers.Length - 1] = String.Concat(padding, assemblyVersionNumbers[assemblyVersionNumbers.Length - 1]);
                                    assemblyVersion = String.Join(".", assemblyVersionNumbers);
                                }
                            }

                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "version", assemblyVersion);
                        }

                        if (assemblyNameValues.ContainsKey("culture"))
                        {
                            string culture = assemblyNameValues["culture"];
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "culture", (String.Empty == culture ? "neutral" : culture));
                        }

                        if (assemblyNameValues.ContainsKey("publicKeyToken"))
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "publicKeyToken", assemblyNameValues["publicKeyToken"]);
                        }

                        if (null != fileRow.ProcessorArchitecture && 0 < fileRow.ProcessorArchitecture.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "processorArchitecture", fileRow.ProcessorArchitecture);
                        }

                        if (assemblyNameValues.ContainsKey("processorArchitecture"))
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "processorArchitecture", assemblyNameValues["processorArchitecture"]);
                        }
                    }
                    else if (FileAssemblyType.Win32Assembly == fileRow.AssemblyType)
                    {
                        FileRow fileManifestRow = fileRow;

                        // would rather look this up through a data structure rather than
                        // do an order n search through the list of files for every
                        // instance of a win32 assembly.  From what I can find, there
                        // are no indexed data structures available at this point
                        // in the code we're left with this expensive search.
                        foreach (OutputRow manifestOutputRow in fileTable.OutputRows)
                        {
                            fileManifestRow = manifestOutputRow.Row as FileRow;
                            if (fileManifestRow.File == fileRow.AssemblyManifest)
                            {
                                break;
                            }
                        }

                        string type = null;
                        string name = null;
                        string version = null;
                        string processorArchitecture = null;
                        string publicKeyToken = null;

                        // loading the dom is expensive we want more performant APIs than the DOM
                        // Navigator is cheaper than dom.  Perhaps there is a cheaper API still.
                        string manifestSourcePath = null;
                        try
                        {
                            manifestSourcePath = this.extension.FileResolutionHandler(fileManifestRow.Source, FileResolutionType.File);
                        }
                        catch (WixFileNotFoundException wfnfe)
                        {
                            this.OnMessage(WixErrors.BinderExtensionMissingFile(fileRow.SourceLineNumbers, ErrorLevel.Normal, wfnfe.Message));
                            continue;
                        }

                        try
                        {
                            XPathDocument doc = new XPathDocument(manifestSourcePath);
                            XPathNavigator nav = doc.CreateNavigator();
                            nav.MoveToRoot();

                            // this assumes a particular schema for a win32 manifest and does not
                            // provide error checking if the file does not conform to schema.
                            // The fallback case here is that nothing is added to the MsiAssemblyName
                            // table for a out of tollerence Win32 manifest.  Perhaps warnings needed.
                            if (nav.MoveToFirstChild())
                            {
                                while (nav.NodeType != XPathNodeType.Element || nav.Name != "assembly")
                                {
                                    nav.MoveToNext();
                                }
                                if (nav.MoveToFirstChild())
                                {
                                    while (nav.NodeType != XPathNodeType.Element || nav.Name != "assemblyIdentity")
                                    {
                                        nav.MoveToNext();
                                    }
                                    if (nav.MoveToAttribute("type", String.Empty))
                                    {
                                        type = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("name", String.Empty))
                                    {
                                        name = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("version", String.Empty))
                                    {
                                        version = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("processorArchitecture", String.Empty))
                                    {
                                        processorArchitecture = nav.Value;
                                        nav.MoveToParent();
                                    }
                                    if (nav.MoveToAttribute("publicKeyToken", String.Empty))
                                    {
                                        publicKeyToken = nav.Value;
                                        nav.MoveToParent();
                                    }
                                }
                            }
                        }
                        catch (XmlException xe)
                        {
                            this.OnMessage(WixErrors.InvalidXml(SourceLineNumberCollection.FromFileName(manifestSourcePath), "manifest", xe.Message));
                        }

                        OutputTable assemblyNameOutputTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiAssemblyName"]);
                        if (null != name && 0 < name.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "name", name);
                        }
                        if (null != version && 0 < version.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "version", version);
                        }
                        if (null != type && 0 < type.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "type", type);
                        }
                        if (null != processorArchitecture && 0 < processorArchitecture.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "processorArchitecture", processorArchitecture);
                        }
                        if (null != publicKeyToken && 0 < publicKeyToken.Length)
                        {
                            this.SetMsiAssemblyName(assemblyNameOutputTable, fileRow, "publicKeyToken", publicKeyToken);
                        }
                    }
                }
            }
        }
Beispiel #40
0
        private static IntermediateSymbol GenerateSymbolFromRow(Wix3.Row row, Dictionary <int, Wix3.WixMediaRow> wixMediaByDiskId, Dictionary <string, Wix3.Row> componentsById, Dictionary <string, Wix3.Row> fontsById, Dictionary <string, Wix3.Row> bindPathsById, Dictionary <string, Wix3.Row> selfRegById, Dictionary <string, Wix3.Row> wixFileById, Dictionary <string, Wix3.Row> wixDirectoryById)
        {
            var name = row.Table.Name;

            switch (name)
            {
            case "_SummaryInformation":
                return(DefaultSymbolFromRow(typeof(SummaryInformationSymbol), row, columnZeroIsId: false));

            case "ActionText":
                return(DefaultSymbolFromRow(typeof(ActionTextSymbol), row, columnZeroIsId: false));

            case "AppId":
                return(DefaultSymbolFromRow(typeof(AppIdSymbol), row, columnZeroIsId: false));

            case "AppSearch":
                return(DefaultSymbolFromRow(typeof(AppSearchSymbol), row, columnZeroIsId: false));

            case "Billboard":
                return(DefaultSymbolFromRow(typeof(BillboardSymbol), row, columnZeroIsId: true));

            case "Binary":
                return(DefaultSymbolFromRow(typeof(BinarySymbol), row, columnZeroIsId: true));

            case "BindPath":
                return(null);

            case "CCPSearch":
                return(DefaultSymbolFromRow(typeof(CCPSearchSymbol), row, columnZeroIsId: true));

            case "Class":
                return(DefaultSymbolFromRow(typeof(ClassSymbol), row, columnZeroIsId: false));

            case "CompLocator":
                return(DefaultSymbolFromRow(typeof(CompLocatorSymbol), row, columnZeroIsId: false));

            case "Component":
            {
                var attributes = FieldAsNullableInt(row, 3);

                var location = ComponentLocation.LocalOnly;
                if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesSourceOnly) == WindowsInstallerConstants.MsidbComponentAttributesSourceOnly)
                {
                    location = ComponentLocation.SourceOnly;
                }
                else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesOptional) == WindowsInstallerConstants.MsidbComponentAttributesOptional)
                {
                    location = ComponentLocation.Either;
                }

                var keyPath     = FieldAsString(row, 5);
                var keyPathType = String.IsNullOrEmpty(keyPath) ? ComponentKeyPathType.Directory : ComponentKeyPathType.File;
                if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath) == WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath)
                {
                    keyPathType = ComponentKeyPathType.Registry;
                }
                else if ((attributes & WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource) == WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource)
                {
                    keyPathType = ComponentKeyPathType.OdbcDataSource;
                }

                return(new ComponentSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        ComponentId = FieldAsString(row, 1),
                        DirectoryRef = FieldAsString(row, 2),
                        Condition = FieldAsString(row, 4),
                        KeyPath = keyPath,
                        Location = location,
                        DisableRegistryReflection = (attributes & WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection) == WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection,
                        NeverOverwrite = (attributes & WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite) == WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite,
                        Permanent = (attributes & WindowsInstallerConstants.MsidbComponentAttributesPermanent) == WindowsInstallerConstants.MsidbComponentAttributesPermanent,
                        SharedDllRefCount = (attributes & WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount) == WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount,
                        Shared = (attributes & WindowsInstallerConstants.MsidbComponentAttributesShared) == WindowsInstallerConstants.MsidbComponentAttributesShared,
                        Transitive = (attributes & WindowsInstallerConstants.MsidbComponentAttributesTransitive) == WindowsInstallerConstants.MsidbComponentAttributesTransitive,
                        UninstallWhenSuperseded = (attributes & WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence) == WindowsInstallerConstants.MsidbComponentAttributesUninstallOnSupersedence,
                        Win64 = (attributes & WindowsInstallerConstants.MsidbComponentAttributes64bit) == WindowsInstallerConstants.MsidbComponentAttributes64bit,
                        KeyPathType = keyPathType,
                    });
            }

            case "Condition":
                return(DefaultSymbolFromRow(typeof(ConditionSymbol), row, columnZeroIsId: false));

            case "CreateFolder":
                return(DefaultSymbolFromRow(typeof(CreateFolderSymbol), row, columnZeroIsId: false));

            case "CustomAction":
            {
                var caType        = FieldAsInt(row, 1);
                var executionType = DetermineCustomActionExecutionType(caType);
                var sourceType    = DetermineCustomActionSourceType(caType);
                var targetType    = DetermineCustomActionTargetType(caType);

                return(new CustomActionSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        ExecutionType = executionType,
                        SourceType = sourceType,
                        Source = FieldAsString(row, 2),
                        TargetType = targetType,
                        Target = FieldAsString(row, 3),
                        Win64 = (caType & WindowsInstallerConstants.MsidbCustomActionType64BitScript) == WindowsInstallerConstants.MsidbCustomActionType64BitScript,
                        TSAware = (caType & WindowsInstallerConstants.MsidbCustomActionTypeTSAware) == WindowsInstallerConstants.MsidbCustomActionTypeTSAware,
                        Impersonate = (caType & WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate) != WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate,
                        IgnoreResult = (caType & WindowsInstallerConstants.MsidbCustomActionTypeContinue) == WindowsInstallerConstants.MsidbCustomActionTypeContinue,
                        Hidden = (caType & WindowsInstallerConstants.MsidbCustomActionTypeHideTarget) == WindowsInstallerConstants.MsidbCustomActionTypeHideTarget,
                        Async = (caType & WindowsInstallerConstants.MsidbCustomActionTypeAsync) == WindowsInstallerConstants.MsidbCustomActionTypeAsync,
                    });
            }

            case "Directory":
            {
                var id     = FieldAsString(row, 0);
                var splits = SplitDefaultDir(FieldAsString(row, 2));

                var symbol = new DirectorySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id))
                {
                    ParentDirectoryRef = FieldAsString(row, 1),
                    Name            = splits[0],
                    ShortName       = splits[1],
                    SourceName      = splits[2],
                    SourceShortName = splits[3]
                };

                if (wixDirectoryById.TryGetValue(id, out var wixDirectoryRow))
                {
                    symbol.ComponentGuidGenerationSeed = FieldAsString(wixDirectoryRow, 1);
                }

                return(symbol);
            }

            case "DrLocator":
                return(DefaultSymbolFromRow(typeof(DrLocatorSymbol), row, columnZeroIsId: false));

            case "DuplicateFile":
            {
                var splitName = FieldAsString(row, 3)?.Split('|');

                var symbol = new DuplicateFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                {
                    ComponentRef         = FieldAsString(row, 1),
                    FileRef              = FieldAsString(row, 2),
                    DestinationName      = splitName == null ? null : splitName.Length > 1 ? splitName[1] : splitName[0],
                    DestinationShortName = splitName == null ? null : splitName.Length > 1 ? splitName[0] : null,
                    DestinationFolder    = FieldAsString(row, 4)
                };

                return(symbol);
            }

            case "Error":
                return(DefaultSymbolFromRow(typeof(ErrorSymbol), row, columnZeroIsId: false));

            case "Extension":
                return(DefaultSymbolFromRow(typeof(ExtensionSymbol), row, columnZeroIsId: false));

            case "Feature":
            {
                var attributes     = FieldAsInt(row, 7);
                var installDefault = FeatureInstallDefault.Local;
                if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFollowParent) == WindowsInstallerConstants.MsidbFeatureAttributesFollowParent)
                {
                    installDefault = FeatureInstallDefault.FollowParent;
                }
                else if ((attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorSource) == WindowsInstallerConstants.MsidbFeatureAttributesFavorSource)
                {
                    installDefault = FeatureInstallDefault.Source;
                }

                return(new FeatureSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        ParentFeatureRef = FieldAsString(row, 1),
                        Title = FieldAsString(row, 2),
                        Description = FieldAsString(row, 3),
                        Display = FieldAsInt(row, 4), // BUGBUGBUG: FieldAsNullableInt(row, 4),
                        Level = FieldAsInt(row, 5),
                        DirectoryRef = FieldAsString(row, 6),
                        DisallowAbsent = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent) == WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent,
                        DisallowAdvertise = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise,
                        InstallDefault = installDefault,
                        TypicalDefault = (attributes & WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise) == WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise ? FeatureTypicalDefault.Advertise : FeatureTypicalDefault.Install,
                    });
            }

            case "FeatureComponents":
                return(DefaultSymbolFromRow(typeof(FeatureComponentsSymbol), row, columnZeroIsId: false));

            case "File":
            {
                var attributes = FieldAsNullableInt(row, 6);

                FileSymbolAttributes symbolAttributes = 0;
                symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesReadOnly) == WindowsInstallerConstants.MsidbFileAttributesReadOnly ? FileSymbolAttributes.ReadOnly : 0;
                symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesHidden) == WindowsInstallerConstants.MsidbFileAttributesHidden ? FileSymbolAttributes.Hidden : 0;
                symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesSystem) == WindowsInstallerConstants.MsidbFileAttributesSystem ? FileSymbolAttributes.System : 0;
                symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesVital) == WindowsInstallerConstants.MsidbFileAttributesVital ? FileSymbolAttributes.Vital : 0;
                symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesChecksum) == WindowsInstallerConstants.MsidbFileAttributesChecksum ? FileSymbolAttributes.Checksum : 0;
                symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) == WindowsInstallerConstants.MsidbFileAttributesNoncompressed ? FileSymbolAttributes.Uncompressed : 0;
                symbolAttributes |= (attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed ? FileSymbolAttributes.Compressed : 0;

                var id        = FieldAsString(row, 0);
                var splitName = FieldAsString(row, 2).Split('|');

                var symbol = new FileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, id))
                {
                    ComponentRef = FieldAsString(row, 1),
                    Name         = splitName.Length > 1 ? splitName[1] : splitName[0],
                    ShortName    = splitName.Length > 1 ? splitName[0] : null,
                    FileSize     = FieldAsInt(row, 3),
                    Version      = FieldAsString(row, 4),
                    Language     = FieldAsString(row, 5),
                    Attributes   = symbolAttributes
                };

                if (bindPathsById.TryGetValue(id, out var bindPathRow))
                {
                    symbol.BindPath = FieldAsString(bindPathRow, 1) ?? String.Empty;
                }

                if (fontsById.TryGetValue(id, out var fontRow))
                {
                    symbol.FontTitle = FieldAsString(fontRow, 1) ?? String.Empty;
                }

                if (selfRegById.TryGetValue(id, out var selfRegRow))
                {
                    symbol.SelfRegCost = FieldAsNullableInt(selfRegRow, 1) ?? 0;
                }

                if (wixFileById.TryGetValue(id, out var wixFileRow))
                {
                    symbol.DirectoryRef = FieldAsString(wixFileRow, 4);
                    symbol.DiskId       = FieldAsNullableInt(wixFileRow, 5) ?? 0;
                    symbol.Source       = new IntermediateFieldPathValue {
                        Path = FieldAsString(wixFileRow, 6)
                    };
                    symbol.PatchGroup      = FieldAsInt(wixFileRow, 8);
                    symbol.PatchAttributes = (PatchAttributeType)FieldAsInt(wixFileRow, 10);
                }

                return(symbol);
            }

            case "Font":
                return(null);

            case "Icon":
                return(DefaultSymbolFromRow(typeof(IconSymbol), row, columnZeroIsId: true));

            case "IniFile":
            {
                var splitName = FieldAsString(row, 1).Split('|');
                var action    = FieldAsInt(row, 6);

                var symbol = new IniFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                {
                    FileName      = splitName.Length > 1 ? splitName[1] : splitName[0],
                    ShortFileName = splitName.Length > 1 ? splitName[0] : null,
                    DirProperty   = FieldAsString(row, 2),
                    Section       = FieldAsString(row, 3),
                    Key           = FieldAsString(row, 4),
                    Value         = FieldAsString(row, 5),
                    Action        = action == 3 ? IniFileActionType.AddTag : action == 1 ? IniFileActionType.CreateLine : IniFileActionType.AddLine,
                    ComponentRef  = FieldAsString(row, 7),
                };

                return(symbol);
            }

            case "IniLocator":
            {
                var splitName = FieldAsString(row, 1).Split('|');

                var symbol = new IniLocatorSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                {
                    FileName      = splitName.Length > 1 ? splitName[1] : splitName[0],
                    ShortFileName = splitName.Length > 1 ? splitName[0] : null,
                    Section       = FieldAsString(row, 2),
                    Key           = FieldAsString(row, 3),
                    Field         = FieldAsInt(row, 4),
                    Type          = FieldAsInt(row, 5),
                };

                return(symbol);
            }

            case "LockPermissions":
                return(DefaultSymbolFromRow(typeof(LockPermissionsSymbol), row, columnZeroIsId: false));

            case "Media":
            {
                var diskId = FieldAsInt(row, 0);
                var symbol = new MediaSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, diskId))
                {
                    DiskId       = diskId,
                    LastSequence = FieldAsNullableInt(row, 1),
                    DiskPrompt   = FieldAsString(row, 2),
                    Cabinet      = FieldAsString(row, 3),
                    VolumeLabel  = FieldAsString(row, 4),
                    Source       = FieldAsString(row, 5)
                };

                if (wixMediaByDiskId.TryGetValue(diskId, out var wixMediaRow))
                {
                    var compressionLevel = FieldAsString(wixMediaRow, 1);

                    symbol.CompressionLevel = String.IsNullOrEmpty(compressionLevel) ? null : (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), compressionLevel, true);
                    symbol.Layout           = wixMediaRow.Layout;
                }

                return(symbol);
            }

            case "MIME":
                return(DefaultSymbolFromRow(typeof(MIMESymbol), row, columnZeroIsId: false));

            case "ModuleIgnoreTable":
                return(DefaultSymbolFromRow(typeof(ModuleIgnoreTableSymbol), row, columnZeroIsId: true));

            case "MoveFile":
                return(DefaultSymbolFromRow(typeof(MoveFileSymbol), row, columnZeroIsId: true));

            case "MsiAssembly":
            {
                var componentId = FieldAsString(row, 0);
                if (componentsById.TryGetValue(componentId, out var componentRow))
                {
                    return(new AssemblySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(componentRow, 5)))
                        {
                            ComponentRef = componentId,
                            FeatureRef = FieldAsString(row, 1),
                            ManifestFileRef = FieldAsString(row, 2),
                            ApplicationFileRef = FieldAsString(row, 3),
                            Type = FieldAsNullableInt(row, 4) == 1 ? AssemblyType.Win32Assembly : AssemblyType.DotNetAssembly,
                        });
                }

                return(null);
            }

            case "MsiLockPermissionsEx":
                return(DefaultSymbolFromRow(typeof(MsiLockPermissionsExSymbol), row, columnZeroIsId: true));

            case "MsiShortcutProperty":
                return(DefaultSymbolFromRow(typeof(MsiShortcutPropertySymbol), row, columnZeroIsId: true));

            case "ODBCDataSource":
                return(DefaultSymbolFromRow(typeof(ODBCDataSourceSymbol), row, columnZeroIsId: true));

            case "ODBCDriver":
                return(DefaultSymbolFromRow(typeof(ODBCDriverSymbol), row, columnZeroIsId: true));

            case "ODBCTranslator":
                return(DefaultSymbolFromRow(typeof(ODBCTranslatorSymbol), row, columnZeroIsId: true));

            case "ProgId":
                return(DefaultSymbolFromRow(typeof(ProgIdSymbol), row, columnZeroIsId: false));

            case "Property":
                return(DefaultSymbolFromRow(typeof(PropertySymbol), row, columnZeroIsId: true));

            case "PublishComponent":
                return(DefaultSymbolFromRow(typeof(PublishComponentSymbol), row, columnZeroIsId: false));

            case "Registry":
            {
                var value       = FieldAsString(row, 4);
                var valueType   = RegistryValueType.String;
                var valueAction = RegistryValueActionType.Write;

                if (!String.IsNullOrEmpty(value))
                {
                    if (value.StartsWith("#x", StringComparison.Ordinal))
                    {
                        valueType = RegistryValueType.Binary;
                        value     = value.Substring(2);
                    }
                    else if (value.StartsWith("#%", StringComparison.Ordinal))
                    {
                        valueType = RegistryValueType.Expandable;
                        value     = value.Substring(2);
                    }
                    else if (value.StartsWith("#", StringComparison.Ordinal))
                    {
                        valueType = RegistryValueType.Integer;
                        value     = value.Substring(1);
                    }
                    else if (value.StartsWith("[~]", StringComparison.Ordinal) && value.EndsWith("[~]", StringComparison.Ordinal))
                    {
                        value       = value.Substring(3, value.Length - 6);
                        valueType   = RegistryValueType.MultiString;
                        valueAction = RegistryValueActionType.Write;
                    }
                    else if (value.StartsWith("[~]", StringComparison.Ordinal))
                    {
                        value       = value.Substring(3);
                        valueType   = RegistryValueType.MultiString;
                        valueAction = RegistryValueActionType.Append;
                    }
                    else if (value.EndsWith("[~]", StringComparison.Ordinal))
                    {
                        value       = value.Substring(0, value.Length - 3);
                        valueType   = RegistryValueType.MultiString;
                        valueAction = RegistryValueActionType.Prepend;
                    }
                }

                return(new RegistrySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        Root = (RegistryRootType)FieldAsInt(row, 1),
                        Key = FieldAsString(row, 2),
                        Name = FieldAsString(row, 3),
                        Value = value,
                        ComponentRef = FieldAsString(row, 5),
                        ValueAction = valueAction,
                        ValueType = valueType,
                    });
            }

            case "RegLocator":
            {
                var type = FieldAsInt(row, 4);

                return(new RegLocatorSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        Root = (RegistryRootType)FieldAsInt(row, 1),
                        Key = FieldAsString(row, 2),
                        Name = FieldAsString(row, 3),
                        Type = (RegLocatorType)(type & 0xF),
                        Win64 = (type & WindowsInstallerConstants.MsidbLocatorType64bit) == WindowsInstallerConstants.MsidbLocatorType64bit
                    });
            }

            case "RemoveFile":
            {
                var splitName   = FieldAsString(row, 2).Split('|');
                var installMode = FieldAsInt(row, 4);

                return(new RemoveFileSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        ComponentRef = FieldAsString(row, 1),
                        FileName = splitName.Length > 1 ? splitName[1] : splitName[0],
                        ShortFileName = splitName.Length > 1 ? splitName[0] : null,
                        DirPropertyRef = FieldAsString(row, 3),
                        OnInstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnInstall ? (bool?)true : null,
                        OnUninstall = (installMode & WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove) == WindowsInstallerConstants.MsidbRemoveFileInstallModeOnRemove ? (bool?)true : null
                    });
            }

            case "RemoveRegistry":
            {
                return(new RemoveRegistrySymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        Action = RemoveRegistryActionType.RemoveOnInstall,
                        Root = (RegistryRootType)FieldAsInt(row, 1),
                        Key = FieldAsString(row, 2),
                        Name = FieldAsString(row, 3),
                        ComponentRef = FieldAsString(row, 4),
                    });
            }

            case "ReserveCost":
                return(DefaultSymbolFromRow(typeof(ReserveCostSymbol), row, columnZeroIsId: true));

            case "SelfReg":
                return(null);

            case "ServiceControl":
            {
                var events = FieldAsInt(row, 2);
                var wait   = FieldAsNullableInt(row, 4);
                return(new ServiceControlSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        Name = FieldAsString(row, 1),
                        Arguments = FieldAsString(row, 3),
                        Wait = !wait.HasValue || wait.Value == 1,
                        ComponentRef = FieldAsString(row, 5),
                        InstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventDelete) == WindowsInstallerConstants.MsidbServiceControlEventDelete,
                        UninstallRemove = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete) == WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete,
                        InstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventStart) == WindowsInstallerConstants.MsidbServiceControlEventStart,
                        UninstallStart = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStart) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStart,
                        InstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventStop) == WindowsInstallerConstants.MsidbServiceControlEventStop,
                        UninstallStop = (events & WindowsInstallerConstants.MsidbServiceControlEventUninstallStop) == WindowsInstallerConstants.MsidbServiceControlEventUninstallStop,
                    });
            }

            case "ServiceInstall":
                return(DefaultSymbolFromRow(typeof(ServiceInstallSymbol), row, columnZeroIsId: true));

            case "Shortcut":
            {
                var splitName = FieldAsString(row, 2).Split('|');

                return(new ShortcutSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        DirectoryRef = FieldAsString(row, 1),
                        Name = splitName.Length > 1 ? splitName[1] : splitName[0],
                        ShortName = splitName.Length > 1 ? splitName[0] : null,
                        ComponentRef = FieldAsString(row, 3),
                        Target = FieldAsString(row, 4),
                        Arguments = FieldAsString(row, 5),
                        Description = FieldAsString(row, 6),
                        Hotkey = FieldAsNullableInt(row, 7),
                        IconRef = FieldAsString(row, 8),
                        IconIndex = FieldAsNullableInt(row, 9),
                        Show = (ShortcutShowType?)FieldAsNullableInt(row, 10),
                        WorkingDirectory = FieldAsString(row, 11),
                        DisplayResourceDll = FieldAsString(row, 12),
                        DisplayResourceId = FieldAsNullableInt(row, 13),
                        DescriptionResourceDll = FieldAsString(row, 14),
                        DescriptionResourceId = FieldAsNullableInt(row, 15),
                    });
            }

            case "Signature":
                return(DefaultSymbolFromRow(typeof(SignatureSymbol), row, columnZeroIsId: true));

            case "UIText":
                return(DefaultSymbolFromRow(typeof(UITextSymbol), row, columnZeroIsId: true));

            case "Upgrade":
            {
                var attributes = FieldAsInt(row, 4);
                return(new UpgradeSymbol(SourceLineNumber4(row.SourceLineNumbers), new Identifier(AccessModifier.Public, FieldAsString(row, 0)))
                    {
                        UpgradeCode = FieldAsString(row, 0),
                        VersionMin = FieldAsString(row, 1),
                        VersionMax = FieldAsString(row, 2),
                        Language = FieldAsString(row, 3),
                        Remove = FieldAsString(row, 5),
                        ActionProperty = FieldAsString(row, 6),
                        MigrateFeatures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures) == WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures,
                        OnlyDetect = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect,
                        IgnoreRemoveFailures = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure) == WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure,
                        VersionMinInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive,
                        VersionMaxInclusive = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive,
                        ExcludeLanguages = (attributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive,
                    });
            }

            case "Verb":
                return(DefaultSymbolFromRow(typeof(VerbSymbol), row, columnZeroIsId: false));

            case "WixAction":
            {
                var sequenceTable = FieldAsString(row, 0);
                return(new WixActionSymbol(SourceLineNumber4(row.SourceLineNumbers))
                    {
                        SequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), sequenceTable == "AdvtExecuteSequence" ? nameof(SequenceTable.AdvertiseExecuteSequence) : sequenceTable),
                        Action = FieldAsString(row, 1),
                        Condition = FieldAsString(row, 2),
                        Sequence = FieldAsNullableInt(row, 3),
                        Before = FieldAsString(row, 4),
                        After = FieldAsString(row, 5),
                        Overridable = FieldAsNullableInt(row, 6) != 0,
                    });
            }

            case "WixBootstrapperApplication":
                return(DefaultSymbolFromRow(typeof(WixBootstrapperApplicationSymbol), row, columnZeroIsId: true));

            case "WixBundleContainer":
                return(DefaultSymbolFromRow(typeof(WixBundleContainerSymbol), row, columnZeroIsId: true));

            case "WixBundleVariable":
                return(DefaultSymbolFromRow(typeof(WixBundleVariableSymbol), row, columnZeroIsId: true));

            case "WixChainItem":
                return(DefaultSymbolFromRow(typeof(WixChainItemSymbol), row, columnZeroIsId: true));

            case "WixCustomTable":
                return(DefaultSymbolFromRow(typeof(WixCustomTableSymbol), row, columnZeroIsId: true));

            case "WixDirectory":
                return(null);

            case "WixFile":
                return(null);

            case "WixInstanceTransforms":
                return(DefaultSymbolFromRow(typeof(WixInstanceTransformsSymbol), row, columnZeroIsId: true));

            case "WixMedia":
                return(null);

            case "WixMerge":
                return(DefaultSymbolFromRow(typeof(WixMergeSymbol), row, columnZeroIsId: true));

            case "WixPatchBaseline":
                return(DefaultSymbolFromRow(typeof(WixPatchBaselineSymbol), row, columnZeroIsId: true));

            case "WixProperty":
            {
                var attributes = FieldAsInt(row, 1);
                return(new WixPropertySymbol(SourceLineNumber4(row.SourceLineNumbers))
                    {
                        PropertyRef = FieldAsString(row, 0),
                        Admin = (attributes & 0x1) == 0x1,
                        Hidden = (attributes & 0x2) == 0x2,
                        Secure = (attributes & 0x4) == 0x4,
                    });
            }

            case "WixSuppressModularization":
                return(DefaultSymbolFromRow(typeof(WixSuppressModularizationSymbol), row, columnZeroIsId: true));

            case "WixUI":
                return(DefaultSymbolFromRow(typeof(WixUISymbol), row, columnZeroIsId: true));

            case "WixVariable":
                return(DefaultSymbolFromRow(typeof(WixVariableSymbol), row, columnZeroIsId: true));

            default:
                return(GenericSymbolFromCustomRow(row, columnZeroIsId: false));
            }
        }
Beispiel #41
0
 /// <summary>
 /// Creates a symbol for a row.
 /// </summary>
 /// <param name="row">Row for the symbol</param>
 public Symbol(Row row)
 {
     this.row = row;
 }
Beispiel #42
0
 private static string FieldAsString(Wix3.Row row, int column)
 {
     return((string)row[column]);
 }
        private static IEnumerable <string> RowToStrings(Wix3.Row row, Dictionary <int, Wix3.WixMediaRow> wixMediaByDiskId)
        {
            string fields = null;

            // Massage output to match WiX v3 rows and v4 symbols.
            //
            switch (row.Table.Name)
            {
            case "Directory":
                var dirs = SplitDefaultDir((string)row[2]);
                fields = String.Join(",", row[0], row[1], dirs[0], dirs[1], dirs[2], dirs[3]);
                break;

            case "File":
            {
                var fieldValues = row.Fields.Take(7).Select(SafeConvertField).ToArray();
                if (fieldValues[3] == null)
                {
                    // "Somebody" sometimes writes out a null field even when the column definition says
                    // it's non-nullable. Not naming names or anything. (SWID tags.)
                    fieldValues[3] = "0";
                }
                fields = String.Join(",", fieldValues);
                break;
            }

            case "Media":
                var compression = wixMediaByDiskId.TryGetValue((int)row[0], out var wixMedia) ? (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), SafeConvertField(wixMedia.Fields[1]), true) : null;

                fields = String.Join(",", row.Fields.Select(SafeConvertField));
                fields = String.Join(",", fields, (int?)compression, SafeConvertField(wixMedia?.Fields[2]));
                break;

            case "RegLocator":
                var type = (int)row[4];
                fields = String.Join(",", row[0], row[1], row[2], row[3], type & 0xF, (type & 0x10) == 0x10);
                break;

            case "RemoveFile":
                var attributes  = (int)row[4];
                var onInstall   = (attributes & 1) == 1 ? (bool?)true : null;
                var onUninstall = (attributes & 2) == 2 ? (bool?)true : null;
                fields = String.Join(",", row.Fields.Take(4).Select(SafeConvertField));
                fields = String.Join(",", fields, onInstall, onUninstall);
                break;

            case "Shortcut":
                var split     = ((string)row[2]).Split('|');
                var afterName = String.Join(",", row.Fields.Skip(3).Select(SafeConvertField));
                fields = String.Join(",", row[0], row[1], split.Length > 1 ? split[1] : split[0], split.Length > 1 ? split[0] : String.Empty, afterName);
                break;

            case "WixAction":
                var table = (int)SequenceStringToSequenceTable(row[0]);
                fields = String.Join(",", table, row[1], row[2], row[3], row[4], row[5], row[6]);
                break;

            case "WixFile":
            {
                var fieldValues = row.Fields.Select(SafeConvertField).ToArray();
                if (fieldValues[8] == null)
                {
                    // "Somebody" sometimes writes out a null field even when the column definition says
                    // it's non-nullable. Not naming names or anything. (SWID tags.)
                    fieldValues[8] = "0";
                }
                if (fieldValues[10] == null)
                {
                    // WixFile rows that come from merge modules will not have the attributes column set
                    // so initilaize with 0.
                    fieldValues[10] = "0";
                }
                fields = String.Join(",", fieldValues);
                break;
            }

            case "WixMedia":
                break;

            default:
                fields = String.Join(",", row.Fields.Select(SafeConvertField));
                break;
            }

            if (fields != null)
            {
                yield return($"{row.Table.Name}:{fields}");
            }
        }
        public void FillFromPayloadRow(Output output, Row payloadRow)
        {
            SourceLineNumberCollection sourceLineNumbers = payloadRow.SourceLineNumbers;

            this[0] = payloadRow[0];
            this[1] = payloadRow[1];
            this[2] = (string)payloadRow[2] ?? String.Empty;
            this[3] = payloadRow[3];
            this[4] = payloadRow[4];
            this[5] = payloadRow[5] ?? String.Empty;
            this[6] = payloadRow[6];

            // payload files sourced from a cabinet (think WixExtension with embedded binary wixlib) are considered "non-content files".
            ObjectField field = (ObjectField)payloadRow.Fields[2];
            this.ContentFile = String.IsNullOrEmpty(field.CabinetFileId);

            this.Resolve();

            return;
        }
Beispiel #45
0
 public CatalogInfo(Row row, string payloadId)
 {
     this.Initialize((string)row[0], (string)row[1], payloadId);
 }
Beispiel #46
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);
        }
Beispiel #47
0
 /// <summary>
 /// Creates a new instance of the <see cref="ProviderDependency"/> class from a <see cref="Row"/>.
 /// </summary>
 /// <param name="row">The <see cref="Row"/> from which data is imported.</param>
 internal ProvidesDependency(Row row)
     : this((string)row[2], (string)row[3], (string)row[4], (int?)row[5])
 {
 }