Example #1
0
        /// <summary>
        /// Called after all output changes occur and right before the output is bound into its final format.
        /// </summary>
        public override void BundleFinalize(Output output)
        {
            Table tagTable = output.Tables["WixBundleTag"];
            if (null != tagTable)
            {
                Table table = output.Tables["WixBundle"];
                WixBundleRow bundleInfo = (WixBundleRow)table.Rows[0];
                string bundleId = bundleInfo.BundleId.ToString("D").ToUpperInvariant();
                Version bundleVersion = TagBinder.CreateFourPartVersion(bundleInfo.Version);
                string upgradeCode = NormalizeGuid(bundleInfo.UpgradeCode);

                string uniqueId = String.Concat("wix:bundle/", bundleId);

                string persistentId = String.Concat("wix:bundle.upgrade/", upgradeCode);

                // Try to collect all the software id tags from all the child packages.
                IList<SoftwareTag> containedTags = TagBinder.CollectPackageTags(output);

                foreach (Row tagRow in tagTable.Rows)
                {
                    string regid = (string)tagRow[1];
                    string name = (string)tagRow[2];

                    using (MemoryStream ms = new MemoryStream())
                    {
                        TagBinder.CreateTagFile(ms, uniqueId, bundleInfo.Name, bundleVersion, regid, bundleInfo.Publisher, persistentId, containedTags);
                        tagRow[5] = Encoding.UTF8.GetString(ms.ToArray());
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Called after all output changes occur and right before the output is bound into its final format.
        /// </summary>
        public override void BundleFinalize(Output output)
        {
            this.overallRegid = null; // always reset overall regid on initialize.

            Table tagTable = output.Tables["WixBundleTag"];
            if (null != tagTable)
            {
                Table table = output.Tables["WixBundle"];
                WixBundleRow bundleInfo = (WixBundleRow)table.Rows[0];
                Version bundleVersion = TagBinder.CreateFourPartVersion(bundleInfo.Version);

                // Try to collect all the software id tags from all the child packages.
                IList<SoftwareTag> allTags = TagBinder.CollectPackageTags(output);

                foreach (Row tagRow in tagTable.Rows)
                {
                    string regid = (string)tagRow[1];
                    string name = (string)tagRow[2];
                    bool licensed = (null != tagRow[3] && 0 != (int)tagRow[3]);
                    string typeString = (string)tagRow[5];

                    TagType type = String.IsNullOrEmpty(typeString) ? TagType.Unknown : (TagType)Enum.Parse(typeof(TagType), typeString);
                    IList<SoftwareTag> containedTags = TagBinder.CalculateContainedTagsAndType(allTags, ref type);

                    using (MemoryStream ms = new MemoryStream())
                    {
                        TagBinder.CreateTagFile(ms, regid, bundleInfo.BundleId.ToString("D").ToUpperInvariant(), bundleInfo.Name, bundleVersion, bundleInfo.Publisher, licensed, type, containedTags);
                        tagRow[4] = Encoding.UTF8.GetString(ms.ToArray());
                    }
                }
            }
        }
Example #3
0
        /// <summary>
        /// Called before database binding occurs.
        /// </summary>
        public override void DatabaseInitialize(Output output)
        {
            this.overallRegid = null; // always reset overall regid on initialize.

            // Ensure the tag files are generated to be imported by the MSI.
            this.CreateProductTagFiles(output);
        }
Example #4
0
        public static Intermediate ConvertOutput(Wix3.Output output)
#pragma warning restore 1591
        {
            var section = new IntermediateSection(String.Empty, OutputType3ToSectionType4(output.Type), output.Codepage);

            var wixMediaByDiskId = IndexWixMediaTableByDiskId(output);
            var componentsById   = IndexById <Wix3.Row>(output, "Component");
            var bindPathsById    = IndexById <Wix3.Row>(output, "BindPath");
            var fontsById        = IndexById <Wix3.Row>(output, "Font");
            var selfRegById      = IndexById <Wix3.Row>(output, "SelfReg");
            var wixDirectoryById = IndexById <Wix3.Row>(output, "WixDirectory");
            var wixFileById      = IndexById <Wix3.Row>(output, "WixFile");

            foreach (Wix3.Table table in output.Tables)
            {
                foreach (Wix3.Row row in table.Rows)
                {
                    var symbol = GenerateSymbolFromRow(row, wixMediaByDiskId, componentsById, fontsById, bindPathsById, selfRegById, wixFileById, wixDirectoryById);
                    if (symbol != null)
                    {
                        section.Symbols.Add(symbol);
                    }
                }
            }

            return(new Intermediate(String.Empty, new[] { section }, localizationsByCulture: null));
        }
        /// <summary>
        /// Constructor for auto media assigner.
        /// </summary>
        /// <param name="output">Output</param>
        /// <param name="core">Binder core.</param>
        /// <param name="filesCompressed">True if files are compressed by default. </param>
        public AutoMediaAssigner(Output output, BinderCore core, bool filesCompressed)
        {
            this.output = output;
            this.core = core;
            this.filesCompressed = filesCompressed;
            this.cabinetNameTemplate = "Cab{0}.cab";

            uncompressedFileRows = new FileRowCollection();
            mediaRows = new MediaRowCollection();
            cabinets = new Hashtable();
        }
Example #6
0
        /// <summary>
        /// Called after database variable resolution occurs.
        /// </summary>
        public override void DatabaseAfterResolvedFields(Output output)
        {
            Table wixBindUpdateFilesTable = output.Tables["WixBindUpdatedFiles"];

            // We'll end up re-writing the tag files but this time we may have the ProductCode
            // now to use as the unique id.
            List<WixFileRow> updatedFileRows = this.CreateProductTagFiles(output);
            foreach (WixFileRow updateFileRow in updatedFileRows)
            {
                Row row = wixBindUpdateFilesTable.CreateRow(updateFileRow.SourceLineNumbers);
                row[0] = updateFileRow.File;
            }
        }
Example #7
0
        public override void InspectTransform(Output transform)
        {
            Table fileTable = transform.Tables["File"];
            if (null != fileTable && 0 < fileTable.Rows.Count)
            {
                Row fileRow = fileTable.Rows[0];
                this.Core.OnMessage(ValidationWarnings.ExampleWarning(fileRow.SourceLineNumbers));

                return;
            }

            this.Core.OnMessage(ValidationErrors.ExampleError());
        }
Example #8
0
        private static Dictionary <int, Wix3.WixMediaRow> IndexWixMediaTableByDiskId(Wix3.Output output)
        {
            var wixMediaByDiskId = new Dictionary <int, Wix3.WixMediaRow>();
            var wixMediaTable    = output.Tables["WixMedia"];

            if (wixMediaTable != null)
            {
                foreach (Wix3.WixMediaRow row in wixMediaTable.Rows)
                {
                    wixMediaByDiskId.Add(FieldAsInt(row, 0), row);
                }
            }

            return(wixMediaByDiskId);
        }
Example #9
0
        /// <summary>
        /// Instantiate a new substorage.
        /// </summary>
        /// <param name="name">The substorage name.</param>
        /// <param name="data">The substorage data.</param>
        public SubStorage(string name, Output data)
        {
            if (null == name)
            {
                throw new ArgumentNullException("name");
            }

            if (null == data)
            {
                throw new ArgumentNullException("data");
            }

            this.name = name;
            this.data = data;
        }
        public PayloadInfoRow(SourceLineNumberCollection sourceLineNumbers, Output output, string id, string name, string sourceFile,
            bool contentFile, bool suppressSignatureValidation, string downloadUrl, string container, PackagingType packaging) :
            base(sourceLineNumbers, output.Tables["PayloadInfo"])
        {
            this.Id = id;
            this.Name = name;
            this.SourceFile = sourceFile;
            this.ContentFile = contentFile;
            this.SuppressSignatureValidation = suppressSignatureValidation;
            this.DownloadUrl = downloadUrl;
            this.Container = container;
            this.Packaging = packaging;

            this.Resolve();
        }
Example #11
0
        private static Dictionary <string, T> IndexById <T>(Wix3.Output output, string tableName) where T : Wix3.Row
        {
            var byId  = new Dictionary <string, T>();
            var table = output.Tables[tableName];

            if (table != null)
            {
                foreach (T row in table.Rows)
                {
                    byId.Add(FieldAsString(row, 0), row);
                }
            }

            return(byId);
        }
Example #12
0
        public override void InspectPatch(Output patch)
        {
            foreach (SubStorage transform in patch.SubStorages)
            {
                // Skip patch transforms.
                if (transform.Name.StartsWith("#"))
                {
                    continue;
                }

                Table fileTable = transform.Data.Tables["File"];
                if (null != fileTable && 0 < fileTable.Rows.Count)
                {
                    Row fileRow = fileTable.Rows[0];
                    this.Core.OnMessage(ValidationWarnings.AnotherExampleWarning(fileRow.SourceLineNumbers));

                    return;
                }
            }

            this.Core.OnMessage(ValidationErrors.ExampleError());
        }
Example #13
0
 /// <summary>
 /// Determine if a particular table should be decompiled with the current settings.
 /// </summary>
 /// <param name="output">The output being decompiled.</param>
 /// <param name="tableName">The name of a table.</param>
 /// <returns>true if the table should be decompiled; false otherwise.</returns>
 private bool DecompilableTable(Output output, string tableName)
 {
     switch (tableName)
     {
         case "ActionText":
         case "BBControl":
         case "Billboard":
         case "CheckBox":
         case "Control":
         case "ControlCondition":
         case "ControlEvent":
         case "Dialog":
         case "Error":
         case "EventMapping":
         case "RadioButton":
         case "TextStyle":
         case "UIText":
             return !this.suppressUI;
         case "ModuleAdminExecuteSequence":
         case "ModuleAdminUISequence":
         case "ModuleAdvtExecuteSequence":
         case "ModuleAdvtUISequence":
         case "ModuleComponents":
         case "ModuleConfiguration":
         case "ModuleDependency":
         case "ModuleIgnoreTable":
         case "ModuleInstallExecuteSequence":
         case "ModuleInstallUISequence":
         case "ModuleExclusion":
         case "ModuleSignature":
         case "ModuleSubstitution":
             if (OutputType.Module != output.Type)
             {
                 this.core.OnMessage(WixWarnings.SkippingMergeModuleTable(output.SourceLineNumbers, tableName));
                 return false;
             }
             else
             {
                 return true;
             }
         case "ExternalFiles":
         case "FamilyFileRanges":
         case "ImageFamilies":
         case "PatchMetadata":
         case "PatchSequence":
         case "Properties":
         case "TargetFiles_OptionalData":
         case "TargetImages":
         case "UpgradedFiles_OptionalData":
         case "UpgradedFilesToIgnore":
         case "UpgradedImages":
             if (OutputType.PatchCreation != output.Type)
             {
                 this.core.OnMessage(WixWarnings.SkippingPatchCreationTable(output.SourceLineNumbers, tableName));
                 return false;
             }
             else
             {
                 return true;
             }
         case "MsiPatchHeaders":
         case "MsiPatchMetadata":
         case "MsiPatchOldAssemblyName":
         case "MsiPatchOldAssemblyFile":
         case "MsiPatchSequence":
         case "Patch":
         case "PatchPackage":
             this.core.OnMessage(WixWarnings.PatchTable(output.SourceLineNumbers, tableName));
             return false;
         case "_SummaryInformation":
             return true;
         case "_Validation":
         case "MsiAssemblyName":
         case "MsiFileHash":
             return false;
         default: // all other tables are allowed in any output except for a patch creation package
             if (OutputType.PatchCreation == output.Type)
             {
                 this.core.OnMessage(WixWarnings.IllegalPatchCreationTable(output.SourceLineNumbers, tableName));
                 return false;
             }
             else
             {
                 return true;
             }
     }
 }
Example #14
0
        /// <summary>
        /// Finds the entry section and loads the symbols from an array of intermediates.
        /// </summary>
        /// <param name="allowIdenticalRows">Flag specifying whether identical rows are allowed or not.</param>
        /// <param name="messageHandler">Message handler object to route all errors through.</param>
        /// <param name="expectedOutputType">Expected entry output type, based on output file extension provided to the linker.</param>
        /// <param name="entrySection">Located entry section.</param>
        /// <param name="allSymbols">Collection of symbols loaded.</param>
        internal void FindEntrySectionAndLoadSymbols(
            bool allowIdenticalRows,
            IMessageHandler messageHandler,
            OutputType expectedOutputType,
            out Section entrySection,
            out SymbolCollection allSymbols)
        {
            entrySection = null;
            allSymbols   = new SymbolCollection();

            string      outputExtension = Output.GetExtension(expectedOutputType);
            SectionType expectedEntrySectionType;

            try
            {
                expectedEntrySectionType = (SectionType)Enum.Parse(typeof(SectionType), expectedOutputType.ToString());
            }
            catch (ArgumentException)
            {
                expectedEntrySectionType = SectionType.Unknown;
            }

            foreach (Section section in this.collection.Keys)
            {
                if (SectionType.Product == section.Type || SectionType.Module == section.Type || SectionType.PatchCreation == section.Type || SectionType.Patch == section.Type || SectionType.Bundle == section.Type)
                {
                    if (SectionType.Unknown != expectedEntrySectionType && section.Type != expectedEntrySectionType)
                    {
                        messageHandler.OnMessage(WixWarnings.UnexpectedEntrySection(section.SourceLineNumbers, section.Type.ToString(), expectedEntrySectionType.ToString(), outputExtension));
                    }

                    if (null == entrySection)
                    {
                        entrySection = section;
                    }
                    else
                    {
                        messageHandler.OnMessage(WixErrors.MultipleEntrySections(entrySection.SourceLineNumbers, entrySection.Id, section.Id));
                        messageHandler.OnMessage(WixErrors.MultipleEntrySections2(section.SourceLineNumbers));
                    }
                }

                foreach (Symbol symbol in section.GetSymbols(messageHandler))
                {
                    try
                    {
                        Symbol existingSymbol = allSymbols[symbol.Name];
                        if (null == existingSymbol)
                        {
                            allSymbols.Add(symbol);
                        }
                        else if (allowIdenticalRows && existingSymbol.Row.IsIdentical(symbol.Row))
                        {
                            messageHandler.OnMessage(WixWarnings.IdenticalRowWarning(symbol.Row.SourceLineNumbers, existingSymbol.Name));
                            messageHandler.OnMessage(WixWarnings.IdenticalRowWarning2(existingSymbol.Row.SourceLineNumbers));
                        }
                        else
                        {
                            allSymbols.AddDuplicate(symbol);
                        }
                    }
                    catch (DuplicateSymbolsException)
                    {
                        // if there is already a duplicate symbol, just
                        // another to the list, don't bother trying to
                        // see if there are any identical symbols
                        allSymbols.AddDuplicate(symbol);
                    }
                }
            }
        }
Example #15
0
        /// <summary>
        /// Process the complex references.
        /// </summary>
        /// <param name="output">Active output to add sections to.</param>
        /// <param name="sections">Sections that are referenced during the link process.</param>
        /// <param name="referencedSymbols">Collection of all symbols referenced during linking.</param>
        /// <param name="componentsToComponentGroupsComplexReferences">Component to ComponentGroup complex references.</param>
        /// <param name="componentGroupsToFeatures">ComponentGroups to features complex references.</param>
        /// <param name="componentGroupsToModules">ComponentGroups to modules complex references.</param>
        /// <param name="componentsToFeatures">Component to feature complex references.</param>
        /// <param name="featuresToFeatures">Feature to feature complex references.</param>
        private void ProcessComplexReferences(
			Output output,
			SectionCollection sections,
			StringCollection referencedSymbols,
			ComplexReferenceCollection componentsToComponentGroupsComplexReferences,
			ConnectToFeatureCollection componentGroupsToFeatures,
			ConnectToModuleCollection componentGroupsToModules,
			ConnectToFeatureCollection componentsToFeatures,
			ConnectToFeatureCollection featuresToFeatures)
        {
            Hashtable componentsToModules = new Hashtable();

            foreach (Section section in sections)
            {
                foreach (ComplexReference cref in section.ComplexReferences)
                {
                    ConnectToFeature connection;
                    switch (cref.ParentType)
                    {
                        case ComplexReferenceParentType.ComponentGroup:
                        switch (cref.ChildType)
                        {
                            case ComplexReferenceChildType.Component:
                                componentsToComponentGroupsComplexReferences.Add(cref);
                                break;
                            default:
                                throw new ApplicationException("Unexpected complex reference child type."); // TODO: come up with a real exception to throw (Unexpected complex reference child type)
                        }
                            break;
                        case ComplexReferenceParentType.Feature:
                        switch (cref.ChildType)
                        {
                            case ComplexReferenceChildType.Component:
                                connection = componentsToFeatures[cref.ChildId];
                                if (null == connection)
                                {
                                    componentsToFeatures.Add(new ConnectToFeature(section, cref.ChildId, cref.ParentId, cref.IsPrimary));
                                }
                                else if (cref.IsPrimary && connection.IsExplicitPrimaryFeature)
                                {
                                    this.OnMessage(WixErrors.MultiplePrimaryReferences(SourceLineNumberCollection.FromFileName(section.Intermediate.Path), cref.ChildType.ToString(), cref.ChildId, cref.ParentId, connection.PrimaryFeature));
                                    continue;
                                }
                                else if (cref.IsPrimary)
                                {
                                    connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
                                    connection.PrimaryFeature = cref.ParentId; // set the new primary feature
                                    connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
                                }
                                else
                                {
                                    connection.ConnectFeatures.Add(cref.ParentId);
                                }

                                // add a row to the FeatureComponents table
                                Row row = Common.CreateRowInSection(null, section, this.tableDefinitions["FeatureComponents"]);
                                if (this.sectionIdOnTuples)
                                {
                                    row.SectionId = section.Id;
                                }
                                row[0] = cref.ParentId;
                                row[1] = cref.ChildId;

                                // index the component for finding orphaned records
                                string symbolName = String.Concat("Component:", cref.ChildId);
                                if (!referencedSymbols.Contains(symbolName))
                                {
                                    referencedSymbols.Add(symbolName);
                                }

                                break;
                            case ComplexReferenceChildType.ComponentGroup:
                                connection = componentGroupsToFeatures[cref.ChildId];
                                if (null == connection)
                                {
                                    componentGroupsToFeatures.Add(new ConnectToFeature(section, cref.ChildId, cref.ParentId, cref.IsPrimary));
                                }
                                else if (cref.IsPrimary && connection.IsExplicitPrimaryFeature)
                                {
                                    this.OnMessage(WixErrors.MultiplePrimaryReferences(SourceLineNumberCollection.FromFileName(section.Intermediate.Path), cref.ChildType.ToString(), cref.ChildId, cref.ParentId, connection.PrimaryFeature));
                                    continue;
                                }
                                else if (cref.IsPrimary)
                                {
                                    connection.ConnectFeatures.Add(connection.PrimaryFeature);
                                    connection.PrimaryFeature = cref.ParentId;
                                    connection.IsExplicitPrimaryFeature = true;
                                }
                                else
                                {
                                    connection.ConnectFeatures.Add(cref.ParentId);
                                }
                                break;

                            case ComplexReferenceChildType.Feature:
                                connection = featuresToFeatures[cref.ChildId];
                                if (null != connection)
                                {
                                    this.OnMessage(WixErrors.MultiplePrimaryReferences(SourceLineNumberCollection.FromFileName(section.Intermediate.Path), cref.ChildType.ToString(), cref.ChildId, cref.ParentId, connection.PrimaryFeature));
                                    continue;
                                }

                                featuresToFeatures.Add(new ConnectToFeature(section, cref.ChildId, cref.ParentId, cref.IsPrimary));
                                break;

                            case ComplexReferenceChildType.Module:
                                connection = output.ModulesToFeatures[cref.ChildId];
                                if (null == connection)
                                {
                                    output.ModulesToFeatures.Add(new ConnectToFeature(section, cref.ChildId, cref.ParentId, cref.IsPrimary));
                                }
                                else if (cref.IsPrimary && connection.IsExplicitPrimaryFeature)
                                {
                                    this.OnMessage(WixErrors.MultiplePrimaryReferences(SourceLineNumberCollection.FromFileName(section.Intermediate.Path), cref.ChildType.ToString(), cref.ChildId, cref.ParentId, connection.PrimaryFeature));
                                    continue;
                                }
                                else if (cref.IsPrimary)
                                {
                                    connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
                                    connection.PrimaryFeature = cref.ParentId; // set the new primary feature
                                    connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
                                }
                                else
                                {
                                    connection.ConnectFeatures.Add(cref.ParentId);
                                }
                                break;

                            default:
                                throw new ApplicationException("Unexpected complex reference child type"); // TODO: come up with a real exception to throw (Unexpected complex reference child type)
                        }
                            break;

                        case ComplexReferenceParentType.Module:
                        switch (cref.ChildType)
                        {
                            case ComplexReferenceChildType.Component:
                                if (componentsToModules.ContainsKey(cref.ChildId))
                                {
                                    this.OnMessage(WixErrors.ComponentReferencedTwice(SourceLineNumberCollection.FromFileName(section.Intermediate.Path), cref.ChildId));
                                    continue;
                                }
                                else
                                {
                                    componentsToModules.Add(cref.ChildId, cref); // should always be new

                                    // add a row to the ModuleComponents table
                                    Row row = Common.CreateRowInSection(null, section, this.tableDefinitions["ModuleComponents"]);
                                    if (this.sectionIdOnTuples)
                                    {
                                        row.SectionId = section.Id;
                                    }
                                    row[0] = cref.ChildId;
                                    row[1] = cref.ParentId;
                                    row[2] = cref.ParentLanguage;
                                }

                                // index the component for finding orphaned records
                                string componentSymbolName = String.Concat("Component:", cref.ChildId);
                                if (!referencedSymbols.Contains(componentSymbolName))
                                {
                                    referencedSymbols.Add(componentSymbolName);
                                }

                                break;

                            case ComplexReferenceChildType.ComponentGroup:
                                ConnectToModule moduleConnection = componentGroupsToModules[cref.ChildId];
                                if (null == moduleConnection)
                                {
                                    componentGroupsToModules.Add(new ConnectToModule(cref.ChildId, cref.ParentId, cref.ParentLanguage));
                                }
                                break;

                            default:
                                throw new ApplicationException("Unexpected complex reference child type"); // TODO: come up with a real exception to throw (Unexpected complex reference child type)
                        }
                            break;
                    }
                }
            }
        }
Example #16
0
 public void Load(string patchPath)
 {
     this.patch = Output.Load(patchPath, false, false);
 }
Example #17
0
        /// <summary>
        /// Ensure transform is uninstallable.
        /// </summary>
        /// <param name="productCode">Product code in transform.</param>
        /// <param name="transform">Transform generated by torch.</param>
        /// <param name="tables">Tables to be checked</param>
        /// <returns>True if the transform is uninstallable</returns>
        private bool CheckUninstallableTransform(string productCode, Output transform, ArrayList tables)
        {
            bool ret = true;
            foreach (string table in tables)
            {
                Table wixTable = transform.Tables[table];
                if (null != wixTable)
                {
                    foreach (Row row in wixTable.Rows)
                    {
                        if (row.Operation == RowOperation.Add)
                        {
                            ret = false;
                            string primaryKey = row.GetPrimaryKey('/');
                            if (null == primaryKey)
                            {
                                primaryKey = string.Empty;
                            }
                            this.OnMessage(WixErrors.NewRowAddedInTable(row.SourceLineNumbers, productCode, wixTable.Name, primaryKey));
                        }
                    }
                }
            }

            return ret;
        }
Example #18
0
        /// <summary>
        /// Compare two Outputs
        /// </summary>
        /// <param name="targetOutput">The expected output</param>
        /// <param name="updatedOutput">The actual output</param>
        /// <param name="tables">The list of tables to compare</param>
        /// <returns>Any differences found.</returns>
        private static ArrayList CompareOutput(Output targetOutput, Output updatedOutput, params string[] tables)
        {
            ArrayList differences = new ArrayList();

            Differ differ = new Differ();
            differ.SuppressKeepingSpecialRows = true;
            Output transform = differ.Diff(targetOutput, updatedOutput);

            foreach (Table table in transform.Tables)
            {
                if (null != tables && -1 == Array.IndexOf(tables, table.Name))
                {
                    // Skip this table
                    continue;
                }

                switch (table.Operation)
                {
                    case TableOperation.Add:
                        differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table has been added.", table.Name));
                        break;
                    case TableOperation.Drop:
                        differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table has been dropped.", table.Name));
                        continue;
                }

                // index the target rows for better error messages
                Hashtable targetRows = new Hashtable();
                Table targetTable = targetOutput.Tables[table.Name];
                if (null != targetTable)
                {
                    foreach (Row row in targetTable.Rows)
                    {
                        string primaryKey = row.GetPrimaryKey('/');

                        // only index rows with primary keys since these are the ones that can be modified
                        if (null != primaryKey)
                        {
                            targetRows.Add(primaryKey, row);
                        }
                    }
                }

                foreach (Row row in table.Rows)
                {
                    switch (row.Operation)
                    {
                        case RowOperation.Add:
                            differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table, row '{1}' has been added.", table.Name, row.ToString()));
                            break;
                        case RowOperation.Delete:
                            differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table, row '{1}' has been deleted.", table.Name, row.ToString()));
                            break;
                        case RowOperation.Modify:
                            if (!Verifier.Ignore(row))
                            {
                                string primaryKey = row.GetPrimaryKey('/');
                                Row targetRow = (Row)targetRows[primaryKey];

                                differences.Add(String.Format(CultureInfo.InvariantCulture, "The {0} table, row '{1}' has changed to '{2}'.", table.Name, targetRow.ToString(), row.ToString()));
                            }
                            break;
                        default:
                            throw new InvalidOperationException("Unknown diff row.");
                    }
                }
            }

            return differences;
        }
Example #19
0
 /// <summary>
 /// Verifies that a given table exists in the output
 /// </summary>
 /// <param name="output">Output object to verify.</param>
 /// <param name="tableName">Name of the table to verify.</param>
 /// <param name="wixoutFile">File where output object is stored. Only used to display error message.</param>
 public static void VerifyTableExists(Output output, string tableName, string wixoutFile)
 {
     bool tableExists = CheckTableExists(output, tableName);
     Assert.True(tableExists, String.Format("Table '{0}' does not exist in output '{1}'. It was expected to exist.", tableName, wixoutFile));
 }
Example #20
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;
        }
Example #21
0
        /// <summary>
        /// Creates a transform by diffing two outputs.
        /// </summary>
        /// <param name="targetOutput">The target output.</param>
        /// <param name="updatedOutput">The updated output.</param>
        /// <param name="validationFlags"></param>
        /// <returns>The transform.</returns>
        public Output Diff(Output targetOutput, Output updatedOutput, TransformFlags validationFlags)
        {
            Output transform = new Output(null);
            transform.Type = OutputType.Transform;
            transform.Codepage = updatedOutput.Codepage;
            this.transformSummaryInfo = new SummaryInformationStreams();

            // compare the codepages
            if (targetOutput.Codepage != updatedOutput.Codepage && 0 == (TransformFlags.ErrorChangeCodePage & validationFlags))
            {
                this.OnMessage(WixErrors.OutputCodepageMismatch(targetOutput.SourceLineNumbers, targetOutput.Codepage, updatedOutput.Codepage));
                if (null != updatedOutput.SourceLineNumbers)
                {
                    this.OnMessage(WixErrors.OutputCodepageMismatch2(updatedOutput.SourceLineNumbers));
                }
            }

            // compare the output types
            if (targetOutput.Type != updatedOutput.Type)
            {
                throw new WixException(WixErrors.OutputTypeMismatch(targetOutput.SourceLineNumbers, targetOutput.Type.ToString(), updatedOutput.Type.ToString()));
            }

            // compare the contents of the tables
            foreach (Table targetTable in targetOutput.Tables)
            {
                Table updatedTable = updatedOutput.Tables[targetTable.Name];
                TableOperation operation = TableOperation.None;

                RowCollection rows = this.CompareTables(targetOutput, targetTable, updatedTable, out operation);

                if (TableOperation.Drop == operation)
                {
                    Table droppedTable = transform.Tables.EnsureTable(null, targetTable.Definition);
                    droppedTable.Operation = TableOperation.Drop;
                }
                else if(TableOperation.None == operation)
                {
                    Table modified = transform.Tables.EnsureTable(null, updatedTable.Definition);
                    modified.Rows.AddRange(rows);
                }
            }

            // added tables
            foreach (Table updatedTable in updatedOutput.Tables)
            {
                if (null == targetOutput.Tables[updatedTable.Name])
                {
                    Table addedTable = transform.Tables.EnsureTable(null, updatedTable.Definition);
                    addedTable.Operation = TableOperation.Add;

                    foreach (Row updatedRow in updatedTable.Rows)
                    {
                        updatedRow.Operation = RowOperation.Add;
                        updatedRow.SectionId = sectionDelimiter + updatedRow.SectionId;
                        addedTable.Rows.Add(updatedRow);
                    }
                }
            }

            // set summary information properties
            if (!this.suppressKeepingSpecialRows)
            {
                Table summaryInfoTable = transform.Tables["_SummaryInformation"];
                this.UpdateTransformSummaryInformationTable(summaryInfoTable, validationFlags);
            }

            // inspect the transform
            InspectorCore inspectorCore = new InspectorCore(this.Message);
            foreach (InspectorExtension inspectorExtension in this.inspectorExtensions)
            {
                inspectorExtension.Core = inspectorCore;
                inspectorExtension.InspectTransform(transform);

                // reset
                inspectorExtension.Core = null;
            }

            return transform;
        }
 /// <summary>
 /// Inspect the patch after filtering contained transforms.
 /// </summary>
 /// <param name="transform">The <see cref="Output"/> for the patch.</param>
 /// <remarks>
 /// To inspect filtered transforms, enumerate <see cref="Output.SubStorages"/>.
 /// Transforms where the <see cref="SubStorage.Name"/> begins with "#" are
 /// called patch transforms and instruct Windows Installer how to apply the
 /// authored transforms - those that do not begin with "#". The authored
 /// transforms are the primary transforms you'll typically want to inspect
 /// and contain your changes to target products.
 /// </remarks>
 public virtual void InspectPatch(Output patch)
 {
 }
Example #23
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);
        }
Example #24
0
        /// <summary>
        /// Verifies that a given table exists in the output
        /// </summary>
        /// <param name="output">Output object to verify.</param>
        /// <param name="tableName">Name of the table to check for.</param>
        /// <returns>True if the table exists in the output, false otherwise</returns>
        public static bool CheckTableExists(Output output, string tableName)
        {
            bool tableExists = true;
            try
            {
                int i = output.Tables[tableName].Rows.Count;
            }
            catch (Exception)
            {
                tableExists = false;
            }

            return tableExists;
        }
Example #25
0
 /// <summary>
 /// Verifies that a given table does not exists in the output
 /// </summary>
 /// <param name="output">Output object to verify.</param>
 /// <param name="tableName">Name of the table to verify.</param>
 /// <param name="wixoutFile">File where output object is stored. Only used to display error message.</param>
 public static void VerifyNotTableExists(Output output, string tableName, string wixoutFile)
 {
     bool tableExists = CheckTableExists(output, tableName);
     Assert.False(tableExists, String.Format("Table '{0}' exists in output '{1}'. It was NOT expected to exist.", tableName, wixoutFile));
 }
Example #26
0
 /// <summary>
 /// Creates a transform by diffing two outputs.
 /// </summary>
 /// <param name="targetOutput">The target output.</param>
 /// <param name="updatedOutput">The updated output.</param>
 /// <returns>The transform.</returns>
 public Output Diff(Output targetOutput, Output updatedOutput)
 {
     return Diff(targetOutput, updatedOutput, 0);
 }
Example #27
0
 /// <summary>
 /// Compare two Outputs
 /// </summary>
 /// <param name="targetOutput">The expected output</param>
 /// <param name="updatedOutput">The actual output</param>
 /// <returns>Any differences found.</returns>
 private static ArrayList CompareOutput(Output targetOutput, Output updatedOutput)
 {
     return Verifier.CompareOutput(targetOutput, updatedOutput, null);
 }
Example #28
0
        /// <summary>
        /// Resolve the feature backlinks to the final feature that a component will live in.
        /// </summary>
        /// <param name="output">Active output to add sections to.</param>
        /// <param name="componentsToFeatures">Component to feature complex references.</param>
        /// <param name="allSymbols">All symbols loaded from the intermediates.</param>
        /// <param name="referencedSymbols">Collection of all symbols referenced during linking.</param>
        /// <param name="unresolvedReferences">Unresolved references.</param>
        private void ResolveFeatureBacklinks(
			Output output,
			ConnectToFeatureCollection componentsToFeatures,
			SymbolCollection allSymbols,
			StringCollection referencedSymbols,
			ArrayList unresolvedReferences)
        {
            Hashtable uniqueComponentIds = new Hashtable();

            foreach (Section section in output.Sections)
            {
                foreach (FeatureBacklink blink in section.FeatureBacklinks)
                {
                    Reference reference = blink.Reference;
                    Symbol symbol = Common.GetSymbolForReference(section, reference, allSymbols, referencedSymbols, unresolvedReferences, this);
                    if (null == symbol)
                    {
                        continue;
                    }

                    Row row = symbol.Row;
                    string parentFeature;
                    if (OutputType.Module == output.Type)
                    {
                        parentFeature = Guid.Empty.ToString("B");
                    }
                    else
                    {
                        ConnectToFeature connection = componentsToFeatures[blink.Component];
                        if (null == connection)
                        {
                            throw new WixMissingFeatureException(SourceLineNumberCollection.FromFileName(section.Intermediate.Path), blink);
                        }

                        parentFeature = connection.PrimaryFeature;

                        // check for unique, implicit, primary feature parents with multiple possible parent features
                        if (PedanticLevel.Legendary == this.pedanticLevel &&
                            !connection.IsExplicitPrimaryFeature &&
                            0 < connection.ConnectFeatures.Count &&
                            !uniqueComponentIds.Contains(blink.Component))
                        {
                            this.OnMessage(WixWarnings.ImplicitPrimaryFeature(blink.Component));

                            // remember this component so only one warning is generated for it
                            uniqueComponentIds[blink.Component] = null;
                        }
                    }

                    switch (blink.Type)
                    {
                        case FeatureBacklinkType.Class:
                            row[11] = parentFeature;
                            break;
                        case FeatureBacklinkType.Extension:
                            row[4] = parentFeature;
                            break;
                        case FeatureBacklinkType.PublishComponent:
                            row[4] = parentFeature;
                            break;
                        case FeatureBacklinkType.Shortcut:
                            row[4] = parentFeature;
                            break;
                        case FeatureBacklinkType.TypeLib:
                            row[6] = parentFeature;
                            break;
                        default:
                            throw new ApplicationException("Internal Error: Unknown FeatureBackLinkType.");
                    }
                }
            }
        }
Example #29
0
 /// <summary>
 /// Called after database variable resolution occurs.
 /// </summary>
 public virtual void DatabaseAfterResolvedFields(Output output)
 {
 }
Example #30
0
        /// <summary>
        /// Creates a transform by diffing two outputs.
        /// </summary>
        /// <param name="targetOutput">The target output.</param>
        /// <param name="updatedOutput">The updated output.</param>
        /// <param name="validationFlags"></param>
        /// <returns>The transform.</returns>
        public Output Diff(Output targetOutput, Output updatedOutput, TransformFlags validationFlags)
        {
            Output transform = new Output(null);

            transform.Type            = OutputType.Transform;
            transform.Codepage        = updatedOutput.Codepage;
            this.transformSummaryInfo = new SummaryInformationStreams();

            // compare the codepages
            if (targetOutput.Codepage != updatedOutput.Codepage && 0 == (TransformFlags.ErrorChangeCodePage & validationFlags))
            {
                this.OnMessage(WixErrors.OutputCodepageMismatch(targetOutput.SourceLineNumbers, targetOutput.Codepage, updatedOutput.Codepage));
                if (null != updatedOutput.SourceLineNumbers)
                {
                    this.OnMessage(WixErrors.OutputCodepageMismatch2(updatedOutput.SourceLineNumbers));
                }
            }

            // compare the output types
            if (targetOutput.Type != updatedOutput.Type)
            {
                throw new WixException(WixErrors.OutputTypeMismatch(targetOutput.SourceLineNumbers, targetOutput.Type.ToString(), updatedOutput.Type.ToString()));
            }

            // compare the contents of the tables
            foreach (Table targetTable in targetOutput.Tables)
            {
                Table          updatedTable = updatedOutput.Tables[targetTable.Name];
                TableOperation operation    = TableOperation.None;

                RowCollection rows = this.CompareTables(targetOutput, targetTable, updatedTable, out operation);

                if (TableOperation.Drop == operation)
                {
                    Table droppedTable = transform.Tables.EnsureTable(null, targetTable.Definition);
                    droppedTable.Operation = TableOperation.Drop;
                }
                else if (TableOperation.None == operation)
                {
                    Table modified = transform.Tables.EnsureTable(null, updatedTable.Definition);
                    modified.Rows.AddRange(rows);
                }
            }

            // added tables
            foreach (Table updatedTable in updatedOutput.Tables)
            {
                if (null == targetOutput.Tables[updatedTable.Name])
                {
                    Table addedTable = transform.Tables.EnsureTable(null, updatedTable.Definition);
                    addedTable.Operation = TableOperation.Add;

                    foreach (Row updatedRow in updatedTable.Rows)
                    {
                        updatedRow.Operation = RowOperation.Add;
                        updatedRow.SectionId = sectionDelimiter + updatedRow.SectionId;
                        addedTable.Rows.Add(updatedRow);
                    }
                }
            }

            // set summary information properties
            if (!this.suppressKeepingSpecialRows)
            {
                Table summaryInfoTable = transform.Tables["_SummaryInformation"];
                this.UpdateTransformSummaryInformationTable(summaryInfoTable, validationFlags);
            }

            // inspect the transform
            InspectorCore inspectorCore = new InspectorCore(this.Message);

            foreach (InspectorExtension inspectorExtension in this.inspectorExtensions)
            {
                inspectorExtension.Core = inspectorCore;
                inspectorExtension.InspectTransform(transform);

                // reset
                inspectorExtension.Core = null;
            }

            return(transform);
        }
Example #31
0
        /// <summary>
        /// Reduce the transform according to the patch references.
        /// </summary>
        /// <param name="transform">transform generated by torch.</param>
        /// <param name="patchRefTable">Table contains patch family filter.</param>
        /// <returns>true if the transform is not empty</returns>
        public static bool ReduceTransform(Output transform, Table patchRefTable)
        {
            // identify sections to keep
            Hashtable oldSections = new Hashtable(patchRefTable.Rows.Count);
            Hashtable newSections = new Hashtable(patchRefTable.Rows.Count);
            Hashtable tableKeyRows = new Hashtable();
            ArrayList sequenceList = new ArrayList();
            Hashtable componentFeatureAddsIndex = new Hashtable();
            Hashtable customActionTable = new Hashtable();
            Hashtable directoryTableAdds = new Hashtable();
            Hashtable featureTableAdds = new Hashtable();
            ArrayList keptComponentTableAdds = new ArrayList();
            Hashtable keptDirectories = new Hashtable();
            Hashtable keptFeatures = new Hashtable();

            foreach (Row patchRefRow in patchRefTable.Rows)
            {
                string tableName = (string)patchRefRow[0];
                string key = (string)patchRefRow[1];

                Table table = transform.Tables[tableName];
                if (table == null)
                {
                    // table not found
                    continue;
                }

                // index this table
                if (!tableKeyRows.Contains(tableName))
                {
                    Hashtable newKeyRows = new Hashtable();
                    foreach (Row newRow in table.Rows)
                    {
                        newKeyRows[newRow.GetPrimaryKey('/')] = newRow;
                    }
                    tableKeyRows[tableName] = newKeyRows;
                }
                Hashtable keyRows = (Hashtable)tableKeyRows[tableName];

                Row row = (Row)keyRows[key];
                if (row == null)
                {
                    // row not found
                    continue;
                }

                // Differ.sectionDelimiter
                string[] sections = row.SectionId.Split('/');
                oldSections[sections[0]] = row;
                newSections[sections[1]] = row;
            }

            // throw away sections not referenced
            int keptRows = 0;
            Table directoryTable = null;
            Table featureTable = null;
            foreach (Table table in transform.Tables)
            {
                if ("_SummaryInformation" == table.Name)
                {
                    continue;
                }

                if (table.Name == "AdminExecuteSequence"
                    || table.Name == "AdminUISequence"
                    || table.Name == "AdvtExecuteSequence"
                    || table.Name == "InstallUISequence"
                    || table.Name == "InstallExecuteSequence")
                {
                    sequenceList.Add(table);
                    continue;
                }

                for (int i = 0; i < table.Rows.Count; i++)
                {
                    Row row = table.Rows[i];

                    if (table.Name == "CustomAction")
                    {
                        customActionTable.Add(row[0], row);
                    }

                    if (table.Name == "Directory")
                    {
                        directoryTable = table;
                        if (RowOperation.Add == row.Operation)
                        {
                            directoryTableAdds.Add(row[0], row);
                        }
                    }

                    if (table.Name == "Feature")
                    {
                        featureTable = table;
                        if (RowOperation.Add == row.Operation)
                        {
                            featureTableAdds.Add(row[0], row);
                        }
                    }

                    if (table.Name == "FeatureComponents")
                    {
                        if (RowOperation.Add == row.Operation)
                        {
                            string featureId = (string)row[0];
                            string componentId = (string)row[1];

                            if (componentFeatureAddsIndex.ContainsKey(componentId))
                            {
                                ArrayList featureList = (ArrayList)componentFeatureAddsIndex[componentId];
                                featureList.Add(featureId);
                            }
                            else
                            {
                                ArrayList featureList = new ArrayList();
                                componentFeatureAddsIndex.Add(componentId, featureList);
                                featureList.Add(featureId);
                            }
                        }
                    }

                    if (null == row.SectionId)
                    {
                        table.Rows.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        string[] sections = row.SectionId.Split('/');
                        // ignore the row without section id.
                        if (0 == sections[0].Length && 0 == sections[1].Length)
                        {
                            table.Rows.RemoveAt(i);
                            i--;
                        }
                        else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
                        {
                            if ("Component" == table.Name)
                            {
                                if (RowOperation.Add == row.Operation)
                                {
                                    keptComponentTableAdds.Add(row);
                                }
                            }

                            if ("Directory" == table.Name)
                            {
                                keptDirectories.Add(row[0], row);
                            }

                            if ("Feature" == table.Name)
                            {
                                keptFeatures.Add(row[0], row);
                            }

                            keptRows++;
                        }
                        else
                        {
                            table.Rows.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }

            keptRows += ReduceTransformSequenceTable(sequenceList, oldSections, newSections, customActionTable);

            if (null != directoryTable)
            {
                foreach (Row componentRow in keptComponentTableAdds)
                {
                    // make sure each added component has its required directory and feature heirarchy.
                    string directoryId = (string)componentRow[2];
                    while (null != directoryId && directoryTableAdds.ContainsKey(directoryId))
                    {
                        Row directoryRow = (Row)directoryTableAdds[directoryId];

                        if (!keptDirectories.ContainsKey(directoryId))
                        {
                            directoryTable.Rows.Add(directoryRow);
                            keptDirectories.Add(directoryRow[0], null);
                            keptRows++;
                        }

                        directoryId = (string)directoryRow[1];
                    }

                    string componentId = (string)componentRow[0];

                    if (componentFeatureAddsIndex.ContainsKey(componentId))
                    {
                        foreach (string featureId in (ArrayList)componentFeatureAddsIndex[componentId])
                        {
                            string currentFeatureId = featureId;
                            while (null != currentFeatureId && featureTableAdds.ContainsKey(currentFeatureId))
                            {
                                Row featureRow = (Row)featureTableAdds[currentFeatureId];

                                if (!keptFeatures.ContainsKey(currentFeatureId))
                                {
                                    featureTable.Rows.Add(featureRow);
                                    keptFeatures.Add(featureRow[0], null);
                                    keptRows++;
                                }

                                currentFeatureId = (string)featureRow[1];
                            }
                        }
                    }
                }
            }

            keptRows += ReduceTransformSequenceTable(sequenceList, oldSections, newSections, customActionTable);

            // Delete tables that are empty.
            ArrayList tablesToDelete = new ArrayList();
            foreach (Table table in transform.Tables)
            {
                if (0 == table.Rows.Count)
                {
                    tablesToDelete.Add(table.Name);
                }
            }

            // delete separately to avoid messing up enumeration
            foreach (string tableName in tablesToDelete)
            {
                transform.Tables.Remove(tableName);
            }

            return keptRows > 0;
        }
Example #32
0
        public Wix.Wix Decompile(Output output)
        {
            if (null == output)
            {
                throw new ArgumentNullException("output");
            }

            this.codepage = output.Codepage;
            this.outputType = output.Type;

            // collect the table definitions from the output
            this.tableDefinitions.Clear();
            foreach (Table table in output.Tables)
            {
                this.tableDefinitions.Add(table.Definition);
            }

            // add any missing standard and wix-specific table definitions
            foreach (TableDefinition tableDefinition in Installer.GetTableDefinitions())
            {
                if (!this.tableDefinitions.Contains(tableDefinition.Name))
                {
                    this.tableDefinitions.Add(tableDefinition);
                }
            }

            // add any missing extension table definitions
            foreach (WixExtension extension in this.extensions)
            {
                if (null != extension.TableDefinitions)
                {
                    foreach (TableDefinition tableDefinition in extension.TableDefinitions)
                    {
                        if (!this.tableDefinitions.Contains(tableDefinition.Name))
                        {
                            this.tableDefinitions.Add(tableDefinition);
                        }
                    }
                }
            }

            // if we don't have the temporary files object yet, get one
            if (null == this.tempFiles)
            {
                this.TempFilesLocation = null;
            }
            Directory.CreateDirectory(this.tempFiles.BasePath); // ensure the base path is there

            bool encounteredError = false;
            Wix.IParentElement rootElement;
            Wix.Wix wixElement = new Wix.Wix();

            switch (this.outputType)
            {
                case OutputType.Module:
                    rootElement = new Wix.Module();
                    break;
                case OutputType.PatchCreation:
                    rootElement = new Wix.PatchCreation();
                    break;
                case OutputType.Product:
                    rootElement = new Wix.Product();
                    break;
                default:
                    throw new InvalidOperationException(WixStrings.EXP_UnknownOutputType);
            }
            wixElement.AddChild((Wix.ISchemaElement)rootElement);

            // try to decompile the database file
            try
            {
                this.core = new DecompilerCore(rootElement, this.Message);
                this.core.ShowPedanticMessages = this.showPedanticMessages;

                // stop processing if an error previously occurred
                if (this.core.EncounteredError)
                {
                    return null;
                }

                // initialize the decompiler and its extensions
                foreach (WixExtension extension in this.extensions)
                {
                    if (null != extension.DecompilerExtension)
                    {
                        extension.DecompilerExtension.Core = this.core;
                        extension.DecompilerExtension.InitializeDecompile(output.Tables);
                    }
                }
                this.InitializeDecompile(output.Tables);

                // stop processing if an error previously occurred
                if (this.core.EncounteredError)
                {
                    return null;
                }

                // decompile the tables
                this.DecompileTables(output);

                // finalize the decompiler and its extensions
                this.FinalizeDecompile(output.Tables);
                foreach (WixExtension extension in this.extensions)
                {
                    if (null != extension.DecompilerExtension)
                    {
                        extension.DecompilerExtension.FinalizeDecompile(output.Tables);
                    }
                }
            }
            finally
            {
                encounteredError = this.core.EncounteredError;

                this.core = null;
                foreach (WixExtension extension in this.extensions)
                {
                    if (null != extension.DecompilerExtension)
                    {
                        extension.DecompilerExtension.Core = null;
                    }
                }
            }

            // return the root element only if decompilation completed successfully
            return (encounteredError ? null : wixElement);
        }
Example #33
0
        public Output BuildPairedTransform(string patchId, string clientPatchId, Output mainTransform, MediaRow mediaRow, int validationFlags, out string productCode)
        {
            productCode = null;
            Output pairedTransform = new Output(null);
            pairedTransform.Type = OutputType.Transform;
            pairedTransform.Codepage = mainTransform.Codepage;

            // lookup productVersion property to correct summaryInformation
            string newProductVersion = null;
            Table mainPropertyTable = mainTransform.Tables["Property"];
            if (null != mainPropertyTable)
            {
                foreach (Row row in mainPropertyTable.Rows)
                {
                    if ("ProductVersion" == (string)row[0])
                    {
                        newProductVersion = (string)row[1];
                    }
                }
            }

            // TODO: build class for manipulating SummaryInformation table
            Table mainSummaryTable = mainTransform.Tables["_SummaryInformation"];
            // add required properties
            Hashtable mainSummaryRows = new Hashtable();
            foreach (Row mainSummaryRow in mainSummaryTable.Rows)
            {
                mainSummaryRows[mainSummaryRow[0]] = mainSummaryRow;
            }
            if (!mainSummaryRows.Contains((int)SummaryInformation.Transform.ValidationFlags))
            {
                Row mainSummaryRow = mainSummaryTable.CreateRow(null);
                mainSummaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags;
                mainSummaryRow[1] = validationFlags.ToString(CultureInfo.InvariantCulture);
            }

            // copy summary information from core transform
            Table pairedSummaryTable = pairedTransform.EnsureTable(this.tableDefinitions["_SummaryInformation"]);
            foreach (Row mainSummaryRow in mainSummaryTable.Rows)
            {
                string value = (string)mainSummaryRow[1];
                switch ((SummaryInformation.Transform)mainSummaryRow[0])
                {
                    case SummaryInformation.Transform.ProductCodes:
                        string[] propertyData = value.Split(';');
                        string oldProductVersion = propertyData[0].Substring(38);
                        string upgradeCode = propertyData[2];
                        productCode = propertyData[0].Substring(0, 38);
                        if (newProductVersion == null)
                        {
                            newProductVersion = oldProductVersion;
                        }

                        // force mainTranform to old;new;upgrade and pairedTransform to new;new;upgrade
                        mainSummaryRow[1] = String.Concat(productCode, oldProductVersion, ';', productCode, newProductVersion, ';', upgradeCode);
                        value = String.Concat(productCode, newProductVersion, ';', productCode, newProductVersion, ';', upgradeCode);
                        break;
                    case SummaryInformation.Transform.ValidationFlags:
                        // use validation flags authored into the patch XML
                        mainSummaryRow[1] = value = validationFlags.ToString(CultureInfo.InvariantCulture);
                        break;
                }
                Row pairedSummaryRow = pairedSummaryTable.CreateRow(null);
                pairedSummaryRow[0] = mainSummaryRow[0];
                pairedSummaryRow[1] = value;
            }

            if (productCode == null)
            {
                throw new InvalidOperationException(WixStrings.EXP_CouldnotDetermineProductCodeFromTransformSummaryInfo);
            }

            // copy File table
            Table mainFileTable = mainTransform.Tables["File"];
            if (null != mainFileTable && 0 < mainFileTable.Rows.Count)
            {
                // We require file source information.
                Table mainWixFileTable = mainTransform.Tables["WixFile"];
                if (null == mainWixFileTable)
                {
                    throw new WixException(WixErrors.AdminImageRequired(productCode));
                }

                FileRowCollection mainFileRows = new FileRowCollection();
                mainFileRows.AddRange(mainFileTable.Rows);

                Table pairedFileTable = pairedTransform.EnsureTable(mainFileTable.Definition);
                foreach (WixFileRow mainWixFileRow in mainWixFileTable.Rows)
                {
                    FileRow mainFileRow = mainFileRows[mainWixFileRow.File];

                    // set File.Sequence to non null to satisfy transform bind
                    mainFileRow.Sequence = 1;

                    // delete's don't need rows in the paired transform
                    if (mainFileRow.Operation == RowOperation.Delete)
                    {
                        continue;
                    }

                    FileRow pairedFileRow = (FileRow)pairedFileTable.CreateRow(null);
                    pairedFileRow.Operation = RowOperation.Modify;
                    for (int i = 0; i < mainFileRow.Fields.Length; i++)
                    {
                        pairedFileRow[i] = mainFileRow[i];
                    }

                    // override authored media for patch bind
                    // TODO: consider using File/@DiskId for patch media
                    mainFileRow.DiskId = mediaRow.DiskId;
                    mainWixFileRow.DiskId = mediaRow.DiskId;
                    // suppress any change to File.Sequence to avoid bloat
                    mainFileRow.Fields[7].Modified = false;

                    // force File row to appear in the transform
                    switch (mainFileRow.Operation)
                    {
                        case RowOperation.Modify:
                        case RowOperation.Add:
                            // set msidbFileAttributesPatchAdded
                            pairedFileRow.Attributes |= MsiInterop.MsidbFileAttributesPatchAdded;
                            pairedFileRow.Fields[6].Modified = true;
                            pairedFileRow.Operation = mainFileRow.Operation;
                            break;
                        default:
                            pairedFileRow.Fields[6].Modified = false;
                            break;
                    }
                }
            }

            // add Media row to pairedTransform
            Table pairedMediaTable = pairedTransform.EnsureTable(this.tableDefinitions["Media"]);
            Row pairedMediaRow = pairedMediaTable.CreateRow(null);
            pairedMediaRow.Operation = RowOperation.Add;
            for (int i = 0; i < mediaRow.Fields.Length; i++)
            {
                pairedMediaRow[i] = mediaRow[i];
            }

            // add PatchPackage for this Media
            Table pairedPackageTable = pairedTransform.EnsureTable(this.tableDefinitions["PatchPackage"]);
            pairedPackageTable.Operation = TableOperation.Add;
            Row pairedPackageRow = pairedPackageTable.CreateRow(null);
            pairedPackageRow.Operation = RowOperation.Add;
            pairedPackageRow[0] = patchId;
            pairedPackageRow[1] = mediaRow.DiskId;

            // add property to both identify client patches and whether those patches are removable or not
            int allowRemoval = 0;
            Table msiPatchMetadataTable = this.patch.Tables["MsiPatchMetadata"];
            if (null != msiPatchMetadataTable)
            {
                foreach (Row msiPatchMetadataRow in msiPatchMetadataTable.Rows)
                {
                    // get the value of the standard AllowRemoval property, if present
                    string company = (string)msiPatchMetadataRow[0];
                    if ((null == company || 0 == company.Length) && "AllowRemoval" == (string)msiPatchMetadataRow[1])
                    {
                        allowRemoval = Int32.Parse((string)msiPatchMetadataRow[2], CultureInfo.InvariantCulture);
                    }
                }
            }

            // add the property to the patch transform's Property table
            Table pairedPropertyTable = pairedTransform.EnsureTable(this.tableDefinitions["Property"]);
            pairedPropertyTable.Operation = TableOperation.Add;
            Row pairedPropertyRow = pairedPropertyTable.CreateRow(null);
            pairedPropertyRow.Operation = RowOperation.Add;
            pairedPropertyRow[0] = string.Concat(clientPatchId, ".AllowRemoval");
            pairedPropertyRow[1] = allowRemoval.ToString(CultureInfo.InvariantCulture);

            // add this patch code GUID to the patch transform to identify
            // which patches are installed, including in multi-patch
            // installations.
            pairedPropertyRow = pairedPropertyTable.CreateRow(null);
            pairedPropertyRow.Operation = RowOperation.Add;
            pairedPropertyRow[0] = string.Concat(clientPatchId, ".PatchCode");
            pairedPropertyRow[1] = patchId;

            // add PATCHNEWPACKAGECODE to apply to admin layouts
            pairedPropertyRow = pairedPropertyTable.CreateRow(null);
            pairedPropertyRow.Operation = RowOperation.Add;
            pairedPropertyRow[0] = "PATCHNEWPACKAGECODE";
            pairedPropertyRow[1] = patchId;

            // add PATCHNEWSUMMARYCOMMENTS and PATCHNEWSUMMARYSUBJECT to apply to admin layouts
            Table _summaryInformationTable = this.patch.Tables["_SummaryInformation"];
            if (null != _summaryInformationTable)
            {
                foreach (Row row in _summaryInformationTable.Rows)
                {
                    if (3 == (int)row[0]) // PID_SUBJECT
                    {
                        pairedPropertyRow = pairedPropertyTable.CreateRow(null);
                        pairedPropertyRow.Operation = RowOperation.Add;
                        pairedPropertyRow[0] = "PATCHNEWSUMMARYSUBJECT";
                        pairedPropertyRow[1] = row[1];
                    }
                    else if (6 == (int)row[0]) // PID_COMMENTS
                    {
                        pairedPropertyRow = pairedPropertyTable.CreateRow(null);
                        pairedPropertyRow.Operation = RowOperation.Add;
                        pairedPropertyRow[0] = "PATCHNEWSUMMARYCOMMENTS";
                        pairedPropertyRow[1] = row[1];
                    }
                }
            }

            return pairedTransform;
        }
Example #34
0
        /// <summary>
        /// Decompile the tables.
        /// </summary>
        /// <param name="output">The output being decompiled.</param>
        private void DecompileTables(Output output)
        {
            StringCollection sortedTableNames = this.GetSortedTableNames();

            foreach (string tableName in sortedTableNames)
            {
                Table table = output.Tables[tableName];

                // table does not exist in this database or should not be decompiled
                if (null == table || !this.DecompilableTable(output, tableName))
                {
                    continue;
                }

                this.core.OnMessage(WixVerboses.DecompilingTable(table.Name));

                // empty tables may be kept with EnsureTable if the user set the proper option
                if (0 == table.Rows.Count && this.suppressDroppingEmptyTables)
                {
                    Wix.EnsureTable ensureTable = new Wix.EnsureTable();
                    ensureTable.Id = table.Name;
                    this.core.RootElement.AddChild(ensureTable);
                }

                switch (table.Name)
                {
                    case "_SummaryInformation":
                        this.Decompile_SummaryInformationTable(table);
                        break;
                    case "AdminExecuteSequence":
                    case "AdminUISequence":
                    case "AdvtExecuteSequence":
                    case "InstallExecuteSequence":
                    case "InstallUISequence":
                    case "ModuleAdminExecuteSequence":
                    case "ModuleAdminUISequence":
                    case "ModuleAdvtExecuteSequence":
                    case "ModuleInstallExecuteSequence":
                    case "ModuleInstallUISequence":
                        // handled in FinalizeSequenceTables
                        break;
                    case "ActionText":
                        this.DecompileActionTextTable(table);
                        break;
                    case "AdvtUISequence":
                        this.core.OnMessage(WixWarnings.DeprecatedTable(table.Name));
                        break;
                    case "AppId":
                        this.DecompileAppIdTable(table);
                        break;
                    case "AppSearch":
                        // handled in FinalizeSearchTables
                        break;
                    case "BBControl":
                        this.DecompileBBControlTable(table);
                        break;
                    case "Billboard":
                        this.DecompileBillboardTable(table);
                        break;
                    case "Binary":
                        this.DecompileBinaryTable(table);
                        break;
                    case "BindImage":
                        this.DecompileBindImageTable(table);
                        break;
                    case "CCPSearch":
                        // handled in FinalizeSearchTables
                        break;
                    case "CheckBox":
                        // handled in FinalizeCheckBoxTable
                        break;
                    case "Class":
                        this.DecompileClassTable(table);
                        break;
                    case "ComboBox":
                        this.DecompileComboBoxTable(table);
                        break;
                    case "Control":
                        this.DecompileControlTable(table);
                        break;
                    case "ControlCondition":
                        this.DecompileControlConditionTable(table);
                        break;
                    case "ControlEvent":
                        this.DecompileControlEventTable(table);
                        break;
                    case "CreateFolder":
                        this.DecompileCreateFolderTable(table);
                        break;
                    case "CustomAction":
                        this.DecompileCustomActionTable(table);
                        break;
                    case "CompLocator":
                        this.DecompileCompLocatorTable(table);
                        break;
                    case "Complus":
                        this.DecompileComplusTable(table);
                        break;
                    case "Component":
                        this.DecompileComponentTable(table);
                        break;
                    case "Condition":
                        this.DecompileConditionTable(table);
                        break;
                    case "Dialog":
                        this.DecompileDialogTable(table);
                        break;
                    case "Directory":
                        this.DecompileDirectoryTable(table);
                        break;
                    case "DrLocator":
                        this.DecompileDrLocatorTable(table);
                        break;
                    case "DuplicateFile":
                        this.DecompileDuplicateFileTable(table);
                        break;
                    case "Environment":
                        this.DecompileEnvironmentTable(table);
                        break;
                    case "Error":
                        this.DecompileErrorTable(table);
                        break;
                    case "EventMapping":
                        this.DecompileEventMappingTable(table);
                        break;
                    case "Extension":
                        this.DecompileExtensionTable(table);
                        break;
                    case "ExternalFiles":
                        this.DecompileExternalFilesTable(table);
                        break;
                    case "FamilyFileRanges":
                        // handled in FinalizeFamilyFileRangesTable
                        break;
                    case "Feature":
                        this.DecompileFeatureTable(table);
                        break;
                    case "FeatureComponents":
                        this.DecompileFeatureComponentsTable(table);
                        break;
                    case "File":
                        this.DecompileFileTable(table);
                        break;
                    case "FileSFPCatalog":
                        this.DecompileFileSFPCatalogTable(table);
                        break;
                    case "Font":
                        this.DecompileFontTable(table);
                        break;
                    case "Icon":
                        this.DecompileIconTable(table);
                        break;
                    case "ImageFamilies":
                        this.DecompileImageFamiliesTable(table);
                        break;
                    case "IniFile":
                        this.DecompileIniFileTable(table);
                        break;
                    case "IniLocator":
                        this.DecompileIniLocatorTable(table);
                        break;
                    case "IsolatedComponent":
                        this.DecompileIsolatedComponentTable(table);
                        break;
                    case "LaunchCondition":
                        this.DecompileLaunchConditionTable(table);
                        break;
                    case "ListBox":
                        this.DecompileListBoxTable(table);
                        break;
                    case "ListView":
                        this.DecompileListViewTable(table);
                        break;
                    case "LockPermissions":
                        this.DecompileLockPermissionsTable(table);
                        break;
                    case "Media":
                        this.DecompileMediaTable(table);
                        break;
                    case "MIME":
                        this.DecompileMIMETable(table);
                        break;
                    case "ModuleAdvtUISequence":
                        this.core.OnMessage(WixWarnings.DeprecatedTable(table.Name));
                        break;
                    case "ModuleComponents":
                        // handled by DecompileComponentTable (since the ModuleComponents table
                        // rows are created by nesting components under the Module element)
                        break;
                    case "ModuleConfiguration":
                        this.DecompileModuleConfigurationTable(table);
                        break;
                    case "ModuleDependency":
                        this.DecompileModuleDependencyTable(table);
                        break;
                    case "ModuleExclusion":
                        this.DecompileModuleExclusionTable(table);
                        break;
                    case "ModuleIgnoreTable":
                        this.DecompileModuleIgnoreTableTable(table);
                        break;
                    case "ModuleSignature":
                        this.DecompileModuleSignatureTable(table);
                        break;
                    case "ModuleSubstitution":
                        this.DecompileModuleSubstitutionTable(table);
                        break;
                    case "MoveFile":
                        this.DecompileMoveFileTable(table);
                        break;
                    case "MsiAssembly":
                        // handled in FinalizeFileTable
                        break;
                    case "MsiDigitalCertificate":
                        this.DecompileMsiDigitalCertificateTable(table);
                        break;
                    case "MsiDigitalSignature":
                        this.DecompileMsiDigitalSignatureTable(table);
                        break;
                    case "MsiEmbeddedChainer":
                        this.DecompileMsiEmbeddedChainerTable(table);
                        break;
                    case "MsiEmbeddedUI":
                        this.DecompileMsiEmbeddedUITable(table);
                        break;
                    case "MsiLockPermissionsEx":
                        this.DecompileMsiLockPermissionsExTable(table);
                        break;
                    case "MsiPackageCertificate":
                        this.DecompileMsiPackageCertificateTable(table);
                        break;
                    case "MsiPatchCertificate":
                        this.DecompileMsiPatchCertificateTable(table);
                        break;
                    case "MsiShortcutProperty":
                        this.DecompileMsiShortcutPropertyTable(table);
                        break;
                    case "ODBCAttribute":
                        this.DecompileODBCAttributeTable(table);
                        break;
                    case "ODBCDataSource":
                        this.DecompileODBCDataSourceTable(table);
                        break;
                    case "ODBCDriver":
                        this.DecompileODBCDriverTable(table);
                        break;
                    case "ODBCSourceAttribute":
                        this.DecompileODBCSourceAttributeTable(table);
                        break;
                    case "ODBCTranslator":
                        this.DecompileODBCTranslatorTable(table);
                        break;
                    case "PatchMetadata":
                        this.DecompilePatchMetadataTable(table);
                        break;
                    case "PatchSequence":
                        this.DecompilePatchSequenceTable(table);
                        break;
                    case "ProgId":
                        this.DecompileProgIdTable(table);
                        break;
                    case "Properties":
                        this.DecompilePropertiesTable(table);
                        break;
                    case "Property":
                        this.DecompilePropertyTable(table);
                        break;
                    case "PublishComponent":
                        this.DecompilePublishComponentTable(table);
                        break;
                    case "RadioButton":
                        this.DecompileRadioButtonTable(table);
                        break;
                    case "Registry":
                        this.DecompileRegistryTable(table);
                        break;
                    case "RegLocator":
                        this.DecompileRegLocatorTable(table);
                        break;
                    case "RemoveFile":
                        this.DecompileRemoveFileTable(table);
                        break;
                    case "RemoveIniFile":
                        this.DecompileRemoveIniFileTable(table);
                        break;
                    case "RemoveRegistry":
                        this.DecompileRemoveRegistryTable(table);
                        break;
                    case "ReserveCost":
                        this.DecompileReserveCostTable(table);
                        break;
                    case "SelfReg":
                        this.DecompileSelfRegTable(table);
                        break;
                    case "ServiceControl":
                        this.DecompileServiceControlTable(table);
                        break;
                    case "ServiceInstall":
                        this.DecompileServiceInstallTable(table);
                        break;
                    case "SFPCatalog":
                        this.DecompileSFPCatalogTable(table);
                        break;
                    case "Shortcut":
                        this.DecompileShortcutTable(table);
                        break;
                    case "Signature":
                        this.DecompileSignatureTable(table);
                        break;
                    case "TargetFiles_OptionalData":
                        this.DecompileTargetFiles_OptionalDataTable(table);
                        break;
                    case "TargetImages":
                        this.DecompileTargetImagesTable(table);
                        break;
                    case "TextStyle":
                        this.DecompileTextStyleTable(table);
                        break;
                    case "TypeLib":
                        this.DecompileTypeLibTable(table);
                        break;
                    case "Upgrade":
                        this.DecompileUpgradeTable(table);
                        break;
                    case "UpgradedFiles_OptionalData":
                        this.DecompileUpgradedFiles_OptionalDataTable(table);
                        break;
                    case "UpgradedFilesToIgnore":
                        this.DecompileUpgradedFilesToIgnoreTable(table);
                        break;
                    case "UpgradedImages":
                        this.DecompileUpgradedImagesTable(table);
                        break;
                    case "UIText":
                        this.DecompileUITextTable(table);
                        break;
                    case "Verb":
                        this.DecompileVerbTable(table);
                        break;
                    default:
                        DecompilerExtension extension = (DecompilerExtension)this.extensionsByTableName[table.Name];

                        if (null != extension)
                        {
                            extension.DecompileTable(table);
                        }
                        else if (!this.suppressCustomTables)
                        {
                            this.DecompileCustomTable(table);
                        }
                        break;
                }
            }
        }
Example #35
0
        /// <summary>
        /// Resolve component groups.
        /// </summary>
        /// <param name="output">Active output to add sections to.</param>
        /// <param name="referencedSymbols">Collection of all symbols referenced during linking.</param>
        /// <param name="componentsToComponentGroupsComplexReferences">Component to ComponentGroup complex references.</param>
        /// <param name="componentGroupsToFeatures">ComponentGroups to features complex references.</param>
        /// <param name="componentGroupsToModules">ComponentGroups to modules complex references.</param>
        /// <param name="componentsToFeatures">Component to feature complex references.</param>
        private void ResolveComponentGroups(
			Output output,
			StringCollection referencedSymbols,
			ComplexReferenceCollection componentsToComponentGroupsComplexReferences,
			ConnectToFeatureCollection componentGroupsToFeatures,
			ConnectToModuleCollection componentGroupsToModules,
			ConnectToFeatureCollection componentsToFeatures)
        {
            foreach (ComplexReference cref in componentsToComponentGroupsComplexReferences)
            {
                // only connect a Component to a Feature if the ComponentGroup is connected to a Feature
                ConnectToFeature connectComponentGroupToFeature = componentGroupsToFeatures[cref.ParentId];
                if (null != connectComponentGroupToFeature)
                {
                    // create a list of all features (use an ArrayList because StringCollection lacks an AddRange method that takes an ICollection)
                    ArrayList features = new ArrayList(connectComponentGroupToFeature.ConnectFeatures);
                    features.Add(connectComponentGroupToFeature.PrimaryFeature);

                    foreach (string feature in features)
                    {
                        ConnectToFeature connectComponentToFeature = componentsToFeatures[cref.ChildId];
                        bool isExplicitPrimaryFeature = (connectComponentGroupToFeature.IsExplicitPrimaryFeature && (connectComponentGroupToFeature.PrimaryFeature == feature));

                        if (null == connectComponentToFeature)
                        {
                            componentsToFeatures.Add(new ConnectToFeature(connectComponentGroupToFeature.Section, cref.ChildId, feature, isExplicitPrimaryFeature));
                        }
                        else if (isExplicitPrimaryFeature && connectComponentToFeature.IsExplicitPrimaryFeature && feature != connectComponentToFeature.PrimaryFeature)
                        {
                            this.OnMessage(WixErrors.MultiplePrimaryReferences(SourceLineNumberCollection.FromFileName(connectComponentToFeature.Section.Intermediate.Path), cref.ChildType.ToString(), cref.ChildId, cref.ParentId, feature));
                            continue;
                        }
                        else if (isExplicitPrimaryFeature)
                        {
                            connectComponentToFeature.ConnectFeatures.Add(connectComponentToFeature.PrimaryFeature); // move the guessed primary feature to the list of connects
                            connectComponentToFeature.PrimaryFeature = feature; // set the new primary feature
                            connectComponentToFeature.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
                        }
                        else
                        {
                            connectComponentToFeature.ConnectFeatures.Add(feature);
                        }

                        // add a row to the FeatureComponents table
                        Row row = Common.CreateRowInSection(null, output.EntrySection, this.tableDefinitions["FeatureComponents"]);
                        row[0] = feature;
                        row[1] = cref.ChildId;

                        // index the component for finding orphaned records
                        Reference reference = new Reference("Component", cref.ChildId);
                        if (!referencedSymbols.Contains(reference.SymbolicName))
                        {
                            referencedSymbols.Add(reference.SymbolicName);
                        }
                    }
                }

                // only connect a Component to a Module if the ComponentGroup is connected to a Module
                ConnectToModule connectComponentGroupToModule = componentGroupsToModules[cref.ParentId];
                if (null != connectComponentGroupToModule)
                {
                    // add a row to the ModuleComponents table
                    Row row = Common.CreateRowInSection(null, output.EntrySection, this.tableDefinitions["ModuleComponents"]);
                    row[0] = cref.ChildId;
                    row[1] = connectComponentGroupToModule.Module;
                    row[2] = connectComponentGroupToModule.ModuleLanguage;

                    // index the component for finding orphaned records
                    Reference reference = new Reference("Component", cref.ChildId);
                    if (!referencedSymbols.Contains(reference.SymbolicName))
                    {
                        referencedSymbols.Add(reference.SymbolicName);
                    }
                }
            }
        }
 /// <summary>
 /// Called during the generation of sectionIds for an admin image.
 /// </summary>
 public virtual void GenerateSectionIds(Output output)
 {
 }
Example #37
0
        /// <summary>
        /// Links an array of intermediates into an output.
        /// </summary>
        /// <param name="intermediates">Array of intermediates to link together.</param>
        /// <returns>Output object from the linking.</returns>
        public Output Link(Intermediate[] intermediates)
        {
            Output output = null;

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

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

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

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

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

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

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

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

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

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

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

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

                if (this.foundError)
                {
                    return null;
                }

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

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

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

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

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

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

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

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

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

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

                                        suppressActionRows.Add(suppressActionRow);
                                    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                    int currentPrimaryKey = 0;

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

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

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

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

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

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

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

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

                                    customTableDefinitions.Add(customTable);
                                }

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

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

                                copyRows = false;
                                break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                            case "ModuleSubstitution":
                                containsModuleSubstitution = true;
                                break;

                            case "ModuleConfiguration":
                                containsModuleConfiguration = true;
                                break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                    secureProperties[row.ActionProperty] = null;
                                }

                                break;
                            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return (this.foundError ? null : output);
        }
Example #38
0
 /// <summary>
 /// Creates a transform by diffing two outputs.
 /// </summary>
 /// <param name="targetOutput">The target output.</param>
 /// <param name="updatedOutput">The updated output.</param>
 /// <returns>The transform.</returns>
 public Output Diff(Output targetOutput, Output updatedOutput)
 {
     return(Diff(targetOutput, updatedOutput, 0));
 }