/// <summary> /// Parse ignore modularization data from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> private static void ParseIgnoreModularization(Intermediate intermediate, XmlReader reader, Section section) { bool empty = reader.IsEmptyElement; string name = null; string type = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "name": name = reader.Value; break; case "type": type = reader.Value; break; } } if (null == name) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Reference missing required attribute: 'name'"); } if (null == type) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Reference missing required attribute: 'type'"); } if (!empty && reader.Read() && XmlNodeType.EndElement != reader.MoveToContent()) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected content while processing 'ignoreModularization': {0}", reader.NodeType.ToString())); } section.IgnoreModularizations.Add(new IgnoreModularization(name, type)); }
/// <summary> /// Parse a reference from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> private static void ParseReference(Intermediate intermediate, XmlReader reader, Section section) { bool empty = reader.IsEmptyElement; string id = null; string table = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "symbol": id = reader.Value; break; case "table": table = reader.Value; break; } } if (null == table) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Reference missing required attribute: 'table'"); } if (null == id) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Reference missing required attribute: 'id'"); } if (!empty && reader.Read() && XmlNodeType.EndElement != reader.MoveToContent()) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected content while processing 'reference': {0}", reader.NodeType.ToString())); } section.References.Add(new Reference(table, id)); }
/// <summary> /// Loads an intermediate from a XmlReader in memory. /// </summary> /// <param name="reader">XmlReader with intermediate persisted as Xml.</param> /// <param name="path">Path to intermediate file saved on disk.</param> /// <param name="tableDefinitions">Collection containing TableDefinitions to use when reconstituting the intermediate.</param> /// <param name="suppressVersionCheck">Suppresses wix.dll version mismatch check.</param> /// <returns>Returns the loaded intermediate.</returns> /// <remarks>This method will set the SourcePath property to the appropriate values on successful load, but will not update the Path property.</remarks> public static Intermediate Load(XmlReader reader, string path, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { Intermediate intermediate = new Intermediate(); intermediate.path = path; ParseIntermediate(intermediate, reader, tableDefinitions, suppressVersionCheck); return(intermediate); }
/// <summary> /// Parse a table from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> private static void ParseTable(Intermediate intermediate, XmlReader reader, Section section, TableDefinitionCollection tableDefinitions) { bool empty = reader.IsEmptyElement; string name = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "name": name = reader.Value; break; } } if (null == name) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Table missing required attribute: 'name'"); } if (!empty) { bool done = false; // loop through all the rows (tuples) in a table while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "tuple": ParseTuple(intermediate, reader, section, tableDefinitions[name]); break; default: throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected element while processing 'table': '{0}'", reader.LocalName)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Missing end element while processing 'table'.")); } } }
/// <summary> /// Parse a tuple from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> /// <param name="tableDef">Table definition of the tuple to parse.</param> private static void ParseTuple(Intermediate intermediate, XmlReader reader, Section section, TableDefinition tableDef) { bool empty = reader.IsEmptyElement; SourceLineNumberCollection sourceLineNumbers = null; int field = 0; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "sourceLineNumber": sourceLineNumbers = new SourceLineNumberCollection(reader.Value); break; } } Row row = Common.CreateRowInSection(sourceLineNumbers, section, tableDef); if (!empty) { bool done = false; // loop through all the fields in a row while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "field": row[field] = Field.Parse(reader); ++field; break; default: throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected element while processing 'tuple': '{0}'", reader.LocalName)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Missing end element while processing 'tuple'.")); } } }
/// <summary> /// Creates a new section as part of an intermediate. /// </summary> /// <param name="intermediate">Parent intermediate.</param> /// <param name="id">Identifier for section.</param> /// <param name="type">Type of section.</param> /// <param name="codepage">Codepage for resulting database.</param> public Section(Intermediate intermediate, string id, SectionType type, int codepage) { this.intermediate = intermediate; this.id = id; this.type = type; this.codepage = codepage; this.tables = new TableCollection(); this.references = new ReferenceCollection(); this.ignoreModularizations = new IgnoreModularizationCollection(); this.complexReferences = new ComplexReferenceCollection(); this.featureBacklinks = new FeatureBacklinkCollection(); }
/// <summary> /// Parse the root library element. /// </summary> /// <param name="library">Library to read from disk.</param> /// <param name="reader">XmlReader with library persisted as Xml.</param> /// <param name="tableDefinitions">Collection containing TableDefinitions to use when reconstituting the intermediates.</param> /// <param name="suppressVersionCheck">Suppresses check for wix.dll version mismatch.</param> private static void ParseLibrary(Library library, XmlReader reader, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { // read the document root reader.MoveToContent(); if ("wixLibrary" != reader.LocalName) { throw new WixNotLibraryException(SourceLineNumberCollection.FromFileName(library.Path), String.Format("Invalid root element: '{0}', expected 'wixLibrary'", reader.LocalName)); } Version objVersion = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "version": objVersion = new Version(reader.Value); break; } } if (null != objVersion && !suppressVersionCheck) { Version currentVersion = Common.LibraryFormatVersion; if (0 != currentVersion.CompareTo(objVersion)) { throw new WixVersionMismatchException(currentVersion, objVersion, "Library", library.Path); } } // loop through the rest of the xml building up the SectionCollection while (reader.Read()) { if (0 == reader.Depth) { break; } else if (1 != reader.Depth) { // throw exception since we should only be processing tables throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(library.Path), "Unexpected depth while processing element: 'wixLibrary'"); } if (XmlNodeType.Element == reader.NodeType && "wixObject" == reader.LocalName) { Intermediate intermediate = Intermediate.Load(reader, library.Path, tableDefinitions, suppressVersionCheck); library.intermediates.Add(intermediate); } } }
public override void InspectIntermediate(Intermediate output) { foreach (Section section in output.Sections) { Table fileTable = section.Tables["File"]; if (null != fileTable && 0 < fileTable.Rows.Count) { Row fileRow = fileTable.Rows[0]; this.Core.OnMessage(ValidationWarnings.ExampleWarning(fileRow.SourceLineNumbers)); return; } } this.Core.OnMessage(ValidationErrors.ExampleError()); }
/// <summary> /// Get the schemas required to validate a library. /// </summary> /// <returns>The schemas required to validate a library.</returns> internal static XmlSchemaCollection GetSchemas() { if (null == schemas) { Assembly assembly = Assembly.GetExecutingAssembly(); using (Stream librarySchemaStream = assembly.GetManifestResourceStream("Microsoft.Tools.WindowsInstallerXml.Xsd.libraries.xsd")) { schemas = new XmlSchemaCollection(); schemas.Add(Intermediate.GetSchemas()); schemas.Add(Localization.GetSchemas()); XmlSchema librarySchema = XmlSchema.Read(librarySchemaStream, null); schemas.Add(librarySchema); } } return(schemas); }
/// <summary> /// Get the schemas required to validate an object. /// </summary> /// <returns>The schemas required to validate an object.</returns> internal static XmlSchemaCollection GetSchemas() { lock (lockObject) { if (null == schemas) { Assembly assembly = Assembly.GetExecutingAssembly(); using (Stream outputSchemaStream = assembly.GetManifestResourceStream("Microsoft.Tools.WindowsInstallerXml.Xsd.outputs.xsd")) { schemas = new XmlSchemaCollection(); schemas.Add(Intermediate.GetSchemas()); schemas.Add(TableDefinitionCollection.GetSchemas()); XmlSchema outputSchema = XmlSchema.Read(outputSchemaStream, null); schemas.Add(outputSchema); } } } return(schemas); }
/// <summary> /// Loads an intermediate from a path on disk. /// </summary> /// <param name="path">Path to intermediate file saved on disk.</param> /// <param name="tableDefinitions">Collection containing TableDefinitions to use when reconstituting the intermediate.</param> /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param> /// <returns>Returns the loaded intermediate.</returns> /// <remarks>This method will set the Path and SourcePath properties to the appropriate values on successful load.</remarks> public static Intermediate Load(string path, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { Intermediate intermediate = new Intermediate(); intermediate.Path = path; XmlTextReader reader = null; try { reader = new XmlTextReader(path); ParseIntermediate(intermediate, reader, tableDefinitions, suppressVersionCheck); } finally { if (null != reader) { reader.Close(); } } return(intermediate); }
/// <summary> /// Inspect the compiled output. /// </summary> /// <param name="output">The compiled output.</param> public virtual void InspectIntermediate(Intermediate output) { }
/// <summary> /// Parse an intermediate from an XML format. /// </summary> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatch.</param> /// <returns>The parsed Intermediate.</returns> internal static Intermediate Parse(XmlReader reader, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { Debug.Assert("wixObject" == reader.LocalName); bool empty = reader.IsEmptyElement; Version objVersion = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "version": objVersion = new Version(reader.Value); break; default: if (!reader.NamespaceURI.StartsWith("http://www.w3.org/", StringComparison.Ordinal)) { throw new WixException(WixErrors.UnexpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixObject", reader.Name)); } break; } } if (null != objVersion && !suppressVersionCheck) { if (0 != currentVersion.CompareTo(objVersion)) { throw new WixException(WixErrors.VersionMismatch(SourceLineNumberCollection.FromUri(reader.BaseURI), "object", objVersion.ToString(), currentVersion.ToString())); } } Intermediate intermediate = new Intermediate(); // loop through the rest of the xml building up the SectionCollection if (!empty) { bool done = false; while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "section": intermediate.sections.Add(Section.Parse(reader, tableDefinitions)); break; default: throw new WixException(WixErrors.UnexpectedElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixObject", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixException(WixErrors.ExpectedEndElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixObject")); } } return(intermediate); }
/// <summary> /// Processes an XmlReader and builds up the output object. /// </summary> /// <param name="reader">Reader to get data from.</param> /// <param name="suppressVersionCheck">Suppresses wix.dll version mismatch check.</param> /// <param name="path">The path to display in an error message.</param> /// <returns>The Output represented by the Xml.</returns> private static Output Parse(XmlReader reader, bool suppressVersionCheck, string path) { Debug.Assert("wixOutput" == reader.LocalName); Output output = new Output(); output.path = path; string entrySectionId = null; SectionType sectionType = SectionType.Unknown; Version objVersion = null; bool empty = reader.IsEmptyElement; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "type": switch (reader.Value) { case "Module": output.type = OutputType.Module; sectionType = SectionType.Module; break; case "Product": output.type = OutputType.Product; sectionType = SectionType.Product; break; case "PatchCreation": output.type = OutputType.PatchCreation; sectionType = SectionType.PatchCreation; break; default: throw new WixParseException(String.Format("The wixOutput/@type attribute contains an unexpected value '{0}'.", reader.Value)); } break; case "codepage": output.codepage = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat); break; case "compressed": output.compressed = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "longFileNames": output.longFileNames = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "entrySectionId": entrySectionId = reader.Value; break; case "moduleGuid": output.moduleGuid = reader.Value; break; case "output": output.path = reader.Value; break; case "suppressAdminSequence": output.suppressAdminSequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "suppressAdvertiseSequence": output.suppressAdvertiseSequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "suppressUISequence": output.suppressUISequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "version": objVersion = new Version(reader.Value); break; case "xmlns": break; default: throw new WixParseException(String.Format("The wixOutput element contains an unexpected attribute {0}.", reader.Name)); } } if (null == entrySectionId) { throw new WixParseException("The wixOutput/@entrySectionId attribute was not found; it is required."); } if (null != objVersion && !suppressVersionCheck) { Version currentVersion = Common.OutputFormatVersion; if (0 != currentVersion.CompareTo(objVersion)) { throw new WixVersionMismatchException(currentVersion, objVersion, "Output", output.Path); } } // create a section for all the rows to belong to Intermediate intermediate = new Intermediate(); output.entrySection = new Section(intermediate, entrySectionId, sectionType, output.codepage); // loop through the rest of the xml building up the Output object if (!empty) { bool done = false; // loop through all the fields in a row while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "outputTable": output.outputTables.Add(OutputTable.Parse(reader, output.entrySection)); break; case "importStream": output.importStreams.Add(ImportStream.Parse(reader)); break; case "componentsToFeatures": case "featuresToFeatures": case "modulesToFeatures": ParseConnectToFeatures(output, reader); break; case "merge": ParseMerge(output, reader); break; case "fileMediaInformation": output.fileMediaInfoCollection.Add(FileMediaInformation.Parse(reader)); break; case "media": ParseMedia(output, reader); break; default: throw new WixParseException(String.Format("The wixOutput element contains an unexpected child element {0}.", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixParseException("Missing end element while processing the wixOutput element."); } } return(output); }
/// <summary> /// Parse a feature backlink from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> private static void ParseFeatureBacklink(Intermediate intermediate, XmlReader reader, Section section) { bool empty = reader.IsEmptyElement; string targetSymbol = null; string component = null; FeatureBacklinkType type = FeatureBacklinkType.Unknown; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "targetSymbol": targetSymbol = reader.Value; break; case "component": component = reader.Value; break; case "type": switch (reader.Value) { case "Class": type = FeatureBacklinkType.Class; break; case "Extension": type = FeatureBacklinkType.Extension; break; case "Shortcut": type = FeatureBacklinkType.Shortcut; break; case "PublishComponent": type = FeatureBacklinkType.PublishComponent; break; case "TypeLib": type = FeatureBacklinkType.TypeLib; break; default: throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Invalid FeatureBacklinkType"); } break; } } if (FeatureBacklinkType.Unknown == type) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Unknown FeatureBackLink type"); } if (null == component) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "FeatureBackLink missing required attribute: 'component'"); } if (null == targetSymbol) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "FeatureBackLink missing required attribute: 'targetSymbol'"); } if (!empty && reader.Read() && XmlNodeType.EndElement != reader.MoveToContent()) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected content while processing 'featureBacklink': {0}", reader.NodeType.ToString())); } section.FeatureBacklinks.Add(new FeatureBacklink(component, type, targetSymbol)); }
/// <summary> /// Loads an intermediate from a XmlReader in memory. /// </summary> /// <param name="reader">XmlReader with intermediate persisted as Xml.</param> /// <param name="path">Path to intermediate file saved on disk.</param> /// <param name="tableDefinitions">Collection containing TableDefinitions to use when reconstituting the intermediate.</param> /// <param name="suppressVersionCheck">Suppresses wix.dll version mismatch check.</param> /// <returns>Returns the loaded intermediate.</returns> /// <remarks>This method will set the SourcePath property to the appropriate values on successful load, but will not update the Path property.</remarks> public static Intermediate Load(XmlReader reader, string path, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { Intermediate intermediate = new Intermediate(); intermediate.path = path; ParseIntermediate(intermediate, reader, tableDefinitions, suppressVersionCheck); return intermediate; }
/// <summary> /// Parse a section from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> private static void ParseSection(Intermediate intermediate, XmlReader reader, TableDefinitionCollection tableDefinitions) { Section section = null; string id = null; SectionType type = SectionType.Unknown; int codepage = 0; bool empty = reader.IsEmptyElement; while (reader.MoveToNextAttribute()) { switch (reader.Name) { case "id": id = reader.Value; break; case "type": switch (reader.Value) { case "fragment": type = SectionType.Fragment; break; case "module": type = SectionType.Module; break; case "product": type = SectionType.Product; break; case "patchCreation": type = SectionType.PatchCreation; break; } break; case "codepage": codepage = Convert.ToInt32(reader.Value); break; } } if (SectionType.Unknown == type) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Unknown section type"); } if (null == id && SectionType.Fragment != type) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Section missing required attribute: 'id'"); } section = new Section(intermediate, id, type, codepage); if (!empty) { bool done = false; while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "reference": ParseReference(intermediate, reader, section); break; case "complexReference": ParseComplexReference(intermediate, reader, section); break; case "featureBacklink": ParseFeatureBacklink(intermediate, reader, section); break; case "table": ParseTable(intermediate, reader, section, tableDefinitions); break; case "ignoreModularization": ParseIgnoreModularization(intermediate, reader, section); break; default: throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected element while processing 'section': '{0}'", reader.LocalName)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Missing end element while processing 'section'.")); } } intermediate.Sections.Add(section); }
/// <summary> /// Parse an intermediate from an XML format. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatch.</param> private static void ParseIntermediate(Intermediate intermediate, XmlReader reader, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { // read the document root reader.MoveToContent(); if ("wixObject" != reader.LocalName) { throw new WixNotIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Invalid root element: '{0}', expected 'wixObject'", reader.LocalName)); } bool empty = reader.IsEmptyElement; Version objVersion = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "src": intermediate.SourcePath = reader.Value; break; case "version": objVersion = new Version(reader.Value); break; } } if (null != objVersion && !suppressVersionCheck) { Version currentVersion = Common.IntermediateFormatVersion; if (0 != currentVersion.CompareTo(objVersion)) { throw new WixVersionMismatchException(currentVersion, objVersion, "Intermediate", intermediate.Path); } } // loop through the rest of the xml building up the SectionCollection if (!empty) { bool done = false; while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "section": ParseSection(intermediate, reader, tableDefinitions); break; default: throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected element while processing 'wixObject': '{0}'", reader.LocalName)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Missing end element while processing 'wixObject'.")); } } }
/// <summary> /// Loads an intermediate from a path on disk. /// </summary> /// <param name="path">Path to intermediate file saved on disk.</param> /// <param name="tableDefinitions">Collection containing TableDefinitions to use when reconstituting the intermediate.</param> /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param> /// <returns>Returns the loaded intermediate.</returns> /// <remarks>This method will set the Path and SourcePath properties to the appropriate values on successful load.</remarks> public static Intermediate Load(string path, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { Intermediate intermediate = new Intermediate(); intermediate.Path = path; XmlTextReader reader = null; try { reader = new XmlTextReader(path); ParseIntermediate(intermediate, reader, tableDefinitions, suppressVersionCheck); } finally { if (null != reader) { reader.Close(); } } return intermediate; }
/// <summary> /// Constructor for all compiler core. /// </summary> /// <param name="intermediate">The Intermediate object representing compiled source document.</param> /// <param name="tableDefinitions">The loaded table definition collection.</param> /// <param name="extensions">The WiX extensions collection.</param> /// <param name="messageHandler">The message handler.</param> internal CompilerCore(Intermediate intermediate, TableDefinitionCollection tableDefinitions, Hashtable extensions, MessageEventHandler messageHandler, XmlSchema schema) { this.tableDefinitions = tableDefinitions; this.extensions = extensions; this.intermediate = intermediate; this.MessageHandler = messageHandler; this.schema = schema; }
/// <summary> /// Finds the entry section and loads the symbols from an array of intermediates. /// </summary> /// <param name="intermediates">Array of intermediates to load symbols for and find entry section.</param> /// <param name="allowIdenticalRows">Flag specifying whether identical rows are allowed or not.</param> /// <param name="messageHandler">Message handler object to route all errors through.</param> /// <param name="entrySection">Located entry section.</param> /// <param name="allSymbols">Collection of symbols loaded.</param> internal static void FindEntrySectionAndLoadSymbols( Intermediate[] intermediates, bool allowIdenticalRows, IMessageHandler messageHandler, out Section entrySection, out SymbolCollection allSymbols) { entrySection = null; allSymbols = new SymbolCollection(); for (int i = 0; i < intermediates.Length; ++i) { foreach (Section section in intermediates[i].Sections) { if (SectionType.Product == section.Type || SectionType.Module == section.Type || SectionType.PatchCreation == section.Type) { if (null == entrySection) { entrySection = section; } else { messageHandler.OnMessage(WixErrors.MultipleEntrySections(SourceLineNumberCollection.FromFileName(entrySection.Intermediate.SourcePath), entrySection.Id, section.Id)); messageHandler.OnMessage(WixErrors.MultipleEntrySections2(SourceLineNumberCollection.FromFileName(section.Intermediate.SourcePath))); } } foreach (Symbol symbol in section.GetSymbols(messageHandler)) { try { Symbol existingSymbol = allSymbols[symbol.Name]; if (null == existingSymbol) { allSymbols.Add(symbol); } else if (allowIdenticalRows && existingSymbol.Row.IsIdentical(symbol.Row)) { messageHandler.OnMessage(WixWarnings.IdenticalRowWarning(symbol.Row.SourceLineNumbers, existingSymbol.Name)); messageHandler.OnMessage(WixWarnings.IdenticalRowWarning2(existingSymbol.Row.SourceLineNumbers)); } else { allSymbols.AddDuplicate(symbol); } } catch (DuplicateSymbolsException) { // if there is already a duplicate symbol, just // another to the list, don't bother trying to // see if there are any identical symbols allSymbols.AddDuplicate(symbol); } } } } }
/// <summary> /// Compiles the provided Xml document into an intermediate object /// </summary> /// <param name="source">Source xml document to compile.</param> /// <param name="sourcePath">Optional original path to xml document on disk.</param> /// <returns>Intermediate object representing compiled source document.</returns> /// <remarks>This method is not thread-safe.</remarks> public Intermediate Compile(XmlDocument source, string sourcePath) { if (null == source) { throw new ArgumentNullException("source"); } bool encounteredError = true; // assume we'll hit an error // create the intermediate Intermediate target = new Intermediate(); target.SourcePath = sourcePath; // try to compile it try { this.core = new CompilerCore(target, this.tableDefinitions, this.Message); this.core.PedanticLevel = this.pedanticLevel; this.extensionMessages = new ExtensionMessages(this.core); foreach (CompilerExtension extension in this.extensions.Values) { extension.Core = this.core; extension.Messages = this.extensionMessages; extension.InitializeCompile(); } // parse the document if ("Wix" == source.DocumentElement.LocalName) { this.ParseWixElement(source.DocumentElement); } else { this.core.OnMessage(WixErrors.InvalidDocumentElement(null, source.DocumentElement.Name, "source", "Wix")); } // perform schema validation if there were no errors and validation isn't suppressed if (!this.core.EncounteredError && !this.suppressValidation) { this.ValidateDocument(source); } } finally { encounteredError = this.core.EncounteredError; foreach (CompilerExtension extension in this.extensions.Values) { extension.FinalizeCompile(); extension.Core = null; } this.core = null; } // return the compiled intermediate only if it completed successfully return (encounteredError ? null : target); }
/// <summary> /// Create a library by combining several intermediates (objects). /// </summary> /// <param name="intermediates">Intermediates to combine.</param> /// <returns>Returns the new library.</returns> public Library Combine(Intermediate[] intermediates) { Library library = new Library(); foreach (Intermediate intermediate in intermediates) { library.Intermediates.Add(intermediate); } // check for multiple entry sections and duplicate symbols this.Validate(this, library); return (this.foundError ? null : library); }
/// <summary> /// Processes an XmlReader and builds up the output object. /// </summary> /// <param name="reader">Reader to get data from.</param> /// <param name="suppressVersionCheck">Suppresses wix.dll version mismatch check.</param> /// <param name="path">The path to display in an error message.</param> /// <returns>The Output represented by the Xml.</returns> private static Output Parse(XmlReader reader, bool suppressVersionCheck, string path) { Debug.Assert("wixOutput" == reader.LocalName); Output output = new Output(); output.path = path; string entrySectionId = null; SectionType sectionType = SectionType.Unknown; Version objVersion = null; bool empty = reader.IsEmptyElement; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "type": switch (reader.Value) { case "Module": output.type = OutputType.Module; sectionType = SectionType.Module; break; case "Product": output.type = OutputType.Product; sectionType = SectionType.Product; break; case "PatchCreation": output.type = OutputType.PatchCreation; sectionType = SectionType.PatchCreation; break; default: throw new WixParseException(String.Format("The wixOutput/@type attribute contains an unexpected value '{0}'.", reader.Value)); } break; case "codepage": output.codepage = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture.NumberFormat); break; case "compressed": output.compressed = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "longFileNames": output.longFileNames = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "entrySectionId": entrySectionId = reader.Value; break; case "moduleGuid": output.moduleGuid = reader.Value; break; case "output": output.path = reader.Value; break; case "suppressAdminSequence": output.suppressAdminSequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "suppressAdvertiseSequence": output.suppressAdvertiseSequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "suppressUISequence": output.suppressUISequence = Common.IsYes(reader.Value, null, "wixOutput", reader.Name, null); break; case "version": objVersion = new Version(reader.Value); break; case "xmlns": break; default: throw new WixParseException(String.Format("The wixOutput element contains an unexpected attribute {0}.", reader.Name)); } } if (null == entrySectionId) { throw new WixParseException("The wixOutput/@entrySectionId attribute was not found; it is required."); } if (null != objVersion && !suppressVersionCheck) { Version currentVersion = Common.OutputFormatVersion; if (0 != currentVersion.CompareTo(objVersion)) { throw new WixVersionMismatchException(currentVersion, objVersion, "Output", output.Path); } } // create a section for all the rows to belong to Intermediate intermediate = new Intermediate(); output.entrySection = new Section(intermediate, entrySectionId, sectionType, output.codepage); // loop through the rest of the xml building up the Output object if (!empty) { bool done = false; // loop through all the fields in a row while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "outputTable": output.outputTables.Add(OutputTable.Parse(reader, output.entrySection)); break; case "importStream": output.importStreams.Add(ImportStream.Parse(reader)); break; case "componentsToFeatures": case "featuresToFeatures": case "modulesToFeatures": ParseConnectToFeatures(output, reader); break; case "merge": ParseMerge(output, reader); break; case "fileMediaInformation": output.fileMediaInfoCollection.Add(FileMediaInformation.Parse(reader)); break; case "media": ParseMedia(output, reader); break; default: throw new WixParseException(String.Format("The wixOutput element contains an unexpected child element {0}.", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixParseException("Missing end element while processing the wixOutput element."); } } return output; }
/// <summary> /// Constructor for all compiler core. /// </summary> /// <param name="intermediate">The Intermediate object representing compiled source document.</param> /// <param name="tableDefinitions">The loaded table definition collection.</param> /// <param name="messageHandler">The message handler.</param> internal CompilerCore(Intermediate intermediate, TableDefinitionCollection tableDefinitions, MessageEventHandler messageHandler) { this.tableDefinitions = tableDefinitions; this.intermediate = intermediate; this.MessageHandler = messageHandler; }
/// <summary> /// Parse a complex reference from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> private static void ParseComplexReference(Intermediate intermediate, XmlReader reader, Section section) { bool empty = reader.IsEmptyElement; ComplexReferenceParentType parentType = ComplexReferenceParentType.Unknown; string parentId = null; string parentLanguage = null; ComplexReferenceChildType childType = ComplexReferenceChildType.Unknown; string childId = null; bool primary = false; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "parent": parentId = reader.Value; break; case "parentLanguage": parentLanguage = reader.Value; break; case "parentType": switch (reader.Value) { case "componentGroup": parentType = ComplexReferenceParentType.ComponentGroup; break; case "feature": parentType = ComplexReferenceParentType.Feature; break; case "module": parentType = ComplexReferenceParentType.Module; break; } break; case "child": childId = reader.Value; break; case "childType": switch (reader.Value) { case "component": childType = ComplexReferenceChildType.Component; break; case "componentGroup": childType = ComplexReferenceChildType.ComponentGroup; break; case "feature": childType = ComplexReferenceChildType.Feature; break; case "fragment": childType = ComplexReferenceChildType.Fragment; break; case "module": childType = ComplexReferenceChildType.Module; break; } break; case "primary": primary = Common.IsYes(reader.Value, SourceLineNumberCollection.FromFileName(intermediate.Path), "complexReference", "primary", parentId); break; } } if (ComplexReferenceParentType.Unknown == parentType) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Unknown ComplexReferenceParentType type"); } if (null == parentId) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "ComplexReference missing required attribute: 'parentId'"); } if (ComplexReferenceChildType.Unknown == childType) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Unknown ComplexReferenceChildType type"); } if (null == childId) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "ComplexReference missing required attribute: 'childId'"); } if (!empty && reader.Read() && XmlNodeType.EndElement != reader.MoveToContent()) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected content while processing 'complexReference': {0}", reader.NodeType.ToString())); } section.ComplexReferences.Add(new ComplexReference(parentType, parentId, parentLanguage, childType, childId, primary)); }
/// <summary> /// Parse an intermediate from an XML format. /// </summary> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatch.</param> /// <returns>The parsed Intermediate.</returns> internal static Intermediate Parse(XmlReader reader, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { Debug.Assert("wixObject" == reader.LocalName); bool empty = reader.IsEmptyElement; Version objVersion = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "version": objVersion = new Version(reader.Value); break; default: if (!reader.NamespaceURI.StartsWith("http://www.w3.org/", StringComparison.Ordinal)) { throw new WixException(WixErrors.UnexpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixObject", reader.Name)); } break; } } if (null != objVersion && !suppressVersionCheck) { if (0 != currentVersion.CompareTo(objVersion)) { throw new WixException(WixErrors.VersionMismatch(SourceLineNumberCollection.FromUri(reader.BaseURI), "object", objVersion.ToString(), currentVersion.ToString())); } } Intermediate intermediate = new Intermediate(); // loop through the rest of the xml building up the SectionCollection if (!empty) { bool done = false; while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "section": intermediate.sections.Add(Section.Parse(reader, tableDefinitions)); break; default: throw new WixException(WixErrors.UnexpectedElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixObject", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixException(WixErrors.ExpectedEndElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixObject")); } } return intermediate; }
public Intermediate Compile(XmlDocument source) { if (null == source) { throw new ArgumentNullException("source"); } bool encounteredError = false; // create the intermediate Intermediate target = new Intermediate(); // try to compile it try { this.core = new CompilerCore(target, this.tableDefinitions, this.extensions, this.Message, this.schema); this.core.ShowPedanticMessages = this.showPedanticMessages; this.core.CurrentPlatform = this.currentPlatform; this.core.FipsCompliant = this.fipsCompliant; foreach (CompilerExtension extension in this.extensions.Values) { extension.Core = this.core; extension.InitializeCompile(); } // parse the document SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(source.DocumentElement); if ("Wix" == source.DocumentElement.LocalName) { if (this.schema.TargetNamespace == source.DocumentElement.NamespaceURI) { this.ParseWixElement(source.DocumentElement); } else // invalid or missing namespace { if (0 == source.DocumentElement.NamespaceURI.Length) { this.core.OnMessage(WixErrors.InvalidWixXmlNamespace(sourceLineNumbers, "Wix", this.schema.TargetNamespace)); } else { this.core.OnMessage(WixErrors.InvalidWixXmlNamespace(sourceLineNumbers, "Wix", source.DocumentElement.NamespaceURI, this.schema.TargetNamespace)); } } } else { this.core.OnMessage(WixErrors.InvalidDocumentElement(sourceLineNumbers, source.DocumentElement.Name, "source", "Wix")); } // perform schema validation if there were no errors and validation isn't suppressed if (!this.core.EncounteredError && !this.suppressValidation) { this.ValidateDocument(source); } // inspect the document InspectorCore inspectorCore = new InspectorCore(this.Message); foreach (InspectorExtension inspectorExtension in this.inspectorExtensions) { inspectorExtension.Core = inspectorCore; inspectorExtension.InspectIntermediate(target); // reset inspectorExtension.Core = null; } if (inspectorCore.EncounteredError) { encounteredError = true; } } finally { if (this.core.EncounteredError) { encounteredError = true; } foreach (CompilerExtension extension in this.extensions.Values) { extension.FinalizeCompile(); extension.Core = null; } this.core = null; } // return the compiled intermediate only if it completed successfully return (encounteredError ? null : target); }
/// <summary> /// Add a new intermediate to the collection. /// </summary> /// <param name="intermediate">Intermediate to add to the collection.</param> public void Add(Intermediate intermediate) { collection.Add(intermediate); }
/// <summary> /// Links an array of intermediates into an output. /// </summary> /// <param name="intermediates">Array of intermediates to link together.</param> /// <returns>Output object from the linking.</returns> public Output Link(Intermediate[] intermediates) { Output output = null; try { SymbolCollection allSymbols; Section entrySection; bool containsModuleSubstitution = false; bool containsModuleConfiguration = false; StringCollection referencedSymbols = new StringCollection(); ArrayList unresolvedReferences = new ArrayList(); ConnectToFeatureCollection componentGroupsToFeatures = new ConnectToFeatureCollection(); ConnectToModuleCollection componentGroupsToModules = new ConnectToModuleCollection(); ComplexReferenceCollection componentsToComponentGroupsComplexReferences = new ComplexReferenceCollection(); ConnectToFeatureCollection componentsToFeatures = new ConnectToFeatureCollection(); ConnectToFeatureCollection featuresToFeatures = new ConnectToFeatureCollection(); this.activeOutput = null; this.foundError = false; SortedList adminProperties = new SortedList(); SortedList secureProperties = new SortedList(); SortedList hiddenProperties = new SortedList(); ActionTable requiredActions = new ActionTable(); RowCollection suppressActionRows = new RowCollection(); TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection(); RowCollection customRows = new RowCollection(); foreach (SchemaExtension extension in this.extensions.Values) { extension.Messages = this.extensionMessages; } // first find the entry section and create the symbols hash for all // the sections in all the intermediates Common.FindEntrySectionAndLoadSymbols(intermediates, this.allowIdenticalRows, this, out entrySection, out allSymbols); // should have found an entry section by now if (null == entrySection) { this.OnMessage(WixErrors.MissingEntrySection()); return null; } // add the standard action symbols to the entry section's symbol table this.LoadStandardActionSymbols(allSymbols, entrySection, this.standardActions); // now that we know where we're starting from, create the output object output = new Output(entrySection); // Note: this entry section will get added to the output section collection later if (null != this.localizer && -1 != this.localizer.Codepage) { output.Codepage = this.localizer.Codepage; } this.activeOutput = output; // resolve the symbol references to find the set of sections we // care about then resolve complex references in those sections Common.ResolveReferences(output.Type, output.Sections, output.EntrySection, allSymbols, referencedSymbols, unresolvedReferences, this); this.ProcessComplexReferences(output, output.Sections, referencedSymbols, componentsToComponentGroupsComplexReferences, componentGroupsToFeatures, componentGroupsToModules, componentsToFeatures, featuresToFeatures); for (int i = 0; i < unresolvedReferences.Count; ++i) { Common.ReferenceSection referenceSection = (Common.ReferenceSection)unresolvedReferences[i]; if (this.allowUnresolvedReferences) { this.OnMessage(WixWarnings.UnresolvedReferenceWarning(SourceLineNumberCollection.FromFileName(referenceSection.section.Intermediate.SourcePath), referenceSection.section.Type.ToString(), referenceSection.section.Id, referenceSection.reference.SymbolicName)); } else { this.OnMessage(WixErrors.UnresolvedReference(SourceLineNumberCollection.FromFileName(referenceSection.section.Intermediate.SourcePath), referenceSection.section.Type.ToString(), referenceSection.section.Id, referenceSection.reference.SymbolicName)); } } if (this.foundError) { return null; } this.ResolveComponentGroups(output, referencedSymbols, componentsToComponentGroupsComplexReferences, componentGroupsToFeatures, componentGroupsToModules, componentsToFeatures); this.FindOrphanedSymbols(referencedSymbols); // resolve the feature backlink for each section then update the feature to feature connects this.ResolveFeatureBacklinks(output, componentsToFeatures, allSymbols, referencedSymbols, unresolvedReferences); this.ResolveFeatureToFeatureConnects(featuresToFeatures, allSymbols, referencedSymbols, unresolvedReferences); // create a Hashtable of all the suppressed sequence types Hashtable suppressedSequenceTypes = new Hashtable(); // create a Hashtable of all the suppressed standard actions Hashtable suppressedStandardActions = new Hashtable(); if (this.suppressAdminSequence) { suppressedSequenceTypes[SequenceType.adminExecute] = null; suppressedSequenceTypes[SequenceType.adminUI] = null; } if (this.suppressAdvertiseSequence) { suppressedSequenceTypes[SequenceType.advertiseExecute] = null; } if (this.suppressUISequence) { suppressedSequenceTypes[SequenceType.adminUI] = null; suppressedSequenceTypes[SequenceType.installUI] = null; } // start generating OutputTables and OutputRows for all the sections in the output RowCollection ensureTableRows = new RowCollection(); foreach (Section section in this.activeOutput.Sections) { // add this sections list of identifiers to ignore modularization this.activeOutput.IgnoreModularizations.Add(section.IgnoreModularizations); foreach (Table table in section.Tables) { bool copyRows = !table.Definition.IsUnreal; // by default, copy rows if the table is not unreal // handle special tables switch (table.Name) { case "Actions": foreach (Row row in table.Rows) { SequenceType sequenceType; string seqType = (string)row[0]; string id = (string)row[1]; int sequence = null == row[3] ? 0 : Convert.ToInt32(row[3]); bool suppress = 1 == Convert.ToInt32(row[6]); switch (seqType) { case "AdminUISequence": sequenceType = SequenceType.adminUI; break; case "AdminExecuteSequence": sequenceType = SequenceType.adminExecute; break; case "AdvertiseExecuteSequence": sequenceType = SequenceType.advertiseExecute; break; case "InstallExecuteSequence": sequenceType = SequenceType.installExecute; break; case "InstallUISequence": sequenceType = SequenceType.installUI; break; default: throw new WixInvalidSequenceTypeException(null, seqType); } if (suppressedSequenceTypes.Contains(sequenceType)) { this.OnMessage(WixWarnings.SuppressAction(id, Action.SequenceTypeToString(sequenceType))); continue; } // create a SuppressAction row to allow suppressing the action from a merge module if (suppress) { Row suppressActionRow = new Row(row.SourceLineNumbers, this.tableDefinitions["SuppressAction"]); if ("AdvertiseExecuteSequence" == (string)row[0]) { suppressActionRow[0] = "AdvtExecuteSequence"; } else { suppressActionRow[0] = row[0]; } suppressActionRow[1] = row[1]; suppressActionRows.Add(suppressActionRow); } Action action = this.standardActions[sequenceType, id]; string beforeAction = (string)row[4]; string afterAction = (string)row[5]; // if this is not a standard action or there is a before or after action specified if (null == action || null != beforeAction || null != afterAction) { action = new Action(sequenceType, id, (string)row[2], sequence, beforeAction, afterAction); requiredActions.Add(action, true); // add the action and overwrite even if it already exists since this is a customization // if the parent action is a standard action add it to the required list string parentActionName = null != beforeAction ? beforeAction : afterAction; Action parentAction = this.standardActions[sequenceType, parentActionName]; if (null != parentAction) { requiredActions.Add(parentAction); } } else if (!suppress) // must have a standard action that is being overriden (when not suppressed) { action.Condition = (string)row[2]; if (0 != sequence) // if the user specified a sequence number, override the default { action.SequenceNumber = sequence; } requiredActions.Add(action, true); // ensure this action is in the required list } // action was suppressed by user if (suppress && null != action) { suppressedStandardActions[String.Concat(action.SequenceType.ToString(), id)] = action; } } break; case "AppSearch": Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Signature"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "AppSearch"]); requiredActions.Add(this.standardActions[SequenceType.installUI, "AppSearch"]); break; case "Binary": case "Icon": case "MsiDigitalCertificate": foreach (Row row in table.Rows) { ImportStreamType importStreamType = ImportStreamType.Unknown; switch (table.Name) { case "Binary": importStreamType = ImportStreamType.Binary; break; case "Icon": importStreamType = ImportStreamType.Icon; break; case "MsiDigitalCertificate": importStreamType = ImportStreamType.DigitalCertificate; break; } ImportStream importStream = new ImportStream(importStreamType, row[0].ToString(), row[1].ToString()); if (this.activeOutput.ImportStreams.Contains(importStream.Name)) { this.OnMessage(WixErrors.DuplicateSymbol(row.SourceLineNumbers, String.Format("{0} element with Id='{1}' is defined multiple times.", table.Name, row.Symbol.Name))); } this.activeOutput.ImportStreams.Add(importStream); } Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions[table.Name]); copyRows = false; break; case "BindImage": requiredActions.Add(this.standardActions[SequenceType.installExecute, "BindImage"]); break; case "CCPSearch": requiredActions.Add(this.standardActions[SequenceType.installExecute, "AppSearch"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "CCPSearch"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RMCCPSearch"]); requiredActions.Add(this.standardActions[SequenceType.installUI, "AppSearch"]); requiredActions.Add(this.standardActions[SequenceType.installUI, "CCPSearch"]); requiredActions.Add(this.standardActions[SequenceType.installUI, "RMCCPSearch"]); break; case "Class": requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterClassInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterClassInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterClassInfo"]); break; case "Complus": requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterComPlus"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterComPlus"]); break; case "CreateFolder": requiredActions.Add(this.standardActions[SequenceType.installExecute, "CreateFolders"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveFolders"]); break; case "CustomAction": if (OutputType.Module == this.activeOutput.Type) { Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminExecuteSequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminUISequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdvtExecuteSequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallExecuteSequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallUISequence"]); } break; case "CustomTables": foreach (Row row in table.Rows) { TableDefinition customTable = new TableDefinition((string)row[0], false); if (null == row[4]) { this.OnMessage(WixErrors.ExpectedAttribute(row.SourceLineNumbers, "CustomTable/Column", "PrimaryKey")); } string[] columnNames = row[2].ToString().Split(tabCharacter); string[] columnTypes = row[3].ToString().Split(tabCharacter); string[] primaryKeys = row[4].ToString().Split(tabCharacter); string[] minValues = row[5] == null ? null : row[5].ToString().Split(tabCharacter); string[] maxValues = row[6] == null ? null : row[6].ToString().Split(tabCharacter); string[] keyTables = row[7] == null ? null : row[7].ToString().Split(tabCharacter); string[] keyColumns = row[8] == null ? null : row[8].ToString().Split(tabCharacter); string[] categories = row[9] == null ? null : row[9].ToString().Split(tabCharacter); string[] sets = row[10] == null ? null : row[10].ToString().Split(tabCharacter); string[] descriptions = row[11] == null ? null : row[11].ToString().Split(tabCharacter); string[] modularizations = row[12] == null ? null : row[12].ToString().Split(tabCharacter); int currentPrimaryKey = 0; for (int i = 0; i < columnNames.Length; ++i) { string name = columnNames[i]; ColumnType type = ColumnType.Unknown; switch (columnTypes[i].Substring(0, 1).ToLower(CultureInfo.InvariantCulture)) { case "s": type = ColumnType.String; break; case "l": type = ColumnType.Localized; break; case "i": type = ColumnType.Number; break; case "g": type = ColumnType.Object; break; default: throw new ApplicationException(String.Format("Unknown custom table column type: {0}", columnTypes[i])); } bool nullable = columnTypes[i].Substring(0, 1) == columnTypes[i].Substring(0, 1).ToUpper(CultureInfo.InvariantCulture); int length = Convert.ToInt32(columnTypes[i].Substring(1)); bool primaryKey = false; if (currentPrimaryKey < primaryKeys.Length && primaryKeys[currentPrimaryKey] == columnNames[i]) { primaryKey = true; currentPrimaryKey++; } bool minValSet = null != minValues && null != minValues[i] && 0 < minValues[i].Length; int minValue = 0; if (minValSet) { minValue = Convert.ToInt32(minValues[i]); } bool maxValSet = null != maxValues && null != maxValues[i] && 0 < maxValues[i].Length; int maxValue = 0; if (maxValSet) { maxValue = Convert.ToInt32(maxValues[i]); } bool keyColumnSet = null != keyColumns && null != keyColumns[i] && 0 < keyColumns[i].Length; int keyColumn = 0; if (keyColumnSet) { keyColumn = Convert.ToInt32(keyColumns[i]); } ColumnCategory category = ColumnCategory.Unknown; if (null != categories && null != categories[i] && 0 < categories[i].Length) { switch (categories[i]) { case "Text": category = ColumnCategory.Text; break; case "UpperCase": category = ColumnCategory.UpperCase; break; case "LowerCase": category = ColumnCategory.LowerCase; break; case "Integer": category = ColumnCategory.Integer; break; case "DoubleInteger": category = ColumnCategory.DoubleInteger; break; case "TimeDate": category = ColumnCategory.TimeDate; break; case "Identifier": category = ColumnCategory.Identifier; break; case "Property": category = ColumnCategory.Property; break; case "Filename": category = ColumnCategory.Filename; break; case "WildCardFilename": category = ColumnCategory.WildCardFilename; break; case "Path": category = ColumnCategory.Path; break; case "Paths": category = ColumnCategory.Paths; break; case "AnyPath": category = ColumnCategory.AnyPath; break; case "DefaultDir": category = ColumnCategory.DefaultDir; break; case "RegPath": category = ColumnCategory.RegPath; break; case "Formatted": category = ColumnCategory.Formatted; break; case "Template": category = ColumnCategory.Template; break; case "Condition": category = ColumnCategory.Condition; break; case "Guid": category = ColumnCategory.Guid; break; case "Version": category = ColumnCategory.Version; break; case "Language": category = ColumnCategory.Language; break; case "Binary": category = ColumnCategory.Binary; break; case "CustomSource": category = ColumnCategory.CustomSource; break; case "Cabinet": category = ColumnCategory.Cabinet; break; case "Shortcut": category = ColumnCategory.Shortcut; break; default: break; } } string keyTable = keyTables != null ? keyTables[i] : null; string setValue = sets != null ? sets[i] : null; string description = descriptions != null ? descriptions[i] : null; string modString = modularizations != null ? modularizations[i] : null; ColumnModularizeType modularization = ColumnModularizeType.None; if (modString != null) { switch (modString) { case "None": modularization = ColumnModularizeType.None; break; case "Column": modularization = ColumnModularizeType.Column; break; case "Property": modularization = ColumnModularizeType.Property; break; case "Condition": modularization = ColumnModularizeType.Condition; break; case "CompanionFile": modularization = ColumnModularizeType.CompanionFile; break; case "SemicolonDelimited": modularization = ColumnModularizeType.SemicolonDelimited; break; } } ColumnDefinition columnDefinition = new ColumnDefinition(name, type, length, primaryKey, false, nullable, modularization, false, ColumnType.Localized == type, minValSet, minValue, maxValSet, maxValue, keyTable, keyColumnSet, keyColumn, category, setValue, description, true, true); customTable.Columns.Add(columnDefinition); } customTableDefinitions.Add(customTable); } copyRows = false; // we've created table definitions from these rows, no need to process them any longer break; case "RowData": foreach (Row row in table.Rows) { customRows.Add(row); } copyRows = false; break; case "Dialog": Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ListBox"]); break; case "Directory": foreach (Row row in table.Rows) { if (OutputType.Module == this.activeOutput.Type && Common.IsStandardDirectory(row[0].ToString())) { // if the directory table contains references to standard windows folders // mergemod.dll will add customactions to set the MSM directory to // the same directory as the standard windows folder and will add references to // custom action to all the standard sequence tables. A problem will occur // if the MSI does not have these tables as mergemod.dll does not add these // tables to the MSI if absent. This code adds the tables in case mergemod.dll // needs them. Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["CustomAction"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminExecuteSequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminUISequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdvtExecuteSequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallExecuteSequence"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallUISequence"]); break; // no need to look here any more, we already found all that we needed to } } break; case "DuplicateFile": requiredActions.Add(this.standardActions[SequenceType.installExecute, "DuplicateFiles"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveDuplicateFiles"]); break; case "EnsureTables": foreach (Row row in table.Rows) { ensureTableRows.Add(row); } break; case "Environment": requiredActions.Add(this.standardActions[SequenceType.installExecute, "WriteEnvironmentStrings"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveEnvironmentStrings"]); break; case "Extension": requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterExtensionInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterExtensionInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterExtensionInfo"]); break; case "File": foreach (FileRow row in table.Rows) { // DiskId is not valid when creating a module, so set it to // 0 for all files to ensure proper sorting in the binder if (OutputType.Module == this.activeOutput.Type) { row.DiskId = 0; } // if we have an assembly, insert the MsiAssembly row and assembly actions if (FileAssemblyType.NotAnAssembly != row.AssemblyType) { string feature; if (OutputType.Module == output.Type) { feature = Guid.Empty.ToString("B"); } else { ConnectToFeature connect = componentsToFeatures[row.Component]; if (null == connect) { throw new WixMissingFeatureException(row.SourceLineNumbers, new FeatureBacklink(row.Component, FeatureBacklinkType.Assembly, row.File)); } feature = connect.PrimaryFeature; } OutputTable assemblyOutputTable = Common.EnsureOutputTable(output, this.tableDefinitions["MsiAssembly"]); Row assemblyRow = new Row(assemblyOutputTable.TableDefinition); assemblyRow[0] = row.Component; assemblyRow[1] = feature; assemblyRow[2] = row.AssemblyManifest; assemblyRow[3] = row.AssemblyApplication; assemblyRow[4] = Convert.ToInt32(row.AssemblyType); assemblyOutputTable.OutputRows.Add(new OutputRow(assemblyRow, this.sectionIdOnTuples ? section.Id : null)); requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "MsiPublishAssemblies"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiPublishAssemblies"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiUnpublishAssemblies"]); } if (null == row.Source) // source to the file must be provided { this.OnMessage(WixErrors.FileSourceRequired(row.SourceLineNumbers, row.File)); } this.activeOutput.FileMediaInformationCollection.Add(new FileMediaInformation(row)); } requiredActions.Add(this.standardActions[SequenceType.installExecute, "InstallFiles"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveFiles"]); break; case "Font": requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterFonts"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterFonts"]); break; case "IniFile": case "RemoveIniFile": requiredActions.Add(this.standardActions[SequenceType.installExecute, "WriteIniValues"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveIniValues"]); break; case "IsolatedComponent": requiredActions.Add(this.standardActions[SequenceType.installExecute, "IsolateComponents"]); break; case "LaunchCondition": requiredActions.Add(this.standardActions[SequenceType.installExecute, "LaunchConditions"]); requiredActions.Add(this.standardActions[SequenceType.installUI, "LaunchConditions"]); break; case "Media": foreach (MediaRow row in table.Rows) { this.activeOutput.MediaRows.Add(row); } copyRows = false; break; case "Merge": // just copy the rows to the output copyRows = true; break; case "MIME": requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterMIMEInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterMIMEInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterMIMEInfo"]); break; case "ModuleSignature": if (OutputType.Module == this.activeOutput.Type) { foreach (Row row in table.Rows) { if (null != this.activeOutput.ModularizationGuid) { throw new ArgumentOutOfRangeException("Unexpected number of rows found in table", "ModuleSignature"); } this.activeOutput.ModularizationGuid = row[3].ToString(); } } break; case "ModuleSubstitution": containsModuleSubstitution = true; break; case "ModuleConfiguration": containsModuleConfiguration = true; break; case "MoveFile": requiredActions.Add(this.standardActions[SequenceType.installExecute, "MoveFiles"]); break; case "MsiAssembly": requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "MsiPublishAssemblies"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiPublishAssemblies"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "MsiUnpublishAssemblies"]); break; case "ODBCDataSource": case "ODBCTranslator": case "ODBCDriver": requiredActions.Add(this.standardActions[SequenceType.installExecute, "SetODBCFolders"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "InstallODBC"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveODBC"]); break; case "ProgId": requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "RegisterProgIdInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterProgIdInfo"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterProgIdInfo"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Extension"]); // Extension table is required with a ProgId table break; case "Property": foreach (PropertyRow row in table.Rows) { // if there is no value in the property, then it must be virtual if (null == row.Value || 0 == row.Value.Length) { row.IsUnreal = true; } if (row.Admin) { adminProperties[row.Id] = null; } if (row.Secure) { secureProperties[row.Id] = null; } if (row.Hidden) { hiddenProperties[row.Id] = null; } } break; case "PublishComponent": requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "PublishComponents"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "PublishComponents"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnpublishComponents"]); break; case "Registry": requiredActions.Add(this.standardActions[SequenceType.installExecute, "WriteRegistryValues"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveRegistryValues"]); break; case "RemoveFile": requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveFiles"]); break; case "SelfReg": requiredActions.Add(this.standardActions[SequenceType.installExecute, "SelfRegModules"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "SelfUnregModules"]); break; case "ServiceControl": requiredActions.Add(this.standardActions[SequenceType.installExecute, "StartServices"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "StopServices"]); break; case "ServiceInstall": requiredActions.Add(this.standardActions[SequenceType.installExecute, "InstallServices"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "DeleteServices"]); break; case "Shortcut": requiredActions.Add(this.standardActions[SequenceType.advertiseExecute, "CreateShortcuts"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "CreateShortcuts"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "RemoveShortcuts"]); break; case "TypeLib": requiredActions.Add(this.standardActions[SequenceType.installExecute, "RegisterTypeLibraries"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "UnregisterTypeLibraries"]); break; case "Upgrade": { requiredActions.Add(this.standardActions[SequenceType.installExecute, "FindRelatedProducts"]); requiredActions.Add(this.standardActions[SequenceType.installExecute, "MigrateFeatureStates"]); requiredActions.Add(this.standardActions[SequenceType.installUI, "FindRelatedProducts"]); requiredActions.Add(this.standardActions[SequenceType.installUI, "MigrateFeatureStates"]); foreach (UpgradeRow row in table.Rows) { // this should never happen because candle will make sure that all UpgradeVersion(s) have an ActionProperty...but still don't let it slide if (null == row.ActionProperty) { this.OnMessage(WixErrors.ExpectedAttribute(row.SourceLineNumbers, "UpgradeVersion", "ActionProperty")); } secureProperties[row.ActionProperty] = null; } break; } case "_SummaryInformation": // if we are processing a product, reach into the summary // information and pull out the bits that say if the layout // image is supposed to have long file names and is compressed if (OutputType.Product == output.Type) { foreach (Row row in table.Rows) { // we're looking for the "Word Count" property which happens to // be number 15 (and I thought the answer to the universe was 42, heh). if ("15" == row[0].ToString()) { output.LongFileNames = (0 == (Convert.ToInt32(row[1]) & 1)); output.Compressed = (2 == (Convert.ToInt32(row[1]) & 2)); break; // we're done looking for what we came looking for } } } break; } if (copyRows) { OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions[table.Name]); this.CopyTableRowsToOutputTable(table, outputTable, section.Id); } } } if (0 < ensureTableRows.Count) { foreach (Row row in ensureTableRows) { string tableId = (string)row[0]; TableDefinition tableDef = null; try { tableDef = this.tableDefinitions[tableId]; } catch (WixMissingTableDefinitionException) { tableDef = customTableDefinitions[tableId]; } Common.EnsureOutputTable(this.activeOutput, tableDef); } } // copy all the suppress action rows to the output to suppress actions from merge modules if (0 < suppressActionRows.Count) { OutputTable suppressActionOutputTable = new OutputTable(this.tableDefinitions["SuppressAction"]); this.activeOutput.OutputTables.Add(suppressActionOutputTable); foreach (Row suppressActionRow in suppressActionRows) { suppressActionOutputTable.OutputRows.Add(new OutputRow(suppressActionRow)); } } foreach (Action suppressedAction in suppressedStandardActions.Values) { if (requiredActions.Contains(suppressedAction)) { // We thought they really ought to have a standard action // that they wanted to suppress, so warn them and remove it this.OnMessage(WixWarnings.SuppressAction(suppressedAction.Id, Action.SequenceTypeToString(suppressedAction.SequenceType))); requiredActions.Remove(suppressedAction); } } // check for missing table and add them or display an error as appropriate switch (this.activeOutput.Type) { case OutputType.Module: Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Component"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Directory"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["FeatureComponents"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["File"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleComponents"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleSignature"]); break; case OutputType.PatchCreation: OutputTable imageFamiliesTable = this.activeOutput.OutputTables["ImageFamilies"]; OutputTable targetImagesTable = this.activeOutput.OutputTables["TargetImages"]; OutputTable upgradedImagesTable = this.activeOutput.OutputTables["UpgradedImages"]; if (null == imageFamiliesTable || 1 > imageFamiliesTable.OutputRows.Count) { this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("ImageFamilies")); } if (null == targetImagesTable || 1 > targetImagesTable.OutputRows.Count) { this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("TargetImages")); } if (null == upgradedImagesTable || 1 > upgradedImagesTable.OutputRows.Count) { this.OnMessage(WixErrors.ExpectedRowInPatchCreationPackage("UpgradedImages")); } Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Properties"]); break; case OutputType.Product: // AdminExecuteSequence Table this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "CostInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "CostInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "FileCost"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "CostFinalize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallValidate"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallFiles"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallAdminPackage"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminExecute, "InstallFinalize"]); // AdminUISequence Table this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "CostInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "FileCost"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "CostFinalize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.adminUI, "ExecuteAction"]); // AdvtExecuteSequence Table this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "CostInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "CostFinalize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "InstallValidate"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "InstallInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "PublishFeatures"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "PublishProduct"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.advertiseExecute, "InstallFinalize"]); // InstallExecuteSequence Table this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "ValidateProductID"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "CostInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "FileCost"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "CostFinalize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "InstallValidate"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "InstallInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "ProcessComponents"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "UnpublishFeatures"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "CostInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "RegisterUser"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "RegisterProduct"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "PublishFeatures"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "PublishProduct"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installExecute, "InstallFinalize"]); // InstallUISequence Table this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "ValidateProductID"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "CostInitialize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "FileCost"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "CostFinalize"]); this.AddIfNotSuppressed(requiredActions, suppressedStandardActions, this.standardActions[SequenceType.installUI, "ExecuteAction"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["File"]); Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Media"]); break; } // check for illegal tables foreach (OutputTable table in this.activeOutput.OutputTables) { switch (this.activeOutput.Type) { case OutputType.Module: if ("BBControl" == table.Name || "Billboard" == table.Name || "CCPSearch" == table.Name || "Feature" == table.Name || "LaunchCondition" == table.Name || "Media" == table.Name || "Merge" == table.Name || "Patch" == table.Name || "Upgrade" == table.Name) { foreach (OutputRow outputRow in table.OutputRows) { this.OnMessage(WixErrors.UnexpectedTableInMergeModule(outputRow.Row.SourceLineNumbers, table.Name)); } } else if ("Error" == table.Name) { foreach (OutputRow outputRow in table.OutputRows) { this.OnMessage(WixWarnings.DangerousTableInMergeModule(outputRow.Row.SourceLineNumbers, table.Name)); } } break; case OutputType.PatchCreation: if ("_SummaryInformation" != table.Name && "ExternalFiles" != table.Name && "FamilyFileRanges" != table.Name && "ImageFamilies" != table.Name && "PatchMetadata" != table.Name && "PatchSequence" != table.Name && "Properties" != table.Name && "TargetFiles_OptionalData" != table.Name && "TargetImages" != table.Name && "UpgradedFiles_OptionalData" != table.Name && "UpgradedFilesToIgnore" != table.Name && "UpgradedImages" != table.Name) { foreach (OutputRow outputRow in table.OutputRows) { this.OnMessage(WixErrors.UnexpectedTableInPatchCreationPackage(outputRow.Row.SourceLineNumbers, table.Name)); } } break; case OutputType.Product: if ("ModuleAdminExecuteSequence" == table.Name || "ModuleAdminUISequence" == table.Name || "ModuleAdvtExecuteSequence" == table.Name || "ModuleAdvtUISequence" == table.Name || "ModuleComponents" == table.Name || "ModuleConfiguration" == table.Name || "ModuleDependency" == table.Name || "ModuleExclusion" == table.Name || "ModuleIgnoreTable" == table.Name || "ModuleInstallExecuteSequence" == table.Name || "ModuleInstallUISequence" == table.Name || "ModuleSignature" == table.Name || "ModuleSubstitution" == table.Name) { foreach (OutputRow outputRow in table.OutputRows) { this.OnMessage(WixWarnings.UnexpectedTableInProduct(outputRow.Row.SourceLineNumbers, table.Name)); } } break; } } // add the custom row data foreach (Row row in customRows) { TableDefinition customTable = (TableDefinition)customTableDefinitions[row[0].ToString()]; string[] data = row[2].ToString().Split(tabCharacter); Row customRow = new Row(customTable); for (int i = 0; i < data.Length; ++i) { string[] item = data[i].Split(colonCharacter, 2); customRow.SetData(item[0], item[1]); } bool dataErrors = false; for (int i = 0; i < customTable.Columns.Count; ++i) { if (!customTable.Columns[i].IsNullable && customRow.IsColumnEmpty(i)) { this.OnMessage(WixErrors.NoDataForColumn(row.SourceLineNumbers, customTable.Columns[i].Name, customTable.Name)); dataErrors = true; } } if (!dataErrors) { OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, customTable); outputTable.OutputRows.Add(new OutputRow(customRow)); } } // update the special properties if (0 < adminProperties.Count) { Row newRow = new Row(this.tableDefinitions["Property"]); newRow[0] = "AdminProperties"; newRow[1] = GetPropertyListString(adminProperties); OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Property"]); outputTable.OutputRows.Add(new OutputRow(newRow)); } if (0 < secureProperties.Count) { Row newRow = new Row(this.tableDefinitions["Property"]); newRow[0] = "SecureCustomProperties"; newRow[1] = GetPropertyListString(secureProperties); OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Property"]); outputTable.OutputRows.Add(new OutputRow(newRow)); } if (0 < hiddenProperties.Count) { Row newRow = new Row(this.tableDefinitions["Property"]); newRow[0] = "MsiHiddenProperties"; newRow[1] = GetPropertyListString(hiddenProperties); OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["Property"]); outputTable.OutputRows.Add(new OutputRow(newRow)); } if (containsModuleSubstitution) { Row newRow = new Row(this.tableDefinitions["ModuleIgnoreTable"]); newRow[0] = "ModuleSubstitution"; OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleIgnoreTable"]); outputTable.OutputRows.Add(new OutputRow(newRow)); } if (containsModuleConfiguration) { Row newRow = new Row(this.tableDefinitions["ModuleIgnoreTable"]); newRow[0] = "ModuleConfiguration"; OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["ModuleIgnoreTable"]); outputTable.OutputRows.Add(new OutputRow(newRow)); } // process the actions foreach (Action action in requiredActions) { // skip actions in suppressed sequences if (suppressedSequenceTypes.Contains(action.SequenceType)) { continue; } if (OutputType.Product == this.activeOutput.Type) { this.ResolveActionSequence(action, requiredActions); } TableDefinition sequenceTableDef = null; bool module = OutputType.Module == this.activeOutput.Type; switch (action.SequenceType) { case SequenceType.adminExecute: if (module) { Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminExecuteSequence"]); sequenceTableDef = this.tableDefinitions["ModuleAdminExecuteSequence"]; } else { sequenceTableDef = this.tableDefinitions["AdminExecuteSequence"]; } break; case SequenceType.adminUI: if (module) { Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdminUISequence"]); sequenceTableDef = this.tableDefinitions["ModuleAdminUISequence"]; } else { sequenceTableDef = this.tableDefinitions["AdminUISequence"]; } break; case SequenceType.advertiseExecute: if (module) { Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["AdvtExecuteSequence"]); sequenceTableDef = this.tableDefinitions["ModuleAdvtExecuteSequence"]; } else { sequenceTableDef = this.tableDefinitions["AdvtExecuteSequence"]; } break; case SequenceType.installExecute: if (module) { Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallExecuteSequence"]); sequenceTableDef = this.tableDefinitions["ModuleInstallExecuteSequence"]; } else { sequenceTableDef = this.tableDefinitions["InstallExecuteSequence"]; } break; case SequenceType.installUI: if (module) { Common.EnsureOutputTable(this.activeOutput, this.tableDefinitions["InstallUISequence"]); sequenceTableDef = this.tableDefinitions["ModuleInstallUISequence"]; } else { sequenceTableDef = this.tableDefinitions["InstallUISequence"]; } break; } Row row = new Row(sequenceTableDef); if (module) { row[0] = action.Id; if (0 != action.SequenceNumber) { row[1] = action.SequenceNumber; } else { bool after = null == action.Before; row[2] = after ? action.After : action.Before; row[3] = after ? 1 : 0; } row[4] = action.Condition; } else // add the row to the sequence table { row[0] = action.Id; row[1] = action.Condition; row[2] = action.SequenceNumber; } OutputTable outputTable = Common.EnsureOutputTable(this.activeOutput, sequenceTableDef); outputTable.OutputRows.Add(new OutputRow(row)); } // set the suppressed action sequences if (this.suppressAdminSequence) { this.activeOutput.SuppressAdminSequence = true; } if (this.suppressAdvertiseSequence) { this.activeOutput.SuppressAdvertiseSequence = true; } if (this.suppressUISequence) { this.activeOutput.SuppressUISequence = true; } } finally { this.activeOutput = null; } return (this.foundError ? null : output); }