Пример #1
0
 /// <summary>
 /// Creates a new empty output object.
 /// </summary>
 /// <param name="sourceLineNumbers">The source line information for the output.</param>
 internal Output(SourceLineNumberCollection sourceLineNumbers)
 {
     this.sections = new SectionCollection();
     this.sourceLineNumbers = sourceLineNumbers;
     this.subStorages = new ArrayList();
     this.tables = new TableCollection();
 }
        /// <summary>
        /// Adds a SectionCollection to the collection.
        /// </summary>
        /// <param name="sections">SectionCollection to add to collection.</param>
        public void AddRange(SectionCollection sections)
        {
            if (0 == this.collection.Count)
            {
                this.collection = new Dictionary<Section, object>(sections.Count);
            }

            foreach (Section section in sections.collection.Keys)
            {
                this.collection.Add(section, null);
            }
        }
Пример #3
0
        private static void LoadSections(string inputFile, IDictionary<Section, string> sectionFiles, SectionCollection sections)
        {
            var fragments = new List<Section>();

            foreach (Section section in sections)
            {
                if (SectionType.Fragment == section.Type)
                {
                    fragments.Add(section);
                }
                else
                {
                    // reject any file that isn't all fragments
                    return;
                }
            }

            foreach (Section section in fragments)
            {
                sectionFiles[section] = inputFile;
            }
        }
Пример #4
0
        public Output Link(SectionCollection sections, ArrayList transforms, OutputType expectedOutputType)
        {
            Output output = null;

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

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

                ConnectToFeatureCollection componentsToFeatures = new ConnectToFeatureCollection();
                ConnectToFeatureCollection featuresToFeatures = new ConnectToFeatureCollection();
                ConnectToFeatureCollection modulesToFeatures = new ConnectToFeatureCollection();

                this.activeOutput = null;
                this.encounteredError = false;

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

                RowCollection actionRows = new RowCollection();
                RowCollection suppressActionRows = new RowCollection();

                TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection();
                RowCollection customRows = new RowCollection();

                StringCollection generatedShortFileNameIdentifiers = new StringCollection();
                Hashtable generatedShortFileNames = new Hashtable();

                Hashtable multipleFeatureComponents = new Hashtable();

                Hashtable wixVariables = new Hashtable();

                // verify that modularization types match for foreign key relationships
                foreach (TableDefinition tableDefinition in this.tableDefinitions)
                {
                    foreach (ColumnDefinition columnDefinition in tableDefinition.Columns)
                    {
                        if (null != columnDefinition.KeyTable && 0 > columnDefinition.KeyTable.IndexOf(';') && columnDefinition.IsKeyColumnSet)
                        {
                            try
                            {
                                TableDefinition keyTableDefinition = this.tableDefinitions[columnDefinition.KeyTable];

                                if (0 >= columnDefinition.KeyColumn || keyTableDefinition.Columns.Count < columnDefinition.KeyColumn)
                                {
                                    this.OnMessage(WixErrors.InvalidKeyColumn(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn));
                                }
                                else if (keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType != columnDefinition.ModularizeType && ColumnModularizeType.CompanionFile != columnDefinition.ModularizeType)
                                {
                                    this.OnMessage(WixErrors.CollidingModularizationTypes(tableDefinition.Name, columnDefinition.Name, columnDefinition.KeyTable, columnDefinition.KeyColumn, columnDefinition.ModularizeType.ToString(), keyTableDefinition.Columns[columnDefinition.KeyColumn - 1].ModularizeType.ToString()));
                                }
                            }
                            catch (WixMissingTableDefinitionException)
                            {
                                // ignore missing table definitions - this error is caught in other places
                            }
                        }
                    }
                }

                // add in the extension sections
                foreach (WixExtension extension in this.extensions)
                {
                    Library library = extension.GetLibrary(this.tableDefinitions);

                    if (null != library)
                    {
                        sections.AddRange(library.Sections);
                    }
                }

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

                // should have found an entry section by now
                if (null == entrySection)
                {
                    throw new WixException(WixErrors.MissingEntrySection(expectedOutputType.ToString()));
                }

                // add the missing standard action symbols
                this.LoadStandardActionSymbols(allSymbols);

                // now that we know where we're starting from, create the output object
                output = new Output(null);
                output.EntrySection = entrySection; // Note: this entry section will get added to the Output.Sections 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 for linking.  Of course, we start with the entry
                // section (that's how it got its name after all).
                output.Sections.AddRange(output.EntrySection.ResolveReferences(output.Type, allSymbols, referencedSymbols, unresolvedReferences, this));

                // Flattening the complex references that participate in groups.
                this.FlattenSectionsComplexReferences(output.Sections);

                if (this.encounteredError)
                {
                    return null;
                }

                // The hard part in linking is processing the complex references.
                this.ProcessComplexReferences(output, output.Sections, referencedSymbols, componentsToFeatures, featuresToFeatures, modulesToFeatures);
                for (int i = 0; i < unresolvedReferences.Count; ++i)
                {
                    Section.SimpleReferenceSection referenceSection = (Section.SimpleReferenceSection)unresolvedReferences[i];
                    if (this.allowUnresolvedReferences)
                    {
                        this.OnMessage(WixWarnings.UnresolvedReferenceWarning(referenceSection.WixSimpleReferenceRow.SourceLineNumbers, referenceSection.Section.Type.ToString(), referenceSection.Section.Id, referenceSection.WixSimpleReferenceRow.SymbolicName));
                    }
                    else
                    {
                        this.OnMessage(WixErrors.UnresolvedReference(referenceSection.WixSimpleReferenceRow.SourceLineNumbers, referenceSection.Section.Type.ToString(), referenceSection.Section.Id, referenceSection.WixSimpleReferenceRow.SymbolicName));
                    }
                }

                if (this.encounteredError)
                {
                    return null;
                }

                SymbolCollection unreferencedSymbols = output.Sections.GetOrphanedSymbols(referencedSymbols, this);

                // Display a warning message for Components that were never referenced by a Feature.
                foreach (Symbol symbol in unreferencedSymbols)
                {
                    if ("Component" == symbol.Row.Table.Name)
                    {
                        this.OnMessage(WixErrors.OrphanedComponent(symbol.Row.SourceLineNumbers, (string)symbol.Row[0]));
                    }
                }

                Dictionary<string, List<Symbol>> duplicatedSymbols = output.Sections.GetDuplicateSymbols(this);

                // Display a warning message for Components that were never referenced by a Feature.
                foreach (List<Symbol> duplicatedSymbolList in duplicatedSymbols.Values)
                {
                    Symbol symbol = duplicatedSymbolList[0];

                    // Certain tables allow duplicates because they allow overrides.
                    if (symbol.Row.Table.Name != "WixAction" &&
                        symbol.Row.Table.Name != "WixVariable")
                    {
                        this.OnMessage(WixErrors.DuplicateSymbol(symbol.Row.SourceLineNumbers, symbol.Name));

                        for (int i = 1; i < duplicatedSymbolList.Count; i++)
                        {
                            Symbol duplicateSymbol = duplicatedSymbolList[i];
                            this.OnMessage(WixErrors.DuplicateSymbol2(duplicateSymbol.Row.SourceLineNumbers));
                        }
                    }
                }

                if (this.encounteredError)
                {
                    return null;
                }

                if (null != this.unreferencedSymbolsFile)
                {
                    sections.GetOrphanedSymbols(referencedSymbols, this).OutputSymbols(this.unreferencedSymbolsFile);
                }

                // resolve the feature to feature connects
                this.ResolveFeatureToFeatureConnects(featuresToFeatures, allSymbols);

                // start generating OutputTables and OutputRows for all the sections in the output
                RowCollection ensureTableRows = new RowCollection();
                int sectionCount = 0;
                foreach (Section section in output.Sections)
                {
                    sectionCount++;
                    string sectionId = section.Id;
                    if (null == sectionId && this.sectionIdOnRows)
                    {
                        sectionId = "wix.section." + sectionCount.ToString(CultureInfo.InvariantCulture);
                    }

                    foreach (Table table in section.Tables)
                    {
                        // By default, copy rows unless we've been asked to drop unreal tables from
                        // the output and it's an unreal table and *not* a UX Manifest table.
                        bool copyRows = true;
                        if (this.dropUnrealTables && table.Definition.IsUnreal && !table.Definition.IsBootstrapperApplicationData)
                        {
                            copyRows = false;
                        }

                        // handle special tables
                        switch (table.Name)
                        {
                            case "AppSearch":
                                this.activeOutput.EnsureTable(this.tableDefinitions["Signature"]);
                                break;

                            case "Class":
                                if (OutputType.Product == output.Type)
                                {
                                    this.ResolveFeatures(table.Rows, 2, 11, componentsToFeatures, multipleFeatureComponents);
                                }
                                break;

                            case "ChainPackage":
                            case "ChainPackageGroup":
                            case "MsiProperty":
                                copyRows = true;
                                break;

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

                                foreach (Row row in table.Rows)
                                {
                                    // For script CAs that specify HideTarget we should also hide the CA data property for the action.
                                    int bits = Convert.ToInt32(row[1]);
                                    if (MsiInterop.MsidbCustomActionTypeHideTarget == (bits & MsiInterop.MsidbCustomActionTypeHideTarget) &&
                                        MsiInterop.MsidbCustomActionTypeInScript == (bits & MsiInterop.MsidbCustomActionTypeInScript))
                                    {
                                        hiddenProperties[Convert.ToString(row[0])] = null;
                                    }
                                }
                                break;

                            case "Dialog":
                                this.activeOutput.EnsureTable(this.tableDefinitions["ListBox"]);
                                break;

                            case "Directory":
                                foreach (Row row in table.Rows)
                                {
                                    if (OutputType.Module == this.activeOutput.Type)
                                    {
                                        string directory = row[0].ToString();
                                        if (Util.IsStandardDirectory(directory))
                                        {
                                            // 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.
                                            this.activeOutput.EnsureTable(this.tableDefinitions["CustomAction"]);
                                            this.activeOutput.EnsureTable(this.tableDefinitions["AdminExecuteSequence"]);
                                            this.activeOutput.EnsureTable(this.tableDefinitions["AdminUISequence"]);
                                            this.activeOutput.EnsureTable(this.tableDefinitions["AdvtExecuteSequence"]);
                                            this.activeOutput.EnsureTable(this.tableDefinitions["InstallExecuteSequence"]);
                                            this.activeOutput.EnsureTable(this.tableDefinitions["InstallUISequence"]);
                                        }
                                        else
                                        {
                                            foreach (string standardDirectory in Util.StandardDirectories.Keys)
                                            {
                                                if (directory.StartsWith(standardDirectory, StringComparison.Ordinal))
                                                {
                                                    this.OnMessage(WixWarnings.StandardDirectoryConflictInMergeModule(row.SourceLineNumbers, directory, standardDirectory));
                                                }
                                            }
                                        }
                                    }
                                }
                                break;

                            case "Extension":
                                if (OutputType.Product == output.Type)
                                {
                                    this.ResolveFeatures(table.Rows, 1, 4, componentsToFeatures, multipleFeatureComponents);
                                }
                                break;

                            case "ModuleSubstitution":
                                containsModuleSubstitution = true;
                                break;

                            case "ModuleConfiguration":
                                containsModuleConfiguration = true;
                                break;

                            case "MsiAssembly":
                                if (this.suppressMsiAssemblyTable)
                                {
                                    copyRows = false;
                                }
                                else if (OutputType.Product == output.Type)
                                {
                                    this.ResolveFeatures(table.Rows, 0, 1, componentsToFeatures, multipleFeatureComponents);
                                }
                                break;

                            case "ProgId":
                                // the Extension table is required with a ProgId table
                                this.activeOutput.EnsureTable(this.tableDefinitions["Extension"]);
                                break;

                            case "Property":
                                for (int i = 0; i < table.Rows.Count; i++)
                                {
                                    if (null == table.Rows[i][1])
                                    {
                                        table.Rows.RemoveAt(i);
                                        i--;
                                    }
                                }
                                break;

                            case "PublishComponent":
                                if (OutputType.Product == output.Type)
                                {
                                    this.ResolveFeatures(table.Rows, 2, 4, componentsToFeatures, multipleFeatureComponents);
                                }
                                break;

                            case "Shortcut":
                                if (OutputType.Product == output.Type)
                                {
                                    this.ResolveFeatures(table.Rows, 3, 4, componentsToFeatures, multipleFeatureComponents);
                                }
                                break;

                            case "TypeLib":
                                if (OutputType.Product == output.Type)
                                {
                                    this.ResolveFeatures(table.Rows, 2, 6, componentsToFeatures, multipleFeatureComponents);
                                }
                                break;

                            case "Upgrade":
                                foreach (UpgradeRow row in table.Rows)
                                {
                                    secureProperties[row.ActionProperty] = null;
                                }
                                break;

                            case "Variable":
                                copyRows = true;
                                break;

                            case "WixAction":
                                if (this.sectionIdOnRows)
                                {
                                    foreach (Row row in table.Rows)
                                    {
                                        row.SectionId = sectionId;
                                    }
                                }
                                actionRows.AddRange(table.Rows);
                                break;

                            case "WixBBControl":
                            case "WixControl":
                                copyRows = true;
                                break;

                            case "WixCustomTable":
                                this.LinkCustomTable(table, customTableDefinitions);
                                copyRows = false; // we've created table definitions from these rows, no need to process them any longer
                                break;

                            case "WixCustomRow":
                                foreach (Row row in table.Rows)
                                {
                                    row.SectionId = (this.sectionIdOnRows ? sectionId : null);
                                    customRows.Add(row);
                                }
                                copyRows = false;
                                break;

                            case "WixEnsureTable":
                                ensureTableRows.AddRange(table.Rows);
                                break;

                            case "WixFile":
                                foreach (Row 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[5] = 0;
                                    }

                                    // if the short file name was generated, check for collisions
                                    if (0x1 == (int)row[9])
                                    {
                                        generatedShortFileNameIdentifiers.Add((string)row[0]);
                                    }
                                }
                                copyRows = true;
                                break;

                            case "WixFragment":
                                copyRows = true;
                                break;

                            case "WixGroup":
                                copyRows = true;
                                break;

                            case "WixInstanceTransforms":
                                copyRows = true;
                                break;

                            case "WixMedia":
                                copyRows = true;
                                break;

                            case "WixMerge":
                                if (OutputType.Product == output.Type)
                                {
                                    this.ResolveFeatures(table.Rows, 0, 7, modulesToFeatures, null);
                                }
                                copyRows = true;
                                break;

                            case "WixOrdering":
                                copyRows = true;
                                break;

                            case "WixProperty":
                                foreach (WixPropertyRow wixPropertyRow in table.Rows)
                                {
                                    if (wixPropertyRow.Admin)
                                    {
                                        adminProperties[wixPropertyRow.Id] = null;
                                    }

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

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

                            case "WixSuppressAction":
                                suppressActionRows.AddRange(table.Rows);
                                break;

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

                            case "WixVariable":
                                // check for colliding values and collect the wix variable rows
                                foreach (WixVariableRow row in table.Rows)
                                {
                                    WixVariableRow collidingRow = (WixVariableRow)wixVariables[row.Id];

                                    if (null == collidingRow || (collidingRow.Overridable && !row.Overridable))
                                    {
                                        wixVariables[row.Id] = row;
                                    }
                                    else if (!row.Overridable || (collidingRow.Overridable && row.Overridable))
                                    {
                                        this.OnMessage(WixErrors.WixVariableCollision(row.SourceLineNumbers, row.Id));
                                    }
                                }
                                copyRows = false;
                                break;
                            case "WixPatchRef":
                            case "WixPatchBaseline":
                            case "WixPatchId":
                                copyRows = true;
                                break;
                        }

                        if (copyRows)
                        {
                            Table outputTable = this.activeOutput.EnsureTable(this.tableDefinitions[table.Name]);
                            this.CopyTableRowsToOutputTable(table, outputTable, sectionId);
                        }
                    }
                }

                // Verify that there were no duplicate fragment Id's.
                Table wixFragmentTable = this.activeOutput.Tables["WixFragment"];
                Hashtable fragmentIdIndex = new Hashtable();
                if (null != wixFragmentTable)
                {
                    foreach (Row row in wixFragmentTable.Rows)
                    {
                        string fragmentId = row.Fields[0].Data.ToString();
                        if (!fragmentIdIndex.ContainsKey(fragmentId))
                        {
                            fragmentIdIndex.Add(fragmentId, row.SourceLineNumbers);
                        }
                        else
                        {
                            this.OnMessage(WixErrors.DuplicateSymbol(row.SourceLineNumbers, fragmentId));
                            if (null != fragmentIdIndex[fragmentId])
                            {
                                this.OnMessage(WixErrors.DuplicateSymbol2((SourceLineNumberCollection)fragmentIdIndex[fragmentId]));
                            }
                        }
                    }
                }

                // copy the module to feature connections into the output
                if (0 < modulesToFeatures.Count)
                {
                    Table wixFeatureModulesTable = this.activeOutput.EnsureTable(this.tableDefinitions["WixFeatureModules"]);

                    foreach (ConnectToFeature connectToFeature in modulesToFeatures)
                    {
                        foreach (string feature in connectToFeature.ConnectFeatures)
                        {
                            Row row = wixFeatureModulesTable.CreateRow(null);
                            row[0] = feature;
                            row[1] = connectToFeature.ChildId;
                        }
                    }
                }

                // ensure the creation of tables that need to exist
                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];
                        }

                        this.activeOutput.EnsureTable(tableDef);
                    }
                }

                // copy all the suppress action rows to the output to suppress actions from merge modules
                if (0 < suppressActionRows.Count)
                {
                    Table suppressActionTable = this.activeOutput.EnsureTable(this.tableDefinitions["WixSuppressAction"]);
                    suppressActionTable.Rows.AddRange(suppressActionRows);
                }

                // sequence all the actions
                this.SequenceActions(actionRows, suppressActionRows);

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

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

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

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

                        this.activeOutput.EnsureTable(this.tableDefinitions["Properties"]);
                        break;
                    case OutputType.Product:
                        this.activeOutput.EnsureTable(this.tableDefinitions["File"]);
                        this.activeOutput.EnsureTable(this.tableDefinitions["Media"]);
                        break;
                }

                this.CheckForIllegalTables(this.activeOutput);

                // add the custom row data
                foreach (Row row in customRows)
                {
                    TableDefinition customTableDefinition = (TableDefinition)customTableDefinitions[row[0].ToString()];
                    Table customTable = this.activeOutput.EnsureTable(customTableDefinition);
                    Row customRow = customTable.CreateRow(row.SourceLineNumbers);

                    customRow.SectionId = row.SectionId;

                    string[] data = row[1].ToString().Split(Common.CustomRowFieldSeparator);

                    for (int i = 0; i < data.Length; ++i)
                    {
                        bool foundColumn = false;
                        string[] item = data[i].Split(colonCharacter, 2);

                        for (int j = 0; j < customRow.Fields.Length; ++j)
                        {
                            if (customRow.Fields[j].Column.Name == item[0])
                            {
                                if (0 < item[1].Length)
                                {
                                    if (ColumnType.Number == customRow.Fields[j].Column.Type)
                                    {
                                        try
                                        {
                                            customRow.Fields[j].Data = Convert.ToInt32(item[1], CultureInfo.InvariantCulture);
                                        }
                                        catch (FormatException)
                                        {
                                            this.OnMessage(WixErrors.IllegalIntegerValue(row.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1]));
                                        }
                                        catch (OverflowException)
                                        {
                                            this.OnMessage(WixErrors.IllegalIntegerValue(row.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name, item[1]));
                                        }
                                    }
                                    else if (ColumnCategory.Identifier == customRow.Fields[j].Column.Category)
                                    {
                                        if (CompilerCore.IsIdentifier(item[1]) || Common.IsValidBinderVariable(item[1]) || ColumnCategory.Formatted == customRow.Fields[j].Column.Category)
                                        {
                                            customRow.Fields[j].Data = item[1];
                                        }
                                        else
                                        {
                                            this.OnMessage(WixErrors.IllegalIdentifier(row.SourceLineNumbers, "Data", item[1]));
                                        }
                                    }
                                    else
                                    {
                                        customRow.Fields[j].Data = item[1];
                                    }
                                }
                                foundColumn = true;
                                break;
                            }
                        }

                        if (!foundColumn)
                        {
                            this.OnMessage(WixErrors.UnexpectedCustomTableColumn(row.SourceLineNumbers, item[0]));
                        }
                    }

                    for (int i = 0; i < customTableDefinition.Columns.Count; ++i)
                    {
                        if (!customTableDefinition.Columns[i].IsNullable && (null == customRow.Fields[i].Data || 0 == customRow.Fields[i].Data.ToString().Length))
                        {
                            this.OnMessage(WixErrors.NoDataForColumn(row.SourceLineNumbers, customTableDefinition.Columns[i].Name, customTableDefinition.Name));
                        }
                    }
                }

                //correct the section Id in FeatureComponents table
                if (this.sectionIdOnRows)
                {
                    Hashtable componentSectionIds = new Hashtable();
                    Table componentTable = output.Tables["Component"];

                    if (null != componentTable)
                    {
                        foreach (Row componentRow in componentTable.Rows)
                        {
                            componentSectionIds.Add(componentRow.Fields[0].Data.ToString(), componentRow.SectionId);
                        }
                    }

                    Table featureComponentsTable = output.Tables["FeatureComponents"];

                    if (null != featureComponentsTable)
                    {
                        foreach (Row featureComponentsRow in featureComponentsTable.Rows)
                        {
                            if (componentSectionIds.Contains(featureComponentsRow.Fields[1].Data.ToString()))
                            {
                                featureComponentsRow.SectionId = (string)componentSectionIds[featureComponentsRow.Fields[1].Data.ToString()];
                            }
                        }
                    }
                }

                // update the special properties
                if (0 < adminProperties.Count)
                {
                    Table propertyTable = this.activeOutput.EnsureTable(this.tableDefinitions["Property"]);

                    Row row = propertyTable.CreateRow(null);
                    row[0] = "AdminProperties";
                    row[1] = GetPropertyListString(adminProperties);
                }

                if (0 < secureProperties.Count)
                {
                    Table propertyTable = this.activeOutput.EnsureTable(this.tableDefinitions["Property"]);

                    Row row = propertyTable.CreateRow(null);
                    row[0] = "SecureCustomProperties";
                    row[1] = GetPropertyListString(secureProperties);
                }

                if (0 < hiddenProperties.Count)
                {
                    Table propertyTable = this.activeOutput.EnsureTable(this.tableDefinitions["Property"]);

                    Row row = propertyTable.CreateRow(null);
                    row[0] = "MsiHiddenProperties";
                    row[1] = GetPropertyListString(hiddenProperties);
                }

                // add the ModuleSubstitution table to the ModuleIgnoreTable
                if (containsModuleSubstitution)
                {
                    Table moduleIgnoreTableTable = this.activeOutput.EnsureTable(this.tableDefinitions["ModuleIgnoreTable"]);

                    Row moduleIgnoreTableRow = moduleIgnoreTableTable.CreateRow(null);
                    moduleIgnoreTableRow[0] = "ModuleSubstitution";
                }

                // add the ModuleConfiguration table to the ModuleIgnoreTable
                if (containsModuleConfiguration)
                {
                    Table moduleIgnoreTableTable = this.activeOutput.EnsureTable(this.tableDefinitions["ModuleIgnoreTable"]);

                    Row moduleIgnoreTableRow = moduleIgnoreTableTable.CreateRow(null);
                    moduleIgnoreTableRow[0] = "ModuleConfiguration";
                }

                // index all the file rows
                FileRowCollection indexedFileRows = new FileRowCollection();
                Table fileTable = this.activeOutput.Tables["File"];
                if (null != fileTable)
                {
                    indexedFileRows.AddRange(fileTable.Rows);
                }

                // flag all the generated short file name collisions
                foreach (string fileId in generatedShortFileNameIdentifiers)
                {
                    FileRow fileRow = indexedFileRows[fileId];

                    string[] names = fileRow.FileName.Split('|');
                    string shortFileName = names[0];

                    // create lists of conflicting generated short file names
                    if (!generatedShortFileNames.Contains(shortFileName))
                    {
                        generatedShortFileNames.Add(shortFileName, new ArrayList());
                    }
                    ((ArrayList)generatedShortFileNames[shortFileName]).Add(fileRow);
                }

                // check for generated short file name collisions
                foreach (DictionaryEntry entry in generatedShortFileNames)
                {
                    string shortFileName = (string)entry.Key;
                    ArrayList fileRows = (ArrayList)entry.Value;

                    if (1 < fileRows.Count)
                    {
                        // sort the rows by DiskId
                        fileRows.Sort();

                        this.OnMessage(WixWarnings.GeneratedShortFileNameConflict(((FileRow)fileRows[0]).SourceLineNumbers, shortFileName));

                        for (int i = 1; i < fileRows.Count; i++)
                        {
                            FileRow fileRow = (FileRow)fileRows[i];

                            if (null != fileRow.SourceLineNumbers)
                            {
                                this.OnMessage(WixWarnings.GeneratedShortFileNameConflict2(fileRow.SourceLineNumbers));
                            }
                        }
                    }
                }

                // copy the wix variable rows to the output after all overriding has been accounted for.
                if (0 < wixVariables.Count)
                {
                    Table wixVariableTable = output.EnsureTable(this.tableDefinitions["WixVariable"]);

                    foreach (WixVariableRow row in wixVariables.Values)
                    {
                        wixVariableTable.Rows.Add(row);
                    }
                }

                // Bundles have groups of data that must be flattened in a way different from other types.
                this.FlattenBundleTables(output);

                if (this.encounteredError)
                {
                    return null;
                }

                this.CheckOutputConsistency(output);

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

                    // reset
                    inspectorExtension.Core = null;
                }

                if (inspectorCore.EncounteredError)
                {
                    this.encounteredError = true;
                }
            }
            finally
            {
                this.activeOutput = null;
            }

            return (this.encounteredError ? null : output);
        }
Пример #5
0
 /// <summary>
 /// Links a collection of sections into an output.
 /// </summary>
 /// <param name="sections">The collection of sections to link together.</param>
 /// <returns>Output object from the linking.</returns>
 public Output Link(SectionCollection sections)
 {
     return this.Link(sections, null, OutputType.Unknown);
 }
Пример #6
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="componentsToFeatures">Component to feature complex references.</param>
        /// <param name="featuresToFeatures">Feature to feature complex references.</param>
        /// <param name="modulesToFeatures">Module to feature complex references.</param>
        private void ProcessComplexReferences(
            Output output,
            SectionCollection sections,
            StringCollection referencedSymbols,
            ConnectToFeatureCollection componentsToFeatures,
            ConnectToFeatureCollection featuresToFeatures,
            ConnectToFeatureCollection modulesToFeatures)
        {
            Hashtable componentsToModules = new Hashtable();

            foreach (Section section in sections)
            {
                Table wixComplexReferenceTable = section.Tables["WixComplexReference"];

                if (null != wixComplexReferenceTable)
                {
                    foreach (WixComplexReferenceRow wixComplexReferenceRow in wixComplexReferenceTable.Rows)
                    {
                        ConnectToFeature connection;
                        switch (wixComplexReferenceRow.ParentType)
                        {
                            case ComplexReferenceParentType.Feature:
                                switch (wixComplexReferenceRow.ChildType)
                                {
                                    case ComplexReferenceChildType.Component:
                                        connection = componentsToFeatures[wixComplexReferenceRow.ChildId];
                                        if (null == connection)
                                        {
                                            componentsToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentId, wixComplexReferenceRow.IsPrimary));
                                        }
                                        else if (wixComplexReferenceRow.IsPrimary)
                                        {
                                            if (connection.IsExplicitPrimaryFeature)
                                            {
                                                this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id)));
                                                continue;
                                            }
                                            else
                                            {
                                                connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
                                                connection.PrimaryFeature = wixComplexReferenceRow.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(wixComplexReferenceRow.ParentId);
                                        }

                                        // add a row to the FeatureComponents table
                                        Table featureComponentsTable = output.EnsureTable(this.tableDefinitions["FeatureComponents"]);
                                        Row row = featureComponentsTable.CreateRow(null);
                                        if (this.sectionIdOnRows)
                                        {
                                            row.SectionId = section.Id;
                                        }
                                        row[0] = wixComplexReferenceRow.ParentId;
                                        row[1] = wixComplexReferenceRow.ChildId;

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

                                        break;

                                    case ComplexReferenceChildType.Feature:
                                        connection = featuresToFeatures[wixComplexReferenceRow.ChildId];
                                        if (null != connection)
                                        {
                                            this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id)));
                                            continue;
                                        }

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

                                    case ComplexReferenceChildType.Module:
                                        connection = modulesToFeatures[wixComplexReferenceRow.ChildId];
                                        if (null == connection)
                                        {
                                            modulesToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentId, wixComplexReferenceRow.IsPrimary));
                                        }
                                        else if (wixComplexReferenceRow.IsPrimary)
                                        {
                                            if (connection.IsExplicitPrimaryFeature)
                                            {
                                                this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id)));
                                                continue;
                                            }
                                            else
                                            {
                                                connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
                                                connection.PrimaryFeature = wixComplexReferenceRow.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(wixComplexReferenceRow.ParentId);
                                        }
                                        break;

                                    default:
                                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
                                }
                                break;

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

                                            // add a row to the ModuleComponents table
                                            Table moduleComponentsTable = output.EnsureTable(this.tableDefinitions["ModuleComponents"]);
                                            Row row = moduleComponentsTable.CreateRow(null);
                                            if (this.sectionIdOnRows)
                                            {
                                                row.SectionId = section.Id;
                                            }
                                            row[0] = wixComplexReferenceRow.ChildId;
                                            row[1] = wixComplexReferenceRow.ParentId;
                                            row[2] = wixComplexReferenceRow.ParentLanguage;
                                        }

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

                                        break;

                                    default:
                                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
                                }
                                break;

                            case ComplexReferenceParentType.Patch:
                                switch(wixComplexReferenceRow.ChildType)
                                {
                                    case ComplexReferenceChildType.PatchFamily:
                                    case ComplexReferenceChildType.PatchFamilyGroup:
                                        break;

                                    default:
                                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
                                }
                                break;

                            case ComplexReferenceParentType.Product:
                                switch (wixComplexReferenceRow.ChildType)
                                {
                                    case ComplexReferenceChildType.Feature:
                                        connection = featuresToFeatures[wixComplexReferenceRow.ChildId];
                                        if (null != connection)
                                        {
                                            this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id)));
                                            continue;
                                        }

                                        featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.ChildId, null, wixComplexReferenceRow.IsPrimary));
                                        break;

                                    default:
                                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
                                }
                                break;

                            default:
                                // Note: Groups have been processed before getting here so they are not handled by any case above.
                                throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceParentType), wixComplexReferenceRow.ParentType)));
                        }
                    }
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Flattens all complex references in all sections in the collection.
        /// </summary>
        /// <param name="sections">Sections that are referenced during the link process.</param>
        private void FlattenSectionsComplexReferences(SectionCollection sections)
        {
            Hashtable parentGroups = new Hashtable();
            Hashtable parentGroupsSections = new Hashtable();
            Hashtable parentGroupsNeedingProcessing = new Hashtable();

            // DisplaySectionComplexReferences("--- section's complex references before flattening ---", sections);

            // Step 1:  Gather all of the complex references that are going participate
            // in the flatting process.  This means complex references that have "grouping
            //  parents" of Features, Modules, and, of course, Groups.  These references
            // that participate in a "grouping parent" will be removed from their section
            // now and after processing added back in Step 3 below.
            foreach (Section section in sections)
            {
                Table wixComplexReferenceTable = section.Tables["WixComplexReference"];

                if (null != wixComplexReferenceTable)
                {
                    // Count down because we'll sometimes remove items from the list.
                    for (int i = wixComplexReferenceTable.Rows.Count - 1; i >= 0; --i)
                    {
                        WixComplexReferenceRow wixComplexReferenceRow = (WixComplexReferenceRow)wixComplexReferenceTable.Rows[i];

                        // Only process the "grouping parents" such as FeatureGroup, ComponentGroup, Feature,
                        // and Module.  Non-grouping complex references are simple and
                        // resolved during normal complex reference resolutions.
                        if (ComplexReferenceParentType.FeatureGroup == wixComplexReferenceRow.ParentType ||
                            ComplexReferenceParentType.ComponentGroup == wixComplexReferenceRow.ParentType ||
                            ComplexReferenceParentType.Feature == wixComplexReferenceRow.ParentType ||
                            ComplexReferenceParentType.Module == wixComplexReferenceRow.ParentType ||
                            ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType ||
                            ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType)
                        {
                            string parentTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.ParentId);

                            // Group all complex references with a common parent
                            // together so we can find them quickly while processing in
                            // Step 2.
                            ArrayList childrenComplexRefs = parentGroups[parentTypeAndId] as ArrayList;
                            if (null == childrenComplexRefs)
                            {
                                childrenComplexRefs = new ArrayList();
                                parentGroups.Add(parentTypeAndId, childrenComplexRefs);
                            }

                            childrenComplexRefs.Add(wixComplexReferenceRow);
                            wixComplexReferenceTable.Rows.RemoveAt(i);

                            // Remember the mapping from set of complex references with a common
                            // parent to their section.  We'll need this to add them back to the
                            // correct section in Step 3.
                            Section parentSection = parentGroupsSections[parentTypeAndId] as Section;
                            if (null == parentSection)
                            {
                                parentGroupsSections.Add(parentTypeAndId, section);
                            }
                            // Debug.Assert(section == (Section)parentGroupsSections[parentTypeAndId]);

                            // If the child of the complex reference is another group, then in Step 2
                            // we're going to have to process this complex reference again to copy
                            // the child group's references into the parent group.
                            if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) ||
                                (ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) ||
                                (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType))
                            {
                                if (!parentGroupsNeedingProcessing.ContainsKey(parentTypeAndId))
                                {
                                    parentGroupsNeedingProcessing.Add(parentTypeAndId, section);
                                }
                                // Debug.Assert(section == (Section)parentGroupsNeedingProcessing[parentTypeAndId]);
                            }
                        }
                    }
                }
            }
            Debug.Assert(parentGroups.Count == parentGroupsSections.Count);
            Debug.Assert(parentGroupsNeedingProcessing.Count <= parentGroups.Count);

            // DisplaySectionComplexReferences("\r\n\r\n--- section's complex references middle of flattening ---", sections);

            // Step 2:  Loop through the parent groups that have nested groups removing
            // them from the hash table as they are processed.  At the end of this the
            // complex references should all be flattened.
            string[] keys = new string[parentGroupsNeedingProcessing.Keys.Count];
            parentGroupsNeedingProcessing.Keys.CopyTo(keys, 0);

            foreach (string key in keys)
            {
                if (parentGroupsNeedingProcessing.Contains(key))
                {
                    Stack loopDetector = new Stack();
                    this.FlattenGroup(key, loopDetector, parentGroups, parentGroupsNeedingProcessing);
                }
                else
                {
                    // the group must have allready been procesed and removed from the hash table
                }
            }
            Debug.Assert(0 == parentGroupsNeedingProcessing.Count);

            // Step 3:  Finally, ensure that all of the groups that were removed
            // in Step 1 and flattened in Step 2 are added to their appropriate
            // section.  This is where we will toss out the final no-longer-needed
            // groups.
            foreach (string parentGroup in parentGroups.Keys)
            {
                Section section = (Section)parentGroupsSections[parentGroup];
                Table wixComplexReferenceTable = section.Tables["WixComplexReference"];

                foreach (WixComplexReferenceRow wixComplexReferenceRow in (ArrayList)parentGroups[parentGroup])
                {
                    if ((ComplexReferenceParentType.FeatureGroup != wixComplexReferenceRow.ParentType) &&
                        (ComplexReferenceParentType.ComponentGroup != wixComplexReferenceRow.ParentType) &&
                        (ComplexReferenceParentType.PatchFamilyGroup != wixComplexReferenceRow.ParentType))
                    {
                        wixComplexReferenceTable.Rows.Add(wixComplexReferenceRow);
                    }
                }
            }

            // DisplaySectionComplexReferences("\r\n\r\n--- section's complex references after flattening ---", sections);
        }
Пример #8
0
 /// <summary>
 /// Adds a SectionCollection to the collection.
 /// </summary>
 /// <param name="sections">SectionCollection to add to collection.</param>
 public void AddRange(SectionCollection sections)
 {
     this.collection.AddRange(sections.collection);
 }
Пример #9
0
 /// <summary>
 /// Instantiate a new Library.
 /// </summary>
 public Library()
 {
     this.localizations = new Hashtable();
     this.sections = new SectionCollection();
 }
Пример #10
0
        /// <summary>
        /// Resolves all the simple references in a section.
        /// </summary>
        /// <param name="outputType">Active output type.</param>
        /// <param name="sections">Collection to add sections to.</param>
        /// <param name="section">Section with references to resolve.</param>
        /// <param name="allSymbols">Collection of all symbols from loaded intermediates.</param>
        /// <param name="referencedSymbols">Collection of all symbols referenced during linking.</param>
        /// <param name="unresolvedReferences">Unresolved references.</param>
        /// <param name="messageHandler">Message handler to report errors through.</param>
        /// <remarks>Note: recursive function.</remarks>
        internal static void ResolveReferences(
			OutputType outputType,
			SectionCollection sections,
			Section section,
			SymbolCollection allSymbols,
			StringCollection referencedSymbols,
			ArrayList unresolvedReferences,
			IMessageHandler messageHandler)
        {
            // if we already have this section bail
            if (sections.Contains(section))
            {
                return;
            }

            // add the section to the output and loop through the rest of the references
            // in a simple depth-first search
            sections.Add(section);
            foreach (Reference reference in section.References)
            {
                // if we're building into an output, modules ignore all references to the Media table
                if (OutputType.Module == outputType && "Media" == reference.TableName)
                {
                    continue;
                }

                Symbol symbol = Common.GetSymbolForReference(section, reference, allSymbols, referencedSymbols, unresolvedReferences, messageHandler);
                if (null != symbol)
                {
                    Common.ResolveReferences(outputType, sections, symbol.Section, allSymbols, referencedSymbols, unresolvedReferences, messageHandler);
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Recursive helper function to resolve all references of passed in section.
        /// </summary>
        /// <param name="section">Section with references to resolve.</param>
        /// <param name="outputType">Parent output type that will get the resolved section collection.</param>
        /// <param name="allSymbols">All symbols that can be used to resolve section's references.</param>
        /// <param name="sections">Collection to add sections to during processing.</param>
        /// <param name="referencedSymbols">Collection populated during resolution of all symbols referenced during linking.</param>
        /// <param name="unresolvedReferences">Collection populated during resolution of all references that are left unresolved.</param>
        /// <param name="messageHandler">Message handler to report any duplicate symbols that may be tripped across.</param>
        /// <remarks>Note: recursive function.</remarks>
        private static void RecursivelyResolveReferences(
            Section section,
            OutputType outputType,
            SymbolCollection allSymbols,
            SectionCollection sections,
            StringCollection referencedSymbols,
            ArrayList unresolvedReferences,
            IMessageHandler messageHandler)
        {
            // if we already have this section bail
            if (sections.Contains(section))
            {
                return;
            }

            // add the passed in section to the collection of sections
            sections.Add(section);

            // process all of the references contained in this section using the collection of
            // symbols provided.  Then recursively call this method to process the
            // located symbol's section.  All in all this is a very simple depth-first
            // search of the references per-section
            Table wixSimpleReferenceTable = section.Tables["WixSimpleReference"];

            if (null != wixSimpleReferenceTable)
            {
                foreach (WixSimpleReferenceRow wixSimpleReferenceRow in wixSimpleReferenceTable.Rows)
                {
                    // If we're building a Merge Module, ignore all references to the Media table
                    // because Merge Modules don't have Media tables.
                    if (OutputType.Module == outputType && "Media" == wixSimpleReferenceRow.TableName)
                    {
                        continue;
                    }

                    if ("WixAction" == wixSimpleReferenceRow.TableName)
                    {
                        Symbol[] symbols = allSymbols.GetSymbolsForSimpleReference(wixSimpleReferenceRow);
                        if (0 == symbols.Length)
                        {
                            if (null != unresolvedReferences)
                            {
                                unresolvedReferences.Add(new SimpleReferenceSection(section, wixSimpleReferenceRow));
                            }
                        }
                        else
                        {
                            foreach (Symbol symbol in symbols)
                            {
                                if (null != symbol.Section)
                                {
                                    // components are indexed in ResolveComplexReferences
                                    if (null != referencedSymbols && null != symbol.Row.TableDefinition.Name && "Component" != symbol.Row.TableDefinition.Name && !referencedSymbols.Contains(symbol.Name))
                                    {
                                        referencedSymbols.Add(symbol.Name);
                                    }

                                    RecursivelyResolveReferences(symbol.Section, outputType, allSymbols, sections, referencedSymbols, unresolvedReferences, messageHandler);
                                }
                            }
                        }
                    }
                    else
                    {
                        Symbol symbol = allSymbols.GetSymbolForSimpleReference(wixSimpleReferenceRow, messageHandler);
                        if (null == symbol)
                        {
                            if (null != unresolvedReferences)
                            {
                                unresolvedReferences.Add(new SimpleReferenceSection(section, wixSimpleReferenceRow));
                            }
                        }
                        else
                        {
                            // components are indexed in ResolveComplexReferences
                            if (null != referencedSymbols && null != symbol.Row.TableDefinition.Name && "Component" != symbol.Row.TableDefinition.Name && !referencedSymbols.Contains(symbol.Name))
                            {
                                referencedSymbols.Add(symbol.Name);
                            }

                            RecursivelyResolveReferences(symbol.Section, outputType, allSymbols, sections, referencedSymbols, unresolvedReferences, messageHandler);
                        }
                    }
                }
            }
        }
Пример #12
0
 /// <summary>
 /// Instantiate a new Library.
 /// </summary>
 public Library()
 {
     this.localizations = new Hashtable();
     this.sections      = new SectionCollection();
 }
Пример #13
0
        /// <summary>
        /// Recursive helper function to resolve all references of passed in section.
        /// </summary>
        /// <param name="section">Section with references to resolve.</param>
        /// <param name="outputType">Parent output type that will get the resolved section collection.</param>
        /// <param name="allSymbols">All symbols that can be used to resolve section's references.</param>
        /// <param name="sections">Collection to add sections to during processing.</param>
        /// <param name="referencedSymbols">Collection populated during resolution of all symbols referenced during linking.</param>
        /// <param name="unresolvedReferences">Collection populated during resolution of all references that are left unresolved.</param>
        /// <param name="messageHandler">Message handler to report any duplicate symbols that may be tripped across.</param>
        /// <remarks>Note: recursive function.</remarks>
        private static void RecursivelyResolveReferences(
            Section section,
            OutputType outputType,
            SymbolCollection allSymbols,
            SectionCollection sections,
            StringCollection referencedSymbols,
            ArrayList unresolvedReferences,
            IMessageHandler messageHandler)
        {
            // if we already have this section bail
            if (sections.Contains(section))
            {
                return;
            }

            // add the passed in section to the collection of sections
            sections.Add(section);

            // process all of the references contained in this section using the collection of
            // symbols provided.  Then recursively call this method to process the
            // located symbol's section.  All in all this is a very simple depth-first
            // search of the references per-section
            Table wixSimpleReferenceTable = section.Tables["WixSimpleReference"];
            if (null != wixSimpleReferenceTable)
            {
                foreach (WixSimpleReferenceRow wixSimpleReferenceRow in wixSimpleReferenceTable.Rows)
                {
                    // If we're building a Merge Module, ignore all references to the Media table
                    // because Merge Modules don't have Media tables.
                    if (OutputType.Module == outputType && "Media" == wixSimpleReferenceRow.TableName)
                    {
                        continue;
                    }

                    if ("WixAction" == wixSimpleReferenceRow.TableName)
                    {
                        Symbol[] symbols = allSymbols.GetSymbolsForSimpleReference(wixSimpleReferenceRow);
                        if (0 == symbols.Length)
                        {
                            if (null != unresolvedReferences)
                            {
                                unresolvedReferences.Add(new SimpleReferenceSection(section, wixSimpleReferenceRow));
                            }
                        }
                        else
                        {
                            foreach (Symbol symbol in symbols)
                            {
                                if (null != symbol.Section)
                                {
                                    // components are indexed in ResolveComplexReferences
                                    if (null != referencedSymbols && null != symbol.Row.TableDefinition.Name && "Component" != symbol.Row.TableDefinition.Name && !referencedSymbols.Contains(symbol.Name))
                                    {
                                        referencedSymbols.Add(symbol.Name);
                                    }

                                    RecursivelyResolveReferences(symbol.Section, outputType, allSymbols, sections, referencedSymbols, unresolvedReferences, messageHandler);
                                }
                            }
                        }
                    }
                    else
                    {
                        Symbol symbol = allSymbols.GetSymbolForSimpleReference(wixSimpleReferenceRow, messageHandler);
                        if (null == symbol)
                        {
                            if (null != unresolvedReferences)
                            {
                                unresolvedReferences.Add(new SimpleReferenceSection(section, wixSimpleReferenceRow));
                            }
                        }
                        else
                        {
                            // components are indexed in ResolveComplexReferences
                            if (null != referencedSymbols && null != symbol.Row.TableDefinition.Name && "Component" != symbol.Row.TableDefinition.Name && !referencedSymbols.Contains(symbol.Name))
                            {
                                referencedSymbols.Add(symbol.Name);
                            }

                            RecursivelyResolveReferences(symbol.Section, outputType, allSymbols, sections, referencedSymbols, unresolvedReferences, messageHandler);
                        }
                    }
                }
            }
        }
Пример #14
0
        /// <summary>
        /// Resolves all the simple references in a section.
        /// </summary>
        /// <param name="outputType">Parent output type that will get the resolved section collection.</param>
        /// <param name="allSymbols">Collection of all symbols from loaded intermediates.</param>
        /// <param name="referencedSymbols">Collection populated during resolution of all symbols referenced during linking.</param>
        /// <param name="unresolvedReferences">Collection populated during resolution of all references that are left unresolved.</param>
        /// <param name="messageHandler">Message handler to report any duplicate symbols that may be tripped across.</param>
        /// <returns>The resolved sections.</returns>
        internal SectionCollection ResolveReferences(
            OutputType outputType,
            SymbolCollection allSymbols,
            StringCollection referencedSymbols,
            ArrayList unresolvedReferences,
            IMessageHandler messageHandler)
        {
            SectionCollection sections = new SectionCollection();

            RecursivelyResolveReferences(this, outputType, allSymbols, sections, referencedSymbols, unresolvedReferences, messageHandler);
            return sections;
        }
Пример #15
0
        /// <summary>
        /// Validate that a library contains one entry section and no duplicate symbols.
        /// </summary>
        /// <param name="messageHandler">Message handler for errors.</param>
        /// <param name="library">Library to validate.</param>
        private void Validate(IMessageHandler messageHandler, Library library)
        {
            Section entrySection;
            SymbolCollection allSymbols;

            ArrayList intermediates = new ArrayList();
            SectionCollection sections = new SectionCollection();

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

            intermediates.AddRange(library.Intermediates);
            Common.FindEntrySectionAndLoadSymbols((Intermediate[])intermediates.ToArray(typeof(Intermediate)), false, this, out entrySection, out allSymbols);

            foreach (Intermediate intermediate in library.Intermediates)
            {
                foreach (Section section in intermediate.Sections)
                {
                    Common.ResolveReferences(OutputType.Unknown, sections, section, allSymbols, referencedSymbols, unresolvedReferences, this);
                }
            }
        }
Пример #16
0
        /// <summary>
        /// Create a library by combining several intermediates (objects).
        /// </summary>
        /// <param name="sections">The sections to combine into a library.</param>
        /// <returns>Returns the new library.</returns>
        public Library Combine(SectionCollection sections)
        {
            Library library = new Library();

            library.Sections.AddRange(sections);

            // check for multiple entry sections and duplicate symbols
            this.Validate(library);

            return (this.encounteredError ? null : library);
        }
Пример #17
0
 /// <summary>
 /// Instantiate a new Intermediate.
 /// </summary>
 public Intermediate()
 {
     this.sections = new SectionCollection();
 }
Пример #18
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;
                    }
                }
            }
        }
Пример #19
0
        /// <summary>
        /// Creates a new output object with the specified entry section.
        /// </summary>
        /// <param name="entrySection">Entry section for the output.</param>
        internal Output(Section entrySection)
            : this()
        {
            this.entrySection = entrySection;
            this.sections = new SectionCollection();
            this.codepage = entrySection.Codepage;

            switch (this.entrySection.Type)
            {
                case SectionType.Product:
                    this.type = OutputType.Product;
                    this.compressed = false;
                    break;
                case SectionType.Module:
                    this.type = OutputType.Module;
                    this.compressed = true;
                    break;
                case SectionType.PatchCreation:
                    this.type = OutputType.PatchCreation;
                    this.compressed = false;
                    break;
                default:
                    throw new ApplicationException(String.Format("Unexpected entry section type: {0}", this.entrySection.Type));
            }
        }